Merge: Fix warnings in the JSON, SAX and SAXophoNit libraries and in the `neo_doxygen...
[nit.git] / src / model_utils.nit
index e1d0f52..7af444d 100644 (file)
 # Model exploration and traversing facilities
 module model_utils
 
-import modelbuilder
+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 fun concern_rank is cached 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.intro_mclasses
+               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
@@ -31,7 +56,7 @@ redef class MGroup
        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.redef_mclasses
+               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
@@ -61,6 +86,15 @@ redef class MGroup
                end
                return res
        end
+
+       redef fun concern_rank is cached 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
@@ -89,6 +123,17 @@ redef class MModule
                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]
@@ -98,6 +143,16 @@ redef class MModule
                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]
@@ -111,7 +166,7 @@ redef class MModule
        fun in_nesting_intro_mclasses(min_visibility: MVisibility): Set[MClass] do
                var res = new HashSet[MClass]
                for mmodule in in_nesting.greaters do
-                       for mclass in mmodule.intro_mclasses do
+                       for mclass in mmodule.filter_intro_mclasses(min_visibility) do
                                if mclass.visibility < min_visibility then continue
                                res.add mclass
                        end
@@ -122,7 +177,7 @@ redef class MModule
        fun in_nesting_redef_mclasses(min_visibility: MVisibility): Set[MClass] do
                var res = new HashSet[MClass]
                for mmodule in self.in_nesting.greaters do
-                       for mclass in mmodule.redef_mclasses do
+                       for mclass in mmodule.filter_redef_mclasses(min_visibility) do
                                if mclass.visibility < min_visibility then continue
                                res.add mclass
                        end
@@ -145,19 +200,18 @@ redef class MModule
                end
                return res
        end
-end
 
-redef class MClass
-
-       # Get the public owner of 'self'.
-       fun public_owner: MModule do
-               var public_owner = self.intro_mmodule.public_owner
-               if public_owner == null then
-                       return self.intro_mmodule
-               else
-                       return public_owner
+       redef fun concern_rank is cached 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
+
+redef class MClass
 
        # Get direct parents of 'self'.
        fun parents: Set[MClass] do
@@ -363,8 +417,8 @@ redef class MClass
        # Get the list of all parameter types in 'self'.
        fun parameter_types: Map[String, MType] do
                var res = new HashMap[String, MType]
-               for i in [0..intro.parameter_names.length[ do
-                       res[intro.parameter_names[i]] = intro.bound_mtype.arguments[i]
+               for p in mparameters do
+                       res[p.name] = p
                end
                return res
        end
@@ -408,6 +462,35 @@ redef class MClassDef
                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
@@ -438,40 +521,34 @@ redef class MPropDef
        end
 end
 
-
 # Sorters
 
-# Sort mmodules by their name
-class MModuleNameSorter
-       super AbstractSorter[MModule]
-       redef fun compare(a, b) do return a.name <=> b.name
-       init do end
-end
-
-# Sort mclasses by their name
-class MClassNameSorter
-       super AbstractSorter[MClass]
-       redef fun compare(a, b) do return a.name <=> b.name
-       init do end
-end
-
-# Sort mclassdefs by their name
-class MClassDefNameSorter
-       super AbstractSorter[MClassDef]
-       redef fun compare(a, b) do return a.mclass.name <=> b.mclass.name
-       init do end
-end
-
-# Sort mproperties by their name
-class MPropertyNameSorter
-       super AbstractSorter[MProperty]
+# Sort mentities by their name
+class MEntityNameSorter
+       super Comparator
+       redef type COMPARED: MEntity
        redef fun compare(a, b) do return a.name <=> b.name
-       init do end
 end
 
-# Sort mpropdefs by their name
-class MPropDefNameSorter
-       super AbstractSorter[MPropDef]
-       redef fun compare(a, b) do return a.mproperty.name <=> b.mproperty.name
-       init do 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