X-Git-Url: http://nitlanguage.org diff --git a/src/model/model_collect.nit b/src/model/model_collect.nit index 8585092..bfe5fdf 100644 --- a/src/model/model_collect.nit +++ b/src/model/model_collect.nit @@ -25,7 +25,7 @@ # # 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 +# 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 @@ -33,10 +33,97 @@ import model_views redef class MEntity + # FIXME used to bypass RTA limitation on type resolution. + type MENTITY: SELF + # Collect modifier keywords like `redef`, `private` etc. fun collect_modifiers: Array[String] do return new Array[String] end + + # 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 + print "{mentity} == {self}" + 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 MPackage @@ -45,6 +132,40 @@ redef class MPackage res.add "package" return res end + + # `MPackage` parents are its direct dependencies. + 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 + + # `MPackage` children are 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 + + # `MModules` contained in `self`. + fun collect_mmodules(view: ModelView): HashSet[MModule] do + var res = new HashSet[MModule] + for mgroup in mgroups do + for mmodule in mgroup.mmodules do + if not view.accept_mentity(mmodule) then continue + res.add(mmodule) + end + end + return res + end end redef class MGroup @@ -53,6 +174,30 @@ redef class MGroup res.add "group" return res end + + # `MGroup` parents are its direct dependencies. + 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 + + # `MGroup` children are mgroups that directly depends on `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 end redef class MModule @@ -63,9 +208,9 @@ redef class MModule return res end - # Collect all transitive imports. - fun collect_ancestors(view: ModelView): Set[MModule] do - var res = new HashSet[MModule] + # `MModule` ancestors are all its 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 @@ -74,9 +219,9 @@ redef class MModule return res end - # Collect direct imports. - fun collect_parents(view: ModelView): Set[MModule] do - var res = new HashSet[MModule] + # `MModule` parents are all its direct imports. + 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 @@ -85,9 +230,9 @@ redef class MModule return res end - # Collect direct children (modules that directly import `self`). - fun collect_children(view: ModelView): Set[MModule] do - var res = new HashSet[MModule] + # `MModule` children are 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 @@ -96,9 +241,9 @@ redef class MModule return res end - # Collect all transitive children. - fun collect_descendants(view: ModelView): Set[MModule] do - var res = new HashSet[MModule] + # `MModule` children are modules that transitively import `self`. + 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 @@ -107,17 +252,6 @@ redef class MModule return res end - # Build the importation poset for `self` - fun importation_poset(view: ModelView): POSet[MModule] do - var mmodules = new HashSet[MModule] - mmodules.add self - mmodules.add_all collect_ancestors(view) - mmodules.add_all collect_parents(view) - mmodules.add_all collect_children(view) - mmodules.add_all collect_descendants(view) - return view.mmodules_poset(mmodules) - end - # Collect mclassdefs introduced in `self` with `visibility >= to min_visibility`. fun collect_intro_mclassdefs(view: ModelView): Set[MClassDef] do var res = new HashSet[MClassDef] @@ -165,70 +299,54 @@ redef class MClass redef fun collect_modifiers do return intro.collect_modifiers - # Collect direct parents of `self` with `visibility >= to min_visibility`. - fun collect_parents(view: ModelView): Set[MClass] do - var res = new HashSet[MClass] - for mclassdef in mclassdefs do - for mclasstype in mclassdef.supertypes do - var mclass = mclasstype.mclass - if not view.accept_mentity(mclass) then continue - res.add(mclass) - end - end - return res + redef fun collect_linearization(mainmodule) do + var mclassdefs = self.mclassdefs.to_a + mainmodule.linearize_mclassdefs(mclassdefs) + return mclassdefs end - # Collect all ancestors of `self` with `visibility >= to min_visibility`. - fun collect_ancestors(view: ModelView): 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 not view.accept_mentity(mclass) then continue - res.add(mclass) + # `MClass` parents are the 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(view: ModelView): 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 not view.accept_mentity(mclass) then continue - res.add(mclass) + # Collect all ancestors of `self` with `visibility >= to min_visibility`. + 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 collect_descendants(view: ModelView): 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 not view.accept_mentity(mclass) then continue - res.add(mclass) + # `MClass` parents are the direct parents 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 - # Build a class hierarchy poset for `self` based on its ancestors and descendants. - fun hierarchy_poset(mainmodule: MModule, view: ModelView): POSet[MClass] do - var mclasses = new HashSet[MClass] - mclasses.add self - mclasses.add_all collect_ancestors(view) - mclasses.add_all collect_descendants(view) - return view.mclasses_poset(mainmodule, mclasses) - end - # Collect all mproperties introduced in 'self' with `visibility >= min_visibility`. fun collect_intro_mproperties(view: ModelView): Set[MProperty] do var set = new HashSet[MProperty] @@ -318,6 +436,17 @@ redef class MClass return res end + # Collect all mmethods accessible by 'self' with `visibility >= min_visibility`. + # + # This include introduced, redefined, inherited mmethods. + 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 mattributes introduced in 'self' with `visibility >= min_visibility`. fun collect_intro_mattributes(view: ModelView): Set[MAttribute] do var res = new HashSet[MAttribute] @@ -409,10 +538,66 @@ redef class MClass set.add_all(collect_inherited_inits(view)) return set end + + # Collect all virtual types accessible by 'self' if accepted by `view`. + # + # 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_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 + + # `MClassDef` ancestors are its direct and transitive super classes. + 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 + + # `MClassDef` parents are its direct super classes. + 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 + + # `MClassDef` children are its direct subclasses. + 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 mpropdefs in 'self' with `visibility >= min_visibility`. fun collect_mpropdefs(view: ModelView): Set[MPropDef] do var res = new HashSet[MPropDef] @@ -459,6 +644,50 @@ end 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 mpropdefs in 'self' with `visibility >= min_visibility`. + 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 + + # `MProperty` parents are all direct super definition of `self`. + # + # This method uses a flattened hierarchy containing all the mpropdefs. + 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 + + # `MProperty` parents are all direct sub definition of `self`. + # + # This method uses a flattened hierarchy containing all the mpropdefs. + 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 + return res + end end redef class MPropDef @@ -488,4 +717,36 @@ redef class MPropDef 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 + + # `MPropDef` parents include 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 + + # `MPropdef` children are definitions that directly depends 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 end