model_collect: collect more things
[nit.git] / src / model / model_collect.nit
index e6260c6..627f982 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Collect things from a `Model`.
+# Collect things from a `ModelView`
+#
+# This module introduce several usefull methods to list and count things from a
+# ModelView.
+#
+# First setup you view from a Model:
+#
+# ~~~nitih
+# var view = new ModelView(model)
+# ~~~
+#
+# Then ask question using the view:
+#
+# ~~~nitish
+# print number of parents for `{my_class}`
+# print my_class.collect_parents(view).count
+# ~~~
 #
 # **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
+# 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
+# `nitx`, `nitmetrics` or `nituml`.
+# It should 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
+import model_views
 
 redef class MEntity
 
-       # Collect mentities with a fully qualified `namespace`.
-       fun collect_by_namespace(namespace: String): Array[MEntity] is abstract
+       # FIXME used to bypass RTA limitation on type resolution
+       type MENTITY: SELF
 
-       private fun lookup_in(mentities: Collection[MEntity], namespace: String, res: Array[MEntity]) do
-               var parts = namespace.split_once_on("::")
-               var name = parts.shift
-               for mentity in mentities do
-                       if mentity.name != name then continue
-                       if parts.is_empty then
-                               res.add mentity
-                       else
-                               res.add_all mentity.collect_by_namespace(parts.first)
+       # Collect modifier keywords like `redef`, `private` etc
+       fun collect_modifiers: Array[String] do return new Array[String]
+
+       # Collect `self` linearization anchored on `mainmodule`
+       fun collect_linearization(mainmodule: MModule): nullable Array[MEntity] do
+               return null
+       end
+
+       # Collect `self` ancestors (direct and indirect)
+       #
+       # The concept of ancestor is abstract at this stage.
+       fun collect_ancestors(view: ModelView): Set[MENTITY] do
+               var done = new HashSet[MENTITY]
+               var todo = new Array[MENTITY]
+
+               todo.add_all collect_parents(view)
+               while todo.not_empty do
+                       var mentity = todo.pop
+                       if mentity == self or done.has(mentity) then continue
+                       done.add mentity
+                       todo.add_all mentity.collect_parents(view)
+               end
+               return done
+       end
+
+       # Collect `self` parents (direct ancestors)
+       #
+       # The concept of parent is abstract at this stage.
+       fun collect_parents(view: ModelView): Set[MENTITY] is abstract
+
+       # Collect `self` children (direct descendants)
+       #
+       # The concept of child is abstract at this stage.
+       fun collect_children(view: ModelView): Set[MENTITY] is abstract
+
+       # Collect `self` descendants (direct and direct)
+       #
+       # The concept of descendant is abstract at this stage.
+       fun collect_descendants(view: ModelView): Set[MENTITY] do
+               var done = new HashSet[MENTITY]
+               var todo = new Array[MENTITY]
+
+               todo.add_all collect_children(view)
+               while todo.not_empty do
+                       var mentity = todo.pop
+                       if mentity == self or done.has(mentity) then continue
+                       done.add mentity
+                       todo.add_all mentity.collect_children(view)
+               end
+               return done
+       end
+
+       # Build a poset representing `self` in it's own hierarchy
+       #
+       # The notion of hierarchy depends on the type of MEntity.
+       #
+       # Here a recap:
+       # * `MPackage`: package dependencies
+       # * `MGroup`: group dependencies
+       # * `MModule`: modules imports
+       # * `MClass`: class inheritance (all classdefs flattened)
+       # * `MClassDef`: classdef inheritance
+       # * `MProperty`: property definitions graph (all propdefs flattened)
+       # * `MPropDef`: property definitions graph
+       fun hierarchy_poset(view: ModelView): POSet[MENTITY] do
+               var done = new HashSet[MENTITY]
+               var mentities = new Array[MENTITY]
+               mentities.add self
+               var poset = new POSet[MENTITY]
+               while mentities.not_empty do
+                       var mentity = mentities.pop
+                       if done.has(mentity) then continue
+                       done.add mentity
+                       poset.add_node mentity
+                       for parent in mentity.collect_parents(view) do
+                               poset.add_edge(mentity, parent)
+                               mentities.add parent
+                       end
+                       for child in mentity.collect_children(view) do
+                               poset.add_edge(child, mentity)
+                               mentities.add child
                        end
                end
+               return poset
        end
 end
 
 redef class Model
-       redef fun collect_by_namespace(namespace) do
-               var res = new Array[MEntity]
-               var parts = namespace.split_once_on("::")
-               var name = parts.shift
-               for mentity in mpackages do
-                       if mentity.name != name then continue
-                       if parts.is_empty then
-                               res.add mentity
-                       else
-                               res.add_all mentity.collect_by_namespace(parts.first)
-                       end
+
+       # Collect all MPackages in `self`
+       fun collect_mpackages(view: ModelView): HashSet[MPackage] do
+               var res = new HashSet[MPackage]
+               for mpackage in mpackages do
+                       if not view.accept_mentity(mpackage) then continue
+                       res.add(mpackage)
+               end
+               return res
+       end
+
+       # Collect all MModules in `self`
+       fun collect_mmodules(view: ModelView): HashSet[MModule] do
+               var res = new HashSet[MModule]
+               for mpackage in collect_mpackages(view) do
+                       res.add_all mpackage.collect_all_mmodules(view)
+               end
+               return res
+       end
+
+       # Collect all MClasses introduced in `self`
+       fun collect_intro_mclasses(view: ModelView): HashSet[MClass] do
+               var res = new HashSet[MClass]
+               for mpackage in collect_mpackages(view) do
+                       res.add_all mpackage.collect_intro_mclasses(view)
+               end
+               return res
+       end
+
+       # Collect all MProperties introduced in `self`
+       fun collect_intro_mproperties(view: ModelView): HashSet[MProperty] do
+               var res = new HashSet[MProperty]
+               for mpackage in collect_mpackages(view) do
+                       res.add_all mpackage.collect_intro_mproperties(view)
                end
                return res
        end
 end
 
 redef class MPackage
-       redef fun collect_by_namespace(namespace) do
-               var res = new Array[MEntity]
+
+       redef fun collect_modifiers do return super + ["package"]
+
+       # Collect all packages directly imported by `self`
+       redef fun collect_parents(view) do
+               var res = new HashSet[MENTITY]
+               for mgroup in mgroups do
+                       for parent in mgroup.collect_parents(view) do
+                               var mpackage = parent.mpackage
+                               if mpackage == self or not view.accept_mentity(mpackage) then continue
+                               res.add(mpackage)
+                       end
+               end
+               return res
+       end
+
+       # Collect all packages that directly depends on `self`
+       redef fun collect_children(view) do
+               var res = new HashSet[MENTITY]
+               for mpackage in view.mpackages do
+                       if mpackage.collect_parents(view).has(self) then res.add mpackage
+               end
+               return res
+       end
+
+       # Collect all groups contained in `self`
+       fun collect_all_mgroups(view: ModelView): HashSet[MGroup] do
+               var res = new HashSet[MGroup]
+               for mgroup in mgroups do
+                       if not view.accept_mentity(mgroup) then continue
+                       res.add(mgroup)
+               end
+               return res
+       end
+
+       # Collect only groups contained in `self.root`
+       fun collect_mgroups(view: ModelView): HashSet[MGroup] do
+               var res = new HashSet[MGroup]
                var root = self.root
                if root == null then return res
-               lookup_in([root], namespace, res)
+               res.add_all root.collect_mgroups(view)
+               return res
+       end
+
+       # Collect all modules contained in `self`
+       fun collect_all_mmodules(view: ModelView): HashSet[MModule] do
+               var res = new HashSet[MModule]
+               for mgroup in collect_mgroups(view) do
+                       res.add_all mgroup.collect_mmodules(view)
+               end
+               return res
+       end
+
+       # Collect only modules contained in `self.root`
+       fun collect_mmodules(view: ModelView): HashSet[MModule] do
+               var res = new HashSet[MModule]
+               var root = self.root
+               if root == null then return res
+               res.add_all root.collect_mmodules(view)
+               return res
+       end
+
+       # Collect all classes introduced in `self`
+       fun collect_intro_mclasses(view: ModelView): HashSet[MClass] do
+               var res = new HashSet[MClass]
+               for mgroup in mgroups do
+                       for mmodule in collect_all_mmodules(view) do
+                               res.add_all mmodule.collect_intro_mclasses(view)
+                       end
+               end
+               return res
+       end
+
+       # Collect all classes redefined or refined in `self`
+       fun collect_redef_mclasses(view: ModelView): Set[MClass] do
+               var res = new HashSet[MClass]
+               for mgroup in mgroups do
+                       for mmodule in collect_all_mmodules(view) do
+                               res.add_all mmodule.collect_redef_mclasses(view)
+                       end
+               end
+               return res
+       end
+
+       # Collect all properties introduced in `self`
+       fun collect_intro_mproperties(view: ModelView): HashSet[MProperty] do
+               var res = new HashSet[MProperty]
+               for mgroup in mgroups do
+                       for mmodule in collect_all_mmodules(view) do
+                               res.add_all mmodule.collect_intro_mproperties(view)
+                       end
+               end
+               return res
+       end
+
+       # Collect all properties redefined in `self`
+       fun collect_redef_mproperties(view: ModelView): HashSet[MProperty] do
+               var res = new HashSet[MProperty]
+               for mgroup in mgroups do
+                       for mmodule in collect_all_mmodules(view) do
+                               res.add_all mmodule.collect_redef_mproperties(view)
+                       end
+               end
+               return res
+       end
+
+       # Collect all attributes introduced in `self`
+       fun collect_intro_attributes(view: ModelView): Set[MAttribute] do
+               var res = new HashSet[MAttribute]
+               for mgroup in mgroups do
+                       for mmodule in collect_all_mmodules(view) do
+                               res.add_all mmodule.collect_intro_attributes(view)
+                       end
+               end
+               return res
+       end
+
+       # Collect all inits introduced in `self`
+       fun collect_intro_inits(view: ModelView): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mgroup in mgroups do
+                       for mmodule in collect_all_mmodules(view) do
+                               res.add_all mmodule.collect_intro_inits(view)
+                       end
+               end
+               return res
+       end
+
+       # Collect all methods introduced in `self` excluding inits
+       #
+       # See `collect_intro_inits`.
+       fun collect_intro_methods(view: ModelView): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mgroup in mgroups do
+                       for mmodule in collect_all_mmodules(view) do
+                               res.add_all mmodule.collect_intro_methods(view)
+                       end
+               end
+               return res
+       end
+
+       # Collect all virtual types introduced in `self`
+       fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+               var res = new HashSet[MVirtualTypeProp]
+               for mgroup in mgroups do
+                       for mmodule in collect_all_mmodules(view) do
+                               res.add_all mmodule.collect_intro_vts(view)
+                       end
+               end
                return res
        end
 end
 
 redef class MGroup
-       redef fun collect_by_namespace(namespace) do
-               var res = new Array[MEntity]
-               lookup_in(in_nesting.direct_smallers, namespace, res)
-               lookup_in(mmodules, namespace, res)
+
+       redef fun collect_modifiers do return super + ["group"]
+
+       # Collect all groups directly import by `self`
+       redef fun collect_parents(view) do
+               var res = new HashSet[MENTITY]
+               for mmodule in mmodules do
+                       for parent in mmodule.collect_parents(view) do
+                               var mgroup = parent.mgroup
+                               if mgroup == null or mgroup == self then continue
+                               if not view.accept_mentity(mgroup) then continue
+                               res.add(mgroup)
+                       end
+               end
+               return res
+       end
+
+       # Collect all group that directly import `self`
+       redef fun collect_children(view) do
+               var res = new HashSet[MENTITY]
+               for mgroup in view.mgroups do
+                       if mgroup == self or not view.accept_mentity(mgroup) then continue
+                       if mgroup.collect_parents(view).has(self) then res.add mgroup
+               end
+               return res
+       end
+
+       # Collect all groups contained in `self`
+       fun collect_mgroups(view: ModelView): HashSet[MENTITY] do
+               var res = new HashSet[MENTITY]
+               for mgroup in in_nesting.direct_smallers do
+                       if not view.accept_mentity(mgroup) then continue
+                       res.add(mgroup)
+               end
+               return res
+       end
+
+       # Collect all modules contained in `self`
+       fun collect_mmodules(view: ModelView): HashSet[MModule] do
+               var res = new HashSet[MModule]
+               for mmodule in mmodules do
+                       if not view.accept_mentity(mmodule) then continue
+                       res.add(mmodule)
+               end
                return res
        end
 end
 
 redef class MModule
 
-       redef fun collect_by_namespace(namespace) do
-               var res = new Array[MEntity]
-               lookup_in(mclassdefs, namespace, res)
+       redef fun collect_modifiers do return super + ["module"]
+
+       # Collect all module ancestors of `self` (direct and transitive imports)
+       redef fun collect_ancestors(view) do
+               var res = new HashSet[MENTITY]
+               for mentity in in_importation.greaters do
+                       if mentity == self then continue
+                       if not view.accept_mentity(mentity) then continue
+                       res.add mentity
+               end
+               return res
+       end
+
+       # Collect all modules directly imported by `self`
+       redef fun collect_parents(view) do
+               var res = new HashSet[MENTITY]
+               for mentity in in_importation.direct_greaters do
+                       if mentity == self then continue
+                       if not view.accept_mentity(mentity) then continue
+                       res.add mentity
+               end
+               return res
+       end
+
+       # Collect all modules that directly import `self`
+       redef fun collect_children(view) do
+               var res = new HashSet[MENTITY]
+               for mentity in in_importation.direct_smallers do
+                       if mentity == self then continue
+                       if not view.accept_mentity(mentity) then continue
+                       res.add mentity
+               end
+               return res
+       end
+
+       # Collect all module descendants of `self` (direct and transitive imports)
+       redef fun collect_descendants(view) do
+               var res = new HashSet[MENTITY]
+               for mentity in in_importation.smallers do
+                       if mentity == self then continue
+                       if not view.accept_mentity(mentity) then continue
+                       res.add mentity
+               end
                return res
        end
 
-       # Collect mclassdefs introduced in `self` with `visibility >= to min_visibility`.
-       fun collect_intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
+       # Collect all class definitions introduced in `self`
+       fun collect_intro_mclassdefs(view: ModelView): 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
+                       if not view.accept_mentity(mclassdef) 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
+       # Collect all class definitions refined in `self`
+       fun collect_redef_mclassdefs(view: ModelView): 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
+                       if not view.accept_mentity(mclassdef) 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
+       # Collect all class definitions introduced and refined in `self`
+       fun collect_local_mclassdefs(view: ModelView): Set[MClassDef] do
+               var res = new HashSet[MClassDef]
+               res.add_all collect_intro_mclassdefs(view)
+               res.add_all collect_redef_mclassdefs(view)
+               return res
+       end
+
+       # Collect all classes introduced in `self`
+       fun collect_intro_mclasses(view: ModelView): Set[MClass] do
                var res = new HashSet[MClass]
                for mclass in intro_mclasses do
-                       if mclass.visibility < min_visibility then continue
+                       if not view.accept_mentity(mclass) 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
+       # Collect all classes refined in `self`
+       fun collect_redef_mclasses(view: ModelView): 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)
+               for mclassdef in mclassdefs do
+                       if not view.accept_mentity(mclassdef.mclass) then continue
+                       if not mclassdef.is_intro then mclasses.add(mclassdef.mclass)
                end
                return mclasses
        end
-end
 
-redef class MClass
+       # Collect all classes introduced and refined in `self`
+       fun collect_local_mclasses(view: ModelView): Set[MClass] do
+               var res = new HashSet[MClass]
+               res.add_all collect_intro_mclasses(view)
+               res.add_all collect_redef_mclasses(view)
+               return res
+       end
 
-       # Collect direct parents of `self` with `visibility >= to min_visibility`.
-       fun collect_parents(min_visibility: MVisibility): Set[MClass] do
+       # Collect all classes imported from `self` parents
+       fun collect_imported_mclasses(view: ModelView): Set[MClass] do
                var res = new HashSet[MClass]
+               for parent in collect_parents(view) do
+                       res.add_all parent.collect_intro_mclasses(view)
+                       res.add_all parent.collect_redef_mclasses(view)
+                       res.add_all parent.collect_imported_mclasses(view)
+               end
+               return res
+       end
+
+       # Collect all properties introduced in `self`
+       fun collect_intro_mproperties(view: ModelView): Set[MProperty] do
+               var res = new HashSet[MProperty]
+               for mclass in collect_intro_mclasses(view) do
+                       res.add_all mclass.collect_intro_mproperties(view)
+               end
+               return res
+       end
+
+       # Collect properties redefined in `self`
+       fun collect_redef_mproperties(view: ModelView): Set[MProperty] do
+               var res = new HashSet[MProperty]
                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)
+                       for mpropdef in mclassdef.collect_redef_mpropdefs(view) do
+                               res.add mpropdef.mproperty
                        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)
+       # Collect attributes introduced in `self`
+       fun collect_intro_attributes(view: ModelView): Set[MAttribute] do
+               var res = new HashSet[MAttribute]
+               for mproperty in collect_intro_mproperties(view) do
+                       if mproperty isa MAttribute then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all inits introduced in `self`
+       fun collect_intro_inits(view: ModelView): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mproperty in collect_intro_mproperties(view) do
+                       if mproperty isa MMethod and mproperty.is_init then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect methods introduced in `self` (without inits)
+       fun collect_intro_methods(view: ModelView): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mproperty in collect_intro_mproperties(view) do
+                       if mproperty isa MMethod and not mproperty.is_init then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect virtual types introduced in `self`
+       fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+               var res = new HashSet[MVirtualTypeProp]
+               for mproperty in collect_intro_mproperties(view) do
+                       if mproperty isa MVirtualTypeProp then res.add(mproperty)
+               end
+               return res
+       end
+end
+
+redef class MClass
+
+       redef fun collect_modifiers do return intro.collect_modifiers
+
+       redef fun collect_linearization(mainmodule) do
+               var mclassdefs = self.mclassdefs.to_a
+               mainmodule.linearize_mclassdefs(mclassdefs)
+               return mclassdefs
+       end
+
+       # Collect all direct parents of `self`
+       #
+       # This method uses a flattened hierarchy containing all the mclassdefs.
+       redef fun collect_parents(view) do
+               var res = new HashSet[MENTITY]
+               for mclassdef in mclassdefs do
+                       for parent in mclassdef.collect_parents(view) do
+                               var mclass = parent.mclass
+                               if mclass == self or not view.accept_mentity(parent) 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)
+       # Collect all ancestors of `self`
+       redef fun collect_ancestors(view) do
+               var res = new HashSet[MENTITY]
+               for mclassdef in mclassdefs do
+                       for parent in mclassdef.collect_parents(view) do
+                               if not view.accept_mentity(parent) then continue
+                               res.add parent.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)
+       # Collect all direct children of `self`
+       #
+       # This method uses a flattened hierarchy containing all the mclassdefs.
+       redef fun collect_children(view) do
+               var res = new HashSet[MENTITY]
+               for mclassdef in mclassdefs do
+                       for child in mclassdef.collect_children(view) do
+                               var mclass = child.mclass
+                               if mclass == self or not view.accept_mentity(child) 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
+       # Collect all class definitions of `self`
+       fun collect_mclassdefs(view: ModelView): Set[MClassDef] do
+               var res = new HashSet[MClassDef]
+               for mclassdef in mclassdefs do
+                       if not view.accept_mentity(mclassdef) then continue
+                       res.add mclassdef
+               end
+               return res
+       end
+
+       # Collect all property definitions that are introductions in `self`
+       fun collect_intro_mpropdefs(view: ModelView): 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 not view.accept_mentity(mpropdef) then continue
+                               set.add(mpropdef)
+                       end
+               end
+               return set
+       end
+
+       # Collect all properties introduced in `self`
+       fun collect_intro_mproperties(view: ModelView): 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
+                               if not view.accept_mentity(mprop) 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
+       # Collect all propierty definitions that are redefinition in `self`
+       fun collect_redef_mpropdefs(view: ModelView): 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 not view.accept_mentity(mpropdef) then continue
+                               set.add(mpropdef)
+                       end
+               end
+               return set
+       end
+
+       # Collect all properties redefined in `self`
+       fun collect_redef_mproperties(view: ModelView): 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)
+                               if mpropdef.mproperty.intro_mclassdef.mclass == self then continue
+                               if not view.accept_mentity(mpropdef) then continue
+                               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
+       # Collect all properties introduced and redefined in `self`
+       fun collect_local_mproperties(view: ModelView): 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_intro_mproperties(view)
+               set.add_all collect_redef_mproperties(view)
                return set
        end
 
-       # Collect all mproperties inehrited by 'self' with `visibility >= min_visibility`.
-       fun collect_inherited_mproperties(min_visibility: MVisibility): Set[MProperty] do
+       # Collect all properties inehrited by `self`
+       fun collect_inherited_mproperties(view: ModelView): 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))
+               for parent in collect_parents(view) do
+                       set.add_all(parent.collect_intro_mproperties(view))
+                       set.add_all(parent.collect_inherited_mproperties(view))
                end
                return set
        end
 
-       # Collect all mproperties accessible by 'self' with `visibility >= min_visibility`.
+       # Collect all properties accessible by `self`
        #
-       # This include introduced, redefined, inherited mproperties.
-       fun collect_accessible_mproperties(min_visibility: MVisibility): Set[MProperty] do
+       # This include introduced, redefined, inherited properties.
+       fun collect_accessible_mproperties(view: ModelView): 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))
+               set.add_all(collect_intro_mproperties(view))
+               set.add_all(collect_redef_mproperties(view))
+               set.add_all(collect_inherited_mproperties(view))
                return set
        end
 
-       # Collect mmethods introduced in 'self' with `visibility >= min_visibility`.
-       fun collect_intro_mmethods(min_visibility: MVisibility): Set[MMethod] do
+       # Collect all methods introduced in `self`
+       fun collect_intro_mmethods(view: ModelView): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_intro_mproperties(min_visibility) do
+               for mproperty in collect_intro_mproperties(view) 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
+       # Collect all methods redefined in `self`
+       fun collect_redef_mmethods(view: ModelView): Set[MMethod] do
                var res = new HashSet[MMethod]
-               for mproperty in collect_redef_mproperties(min_visibility) do
+               for mproperty in collect_redef_mproperties(view) 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
+       # Collect all methods introduced and redefined in `self`
+       fun collect_local_mmethods(view: ModelView): Set[MMethod] do
                var set = new HashSet[MMethod]
-               set.add_all collect_intro_mmethods(min_visibility)
-               set.add_all collect_redef_mmethods(min_visibility)
+               set.add_all collect_intro_mmethods(view)
+               set.add_all collect_redef_mmethods(view)
                return set
        end
 
-       # Collect mattributes introduced in 'self' with `visibility >= min_visibility`.
-       fun collect_intro_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+       # Collect all methods inherited by `self`
+       fun collect_inherited_mmethods(view: ModelView): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mproperty in collect_inherited_mproperties(view) do
+                       if mproperty isa MMethod then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all methods accessible by `self`
+       #
+       # This include introduced, redefined, inherited methods.
+       fun collect_accessible_mmethods(view: ModelView): Set[MMethod] do
+               var set = new HashSet[MMethod]
+               set.add_all(collect_intro_mmethods(view))
+               set.add_all(collect_redef_mmethods(view))
+               set.add_all(collect_inherited_mmethods(view))
+               return set
+       end
+
+       # Collect all attributes introduced in `self`
+       fun collect_intro_mattributes(view: ModelView): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_intro_mproperties(min_visibility) do
+               for mproperty in collect_intro_mproperties(view) 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
+       # Collect all attributes redefined in `self`
+       fun collect_redef_mattributes(view: ModelView): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_redef_mproperties(min_visibility) do
+               for mproperty in collect_redef_mproperties(view) 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
+       # Collect all attributes introduced and redefined in `self`
+       fun collect_local_mattributes(view: ModelView): 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_intro_mattributes(view)
+               set.add_all collect_redef_mattributes(view)
                return set
        end
 
-       # Collect mattributes inherited by 'self' with `visibility >= min_visibility`.
-       fun collect_inherited_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+       # Collect all attributes inherited by `self`
+       fun collect_inherited_mattributes(view: ModelView): Set[MAttribute] do
                var res = new HashSet[MAttribute]
-               for mproperty in collect_inherited_mproperties(min_visibility) do
+               for mproperty in collect_inherited_mproperties(view) do
                        if mproperty isa MAttribute then res.add(mproperty)
                end
                return res
        end
 
-       # Collect all mattributes accessible by 'self' with `visibility >= min_visibility`.
+       # Collect all attributes accessible by `self`
        #
        # This include introduced, redefined, inherited mattributes.
-       fun collect_accessible_mattributes(min_visibility: MVisibility): Set[MAttribute] do
+       fun collect_accessible_mattributes(view: ModelView): 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))
+               set.add_all(collect_intro_mattributes(view))
+               set.add_all(collect_redef_mattributes(view))
+               set.add_all(collect_inherited_mattributes(view))
+               return set
+       end
+
+       # Collect all init methods introduced in `self`
+       fun collect_intro_inits(view: ModelView): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mproperty in collect_intro_mmethods(view) do
+                       if mproperty.is_init then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all init methods redefined in `self`
+       fun collect_redef_inits(view: ModelView): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mproperty in collect_redef_mmethods(view) do
+                       if mproperty.is_init then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all init methods introduced and redefined in `self`
+       fun collect_local_inits(view: ModelView): Set[MMethod] do
+               var set = new HashSet[MMethod]
+               set.add_all collect_intro_inits(view)
+               set.add_all collect_redef_inits(view)
+               return set
+       end
+
+       # Collect all init methods inherited by `self`
+       fun collect_inherited_inits(view: ModelView): Set[MMethod] do
+               var res = new HashSet[MMethod]
+               for mproperty in collect_inherited_mmethods(view) do
+                       if mproperty.is_init then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all init methods accessible by `self`
+       #
+       # This include introduced, redefined, inherited inits.
+       fun collect_accessible_inits(view: ModelView): Set[MMethod] do
+               var set = new HashSet[MMethod]
+               set.add_all(collect_intro_inits(view))
+               set.add_all(collect_redef_inits(view))
+               set.add_all(collect_inherited_inits(view))
+               return set
+       end
+
+       # Collect all virtual types introduced in `self`
+       fun collect_intro_vts(view: ModelView): Set[MVirtualTypeProp] do
+               var res = new HashSet[MVirtualTypeProp]
+               for mproperty in collect_intro_mproperties(view) do
+                       if mproperty isa MVirtualTypeProp then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all virtual types redefined in `self`
+       fun collect_redef_vts(view: ModelView): Set[MVirtualTypeProp] do
+               var res = new HashSet[MVirtualTypeProp]
+               for mproperty in collect_intro_mproperties(view) do
+                       if mproperty isa MVirtualTypeProp then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all virtual types introduced or redefined in `self`
+       fun collect_local_vts(view: ModelView): Set[MVirtualTypeProp] do
+               var set = new HashSet[MVirtualTypeProp]
+               set.add_all collect_intro_vts(view)
+               set.add_all collect_redef_vts(view)
+               return set
+       end
+
+       # Collect all virtual types inherited by `self`
+       fun collect_inherited_vts(view: ModelView): Set[MVirtualTypeProp] do
+               var res = new HashSet[MVirtualTypeProp]
+               for mproperty in collect_inherited_mproperties(view) do
+                       if mproperty isa MVirtualTypeProp then res.add(mproperty)
+               end
+               return res
+       end
+
+       # Collect all virtual types accessible by `self`
+       #
+       # This include introduced, redefined, inherited virtual types.
+       fun collect_accessible_vts(view: ModelView): Set[MVirtualTypeProp] do
+               var set = new HashSet[MVirtualTypeProp]
+               for mproperty in collect_accessible_mproperties(view) do
+                       if mproperty isa MVirtualTypeProp then set.add mproperty
+               end
                return set
        end
 end
 
 redef class MClassDef
 
-       redef fun collect_by_namespace(namespace) do
-               var res = new Array[MEntity]
-               lookup_in(mpropdefs, namespace, res)
+       redef fun collect_modifiers do
+               var res = super
+               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
 
-       # Collect mpropdefs in 'self' with `visibility >= min_visibility`.
-       fun collect_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
+       redef fun collect_linearization(mainmodule) do
+               var mclassdefs = new Array[MClassDef]
+               for mclassdef in in_hierarchy.as(not null).greaters do
+                       if mclassdef.mclass == self.mclass then mclassdefs.add mclassdef
+               end
+               mainmodule.linearize_mclassdefs(mclassdefs)
+               return mclassdefs
+       end
+
+       redef fun collect_ancestors(view) do
+               var res = new HashSet[MENTITY]
+               var hierarchy = self.in_hierarchy
+               if hierarchy == null then return res
+               for parent in hierarchy.greaters do
+                       if parent == self or not view.accept_mentity(parent) then continue
+                       res.add parent
+               end
+               return res
+       end
+
+       redef fun collect_parents(view) do
+               var res = new HashSet[MENTITY]
+               var hierarchy = self.in_hierarchy
+               if hierarchy == null then return res
+               for parent in hierarchy.direct_greaters do
+                       if parent == self or not view.accept_mentity(parent) then continue
+                       res.add parent
+               end
+               return res
+       end
+
+       redef fun collect_children(view) do
+               var res = new HashSet[MENTITY]
+               var hierarchy = self.in_hierarchy
+               if hierarchy == null then return res
+               for child in hierarchy.direct_smallers do
+                       if child == self or not view.accept_mentity(child) then continue
+                       res.add child
+               end
+               return res
+       end
+
+       # Collect all property definitions in `self`
+       fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
                var res = new HashSet[MPropDef]
                for mpropdef in mpropdefs do
-                       if mpropdef.mproperty.visibility < min_visibility then continue
+                       if not view.accept_mentity(mpropdef) then continue
+                       res.add mpropdef
+               end
+               return res
+       end
+
+       # Collect all attribute definitions in `self`
+       fun collect_mattributedefs(view: ModelView): Set[MAttributeDef] do
+               var res = new HashSet[MAttributeDef]
+               for mpropdef in collect_mpropdefs(view) do
+                       if not mpropdef isa MAttributeDef then continue
+                       res.add mpropdef
+               end
+               return res
+       end
+
+       # Collect all methods definitions in `self`
+       fun collect_mmethoddefs(view: ModelView): Set[MMethodDef] do
+               var res = new HashSet[MMethodDef]
+               for mpropdef in collect_mpropdefs(view) do
+                       if not mpropdef isa MMethodDef 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
+       # Collect all virtual types definitions in `self`
+       fun collect_mtypedefs(view: ModelView): Set[MVirtualTypeDef] do
+               var res = new HashSet[MVirtualTypeDef]
+               for mpropdef in collect_mpropdefs(view) do
+                       if not mpropdef isa MVirtualTypeDef then continue
+                       res.add mpropdef
+               end
+               return res
+       end
+
+       # Collect all property definitions that are introduction in `self`
+       fun collect_intro_mpropdefs(view: ModelView): 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
+                       if not view.accept_mentity(mpropdef) 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
+       # Collect all property definitions that are redefinition in `self`
+       fun collect_redef_mpropdefs(view: ModelView): 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
+                       if not view.accept_mentity(mpropdef) then continue
                        res.add mpropdef
                end
                return res
        end
+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
+redef class MProperty
+       redef fun collect_modifiers do return intro.collect_modifiers
+
+       redef fun collect_linearization(mainmodule) do
+               var mpropdefs = self.mpropdefs.to_a
+               mainmodule.linearize_mpropdefs(mpropdefs)
+               return mpropdefs
+       end
+
+       # Collect all property definitions of `self`
+       fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
+               var res = new HashSet[MPropDef]
+               for mpropdef in mpropdefs do
+                       if not view.accept_mentity(mpropdef) then continue
+                       res.add mpropdef
+               end
+               return res
+       end
+
+       # Collect all direct super definitions of `self`
+       redef fun collect_parents(view) do
+               var res = new HashSet[MENTITY]
+               for mpropdef in mpropdefs do
+                       for parent in mpropdef.collect_parents(view) do
+                               if not view.accept_mentity(parent) then continue
+                               res.add parent.mproperty
+                       end
+               end
+               return res
+       end
+
+       # Collection all definitions that have `self` as a direct super definition
+       redef fun collect_children(view) do
+               var res = new HashSet[MENTITY]
+               for mpropdef in mpropdefs do
+                       for child in mpropdef.collect_parents(view) do
+                               if not view.accept_mentity(child) then continue
+                               res.add child.mproperty
+                       end
                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]
+
+       redef fun collect_modifiers do
+               var res = super
                if not is_intro then
                        res.add "redef"
                else
@@ -396,6 +1068,40 @@ redef class MPropDef
                        else
                                res.add "fun"
                        end
+               else if mprop isa MAttributeDef then
+                       res.add "var"
+               end
+               return res
+       end
+
+       redef fun collect_linearization(mainmodule) do
+               var mpropdefs = new Array[MPropDef]
+               var mentity = self
+               while not mentity.is_intro do
+                       mpropdefs.add mentity
+                       mentity = mentity.lookup_next_definition(mainmodule, mentity.mclassdef.bound_mtype)
+               end
+               mpropdefs.add mentity
+               mainmodule.linearize_mpropdefs(mpropdefs)
+               return mpropdefs
+       end
+
+       # Collect only the next definition of `self`
+       redef fun collect_parents(view) do
+               var res = new HashSet[MENTITY]
+               var mpropdef = self
+               while not mpropdef.is_intro do
+                       mpropdef = mpropdef.lookup_next_definition(mclassdef.mmodule, mclassdef.bound_mtype)
+                       res.add mpropdef
+               end
+               return res
+       end
+
+       # Collect all children definitions that directly depend on `self`
+       redef fun collect_children(view) do
+               var res = new HashSet[MENTITY]
+               for mpropdef in mproperty.collect_mpropdefs(view) do
+                       if mpropdef.collect_parents(view).has(self) then res.add mpropdef
                end
                return res
        end