Merge: Kill `model_utils`
authorJean Privat <jean@pryen.org>
Sat, 30 May 2015 12:15:42 +0000 (08:15 -0400)
committerJean Privat <jean@pryen.org>
Sat, 30 May 2015 12:15:42 +0000 (08:15 -0400)
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 <jean@pryen.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

23 files changed:
src/doc/doc_base.nit
src/doc/doc_phases/doc_concerns.nit
src/doc/doc_phases/doc_html.nit
src/doc/doc_phases/doc_intros_redefs.nit
src/doc/doc_phases/doc_poset.nit
src/doc/doc_phases/doc_structure.nit
src/doc/html_templates/html_model.nit
src/doc/vim_autocomplete.nit
src/metrics/mclasses_metrics.nit
src/metrics/mendel_metrics.nit
src/metrics/metrics_base.nit
src/metrics/nullables_metrics.nit
src/model/model.nit
src/model/model_base.nit
src/model/model_collect.nit [new file with mode: 0644]
src/model_utils.nit [deleted file]
src/nitserial.nit
src/test_neo.nit
src/uml/uml_base.nit
src/uml/uml_class.nit
tests/sav/nitmetrics_args1.res
tests/sav/nituml_args3.res
tests/sav/nituml_args4.res

index 4338eee..4d29cd7 100644 (file)
@@ -16,7 +16,6 @@
 module doc_base
 
 import toolcontext
-import model_utils
 import model_ext
 
 # The model of a Nitdoc documentation.
index cca6346..5c9b2e9 100644 (file)
@@ -16,6 +16,7 @@
 module doc_concerns
 
 import doc_pages
+import model::model_collect
 
 # ConcernsPhase computes the ConcernsTree used for each page layout.
 class ConcernsPhase
@@ -23,7 +24,7 @@ class ConcernsPhase
 
        # Populates the given DocModel.
        redef fun apply do
-               for page in doc.pages.values do page.build_concerns(doc)
+               for page in doc.pages.values do page.build_concerns(self)
        end
 end
 
@@ -32,7 +33,7 @@ redef class DocPage
        # Build the `concerns` tree for this page.
        #
        # Since only `MEntityPage`, this method is a no-op for everything else.
-       private fun build_concerns(doc: DocModel) do end
+       private fun build_concerns(v: ConcernsPhase) do end
 end
 
 redef class MEntityPage
@@ -53,15 +54,16 @@ redef class MGroupPage
        # Refined classes in `mentity` that should appear in this page.
        var redefs = new HashSet[MClass]
 
-       redef fun build_concerns(doc) do
+       redef fun build_concerns(v) do
+               var doc = v.doc
                var mmodules = new HashSet[MModule]
-               for mmodule in mentity.collect_mmodules do
+               for mmodule in mentity.mmodules do
                        if doc.mmodules.has(mmodule) then mmodules.add mmodule
                        # collect mclasses
                        for mclass in mmodule.intro_mclasses do
                                if doc.mclasses.has(mclass) then intros.add mclass
                        end
-                       for mclass in mmodule.redef_mclasses do
+                       for mclass in mmodule.collect_redef_mclasses(v.ctx.min_visibility) do
                                if doc.mclasses.has(mclass) then redefs.add mclass
                        end
                end
@@ -77,7 +79,8 @@ redef class MModulePage
        # MClassDefs located in `mentity` to display in this page.
        var mclassdefs = new HashSet[MClassDef]
 
-       redef fun build_concerns(doc) do
+       redef fun build_concerns(v) do
+               var doc = v.doc
                # extract mclassdefs in mmodule
                for mclassdef in mentity.mclassdefs do
                        if doc.mclassdefs.has(mclassdef) then mclassdefs.add mclassdef
@@ -105,7 +108,8 @@ redef class MClassPage
        # MPropdefs to display in this page.
        var mpropdefs = new HashSet[MPropDef]
 
-       redef fun build_concerns(doc) do
+       redef fun build_concerns(v) do
+               var doc = v.doc
                # collect mclassdefs
                for mclassdef in mentity.mclassdefs do
                        if doc.mclassdefs.has(mclassdef) then mclassdefs.add mclassdef
@@ -131,7 +135,8 @@ redef class MPropertyPage
        # MPropdefs to display in this page.
        var mpropdefs = new HashSet[MPropDef]
 
-       redef fun build_concerns(doc) do
+       redef fun build_concerns(v) do
+               var doc = v.doc
                # collect mpropdefs
                for mpropdef in mentity.mpropdefs do
                        # FIXME diff hack
index 83a2cc9..6532a1d 100644 (file)
@@ -302,8 +302,8 @@ redef class MModulePage
                # 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"
@@ -410,8 +410,8 @@ redef class MClassPage
 
        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
index ae341f9..abc4f1d 100644 (file)
@@ -18,6 +18,7 @@
 module doc_intros_redefs
 
 import doc_structure
+import model::model_collect
 
 # Computes intro / redef mentity list for each DefinitionArticle.
 class IntroRedefListPhase
@@ -57,10 +58,10 @@ redef class DefinitionArticle
                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 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 MEntitiesListArticle("{mentity.nitdoc_id}.redefs", "Redefines", redefs)
                section.add_child group
index 556733e..316438e 100644 (file)
@@ -16,6 +16,7 @@
 module doc_poset
 
 import doc_pages
+import model::model_collect
 
 # This phase computes importation and inheritance POSet for pages.
 class POSetPhase
@@ -82,7 +83,10 @@ redef class MModulePage
                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
index f9824d3..96bc219 100644 (file)
@@ -399,3 +399,75 @@ class IndexArticle
                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
index 46953d9..b5ccd96 100644 (file)
@@ -20,6 +20,7 @@ import doc_down
 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 @@ redef class MClassDef
        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 @@ redef class MPropDef
        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
index 7781fe8..290ed9d 100644 (file)
@@ -31,7 +31,7 @@ module vim_autocomplete
 import modelbuilder
 import phase
 import modelize::modelize_class
-import model_utils
+import model::model_collect
 
 redef class ToolContext
        # Phase generating the files for the Vim plugin
@@ -197,7 +197,7 @@ redef class MClassType
                stream.write line_separator*2
                stream.write "## Properties"
                stream.write line_separator
-               var props = mclass.all_mproperties(mainmodule, protected_visibility).to_a
+               var props = mclass.collect_accessible_mproperties(protected_visibility).to_a
                alpha_comparator.sort props
                for prop in props do
                        if mclass.name == "Object" or prop.intro.mclassdef.mclass.name != "Object" then
@@ -263,7 +263,7 @@ private class AutocompletePhase
                        # Can it be instantiated?
                        if mclass.kind != interface_kind and mclass.kind != abstract_kind then
 
-                               for prop in mclass.all_mproperties(mainmodule, public_visibility) do
+                               for prop in mclass.collect_accessible_mproperties(public_visibility) do
                                        if prop isa MMethod and prop.is_init then
                                                mclass_intro.target_constructor = prop.intro
                                                mclass_intro.write_doc(mainmodule, constructors_stream)
index fabd573..ed41a9f 100644 (file)
@@ -18,6 +18,7 @@
 module mclasses_metrics
 
 import metrics_base
+import model::model_collect
 
 redef class ToolContext
        var mclasses_metrics_phase: Phase = new MClassesMetricsPhase(self, null)
@@ -192,7 +193,7 @@ class CNBP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.all_mproperties(mainmodule, min_visibility).length
+                       values[mclass] = mclass.collect_accessible_mproperties(min_visibility).length
                end
        end
 end
@@ -214,7 +215,7 @@ class CNBA
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.all_mattributes(mainmodule, min_visibility).length
+                       values[mclass] = mclass.collect_accessible_mattributes(min_visibility).length
                end
        end
 end
@@ -236,7 +237,7 @@ class CNBIP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.intro_mproperties(min_visibility).length
+                       values[mclass] = mclass.collect_intro_mproperties(min_visibility).length
                end
        end
 end
@@ -258,7 +259,7 @@ class CNBRP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.redef_mproperties(min_visibility).length
+                       values[mclass] = mclass.collect_redef_mproperties(min_visibility).length
                end
        end
 end
@@ -280,7 +281,7 @@ class CNBHP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.inherited_mproperties(mainmodule, min_visibility).length
+                       values[mclass] = mclass.collect_inherited_mproperties(min_visibility).length
                end
        end
 end
@@ -302,7 +303,7 @@ class CNBLP
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       values[mclass] = mclass.local_mproperties(min_visibility).length
+                       values[mclass] = mclass.collect_local_mproperties(min_visibility).length
                end
        end
 end
index 3209720..23daf06 100644 (file)
@@ -142,7 +142,7 @@ class CBMS
 
        redef fun collect(mclasses) do
                for mclass in mclasses do
-                       var totc = mclass.all_mproperties(mainmodule, protected_visibility).length
+                       var totc = mclass.collect_accessible_mproperties(protected_visibility).length
                        var ditc = mclass.in_hierarchy(mainmodule).depth
                        values[mclass] = totc.to_f / (ditc + 1).to_f
                end
@@ -169,7 +169,7 @@ class CNVI
                                cbms.clear
                                cbms.collect(new HashSet[MClass].from(parents))
                                # compute class novelty index
-                               var locc = mclass.local_mproperties(protected_visibility).length
+                               var locc = mclass.collect_accessible_mproperties(protected_visibility).length
                                values[mclass] = locc.to_f / cbms.avg
                        else
                                values[mclass] = 0.0
@@ -193,7 +193,7 @@ class CNVS
                var cnvi = new CNVI(mainmodule)
                cnvi.collect(mclasses)
                for mclass in mclasses do
-                       var locc = mclass.local_mproperties(protected_visibility).length
+                       var locc = mclass.collect_local_mproperties(protected_visibility).length
                        values[mclass] = cnvi.values[mclass] * locc.to_f
                end
        end
@@ -228,34 +228,34 @@ redef class MClass
 
        # pure overriders contain only redefinitions
        private fun is_pure_overrider(min_visibility: MVisibility): Bool do
-               var news = intro_mproperties(min_visibility).length
-               var locs = local_mproperties(min_visibility).length
+               var news = collect_intro_mproperties(min_visibility).length
+               var locs = collect_local_mproperties(min_visibility).length
                if news == 0 and locs > 0 then return true
                return false
        end
 
        # overriders contain more definitions than introductions
        private fun is_overrider(min_visibility: MVisibility): Bool do
-               var rdfs = redef_mproperties(min_visibility).length
-               var news = intro_mproperties(min_visibility).length
-               var locs = local_mproperties(min_visibility).length
+               var rdfs = collect_redef_mproperties(min_visibility).length
+               var news = collect_intro_mproperties(min_visibility).length
+               var locs = collect_local_mproperties(min_visibility).length
                if rdfs >= news and locs > 0 then return true
                return false
        end
 
        # pure extenders contain only introductions
        private fun is_pure_extender(min_visibility: MVisibility): Bool do
-               var rdfs = redef_mproperties(min_visibility).length
-               var locs = local_mproperties(min_visibility).length
+               var rdfs = collect_redef_mproperties(min_visibility).length
+               var locs = collect_local_mproperties(min_visibility).length
                if rdfs == 0 and locs > 0 then return true
                return false
        end
 
        # extenders contain more introduction than redefinitions
        private fun is_extender(min_visibility: MVisibility): Bool do
-               var rdfs = redef_mproperties(min_visibility).length
-               var news = intro_mproperties(min_visibility).length
-               var locs = local_mproperties(min_visibility).length
+               var rdfs = collect_redef_mproperties(min_visibility).length
+               var news = collect_intro_mproperties(min_visibility).length
+               var locs = collect_local_mproperties(min_visibility).length
                if news > rdfs and locs > 0 then return true
                return false
        end
@@ -263,7 +263,7 @@ redef class MClass
        # pure specializers always call to super in its redefinitions
        private fun is_pure_specializer(min_visibility: MVisibility): Bool do
                var ovrs = overriden_mproperties(min_visibility).length
-               var rdfs = redef_mproperties(min_visibility).length
+               var rdfs = collect_redef_mproperties(min_visibility).length
                if ovrs == 0 and rdfs > 0 then return true
                return false
        end
@@ -272,7 +272,7 @@ redef class MClass
        private fun is_specializer(min_visibility: MVisibility): Bool do
                var spcs = extended_mproperties(min_visibility).length
                var ovrs = overriden_mproperties(min_visibility).length
-               var rdfs = redef_mproperties(min_visibility).length
+               var rdfs = collect_redef_mproperties(min_visibility).length
                if spcs > ovrs and rdfs > 0 then return true
                return false
        end
@@ -280,7 +280,7 @@ redef class MClass
        # pure replacers never call to super in its redefinitions
        private fun is_pure_replacer(min_visibility: MVisibility): Bool do
                var spcs = extended_mproperties(min_visibility).length
-               var rdfs = redef_mproperties(min_visibility).length
+               var rdfs = collect_redef_mproperties(min_visibility).length
                if spcs == 0 and rdfs > 0 then return true
                return false
        end
@@ -289,7 +289,7 @@ redef class MClass
        private fun is_replacer(min_visibility: MVisibility): Bool do
                var spcs = extended_mproperties(min_visibility).length
                var ovrs = overriden_mproperties(min_visibility).length
-               var rdfs = redef_mproperties(min_visibility).length
+               var rdfs = collect_redef_mproperties(min_visibility).length
                if ovrs > spcs and rdfs > 0 then return true
                return false
        end
@@ -298,7 +298,7 @@ redef class MClass
        private fun is_equal(min_visibility: MVisibility): Bool do
                var spcs = extended_mproperties(min_visibility).length
                var ovrs = overriden_mproperties(min_visibility).length
-               var rdfs = redef_mproperties(min_visibility).length
+               var rdfs = collect_redef_mproperties(min_visibility).length
                if spcs == ovrs and rdfs > 0 then return true
                return false
        end
index a7ded94..d49f96b 100644 (file)
@@ -18,7 +18,6 @@
 # Helpers for various statistics tools.
 module metrics_base
 
-import model_utils
 import modelbuilder
 import csv
 import counter
index aa145c6..62c8f71 100644 (file)
@@ -93,7 +93,7 @@ class CNBNA
 
        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 @@ class CNBNA
        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
index 4e9be82..f0bfe8b 100644 (file)
@@ -517,6 +517,18 @@ class MClass
 
        # 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
 
 
index fd2e1d1..396d5e1 100644 (file)
@@ -102,6 +102,16 @@ class MVisibility
        end
 end
 
+# A `Comparator` to sort mentities by their names.
+class MEntityNameSorter
+       super Comparator
+
+       redef type COMPARED: MEntity
+
+       # Returns `a.name <=> b.name`.
+       redef fun compare(a, b) do return a.name <=> b.name
+end
+
 # The visibility level `intrude`
 fun intrude_visibility: MVisibility do return once new MVisibility("intrude", 5)
 # The visibility level `public`
diff --git a/src/model/model_collect.nit b/src/model/model_collect.nit
new file mode 100644 (file)
index 0000000..2a64345
--- /dev/null
@@ -0,0 +1,334 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2008 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Collect things from a `Model`.
+#
+# **Warning**
+#
+# `model_collect` offers a flattened view of the model without considering any
+# main module.
+# For this reason, `model_collect` lists all the definitions reachable from all
+# modules
+#
+# This is usefull for tools that need a global view of a model like `nitdoc`,
+# `nitx` or `nituml`.
+# It shoul not be used for compiling stuffs like computing VFT, where the listed
+# entities could not be reachable depending on the modules really imported.
+module model_collect
+
+import model
+
+redef class MModule
+
+       # Collect mclassdefs introduced in `self` with `visibility >= to min_visibility`.
+       fun collect_intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
+               var res = new HashSet[MClassDef]
+               for mclassdef in mclassdefs do
+                       if not mclassdef.is_intro then continue
+                       if mclassdef.mclass.visibility < min_visibility then continue
+                       res.add mclassdef
+               end
+               return res
+       end
+
+       # Collect mclassdefs redefined in `self` with `visibility >= to min_visibility`.
+       fun collect_redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
+               var res = new HashSet[MClassDef]
+               for mclassdef in mclassdefs do
+                       if mclassdef.is_intro then continue
+                       if mclassdef.mclass.visibility < min_visibility then continue
+                       res.add mclassdef
+               end
+               return res
+       end
+
+       # Collect mclasses introduced in `self` with `visibility >= to min_visibility`.
+       fun collect_intro_mclasses(min_visibility: MVisibility): Set[MClass] do
+               var res = new HashSet[MClass]
+               for mclass in intro_mclasses do
+                       if mclass.visibility < min_visibility then continue
+                       res.add mclass
+               end
+               return res
+       end
+
+       # Collect mclasses redefined in `self` with `visibility >= to min_visibility`.
+       fun collect_redef_mclasses(min_visibility: MVisibility): Set[MClass] do
+               var mclasses = new HashSet[MClass]
+               for c in mclassdefs do
+                       if c.mclass.visibility < min_visibility then continue
+                       if not c.is_intro then mclasses.add(c.mclass)
+               end
+               return mclasses
+       end
+end
+
+redef class MClass
+
+       # Collect direct parents of `self` with `visibility >= to min_visibility`.
+       fun collect_parents(min_visibility: MVisibility): Set[MClass] do
+               var res = new HashSet[MClass]
+               for mclassdef in mclassdefs do
+                       for mclasstype in mclassdef.supertypes do
+                               var mclass = mclasstype.mclass
+                               if mclass.visibility < min_visibility then continue
+                               res.add(mclass)
+                       end
+               end
+               return res
+       end
+
+       # Collect all ancestors of `self` with `visibility >= to min_visibility`.
+       fun collect_ancestors(min_visibility: MVisibility): Set[MClass] do
+               var res = new HashSet[MClass]
+               for mclassdef in self.mclassdefs do
+                       for super_mclassdef in mclassdef.in_hierarchy.greaters do
+                               if super_mclassdef == mclassdef then continue  # skip self
+                               var mclass = super_mclassdef.mclass
+                               if mclass.visibility < min_visibility then continue
+                               res.add(mclass)
+                       end
+               end
+               return res
+       end
+
+       # Collect direct children of `self` with `visibility >= to min_visibility`.
+       fun collect_children(min_visibility: MVisibility): Set[MClass] do
+               var res = new HashSet[MClass]
+               for mclassdef in self.mclassdefs do
+                       for sub_mclassdef in mclassdef.in_hierarchy.direct_smallers do
+                               if sub_mclassdef == mclassdef then continue  # skip self
+                               var mclass = sub_mclassdef.mclass
+                               if mclass.visibility < min_visibility then continue
+                               res.add(mclass)
+                       end
+               end
+               return res
+       end
+
+       # Collect all descendants of `self` with `visibility >= to min_visibility`.
+       fun descendants(min_visibility: MVisibility): Set[MClass] do
+               var res = new HashSet[MClass]
+               for mclassdef in self.mclassdefs do
+                       for sub_mclassdef in mclassdef.in_hierarchy.smallers do
+                               if sub_mclassdef == mclassdef then continue  # skip self
+                               var mclass = sub_mclassdef.mclass
+                               if mclass.visibility < min_visibility then continue
+                               res.add(mclass)
+                       end
+               end
+               return res
+       end
+
+       # Collect all mproperties introduced in 'self' with `visibility >= min_visibility`.
+       fun collect_intro_mproperties(min_visibility: MVisibility): Set[MProperty] do
+               var set = new HashSet[MProperty]
+               for mclassdef in mclassdefs do
+                       for mprop in mclassdef.intro_mproperties do
+                               if mprop.visibility < min_visibility then continue
+                               set.add(mprop)
+                       end
+               end
+               return set
+       end
+
+       # Collect all mproperties redefined in 'self' with `visibility >= min_visibility`.
+       fun collect_redef_mproperties(min_visibility: MVisibility): Set[MProperty] do
+               var set = new HashSet[MProperty]
+               for mclassdef in mclassdefs do
+                       for mpropdef in mclassdef.mpropdefs do
+                               if mpropdef.mproperty.visibility < min_visibility then continue
+                               if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
+                       end
+               end
+               return set
+       end
+
+       # Collect mproperties introduced and redefined in 'self' with `visibility >= min_visibility`.
+       fun collect_local_mproperties(min_visibility: MVisibility): Set[MProperty] do
+               var set = new HashSet[MProperty]
+               set.add_all collect_intro_mproperties(min_visibility)
+               set.add_all collect_redef_mproperties(min_visibility)
+               return set
+       end
+
+       # Collect all mproperties inehrited by 'self' with `visibility >= min_visibility`.
+       fun collect_inherited_mproperties(min_visibility: MVisibility): Set[MProperty] do
+               var set = new HashSet[MProperty]
+               for parent in collect_parents(min_visibility) do
+                       set.add_all(parent.collect_intro_mproperties(min_visibility))
+                       set.add_all(parent.collect_inherited_mproperties(min_visibility))
+               end
+               return set
+       end
+
+       # Collect all mproperties accessible by 'self' with `visibility >= min_visibility`.
+       #
+       # This include introduced, redefined, inherited mproperties.
+       fun collect_accessible_mproperties(min_visibility: MVisibility): Set[MProperty] do
+               var set = new HashSet[MProperty]
+               set.add_all(collect_intro_mproperties(min_visibility))
+               set.add_all(collect_redef_mproperties(min_visibility))
+               set.add_all(collect_inherited_mproperties(min_visibility))
+               return set
+       end
+
+       # Collect mmethods introduced in 'self' with `visibility >= min_visibility`.
+       fun collect_intro_mmethods(min_visibility: MVisibility): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mproperty in collect_intro_mproperties(min_visibility) do
+                       if mproperty isa MMethod then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect mmethods redefined in 'self' with `visibility >= min_visibility`.
+       fun collect_redef_mmethods(min_visibility: MVisibility): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mproperty in collect_redef_mproperties(min_visibility) do
+                       if mproperty isa MMethod then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect mmethods introduced and redefined in 'self' with `visibility >= min_visibility`.
+       fun collect_local_mmethods(min_visibility: MVisibility): Set[MMethod] do
+               var set = new HashSet[MMethod]
+               set.add_all collect_intro_mmethods(min_visibility)
+               set.add_all collect_redef_mmethods(min_visibility)
+               return set
+       end
+
+       # Collect mattributes introduced in 'self' with `visibility >= min_visibility`.
+       fun collect_intro_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+               var res = new HashSet[MAttribute]
+               for mproperty in collect_intro_mproperties(min_visibility) do
+                       if mproperty isa MAttribute then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect mattributes redefined in 'self' with `visibility >= min_visibility`.
+       fun collect_redef_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+               var res = new HashSet[MAttribute]
+               for mproperty in collect_redef_mproperties(min_visibility) do
+                       if mproperty isa MAttribute then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect mattributes introduced and redefined in 'self' with `visibility >= min_visibility`.
+       fun collect_local_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+               var set = new HashSet[MAttribute]
+               set.add_all collect_intro_mattributes(min_visibility)
+               set.add_all collect_redef_mattributes(min_visibility)
+               return set
+       end
+
+       # Collect mattributes inherited by 'self' with `visibility >= min_visibility`.
+       fun collect_inherited_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+               var res = new HashSet[MAttribute]
+               for mproperty in collect_inherited_mproperties(min_visibility) do
+                       if mproperty isa MAttribute then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all mattributes accessible by 'self' with `visibility >= min_visibility`.
+       #
+       # This include introduced, redefined, inherited mattributes.
+       fun collect_accessible_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+               var set = new HashSet[MAttribute]
+               set.add_all(collect_intro_mattributes(min_visibility))
+               set.add_all(collect_redef_mattributes(min_visibility))
+               set.add_all(collect_inherited_mattributes(min_visibility))
+               return set
+       end
+end
+
+redef class MClassDef
+       # Collect mpropdefs in 'self' with `visibility >= min_visibility`.
+       fun collect_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
+               var res = new HashSet[MPropDef]
+               for mpropdef in mpropdefs do
+                       if mpropdef.mproperty.visibility < min_visibility then continue
+                       res.add mpropdef
+               end
+               return res
+       end
+
+       # Collect mpropdefs introduced in 'self' with `visibility >= min_visibility`.
+       fun collect_intro_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
+               var res = new HashSet[MPropDef]
+               for mpropdef in mpropdefs do
+                       if not mpropdef.is_intro then continue
+                       if mpropdef.mproperty.visibility < min_visibility then continue
+                       res.add mpropdef
+               end
+               return res
+       end
+
+       # Collect mpropdefs redefined in 'self' with `visibility >= min_visibility`.
+       fun collect_redef_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
+               var res = new HashSet[MPropDef]
+               for mpropdef in mpropdefs do
+                       if mpropdef.is_intro then continue
+                       if mpropdef.mproperty.visibility < min_visibility then continue
+                       res.add mpropdef
+               end
+               return res
+       end
+
+       # Collect modifiers like redef, private etc.
+       fun collect_modifiers: Array[String] do
+               var res = new Array[String]
+               if not is_intro then
+                       res.add "redef"
+               else
+                       res.add mclass.visibility.to_s
+               end
+               res.add mclass.kind.to_s
+               return res
+       end
+end
+
+redef class MPropDef
+       # Collect modifiers like redef, private, abstract, intern, fun etc.
+       fun collect_modifiers: Array[String] do
+               var res = new Array[String]
+               if not is_intro then
+                       res.add "redef"
+               else
+                       res.add mproperty.visibility.to_s
+               end
+               var mprop = self
+               if mprop isa MVirtualTypeDef then
+                       res.add "type"
+               else if mprop isa MMethodDef then
+                       if mprop.is_abstract then
+                               res.add "abstract"
+                       else if mprop.is_intern then
+                               res.add "intern"
+                       end
+                       if mprop.mproperty.is_init then
+                               res.add "init"
+                       else
+                               res.add "fun"
+                       end
+               end
+               return res
+       end
+end
diff --git a/src/model_utils.nit b/src/model_utils.nit
deleted file mode 100644 (file)
index 24105e6..0000000
+++ /dev/null
@@ -1,533 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# Copyright 2008 Jean Privat <jean@pryen.org>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Model exploration and traversing facilities
-module model_utils
-
-import model
-
-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
-       fun in_nesting_intro_mclasses(min_visibility: MVisibility): Set[MClass] do
-               var res = new HashSet[MClass]
-               var lst = in_nesting.direct_smallers
-               for mmodule in mmodules do res.add_all mmodule.filter_intro_mclasses(min_visibility)
-               for mgrp in lst do res.add_all mgrp.in_nesting_intro_mclasses(min_visibility)
-               return res
-       end
-
-       fun in_nesting_redef_mclasses(min_visibility: MVisibility): Set[MClass] do
-               var res = new HashSet[MClass]
-               var lst = in_nesting.direct_smallers
-               for mmodule in mmodules do res.add_all mmodule.filter_redef_mclasses(min_visibility)
-               for mgrp in lst do res.add_all mgrp.in_nesting_redef_mclasses(min_visibility)
-               return res
-       end
-
-       fun in_nesting_intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
-               var res = new HashSet[MClassDef]
-               var lst = in_nesting.direct_smallers
-               for mmodule in mmodules do res.add_all mmodule.intro_mclassdefs(min_visibility)
-               for mgrp in lst do res.add_all mgrp.in_nesting_intro_mclassdefs(min_visibility)
-               return res
-       end
-
-       fun in_nesting_redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
-               var res = new HashSet[MClassDef]
-               var lst = in_nesting.direct_smallers
-               for mmodule in mmodules do res.add_all mmodule.redef_mclassdefs(min_visibility)
-               for mgrp in lst do res.add_all mgrp.in_nesting_redef_mclassdefs(min_visibility)
-               return res
-       end
-
-       # Collect nested modules
-       fun collect_mmodules: Set[MModule] do
-               var res = new HashSet[MModule]
-               res.add_all mmodules
-               for mgroup in in_nesting.direct_smallers do
-                       res.add_all mgroup.collect_mmodules
-               end
-               return res
-       end
-
-       redef var concern_rank is lazy do
-               var max = 0
-               for mmodule in collect_mmodules do
-                       var mmax = mmodule.concern_rank
-                       if mmax > max then max = mmax
-               end
-               return max + 1
-       end
-end
-
-redef class MModule
-
-       # The list of intro mclassdef in the module.
-       # with visibility >= to min_visibility
-       fun intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
-               var res = new HashSet[MClassDef]
-               for mclassdef in mclassdefs do
-                       if not mclassdef.is_intro then continue
-                       if mclassdef.mclass.visibility < min_visibility then continue
-                       res.add mclassdef
-               end
-               return res
-       end
-
-       # The list of redef mclassdef in the module.
-       # with visibility >= to min_visibility
-       fun redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
-               var res = new HashSet[MClassDef]
-               for mclassdef in mclassdefs do
-                       if mclassdef.is_intro then continue
-                       if mclassdef.mclass.visibility < min_visibility then continue
-                       res.add mclassdef
-               end
-               return res
-       end
-
-       # The list of intro mclass in the module.
-       # with visibility >= to min_visibility
-       fun filter_intro_mclasses(min_visibility: MVisibility): Set[MClass] do
-               var res = new HashSet[MClass]
-               for mclass in intro_mclasses do
-                       if mclass.visibility < min_visibility then continue
-                       res.add mclass
-               end
-               return res
-       end
-
-       # Get the list of mclasses refined in 'self'.
-       fun redef_mclasses: Set[MClass] do
-               var mclasses = new HashSet[MClass]
-               for c in mclassdefs do
-                       if not c.is_intro then mclasses.add(c.mclass)
-               end
-               return mclasses
-       end
-
-       # Get the list of mclasses refined in 'self'.
-       fun filter_redef_mclasses(min_visibility: MVisibility): Set[MClass] do
-               var mclasses = new HashSet[MClass]
-               for c in mclassdefs do
-                       if c.mclass.visibility < min_visibility then continue
-                       if not c.is_intro then mclasses.add(c.mclass)
-               end
-               return mclasses
-       end
-
-       # Get the list of all mclasses imported by 'self'.
-       fun imported_mclasses: Set[MClass] do
-               var mclasses = new HashSet[MClass]
-               for m in in_importation.greaters do
-                       if m == self then continue
-                       for c in m.mclassdefs do mclasses.add(c.mclass)
-               end
-               return mclasses
-       end
-
-       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
-
-       # Find all mmodules nested in `self` if `self` is the default module of a `MGroup`.
-       fun nested_mmodules: Array[MModule] do
-               var res = new Array[MModule]
-               var mgroup = mgroup
-               if mgroup == null or self != mgroup.default_mmodule then return res
-               for mmodule in mgroup.mmodules do
-                       if mmodule == self then continue
-                       res.add mmodule
-               end
-               for nested in mgroup.in_nesting.direct_smallers do
-                       var default = nested.default_mmodule
-                       if default == null then continue
-                       res.add default
-               end
-               return res
-       end
-end
-
-redef class MClass
-
-       # Get direct parents of 'self'.
-       fun parents: Set[MClass] do
-               var ret = new HashSet[MClass]
-               for mclassdef in mclassdefs do
-                       for mclasstype in mclassdef.supertypes do
-                               ret.add(mclasstype.mclass)
-                       end
-               end
-               return ret
-       end
-
-       # Get all ancestors of 'self'.
-       fun ancestors: Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclassdef in self.mclassdefs do
-                       for super_mclassdef in mclassdef.in_hierarchy.greaters do
-                               if super_mclassdef == mclassdef then continue  # skip self
-                               lst.add(super_mclassdef.mclass)
-                       end
-               end
-               return lst
-       end
-
-       # Get direct children of 'self'.
-       fun children: Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclassdef in self.mclassdefs do
-                       for sub_mclassdef in mclassdef.in_hierarchy.direct_smallers do
-                               if sub_mclassdef == mclassdef then continue  # skip self
-                               lst.add(sub_mclassdef.mclass)
-                       end
-               end
-               return lst
-       end
-
-       # Get all children of 'self'.
-       fun descendants: Set[MClass] do
-               var lst = new HashSet[MClass]
-               for mclassdef in self.mclassdefs do
-                       for sub_mclassdef in mclassdef.in_hierarchy.smallers do
-                               if sub_mclassdef == mclassdef then continue  # skip self
-                               lst.add(sub_mclassdef.mclass)
-                       end
-               end
-               return lst
-       end
-
-       # Get the list of constructors available for 'self'.
-       fun constructors: Set[MMethod] do
-               var res = new HashSet[MMethod]
-               for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if mpropdef isa MMethodDef then
-                                       if mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
-                               end
-                       end
-               end
-               return res
-       end
-
-       # Get the list of methods introduced in 'self'.
-       fun intro_methods: Set[MMethod] do
-               var res = new HashSet[MMethod]
-               for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if mpropdef isa MMethodDef then
-                                       if mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
-                               end
-                       end
-               end
-               return res
-       end
-
-       # the set of properties introduced in 'self'.
-       fun intro_mproperties(min_visibility: MVisibility): Set[MProperty] do
-               var set = new HashSet[MProperty]
-               for mclassdef in mclassdefs do
-                       for mprop in mclassdef.intro_mproperties do
-                               if mprop.visibility < min_visibility then continue
-                               set.add(mprop)
-                       end
-               end
-               return set
-       end
-
-       fun intro_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
-               var set = new HashSet[MPropDef]
-               for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if not mpropdef.is_intro then continue
-                               if mpropdef.mproperty.visibility < min_visibility then continue
-                               set.add(mpropdef)
-                       end
-               end
-               return set
-       end
-
-       # the set of locally refined properties in 'self'.
-       fun redef_mproperties(min_visibility: MVisibility): Set[MProperty] do
-               var set = new HashSet[MProperty]
-               for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if mpropdef.mproperty.visibility < min_visibility then continue
-                               if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
-                       end
-               end
-               return set
-       end
-
-       fun redef_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
-               var set = new HashSet[MPropDef]
-               for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if mpropdef.is_intro then continue
-                               if mpropdef.mproperty.visibility < min_visibility then continue
-                               set.add(mpropdef)
-                       end
-               end
-               return set
-       end
-
-       # the set of methods inherited by 'self'.
-       fun inherited_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
-               var set = new HashSet[MProperty]
-               for parent in in_hierarchy(mainmodule).direct_greaters do
-                       set.add_all(parent.intro_mproperties(min_visibility))
-                       set.add_all(parent.inherited_mproperties(mainmodule, min_visibility))
-               end
-               return set
-       end
-
-       # the set of introduced and redefined mproperties
-       fun local_mproperties(min_visibility: MVisibility): Set[MProperty] do
-               var set = new HashSet[MProperty]
-               set.add_all(intro_mproperties(min_visibility))
-               set.add_all(redef_mproperties(min_visibility))
-               return set
-       end
-
-       # the set of all accessible mproperties for this class
-       fun all_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
-               var set = new HashSet[MProperty]
-               set.add_all(local_mproperties(min_visibility))
-               set.add_all(inherited_mproperties(mainmodule, min_visibility))
-               return set
-       end
-
-       # the set of all accessible mattributes for this class
-       fun all_mattributes(mainmodule: MModule, min_visibility: MVisibility): Set[MAttribute] do
-               var set = new HashSet[MAttribute]
-               for mprop in all_mproperties(mainmodule, min_visibility) do
-                       if mprop isa MAttribute then set.add(mprop)
-               end
-               return set
-       end
-
-       # Get the list of locally refined methods in 'self'.
-       fun redef_methods: Set[MMethod] do
-               var res = new HashSet[MMethod]
-               for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if mpropdef isa MMethodDef then
-                                       if not mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
-                               end
-                       end
-               end
-               return res
-       end
-
-       fun inherited_methods: Set[MMethod] do
-               var res = new HashSet[MMethod]
-               for s in ancestors do
-                       for m in s.intro_methods do
-                               if not self.intro_methods.has(m) and not self.redef_methods.has(m) then res.add(m)
-                       end
-               end
-               return res
-       end
-
-       # Get the list of all virtual types available in 'self'.
-       fun virtual_types: Set[MVirtualTypeProp] do
-               var res = new HashSet[MVirtualTypeProp]
-               for mclassdef in mclassdefs do
-                       for mpropdef in mclassdef.mpropdefs do
-                               if mpropdef isa MVirtualTypeDef then
-                                       res.add(mpropdef.mproperty)
-                               end
-                       end
-               end
-               for ancestor in ancestors do
-                       for mclassdef in ancestor.mclassdefs do
-                               for mpropdef in mclassdef.mpropdefs do
-                                       if mpropdef isa MVirtualTypeDef then
-                                               res.add(mpropdef.mproperty)
-                                       end
-                               end
-                       end
-               end
-               return res
-       end
-
-       # Get the list of all parameter types in 'self'.
-       fun parameter_types: Map[String, MType] do
-               var res = new HashMap[String, MType]
-               for p in mparameters do
-                       res[p.name] = p
-               end
-               return res
-       end
-
-       fun is_class: Bool do
-               return self.kind == concrete_kind or self.kind == abstract_kind
-       end
-
-       fun is_interface: Bool do
-               return self.kind == interface_kind
-       end
-
-       fun is_enum: Bool do
-               return self.kind == enum_kind
-       end
-
-       fun is_abstract: Bool do
-               return self.kind == abstract_kind
-       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
-       fun is_nullable: Bool do return intro.static_mtype isa MNullableType
-end
-
-redef class MClassDef
-       # modifiers are keywords like redef, private etc.
-       fun modifiers: Array[String] do
-               var res = new Array[String]
-               if not is_intro then
-                       res.add "redef"
-               else
-                       res.add mclass.visibility.to_s
-               end
-               res.add mclass.kind.to_s
-               return res
-       end
-
-       fun collect_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
-               var res = new HashSet[MPropDef]
-               for mpropdef in mpropdefs do
-                       if mpropdef.mproperty.visibility < min_visibility then continue
-                       res.add mpropdef
-               end
-               return res
-       end
-
-       fun collect_intro_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
-               var res = new HashSet[MPropDef]
-               for mpropdef in mpropdefs do
-                       if not mpropdef.is_intro then continue
-                       if mpropdef.mproperty.visibility < min_visibility then continue
-                       res.add mpropdef
-               end
-               return res
-       end
-
-       fun collect_redef_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
-               var res = new HashSet[MPropDef]
-               for mpropdef in mpropdefs do
-                       if mpropdef.is_intro then continue
-                       if mpropdef.mproperty.visibility < min_visibility then continue
-                       res.add mpropdef
-               end
-               return res
-       end
-end
-
-redef class MPropDef
-       # modifiers are keywords like redef, private etc.
-       fun modifiers: Array[String] do
-               var res = new Array[String]
-               if not is_intro then
-                       res.add "redef"
-               else
-                       res.add mproperty.visibility.to_s
-               end
-               var mprop = self
-               if mprop isa MVirtualTypeDef then
-                       res.add "type"
-               else if mprop isa MMethodDef then
-                       if mprop.is_abstract then
-                               res.add "abstract"
-                       else if mprop.is_intern then
-                               res.add "intern"
-                       end
-                       if mprop.mproperty.is_init then
-                               res.add "init"
-                       else
-                               res.add "fun"
-                       end
-               end
-               return res
-       end
-end
-
-# Sorters
-
-# Sort mentities by their name
-class MEntityNameSorter
-       super Comparator
-       redef type COMPARED: MEntity
-       redef fun compare(a, b) do return a.name <=> b.name
-end
-
-# 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
index 8ead776..83c4c6c 100644 (file)
@@ -27,7 +27,6 @@ module nitserial
 
 import frontend
 import rapid_type_analysis
-import model_utils
 import template
 
 # A Nit module
index 45015a7..4366aac 100644 (file)
@@ -16,7 +16,7 @@
 module test_neo
 
 import neo
-import model_utils
+import model
 import frontend
 
 var test_name = "test_{get_time.to_s}"
index e54ccef..3cb5e92 100644 (file)
@@ -16,7 +16,7 @@
 module uml_base
 
 import toolcontext
-import model_utils
+import model
 
 redef class ToolContext
        # -p
index c985a04..92317a4 100644 (file)
@@ -16,6 +16,7 @@
 module uml_class
 
 import uml_base
+import model::model_collect
 
 redef class UMLModel
        # Generates a UML class diagram from a `Model`
@@ -62,7 +63,7 @@ end
 
 redef class MClass
 
-       redef fun tpl_class(ctx, main): Writable do
+       redef fun tpl_class(ctx, main) do
                var t = new Template
                t.add "{name} [\n label = \"\{"
                if kind == abstract_kind then
@@ -84,9 +85,9 @@ redef class MClass
                t.add "|"
                var props: Collection[MProperty]
                if ctx.private_gen then
-                       props = intro_mproperties(none_visibility)
+                       props = collect_intro_mproperties(none_visibility)
                else
-                       props = intro_mproperties(public_visibility)
+                       props = collect_intro_mproperties(public_visibility)
                end
                for i in props do
                        if i isa MAttribute then
@@ -95,8 +96,13 @@ redef class MClass
                        end
                end
                t.add "|"
-               for i in intro_methods do
-                       if not ctx.private_gen and i.visibility != public_visibility then continue
+               var meths
+               if ctx.private_gen then
+                       meths = collect_intro_mmethods(none_visibility)
+               else
+                       meths = collect_intro_mmethods(public_visibility)
+               end
+               for i in meths do
                        t.add i.tpl_class(ctx, main)
                        t.add "\\l"
                end
index fb5f270..1813e55 100644 (file)
          min: base_simple3 (1)
          std: 0.0
          sum: 1
-
-# MClasses metrics
-
- ## project base_simple3
-  `- group base_simple3
-       cnoa: number of ancestor classes
-         avg: 0.0
-         max: Bool (1)
-         min: Object (0)
-         std: 0.926
-         sum: 6
-       cnop: number of parent classes
-         avg: 0.0
-         max: Bool (1)
-         min: Object (0)
-         std: 0.926
-         sum: 6
-       cnoc: number of child classes
-         avg: 0.0
-         max: Object (6)
-         min: Bool (0)
-         std: 2.268
-         sum: 6
-       cnod: number of descendant classes
-         avg: 0.0
-         max: Object (6)
-         min: Bool (0)
-         std: 2.268
-         sum: 6
-       cdit: depth in class tree
-         avg: 0.0
-         max: Bool (1)
-         min: Object (0)
-         std: 0.926
-         sum: 6
-       cnbp: number of accessible properties (inherited + local)
-         avg: 3.0
-         max: C (7)
-         min: Object (1)
-         std: 2.36
-         sum: 24
-       cnba: number of accessible attributes (inherited + local)
-         avg: 0.0
-         max: C (2)
-         min: Object (0)
-         std: 0.845
-         sum: 3
-       cnbip: number of introduced properties
-         avg: 2.0
-         max: C (6)
-         min: Bool (0)
-         std: 2.268
-         sum: 18
-       cnbrp: number of redefined properties
-         avg: 0.0
-         max: A (1)
-         min: Object (0)
-         std: 0.535
-         sum: 2
-       cnbhp: number of inherited properties
-         avg: 0.0
-         max: Bool (1)
-         min: Object (0)
-         std: 0.926
-         sum: 6
-
- ## global metrics
-       cnoa: number of ancestor classes
-         avg: 0.0
-         max: Bool (1)
-         min: Object (0)
-         std: 0.926
-         sum: 6
-       cnop: number of parent classes
-         avg: 0.0
-         max: Bool (1)
-         min: Object (0)
-         std: 0.926
-         sum: 6
-       cnoc: number of child classes
-         avg: 0.0
-         max: Object (6)
-         min: Bool (0)
-         std: 2.268
-         sum: 6
-       cnod: number of descendant classes
-         avg: 0.0
-         max: Object (6)
-         min: Bool (0)
-         std: 2.268
-         sum: 6
-       cdit: depth in class tree
-         avg: 0.0
-         max: Bool (1)
-         min: Object (0)
-         std: 0.926
-         sum: 6
-       cnbp: number of accessible properties (inherited + local)
-         avg: 3.0
-         max: C (7)
-         min: Object (1)
-         std: 2.36
-         sum: 24
-       cnba: number of accessible attributes (inherited + local)
-         avg: 0.0
-         max: C (2)
-         min: Object (0)
-         std: 0.845
-         sum: 3
-       cnbip: number of introduced properties
-         avg: 2.0
-         max: C (6)
-         min: Bool (0)
-         std: 2.268
-         sum: 18
-       cnbrp: number of redefined properties
-         avg: 0.0
-         max: A (1)
-         min: Object (0)
-         std: 0.535
-         sum: 2
-       cnbhp: number of inherited properties
-         avg: 0.0
-         max: Bool (1)
-         min: Object (0)
-         std: 0.926
-         sum: 6
 --- Metrics of refinement usage ---
 Number of modules: 1
 
@@ -488,6 +361,133 @@ Distribution of direct smallers
   bivariants: 0 (na%)
   invariants: 0 (na%)
   total: 0
+
+# MClasses metrics
+
+ ## project base_simple3
+  `- group base_simple3
+       cnoa: number of ancestor classes
+         avg: 0.0
+         max: Bool (1)
+         min: Object (0)
+         std: 0.926
+         sum: 6
+       cnop: number of parent classes
+         avg: 0.0
+         max: Bool (1)
+         min: Object (0)
+         std: 0.926
+         sum: 6
+       cnoc: number of child classes
+         avg: 0.0
+         max: Object (6)
+         min: Bool (0)
+         std: 2.268
+         sum: 6
+       cnod: number of descendant classes
+         avg: 0.0
+         max: Object (6)
+         min: Bool (0)
+         std: 2.268
+         sum: 6
+       cdit: depth in class tree
+         avg: 0.0
+         max: Bool (1)
+         min: Object (0)
+         std: 0.926
+         sum: 6
+       cnbp: number of accessible properties (inherited + local)
+         avg: 3.0
+         max: C (7)
+         min: Object (1)
+         std: 2.36
+         sum: 24
+       cnba: number of accessible attributes (inherited + local)
+         avg: 0.0
+         max: C (2)
+         min: Object (0)
+         std: 0.845
+         sum: 3
+       cnbip: number of introduced properties
+         avg: 2.0
+         max: C (6)
+         min: Bool (0)
+         std: 2.268
+         sum: 18
+       cnbrp: number of redefined properties
+         avg: 0.0
+         max: A (1)
+         min: Object (0)
+         std: 0.535
+         sum: 2
+       cnbhp: number of inherited properties
+         avg: 0.0
+         max: Bool (1)
+         min: Object (0)
+         std: 0.926
+         sum: 6
+
+ ## global metrics
+       cnoa: number of ancestor classes
+         avg: 0.0
+         max: Bool (1)
+         min: Object (0)
+         std: 0.926
+         sum: 6
+       cnop: number of parent classes
+         avg: 0.0
+         max: Bool (1)
+         min: Object (0)
+         std: 0.926
+         sum: 6
+       cnoc: number of child classes
+         avg: 0.0
+         max: Object (6)
+         min: Bool (0)
+         std: 2.268
+         sum: 6
+       cnod: number of descendant classes
+         avg: 0.0
+         max: Object (6)
+         min: Bool (0)
+         std: 2.268
+         sum: 6
+       cdit: depth in class tree
+         avg: 0.0
+         max: Bool (1)
+         min: Object (0)
+         std: 0.926
+         sum: 6
+       cnbp: number of accessible properties (inherited + local)
+         avg: 3.0
+         max: C (7)
+         min: Object (1)
+         std: 2.36
+         sum: 24
+       cnba: number of accessible attributes (inherited + local)
+         avg: 0.0
+         max: C (2)
+         min: Object (0)
+         std: 0.845
+         sum: 3
+       cnbip: number of introduced properties
+         avg: 2.0
+         max: C (6)
+         min: Bool (0)
+         std: 2.268
+         sum: 18
+       cnbrp: number of redefined properties
+         avg: 0.0
+         max: A (1)
+         min: Object (0)
+         std: 0.535
+         sum: 2
+       cnbhp: number of inherited properties
+         avg: 0.0
+         max: Bool (1)
+         min: Object (0)
+         std: 0.926
+         sum: 6
 generating project_hierarchy.dot
 generating module_hierarchy.dot
 
@@ -697,10 +697,10 @@ Statistics of type usage:
 # Mendel metrics
        large mclasses (threshold: 3.354)
           Sys: 4
-       budding mclasses (threshold: 3.51)
-          Sys: 4.0
-       blooming mclasses (threshold: 12.0)
-          Sys: 16.0
+       budding mclasses (threshold: 4.177)
+          Sys: 5.0
+       blooming mclasses (threshold: 14.626)
+          Sys: 20.0
 --- Detection of the usage of covariance static type conformance ---
 -- Total --
 - Kinds of the subtype -
index 1e16616..33e2d20 100644 (file)
@@ -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 [
index 74c96da..8fc87eb 100644 (file)
@@ -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 [