From: Jean Privat Date: Sat, 30 May 2015 12:15:42 +0000 (-0400) Subject: Merge: Kill `model_utils` X-Git-Tag: v0.7.5~1 X-Git-Url: http://nitlanguage.org?hp=-c Merge: Kill `model_utils` This PR removes the so hated module `model_utils`: * Useful services are kept in a new module `model::model_collect` that allows to collect and filter things from a `Model`. * Clients are migrated from `model_utils` to `model_collect` one by one. Misc functionalities used only by one client are moved in the client. Fixes #710 Pull-Request: #1376 Reviewed-by: Jean Privat Reviewed-by: Lucas Bajolet --- f38919d8532abb044a120fc8a84ac0a6661b2315 diff --combined src/doc/doc_base.nit index 4338eee,4be6da6..4d29cd7 --- a/src/doc/doc_base.nit +++ b/src/doc/doc_base.nit @@@ -16,7 -16,6 +16,6 @@@ module doc_base import toolcontext - import model_utils import model_ext # The model of a Nitdoc documentation. @@@ -75,15 -74,6 +74,15 @@@ class DocPag var root = new DocRoot redef fun to_s do return title + + # Pretty prints the content of this page. + fun pretty_print: Writable do + var res = new Template + res.addn "page: {title}" + res.addn "" + root.pretty_print_in(res) + return res + end end # `DocPage` elements that can be nested in another. @@@ -100,19 -90,6 +99,19 @@@ abstract class DocComposit # Parent element. var parent: nullable DocComposite = null is writable + # Element uniq id. + # + # The `id` is used as name for the generated element (if any). + # Because multiple elements can be generated in the same container + # it should be uniq. + # + # The `id` can also be used to establish links between elements + # (HTML links, HTML anchors, vim links, etc.). + var id: String is writable + + # Item title if any. + var title: nullable String + # Does `self` have a `parent`? fun is_root: Bool do return parent == null @@@ -121,18 -98,8 +120,18 @@@ # Children are ordered, this order can be changed by the `DocPhase`. var children = new Array[DocComposite] - # Does `self` have `children`? - fun is_empty: Bool do return children.is_empty + # Is `self` not displayed in the page. + # + # By default, empty elements are hidden. + fun is_hidden: Bool do return children.is_empty + + # Title used in table of content if any. + var toc_title: nullable String is writable, lazy do return title + + # Is `self` hidden in the table of content? + var is_toc_hidden: Bool is writable, lazy do + return toc_title == null or is_hidden + end # Add a `child` to `self`. # @@@ -147,20 -114,6 +146,20 @@@ if parent == null then return 0 return parent.depth + 1 end + + # Pretty prints this composite recursively. + fun pretty_print: Writable do + var res = new Template + pretty_print_in(res) + return res + end + + # Appends the Pretty print of this composite in `res`. + private fun pretty_print_in(res: Template) do + res.add "#" * depth + res.addn " {id}" + for child in children do child.pretty_print_in(res) + end end # The `DocComposite` element that contains all the other. @@@ -168,12 -121,8 +167,12 @@@ # The root uses a specific subclass to provide different a different behavior # than other `DocComposite` elements. class DocRoot + noautoinit super DocComposite + redef var id = "" + redef var title = "" + # No op for `RootSection`. redef fun parent=(p) do end end diff --combined src/doc/doc_phases/doc_html.nit index 83a2cc9,a98d8a7..6532a1d --- a/src/doc/doc_phases/doc_html.nit +++ b/src/doc/doc_phases/doc_html.nit @@@ -302,8 -302,8 +302,8 @@@ redef class MModulePag # TODO filter here? super var mclasses = new HashSet[MClass] - mclasses.add_all mentity.filter_intro_mclasses(v.ctx.min_visibility) - mclasses.add_all mentity.filter_redef_mclasses(v.ctx.min_visibility) + mclasses.add_all mentity.collect_intro_mclasses(v.ctx.min_visibility) + mclasses.add_all mentity.collect_redef_mclasses(v.ctx.min_visibility) if mclasses.is_empty then return var list = new UnorderedList list.css_classes.add "list-unstyled list-labeled" @@@ -372,7 -372,7 +372,7 @@@ redef class MClassPag if not mprop_is_local(mprop) then classes.add "inherit" var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url - var def_url = "{cls_url}#article:{mprop.nitdoc_id}.definition" + var def_url = "{cls_url}#{mprop.nitdoc_id}.definition" var lnk = new Link(def_url, mprop.html_name) var mdoc = mprop.intro.mdoc_or_fallback if mdoc != null then lnk.title = mdoc.short_comment @@@ -388,7 -388,7 +388,7 @@@ end var def = select_mpropdef(mprop) var anc = def.html_link_to_anchor - anc.href = "#article:{def.nitdoc_id}.definition" + anc.href = "#{def.nitdoc_id}.definition" var lnk = new Template lnk.add new DocHTMLLabel.with_classes(classes) lnk.add anc @@@ -410,8 -410,8 +410,8 @@@ private fun mclass_inherited_mprops(v: RenderHTMLPhase, doc: DocModel): Set[MProperty] do var res = new HashSet[MProperty] - var local = mentity.local_mproperties(v.ctx.min_visibility) - for mprop in mentity.inherited_mproperties(doc.mainmodule, v.ctx.min_visibility) do + var local = mentity.collect_local_mproperties(v.ctx.min_visibility) + for mprop in mentity.collect_inherited_mproperties(v.ctx.min_visibility) do if local.has(mprop) then continue #if mprop isa MMethod and mprop.is_init then continue if mprop.intro.mclassdef.mclass.name == "Object" and @@@ -471,7 -471,7 +471,7 @@@ redef class MEntitySectio title.add mentity.html_signature html_title = title html_subtitle = mentity.html_namespace - toc_title = mentity.html_name + html_toc_title = mentity.html_name end super end @@@ -484,16 -484,16 +484,16 @@@ redef class ConcernSectio var mentity = self.mentity if page isa MGroupPage then html_title = null - toc_title = mentity.html_name + html_toc_title = mentity.html_name is_toc_hidden = false else if page.mentity isa MModule and mentity isa MModule then var title = new Template if mentity == page.mentity then title.add "in " - toc_title = "in {mentity.html_name}" + html_toc_title = "in {mentity.html_name}" else title.add "from " - toc_title = "from {mentity.html_name}" + html_toc_title = "from {mentity.html_name}" end title.add mentity.html_namespace html_title = title @@@ -503,7 -503,7 +503,7 @@@ title.add "in " title.add mentity.html_namespace html_title = title - toc_title = "in {mentity.html_name}" + html_toc_title = "in {mentity.html_name}" end super end @@@ -532,7 -532,7 +532,7 @@@ redef class DefinitionArticl title.add mentity.html_icon title.add mentity.html_namespace html_title = title - toc_title = mentity.html_name + html_toc_title = mentity.html_name if mentity isa MModule then html_source_link = v.html_source_link(mentity.location) end @@@ -542,7 -542,7 +542,7 @@@ title.add mentity.mmodule.html_namespace html_title = mentity.html_declaration html_subtitle = title - toc_title = "in {mentity.html_name}" + html_toc_title = "in {mentity.html_name}" html_source_link = v.html_source_link(mentity.location) if page isa MEntityPage and mentity.is_intro and mentity.mmodule != page.mentity then is_short_comment = true @@@ -555,13 -555,13 +555,13 @@@ title.add mentity.html_declaration html_title = title html_subtitle = mentity.html_namespace - toc_title = mentity.html_name + html_toc_title = mentity.html_name else var title = new Template title.add "in " title.add mentity.mclassdef.html_link html_title = title - toc_title = "in {mentity.mclassdef.html_name}" + html_toc_title = "in {mentity.mclassdef.html_name}" end html_source_link = v.html_source_link(mentity.location) end @@@ -576,7 -576,7 +576,7 @@@ redef class HomeArticl redef fun init_html_render(v, doc, page) do if v.ctx.opt_custom_title.value != null then self.html_title = v.ctx.opt_custom_title.value.to_s - self.toc_title = v.ctx.opt_custom_title.value.to_s + self.html_toc_title = v.ctx.opt_custom_title.value.to_s end self.content = v.ctx.opt_custom_intro.value super @@@ -586,7 -586,7 +586,7 @@@ en redef class GraphArticle redef fun init_html_render(v, doc, page) do var output_dir = v.ctx.output_dir - var path = output_dir / id + var path = output_dir / graph_id var path_sh = path.escape_to_sh var file = new FileWriter.open("{path}.dot") file.write(dot) diff --combined src/doc/doc_phases/doc_intros_redefs.nit index ae341f9,83773f7..abc4f1d --- a/src/doc/doc_phases/doc_intros_redefs.nit +++ b/src/doc/doc_phases/doc_intros_redefs.nit @@@ -18,6 -18,7 +18,7 @@@ module doc_intros_redefs import doc_structure + import model::model_collect # Computes intro / redef mentity list for each DefinitionArticle. class IntroRedefListPhase @@@ -54,33 -55,52 +55,33 @@@ redef class DefinitionArticl # TODO this should move to MEntity? private fun build_mmodule_list(v: IntroRedefListPhase, doc: DocModel, mmodule: MModule) do - var section = new IntrosRedefsSection(mentity) - var group = new PanelGroup("List") + var section = new TabbedGroup("{mentity.nitdoc_id}.intros_redefs") + section.toc_title = "Intros / Redefs" + var group = new PanelGroup("list.group", "List") - var intros = mmodule.intro_mclassdefs(v.ctx.min_visibility).to_a + var intros = mmodule.collect_intro_mclassdefs(v.ctx.min_visibility).to_a doc.mainmodule.linearize_mclassdefs(intros) - group.add_child new IntrosRedefsListArticle(mentity, "Introduces", intros) + group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.intros", "Introduces", intros) - var redefs = mmodule.redef_mclassdefs(v.ctx.min_visibility).to_a + var redefs = mmodule.collect_redef_mclassdefs(v.ctx.min_visibility).to_a doc.mainmodule.linearize_mclassdefs(redefs) - group.add_child new IntrosRedefsListArticle(mentity, "Redefines", redefs) + group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.redefs", "Redefines", redefs) section.add_child group add_child(section) end # TODO this should move to MEntity? private fun build_mclassdef_list(v: IntroRedefListPhase, doc: DocModel, mclassdef: MClassDef) do - var section = new IntrosRedefsSection(mentity) - var group = new PanelGroup("List") + var section = new TabbedGroup("{mentity.nitdoc_id}.intros_redefs") + section.toc_title = "Intros / Redefs" + var group = new PanelGroup("list.group", "List") var intros = mclassdef.collect_intro_mpropdefs(v.ctx.min_visibility).to_a # FIXME avoid diff changes # v.ctx.mainmodule.linearize_mpropdefs(intros) - group.add_child new IntrosRedefsListArticle(mentity, "Introduces", intros) + group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.intros", "Introduces", intros) var redefs = mclassdef.collect_redef_mpropdefs(v.ctx.min_visibility).to_a # FIXME avoid diff changes # v.ctx.mainmodule.linearize_mpropdefs(redefs) - group.add_child new IntrosRedefsListArticle(mentity, "Redefines", redefs) + group.add_child new MEntitiesListArticle("{mentity.nitdoc_id}.redefs", "Redefines", redefs) section.add_child group add_child(section) end - -end - -# Section that contains the intros and redefs lists. -class IntrosRedefsSection - super TabbedGroup - super MEntitySection -end - -# An article that displays a list of introduced / refined mentities. -# -# FIXME diff hack -# This can merged with InheritanceListArticle in a more generic class. -class IntrosRedefsListArticle - super MEntityArticle - - # Title displayed as header of the list. - var list_title: String - - # Intro mentities to list. - var mentities: Array[MEntity] end diff --combined src/doc/doc_phases/doc_poset.nit index 556733e,43445cf..316438e --- a/src/doc/doc_phases/doc_poset.nit +++ b/src/doc/doc_phases/doc_poset.nit @@@ -16,6 -16,7 +16,7 @@@ module doc_poset import doc_pages + import model::model_collect # This phase computes importation and inheritance POSet for pages. class POSetPhase @@@ -46,7 -47,7 +47,7 @@@ redef class MModulePag # Imported modules that should appear in the documentation. var imports = new HashSet[MModule] - # Clients modules that shjould appear in the documentation. + # Clients modules that should appear in the documentation. var clients = new HashSet[MModule] redef fun build_poset(v, doc) do @@@ -82,7 -83,10 +83,10 @@@ end # make poset var mmodules = new HashSet[MModule] - mmodules.add_all mentity.nested_mmodules + var mgroup = mentity.mgroup + if mgroup != null and mgroup.default_mmodule == mentity then + mmodules.add_all mgroup.mmodules + end mmodules.add_all imports if clients.length < 10 then mmodules.add_all clients mmodules.add mentity diff --combined src/doc/doc_phases/doc_structure.nit index f9824d3,2e6a862..96bc219 --- a/src/doc/doc_phases/doc_structure.nit +++ b/src/doc/doc_phases/doc_structure.nit @@@ -47,15 -47,15 +47,15 @@@ en redef class OverviewPage redef fun apply_structure(v, doc) do - var article = new HomeArticle + var article = new HomeArticle("home.article", "Home") root.add_child article # Projects list var mprojects = doc.model.mprojects.to_a var sorter = new MConcernRankSorter sorter.sort mprojects - var section = new ProjectsSection + var section = new DocSection("projects.section", "Projects") for mproject in mprojects do - section.add_child new DefinitionArticle(mproject) + section.add_child new DefinitionArticle("{mproject.nitdoc_id}.definition", mproject) end article.add_child section end @@@ -69,18 -69,18 +69,18 @@@ redef class SearchPag v.name_sorter.sort(mclasses) var mprops = doc.mproperties.to_a v.name_sorter.sort(mprops) - root.add_child new IndexArticle(mmodules, mclasses, mprops) + root.add_child new IndexArticle("index.article", mmodules, mclasses, mprops) end end redef class MGroupPage redef fun apply_structure(v, doc) do - var section = new MEntitySection(mentity) + var section = new MEntitySection("{mentity.nitdoc_name}.section", mentity) root.add_child section if mentity.is_root then - section.add_child new IntroArticle(mentity.mproject) + section.add_child new IntroArticle("{mentity.mproject.nitdoc_id}.intro", mentity.mproject) else - section.add_child new IntroArticle(mentity) + section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", mentity) end var concerns = self.concerns if concerns == null or concerns.is_empty then return @@@ -90,11 -90,11 +90,11 @@@ concerns.sort_with(v.concerns_sorter) mentity.mproject.booster_rank = 0 mentity.booster_rank = 0 - section.add_child new ConcernsArticle(mentity, concerns) + section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", mentity, concerns) for mentity in concerns do - var ssection = new ConcernSection(mentity) + var ssection = new ConcernSection("{mentity.nitdoc_id}.concern", mentity) if mentity isa MModule then - ssection.add_child new DefinitionArticle(mentity) + ssection.add_child new DefinitionArticle("{mentity.nitdoc_id}.definition", mentity) end section.add_child ssection end @@@ -103,9 -103,9 +103,9 @@@ en redef class MModulePage redef fun apply_structure(v, doc) do - var section = new MEntitySection(mentity) + var section = new MEntitySection("{mentity.nitdoc_name}.section", mentity) root.add_child section - section.add_child new IntroArticle(mentity) + section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", mentity) var concerns = self.concerns if concerns == null or concerns.is_empty then return # FIXME avoid diff @@@ -116,25 -116,22 +116,25 @@@ mentity.mgroup.mproject.booster_rank = 0 mentity.mgroup.booster_rank = 0 mentity.booster_rank = 0 - section.add_child new ConcernsArticle(mentity, concerns) + section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", mentity, concerns) # reference list for mentity in concerns do - var ssection = new ConcernSection(mentity) + var ssection = new ConcernSection("{mentity.nitdoc_id}.concern", mentity) if mentity isa MModule then var mclasses = mclasses_for_mmodule(mentity).to_a v.name_sorter.sort(mclasses) for mclass in mclasses do - var article = new DefinitionListArticle(mclass) + var article = new DefinitionListArticle( + "{mclass.intro.nitdoc_id}.definition-list", mclass) var mclassdefs = mclassdefs_for(mclass).to_a if not mclassdefs.has(mclass.intro) then - article.add_child(new DefinitionArticle(mclass.intro)) + article.add_child(new DefinitionArticle( + "{mclass.intro.nitdoc_id}.definition", mclass.intro)) end doc.mainmodule.linearize_mclassdefs(mclassdefs) for mclassdef in mclassdefs do - article.add_child(new DefinitionArticle(mclassdef)) + article.add_child(new DefinitionArticle( + "{mclassdef.nitdoc_id}.definition", mclassdef)) end ssection.add_child article end @@@ -168,9 -165,9 +168,9 @@@ en redef class MClassPage redef fun apply_structure(v, doc) do - var section = new MEntitySection(mentity) + var section = new MEntitySection("{mentity.nitdoc_name}.section", mentity) root.add_child section - section.add_child new IntroArticle(mentity) + section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", mentity) var concerns = self.concerns if concerns == null or concerns.is_empty then return # FIXME diff hack @@@ -181,15 -178,15 +181,15 @@@ mentity.intro_mmodule.mgroup.mproject.booster_rank = 0 mentity.intro_mmodule.mgroup.booster_rank = 0 mentity.intro_mmodule.booster_rank = 0 - var constructors = new ConstructorsSection(mentity) + var constructors = new DocSection("{mentity.nitdoc_id}.constructors", "Constructors") var minit = mentity.root_init if minit != null then - constructors.add_child new DefinitionArticle(minit) + constructors.add_child new DefinitionArticle("{minit.nitdoc_id}.definition", minit) end section.add_child constructors - section.add_child new ConcernsArticle(mentity, concerns) + section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", mentity, concerns) for mentity in concerns do - var ssection = new ConcernSection(mentity) + var ssection = new ConcernSection("{mentity.nitdoc_id}.concern", mentity) if mentity isa MModule then var mprops = mproperties_for(mentity) var by_kind = new PropertiesByKind.with_elements(mprops) @@@ -199,11 -196,9 +199,11 @@@ for mpropdef in mpropdefs_for(mprop, mentity) do if mpropdef isa MMethodDef and mpropdef.mproperty.is_init then if mpropdef == minit then continue - constructors.add_child new DefinitionArticle(mpropdef) + constructors.add_child new DefinitionArticle( + "{mpropdef.nitdoc_id}.definition", mpropdef) else - ssection.add_child new DefinitionArticle(mpropdef) + ssection.add_child new DefinitionArticle( + "{mpropdef.nitdoc_id}.definition", mpropdef) end end end @@@ -243,9 -238,9 +243,9 @@@ en redef class MPropertyPage redef fun apply_structure(v, doc) do - var section = new MEntitySection(mentity) + var section = new MEntitySection("{mentity.nitdoc_name}.section", mentity) root.add_child section - section.add_child new IntroArticle(mentity) + section.add_child new IntroArticle("{mentity.nitdoc_id}.intro", mentity) var concerns = self.concerns if concerns == null or concerns.is_empty then return # FIXME diff hack @@@ -256,16 -251,15 +256,16 @@@ mentity.intro.mclassdef.mmodule.mgroup.mproject.booster_rank = 0 mentity.intro.mclassdef.mmodule.mgroup.booster_rank = 0 mentity.intro.mclassdef.mmodule.booster_rank = 0 - section.add_child new ConcernsArticle(mentity, concerns) + section.add_child new ConcernsArticle("{mentity.nitdoc_id}.concerns", mentity, concerns) for mentity in concerns do - var ssection = new ConcernSection(mentity) + var ssection = new ConcernSection("{mentity.nitdoc_id}.concern", mentity) if mentity isa MModule then # Add mproperties var mpropdefs = mpropdefs_for(mentity).to_a v.name_sorter.sort(mpropdefs) for mpropdef in mpropdefs do - ssection.add_child new DefinitionArticle(mpropdef) + ssection.add_child new DefinitionArticle( + "{mpropdef.nitdoc_id}.definition", mpropdef) end end section.add_child ssection @@@ -294,26 -288,30 +294,26 @@@ en # A group of sections that can be displayed together in a tab panel. class PanelGroup super DocSection - - # The title of this group. - var group_title: String end # A DocComposite element about a MEntity. class MEntityComposite super DocComposite + redef fun title do return mentity.nitdoc_name + # MEntity documented by this page element. var mentity: MEntity end -# A list of constructors. -class ConstructorsSection - super MEntitySection -end - # A Section about a Concern. # # Those sections are used to build the page summary. class ConcernSection super MEntityComposite super DocSection + + redef fun is_toc_hidden do return is_hidden end # An article about a Mentity. @@@ -324,17 -322,6 +324,17 @@@ abstract class MEntityArticl super DocArticle end +# An article that displays a list of mentities. +class MEntitiesListArticle + super DocArticle + + # MEntities to display. + var mentities: Array[MEntity] + + redef fun is_hidden do return mentities.is_empty +end + + # A section about a Mentity. # # Used to regroup content about a MEntity. @@@ -349,9 -336,6 +349,9 @@@ en class IntroArticle super MEntityComposite super DocArticle + + redef var is_hidden = false + redef var is_toc_hidden = true end # An article that display a ConcernsTreee as a list. @@@ -360,11 -344,9 +360,11 @@@ class ConcernsArticl # Concerns to list in this article. var concerns: ConcernsTree + + redef fun is_hidden do return concerns.is_empty end -# An article that displaus a list of definition belonging to a MEntity. +# An article that displays a list of definition belonging to a MEntity. class DefinitionListArticle super TabbedGroup super MEntityArticle @@@ -373,8 -355,6 +373,8 @@@ en # An article that display the definition text of a MEntity. class DefinitionArticle super MEntityArticle + + redef var is_hidden = false end # The main project article. @@@ -382,6 -362,11 +382,6 @@@ class HomeArticl super DocArticle end -# The project list. -class ProjectsSection - super DocArticle -end - # An article that display an index of mmodules, mclasses and mproperties. class IndexArticle super DocArticle @@@ -394,8 -379,76 +394,80 @@@ # List of mproperties to display. var mprops: Array[MProperty] + + redef fun is_hidden do + return mmodules.is_empty and mclasses.is_empty and mprops.is_empty + end end + + # Concerns ranking + + # Sort MConcerns based on the module importation hierarchy ranking + # see also: `MConcern::concern_rank` and `MConcern::booster_rank` + # + # Comparison is made with the formula: + # + # ~~~nitish + # a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran + # ~~~ + # + # If both `a` and `b` have the same ranking, + # ordering is based on lexicographic comparison of `a.name` and `b.name` + class MConcernRankSorter + super Comparator + redef type COMPARED: MConcern + + redef fun compare(a, b) do + if a.concern_rank == b.concern_rank then + return a.name <=> b.name + end + return a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_rank + end + end + + redef class MConcern + + # Boost a MConcern rank + # see: `MConcernRankSorter` + # Use a positive booster to push down a result in the list + # A negative booster can be used to push up the result + var booster_rank: Int = 0 is writable + + # Concern ranking used for ordering + # see: `MConcernRankSorter` + # Rank can be positive or negative + fun concern_rank: Int is abstract + end + + redef class MProject + redef var concern_rank is lazy do + var max = 0 + for mgroup in mgroups do + var mmax = mgroup.concern_rank + if mmax > max then max = mmax + end + return max + 1 + end + end + + redef class MGroup + redef var concern_rank is lazy do + var max = 0 + for mmodule in mmodules do + var mmax = mmodule.concern_rank + if mmax > max then max = mmax + end + return max + 1 + end + end + + redef class MModule + redef var concern_rank is lazy do + var max = 0 + for p in in_importation.direct_greaters do + var pmax = p.concern_rank + if pmax > max then max = pmax + end + return max + 1 + end + end diff --combined src/doc/html_templates/html_model.nit index 46953d9,d722cb7..b5ccd96 --- a/src/doc/html_templates/html_model.nit +++ b/src/doc/html_templates/html_model.nit @@@ -20,6 -20,7 +20,7 @@@ import doc_dow import html_components import html::bootstrap import ordered_tree + import model::model_collect redef class MEntity # URL of this entity’s Nitdoc page. @@@ -330,8 -331,8 +331,8 @@@ redef class MClassDe redef fun css_classes do var set = new HashSet[String] if is_intro then set.add "intro" - for m in mclass.intro.modifiers do set.add m.to_cmangle - for m in modifiers do set.add m.to_cmangle + for m in mclass.intro.collect_modifiers do set.add m.to_cmangle + for m in collect_modifiers do set.add m.to_cmangle return set.to_a end end @@@ -421,8 -422,8 +422,8 @@@ redef class MPropDe redef fun css_classes do var set = new HashSet[String] if is_intro then set.add "intro" - for m in mproperty.intro.modifiers do set.add m.to_cmangle - for m in modifiers do set.add m.to_cmangle + for m in mproperty.intro.collect_modifiers do set.add m.to_cmangle + for m in collect_modifiers do set.add m.to_cmangle return set.to_a end end @@@ -686,7 -687,7 +687,7 @@@ redef class MConcer private fun html_concern_item: ListItem do var lnk = html_link var tpl = new Template - tpl.add new Link.with_title("#concern:{nitdoc_id}", lnk.text, lnk.title) + tpl.add new Link.with_title("#{nitdoc_id}.concern", lnk.text, lnk.title) var comment = html_short_comment if comment != null then tpl.add ": " diff --combined src/metrics/nullables_metrics.nit index aa145c6,76e9b43..62c8f71 --- a/src/metrics/nullables_metrics.nit +++ b/src/metrics/nullables_metrics.nit @@@ -93,7 -93,7 +93,7 @@@ class CNBN redef fun collect(mclasses) do for mclass in mclasses do - var all = mclass.all_mattributes(mainmodule, min_visibility) + var all = mclass.collect_accessible_mattributes(min_visibility) for mattr in all do if mattr.is_nullable then values.inc(mclass) end @@@ -101,6 -101,15 +101,15 @@@ end end + redef class MAttribute + # Is this attribute nullable for sure? + # + # This mean that its introduction is declarred with a nullable static type + # since attributes are invariant this will work on most cases + # attributes with static type anchored with a virtual type are not "nullable for-sure" + # because this type can be redefined in subclasses + private fun is_nullable: Bool do return intro.static_mtype isa MNullableType + end private class NullableSends super Visitor @@@ -131,8 -140,8 +140,8 @@@ end t = t.anchor_to(self.nclassdef.mclassdef.mmodule, self.nclassdef.mclassdef.bound_mtype) if t isa MNullableType then - var name = n.callsite.mproperty.name - if name == "==" or name == "!=" or name == "is_same_instance" then + var p = n.callsite.mproperty + if p.is_null_safe then self.nullable_eq_sends += 1 else self.nullable_sends += 1 diff --combined src/model/model.nit index 4e9be82,999e7f1..f0bfe8b --- a/src/model/model.nit +++ b/src/model/model.nit @@@ -206,9 -206,6 +206,9 @@@ redef class MModul # The primitive type `Int` var int_type: MClassType = self.get_primitive_class("Int").mclass_type is lazy + # The primitive type `Byte` + var byte_type: MClassType = self.get_primitive_class("Byte").mclass_type is lazy + # The primitive type `Char` var char_type: MClassType = self.get_primitive_class("Char").mclass_type is lazy @@@ -517,6 -514,18 +517,18 @@@ class MClas # Is there a `new` factory to allow the pseudo instantiation? var has_new_factory = false is writable + + # Is `self` a standard or abstract class kind? + var is_class: Bool is lazy do return kind == concrete_kind or kind == abstract_kind + + # Is `self` an interface kind? + var is_interface: Bool is lazy do return kind == interface_kind + + # Is `self` an enum kind? + var is_enum: Bool is lazy do return kind == enum_kind + + # Is `self` and abstract class? + var is_abstract: Bool is lazy do return kind == abstract_kind end @@@ -2156,10 -2165,6 +2168,10 @@@ class MMetho do return self.is_init end + + # A specific method that is safe to call on null. + # Currently, only `==`, `!=` and `is_same_instance` are safe + fun is_null_safe: Bool do return name == "==" or name == "!=" or name == "is_same_instance" end # A global attribute diff --combined src/nitserial.nit index 8ead776,f68982e..83c4c6c --- a/src/nitserial.nit +++ b/src/nitserial.nit @@@ -27,7 -27,6 +27,6 @@@ module nitseria import frontend import rapid_type_analysis - import model_utils import template # A Nit module @@@ -94,7 -93,7 +93,7 @@@ en redef class MClassType redef fun is_visible_from(mmodule) do - return mmodule.is_visible(mclass.intro_mmodule, public_visibility) + return mmodule.is_visible(mclass.intro_mmodule, mclass.visibility) end end diff --combined tests/sav/nituml_args3.res index 1e16616,3b2984b..33e2d20 --- a/tests/sav/nituml_args3.res +++ b/tests/sav/nituml_args3.res @@@ -12,7 -12,7 +12,7 @@@ digraph G fontsize = 8 ] Object [ - label = "{interface\nObject||+ object_id(): Int\l+ is_same_type(other: Object): Bool\l+ is_same_instance(other: nullable Object): Bool\l+ ==(other: nullable Object): Bool\l+ !=(other: nullable Object): Bool\l+ output()\l+ output_class_name()\l+ hash(): Int\l+ sys(): Sys\l}" + label = "{interface\nObject||+ object_id(): Int\l+ is_same_type(other: Object): Bool\l+ is_same_instance(other: nullable Object): Bool\l+ ==(other: nullable Object): Bool\l+ !=(other: nullable Object): Bool\l+ output()\l+ output_class_name()\l+ hash(): Int\l+ sys(): Sys\l+ init()\l}" ] Sys [ @@@ -36,7 -36,7 +36,7 @@@ Cloneable Object -> Cloneable [dir=back arrowtail=open style=dashed]; Numeric [ - label = "{interface\nNumeric||+ +(i: OTHER): OTHER\l+ -(i: OTHER): OTHER\l+ unary -(): OTHER\l+ *(i: OTHER): OTHER\l+ /(i: OTHER): OTHER\l+ to_i(): Int\l+ to_f(): Float\l+ is_zero(): Bool\l+ zero(): OTHER\l+ value_of(val: Numeric): OTHER\l}" + label = "{interface\nNumeric||+ +(i: OTHER): OTHER\l+ -(i: OTHER): OTHER\l+ unary -(): OTHER\l+ *(i: OTHER): OTHER\l+ /(i: OTHER): OTHER\l+ to_i(): Int\l+ to_f(): Float\l+ to_b(): Byte\l+ is_zero(): Bool\l+ zero(): OTHER\l+ value_of(val: Numeric): OTHER\l}" ] Comparable -> Numeric [dir=back arrowtail=open style=dashed]; @@@ -50,12 -50,6 +50,12 @@@ Float ] Numeric -> Float [dir=back arrowtail=open style=dashed]; +Byte [ + label = "{Byte||+ %(i: Byte): Byte\l+ lshift(i: Int): Byte\l+ \<\<(i: Int): Byte\l+ rshift(i: Int): Byte\l+ \>\>(i: Int): Byte\l}" +] +Discrete -> Byte [dir=back arrowtail=open style=dashed]; +Numeric -> Byte [dir=back arrowtail=open style=dashed]; + Int [ label = "{Int||+ %(i: Int): Int\l+ lshift(i: Int): Int\l+ \<\<(i: Int): Int\l+ rshift(i: Int): Int\l+ \>\>(i: Int): Int\l+ ascii(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}" ] diff --combined tests/sav/nituml_args4.res index 74c96da,d1bf457..8fc87eb --- a/tests/sav/nituml_args4.res +++ b/tests/sav/nituml_args4.res @@@ -12,7 -12,7 +12,7 @@@ digraph G fontsize = 8 ] Object [ - label = "{interface\nObject||+ object_id(): Int\l+ is_same_type(other: Object): Bool\l+ is_same_instance(other: nullable Object): Bool\l+ ==(other: nullable Object): Bool\l+ !=(other: nullable Object): Bool\l+ output()\l+ output_class_name()\l+ hash(): Int\l+ sys(): Sys\l}" + label = "{interface\nObject||+ object_id(): Int\l+ is_same_type(other: Object): Bool\l+ is_same_instance(other: nullable Object): Bool\l+ ==(other: nullable Object): Bool\l+ !=(other: nullable Object): Bool\l+ output()\l+ output_class_name()\l+ hash(): Int\l+ sys(): Sys\l+ init()\l}" ] Sys [ @@@ -36,7 -36,7 +36,7 @@@ Cloneable Object -> Cloneable [dir=back arrowtail=open style=dashed]; Numeric [ - label = "{interface\nNumeric||+ +(i: OTHER): OTHER\l+ -(i: OTHER): OTHER\l+ unary -(): OTHER\l+ *(i: OTHER): OTHER\l+ /(i: OTHER): OTHER\l+ to_i(): Int\l+ to_f(): Float\l+ is_zero(): Bool\l+ zero(): OTHER\l+ value_of(val: Numeric): OTHER\l}" + label = "{interface\nNumeric||+ +(i: OTHER): OTHER\l+ -(i: OTHER): OTHER\l+ unary -(): OTHER\l+ *(i: OTHER): OTHER\l+ /(i: OTHER): OTHER\l+ to_i(): Int\l+ to_f(): Float\l+ to_b(): Byte\l+ is_zero(): Bool\l+ zero(): OTHER\l+ value_of(val: Numeric): OTHER\l}" ] Comparable -> Numeric [dir=back arrowtail=open style=dashed]; @@@ -49,12 -49,6 +49,12 @@@ Float label = "{Float||+ is_approx(other: Float, precision: Float): Bool\l}" ] Numeric -> Float [dir=back arrowtail=open style=dashed]; + +Byte [ + label = "{Byte||+ %(i: Byte): Byte\l+ lshift(i: Int): Byte\l+ \<\<(i: Int): Byte\l+ rshift(i: Int): Byte\l+ \>\>(i: Int): Byte\l}" +] +Discrete -> Byte [dir=back arrowtail=open style=dashed]; +Numeric -> Byte [dir=back arrowtail=open style=dashed]; Int [ label = "{Int||+ %(i: Int): Int\l+ lshift(i: Int): Int\l+ \<\<(i: Int): Int\l+ rshift(i: Int): Int\l+ \>\>(i: Int): Int\l+ ascii(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}"