X-Git-Url: http://nitlanguage.org diff --git a/src/model/model_collect.nit b/src/model/model_collect.nit index 8585092..1943bad 100644 --- a/src/model/model_collect.nit +++ b/src/model/model_collect.nit @@ -14,460 +14,1116 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Collect things from a `Model`. +# Collect things from the model. +# +# This module introduce several usefull methods to list and count things from a +# Model. +# +# ~~~nitish +# print number of parents for `{my_class}` +# print my_class.collect_parents.count +# ~~~ +# +# Collect methods can also be used with a ModelFilter: +# ~~~nitish +# var filter = new ModelFilter(min_visibility = private_visibility) +# print my_class.collect_parents(filter).count +# ~~~ # # **Warning** # -# `model_collect` offers a flattened view of the model without considering any +# `model_collect` offers a flattened filter 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 +# This is usefull for tools that need a global filter of a model like `nitdoc`, +# `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_views +import model_filters redef class MEntity - # Collect modifier keywords like `redef`, `private` etc. - fun collect_modifiers: Array[String] do - return new Array[String] + # 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] + + # 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(mainmodule: MModule, filter: nullable ModelFilter): Set[MENTITY] do + var done = new HashSet[MENTITY] + var todo = new Array[MENTITY] + + todo.add_all collect_parents(mainmodule, filter) + 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(mainmodule, filter) + end + return done + end + + # Collect `self` parents (direct ancestors) + # + # The concept of parent is abstract at this stage. + fun collect_parents(mainmodule: MModule, filter: nullable ModelFilter): Set[MENTITY] is abstract + + # Collect `self` children (direct descendants) + # + # The concept of child is abstract at this stage. + fun collect_children(mainmodule: MModule, filter: nullable ModelFilter): Set[MENTITY] is abstract + + # Collect `self` descendants (direct and direct) + # + # The concept of descendant is abstract at this stage. + fun collect_descendants(mainmodule: MModule, filter: nullable ModelFilter): Set[MENTITY] do + var done = new HashSet[MENTITY] + var todo = new Array[MENTITY] + + todo.add_all collect_children(mainmodule, filter) + 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(mainmodule, filter) + 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(mainmodule: MModule, filter: nullable ModelFilter): POSet[MENTITY] do + var poset = new POSet[MENTITY] + var parents_done = new HashSet[MENTITY] + var parents = new Array[MENTITY] + parents.add self + while parents.not_empty do + var mentity = parents.pop + if parents_done.has(mentity) then continue + parents_done.add mentity + poset.add_node mentity + for parent in mentity.collect_parents(mainmodule, filter) do + poset.add_edge(mentity, parent) + parents.add parent + end + end + var children_done = new HashSet[MEntity] + var children = new Array[MEntity] + children.add self + while children.not_empty do + var mentity = children.pop + if children_done.has(mentity) then continue + children_done.add mentity + for child in mentity.collect_children(mainmodule, filter) do + poset.add_edge(child, mentity) + children.add child + end + end + return poset + end +end + +redef class Model + + # Collect all MPackages in `self` + fun collect_mpackages(filter: nullable ModelFilter): HashSet[MPackage] do + var res = new HashSet[MPackage] + for mpackage in mpackages do + if filter == null or filter.accept_mentity(mpackage) then res.add(mpackage) + end + return res + end + + # Collect all MGroups in `self` + fun collect_mgroups(filter: nullable ModelFilter): HashSet[MGroup] do + var res = new HashSet[MGroup] + for mpackage in collect_mpackages(filter) do + res.add_all mpackage.collect_all_mgroups(filter) + end + return res + end + + # Collect all MModules in `self` + fun collect_mmodules(filter: nullable ModelFilter): HashSet[MModule] do + var res = new HashSet[MModule] + for mpackage in collect_mpackages(filter) do + res.add_all mpackage.collect_all_mmodules(filter) + end + return res + end + + # Collect all MClasses in `self` + fun collect_mclasses(filter: nullable ModelFilter): HashSet[MClass] do + var res = new HashSet[MClass] + for mclass in mclasses do + if filter == null or filter.accept_mentity(mclass) then res.add mclass + end + return res + end + + # Collect all MClasses introduced in `self` + fun collect_intro_mclasses(filter: nullable ModelFilter): HashSet[MClass] do + var res = new HashSet[MClass] + for mpackage in collect_mpackages(filter) do + res.add_all mpackage.collect_intro_mclasses(filter) + end + return res + end + + # Collect all MClassDefs in `self` + fun collect_mclassdefs(filter: nullable ModelFilter): HashSet[MClassDef] do + var res = new HashSet[MClassDef] + for mclass in collect_mclasses(filter) do + res.add_all mclass.collect_mclassdefs(filter) + end + return res + end + + # Collect all MProperties introduced in `self` + fun collect_intro_mproperties(filter: nullable ModelFilter): HashSet[MProperty] do + var res = new HashSet[MProperty] + for mpackage in collect_mpackages(filter) do + res.add_all mpackage.collect_intro_mproperties(filter) + end + return res + end + + # Collect all MProperties in `self` + fun collect_mproperties(filter: nullable ModelFilter): HashSet[MProperty] do + var res = new HashSet[MProperty] + for mproperty in mproperties do + if filter == null or filter.accept_mentity(mproperty) then res.add mproperty + end + return res + end + + # Collect all MPropDefs in `self` + fun collect_mpropdefs(filter: nullable ModelFilter): HashSet[MPropDef] do + var res = new HashSet[MPropDef] + for mproperty in collect_mproperties(filter) do + for mpropdef in mproperty.mpropdefs do + if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef + end + end + return res + end + + # Collect all MEntities in `self` + fun collect_mentities(filter: nullable ModelFilter): HashSet[MEntity] do + var res = new HashSet[MEntity] + res.add_all collect_mpackages(filter) + res.add_all collect_mgroups(filter) + res.add_all collect_mmodules(filter) + res.add_all collect_mclasses(filter) + res.add_all collect_mclassdefs(filter) + res.add_all collect_mproperties(filter) + res.add_all collect_mpropdefs(filter) + return res + end + + # Searches the MEntity that matches `full_name`. + fun mentity_by_full_name(full_name: String, filter: nullable ModelFilter): nullable MEntity do + for mentity in collect_mentities(filter) do + if filter != null and not filter.accept_mentity(mentity) then continue + if mentity.full_name == full_name then return mentity + end + return null + end + + # Searches the MEntities that matches `full_name`. + fun mentities_by_name(name: String, filter: nullable ModelFilter): Array[MEntity] do + var res = new Array[MEntity] + for mentity in collect_mentities(filter) do + if filter != null and not filter.accept_mentity(mentity) then continue + if mentity.name == name then res.add mentity + end + return res end end redef class MPackage - redef fun collect_modifiers do - var res = super - res.add "package" + + redef fun collect_modifiers do return super + ["package"] + + # Collect all packages directly imported by `self` + redef fun collect_parents(mainmodule, filter) do + var res = new HashSet[MENTITY] + for mgroup in mgroups do + for parent in mgroup.collect_parents(mainmodule, filter) do + var mpackage = parent.mpackage + if mpackage == self then continue + if filter == null or filter.accept_mentity(mpackage) then res.add(mpackage) + end + end + return res + end + + # Collect all packages that directly depends on `self` + redef fun collect_children(mainmodule, filter) do + var res = new HashSet[MENTITY] + for mpackage in model.collect_mpackages(filter) do + if mpackage.collect_parents(mainmodule, filter).has(self) then res.add mpackage + end + return res + end + + # Collect all groups contained in `self` + fun collect_all_mgroups(filter: nullable ModelFilter): HashSet[MGroup] do + var res = new HashSet[MGroup] + for mgroup in mgroups do + if filter == null or filter.accept_mentity(mgroup) then res.add(mgroup) + end + return res + end + + # Collect only groups contained in `self.root` + fun collect_mgroups(filter: nullable ModelFilter): HashSet[MGroup] do + var res = new HashSet[MGroup] + var root = self.root + if root == null then return res + res.add_all root.collect_mgroups(filter) + return res + end + + # Collect all modules contained in `self` + fun collect_all_mmodules(filter: nullable ModelFilter): HashSet[MModule] do + var res = new HashSet[MModule] + for mgroup in collect_all_mgroups(filter) do + res.add_all mgroup.collect_mmodules(filter) + end + return res + end + + # Collect only modules contained in `self.root` + fun collect_mmodules(filter: nullable ModelFilter): HashSet[MModule] do + var res = new HashSet[MModule] + var root = self.root + if root == null then return res + res.add_all root.collect_mmodules(filter) + return res + end + + # Collect all classes introduced in `self` + fun collect_intro_mclasses(filter: nullable ModelFilter): HashSet[MClass] do + var res = new HashSet[MClass] + for mgroup in mgroups do + for mmodule in collect_all_mmodules(filter) do + res.add_all mmodule.collect_intro_mclasses(filter) + end + end + return res + end + + # Collect all classes redefined or refined in `self` + fun collect_redef_mclasses(filter: nullable ModelFilter): Set[MClass] do + var res = new HashSet[MClass] + for mgroup in mgroups do + for mmodule in collect_all_mmodules(filter) do + res.add_all mmodule.collect_redef_mclasses(filter) + end + end + return res + end + + # Collect all properties introduced in `self` + fun collect_intro_mproperties(filter: nullable ModelFilter): HashSet[MProperty] do + var res = new HashSet[MProperty] + for mgroup in mgroups do + for mmodule in collect_all_mmodules(filter) do + res.add_all mmodule.collect_intro_mproperties(filter) + end + end + return res + end + + # Collect all properties redefined in `self` + fun collect_redef_mproperties(filter: nullable ModelFilter): HashSet[MProperty] do + var res = new HashSet[MProperty] + for mgroup in mgroups do + for mmodule in collect_all_mmodules(filter) do + res.add_all mmodule.collect_redef_mproperties(filter) + end + end + return res + end + + # Collect all attributes introduced in `self` + fun collect_intro_attributes(filter: nullable ModelFilter): Set[MAttribute] do + var res = new HashSet[MAttribute] + for mgroup in mgroups do + for mmodule in collect_all_mmodules(filter) do + res.add_all mmodule.collect_intro_attributes(filter) + end + end + return res + end + + # Collect all inits introduced in `self` + fun collect_intro_inits(filter: nullable ModelFilter): Set[MMethod] do + var res = new HashSet[MMethod] + for mgroup in mgroups do + for mmodule in collect_all_mmodules(filter) do + res.add_all mmodule.collect_intro_inits(filter) + end + end + return res + end + + # Collect all methods introduced in `self` excluding inits + # + # See `collect_intro_inits`. + fun collect_intro_methods(filter: nullable ModelFilter): Set[MMethod] do + var res = new HashSet[MMethod] + for mgroup in mgroups do + for mmodule in collect_all_mmodules(filter) do + res.add_all mmodule.collect_intro_methods(filter) + end + end + return res + end + + # Collect all virtual types introduced in `self` + fun collect_intro_vts(filter: nullable ModelFilter): Set[MVirtualTypeProp] do + var res = new HashSet[MVirtualTypeProp] + for mgroup in mgroups do + for mmodule in collect_all_mmodules(filter) do + res.add_all mmodule.collect_intro_vts(filter) + end + end return res end end redef class MGroup - redef fun collect_modifiers do - var res = super - res.add "group" + + redef fun collect_modifiers do return super + ["group"] + + # Collect all groups directly import by `self` + redef fun collect_parents(mainmodule, filter) do + var res = new HashSet[MENTITY] + for mmodule in mmodules do + for parent in mmodule.collect_parents(mainmodule, filter) do + var mgroup = parent.mgroup + if mgroup == null or mgroup == self then continue + if filter == null or filter.accept_mentity(mgroup) then res.add(mgroup) + end + end return res end -end -redef class MModule + # Collect all group that directly import `self` + redef fun collect_children(mainmodule, filter) do + var res = new HashSet[MENTITY] + for mgroup in model.collect_mgroups(filter) do + if mgroup == self then continue + if filter != null and not filter.accept_mentity(mgroup) then continue + if mgroup.collect_parents(mainmodule, filter).has(self) then res.add mgroup + end + return res + end - redef fun collect_modifiers do - var res = super - res.add "module" + # Collect all groups contained in `self` + fun collect_mgroups(filter: nullable ModelFilter): HashSet[MENTITY] do + var res = new HashSet[MENTITY] + for mgroup in in_nesting.direct_smallers do + if filter == null or filter.accept_mentity(mgroup) then res.add(mgroup) + end + return res + end + + # Collect all modules contained in `self` + fun collect_all_mmodules(filter: nullable ModelFilter): HashSet[MModule] do + var res = new HashSet[MModule] + for mgroup in collect_mgroups(filter) do + res.add_all mgroup.collect_all_mmodules(filter) + end return res end - # Collect all transitive imports. - fun collect_ancestors(view: ModelView): Set[MModule] do + # Collect all modules contained in `self` + fun collect_mmodules(filter: nullable ModelFilter): HashSet[MModule] do var res = new HashSet[MModule] + for mmodule in mmodules do + if filter == null or filter.accept_mentity(mmodule) then res.add(mmodule) + end + return res + end +end + +redef class MModule + + redef fun collect_modifiers do return super + ["module"] + + # Collect all modules directly imported by `self` + redef fun collect_ancestors(mainmodule, filter) 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 + if filter == null or filter.accept_mentity(mentity) then res.add mentity end return res end - # Collect direct imports. - fun collect_parents(view: ModelView): Set[MModule] do - var res = new HashSet[MModule] + # Collect all modules directly imported by `self` + redef fun collect_parents(mainmodule, filter) 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 + if filter == null or filter.accept_mentity(mentity) then res.add mentity end return res end - # Collect direct children (modules that directly import `self`). - fun collect_children(view: ModelView): Set[MModule] do - var res = new HashSet[MModule] + # Collect all modules that directly import `self` + redef fun collect_children(mainmodule, filter) 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 + if filter == null or filter.accept_mentity(mentity) then res.add mentity end return res end - # Collect all transitive children. - fun collect_descendants(view: ModelView): Set[MModule] do - var res = new HashSet[MModule] + # Collect all module descendants of `self` (direct and transitive imports) + redef fun collect_descendants(mainmodule, filter) 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 + if filter == null or filter.accept_mentity(mentity) then res.add mentity end 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 + # Collect all class definitions introduced in `self` + fun collect_intro_mclassdefs(filter: nullable ModelFilter): Set[MClassDef] do var res = new HashSet[MClassDef] for mclassdef in mclassdefs do if not mclassdef.is_intro then continue - if not view.accept_mentity(mclassdef) then continue - res.add mclassdef + if filter == null or filter.accept_mentity(mclassdef) then res.add mclassdef end return res end - # Collect mclassdefs redefined in `self` with `visibility >= to min_visibility`. - fun collect_redef_mclassdefs(view: ModelView): Set[MClassDef] do + # Collect all class definitions refined in `self` + fun collect_redef_mclassdefs(filter: nullable ModelFilter): Set[MClassDef] do var res = new HashSet[MClassDef] for mclassdef in mclassdefs do if mclassdef.is_intro then continue - if not view.accept_mentity(mclassdef) then continue - res.add mclassdef + if filter == null or filter.accept_mentity(mclassdef) then res.add mclassdef end return res end - # Collect mclasses introduced in `self` with `visibility >= to min_visibility`. - fun collect_intro_mclasses(view: ModelView): Set[MClass] do + # Collect all class definitions introduced and refined in `self` + fun collect_local_mclassdefs(filter: nullable ModelFilter): Set[MClassDef] do + var res = new HashSet[MClassDef] + res.add_all collect_intro_mclassdefs(filter) + res.add_all collect_redef_mclassdefs(filter) + return res + end + + # Collect all classes introduced in `self` + fun collect_intro_mclasses(filter: nullable ModelFilter): Set[MClass] do var res = new HashSet[MClass] for mclass in intro_mclasses do - if not view.accept_mentity(mclass) then continue - res.add mclass + if filter == null or filter.accept_mentity(mclass) then res.add mclass end return res end - # Collect mclasses redefined in `self` with `visibility >= to min_visibility`. - fun collect_redef_mclasses(view: ModelView): Set[MClass] do + # Collect all classes refined in `self` + fun collect_redef_mclasses(filter: nullable ModelFilter): Set[MClass] do var mclasses = new HashSet[MClass] for mclassdef in mclassdefs do - if not view.accept_mentity(mclassdef) then continue + if filter != null and not filter.accept_mentity(mclassdef.mclass) then continue if not mclassdef.is_intro then mclasses.add(mclassdef.mclass) end return mclasses end + + # Collect all classes introduced and refined in `self` + fun collect_local_mclasses(filter: nullable ModelFilter): Set[MClass] do + var res = new HashSet[MClass] + res.add_all collect_intro_mclasses(filter) + res.add_all collect_redef_mclasses(filter) + return res + end + + # Collect all classes imported from `self` parents + fun collect_imported_mclasses(mainmodule: MModule, filter: nullable ModelFilter): Set[MClass] do + var res = new HashSet[MClass] + for parent in collect_parents(mainmodule, filter) do + res.add_all parent.collect_intro_mclasses(filter) + res.add_all parent.collect_redef_mclasses(filter) + res.add_all parent.collect_imported_mclasses(mainmodule, filter) + end + return res + end + + # Collect all properties introduced in `self` + fun collect_intro_mproperties(filter: nullable ModelFilter): Set[MProperty] do + var res = new HashSet[MProperty] + for mclass in collect_intro_mclasses(filter) do + res.add_all mclass.collect_intro_mproperties(filter) + end + return res + end + + # Collect properties redefined in `self` + fun collect_redef_mproperties(filter: nullable ModelFilter): Set[MProperty] do + var res = new HashSet[MProperty] + for mclassdef in mclassdefs do + for mpropdef in mclassdef.collect_redef_mpropdefs(filter) do + res.add mpropdef.mproperty + end + end + return res + end + + # Collect attributes introduced in `self` + fun collect_intro_attributes(filter: nullable ModelFilter): Set[MAttribute] do + var res = new HashSet[MAttribute] + for mproperty in collect_intro_mproperties(filter) do + if mproperty isa MAttribute then res.add(mproperty) + end + return res + end + + # Collect all inits introduced in `self` + fun collect_intro_inits(filter: nullable ModelFilter): Set[MMethod] do + var res = new HashSet[MMethod] + for mproperty in collect_intro_mproperties(filter) 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(filter: nullable ModelFilter): Set[MMethod] do + var res = new HashSet[MMethod] + for mproperty in collect_intro_mproperties(filter) 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(filter: nullable ModelFilter): Set[MVirtualTypeProp] do + var res = new HashSet[MVirtualTypeProp] + for mproperty in collect_intro_mproperties(filter) 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 - # 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 + redef fun collect_linearization(mainmodule) do + var mclassdefs = self.mclassdefs.to_a + mainmodule.linearize_mclassdefs(mclassdefs) + return mclassdefs + end + + # Collect all ancestors of `self` + redef fun collect_ancestors(mainmodule, filter) do + var res = new HashSet[MENTITY] + if not mainmodule.flatten_mclass_hierarchy.has(self) then return res + for mclass in in_hierarchy(mainmodule).greaters do + if mclass == self then continue + if filter == null or filter.accept_mentity(mclass) then res.add mclass end return res 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) - end + # Collect all direct parents of `self` + redef fun collect_parents(mainmodule, filter) do + var res = new HashSet[MENTITY] + if not mainmodule.flatten_mclass_hierarchy.has(self) then return res + for mclass in in_hierarchy(mainmodule).direct_greaters do + if mclass == self then continue + if filter == null or filter.accept_mentity(mclass) then res.add mclass 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) - end + # Collect all direct children of `self` + redef fun collect_children(mainmodule, filter) do + var res = new HashSet[MENTITY] + if not mainmodule.flatten_mclass_hierarchy.has(self) then return res + for mclass in in_hierarchy(mainmodule).direct_smallers do + if mclass == self then continue + if filter == null or filter.accept_mentity(mclass) then res.add mclass 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) - end + # Collect all descendants of `self` + redef fun collect_descendants(mainmodule, filter) do + var res = new HashSet[MENTITY] + if not mainmodule.flatten_mclass_hierarchy.has(self) then return res + for mclass in in_hierarchy(mainmodule).smallers do + if mclass == self then continue + if filter == null or filter.accept_mentity(mclass) then res.add mclass 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) + # Collect all class definitions of `self` + fun collect_mclassdefs(filter: nullable ModelFilter): Set[MClassDef] do + var res = new HashSet[MClassDef] + for mclassdef in mclassdefs do + if filter == null or filter.accept_mentity(mclassdef) then res.add mclassdef + end + return res + end + + # Collect all property definitions that are introductions in `self` + fun collect_intro_mpropdefs(filter: nullable ModelFilter): 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 filter == null or filter.accept_mentity(mpropdef) then set.add(mpropdef) + end + end + return set end - # Collect all mproperties introduced in 'self' with `visibility >= min_visibility`. - fun collect_intro_mproperties(view: ModelView): Set[MProperty] do + # Collect all properties introduced in `self` + fun collect_intro_mproperties(filter: nullable ModelFilter): Set[MProperty] do var set = new HashSet[MProperty] for mclassdef in mclassdefs do for mprop in mclassdef.intro_mproperties do - if not view.accept_mentity(mprop) then continue - set.add(mprop) + if filter == null or filter.accept_mentity(mprop) then set.add(mprop) end end return set end - # Collect all mproperties redefined in 'self' with `visibility >= min_visibility`. - fun collect_redef_mproperties(view: ModelView): Set[MProperty] do + # Collect all propierty definitions that are redefinition in `self` + fun collect_redef_mpropdefs(filter: nullable ModelFilter): 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 filter == null or filter.accept_mentity(mpropdef) then set.add(mpropdef) + end + end + return set + end + + # Collect all properties redefined in `self` + fun collect_redef_mproperties(filter: nullable ModelFilter): Set[MProperty] do var set = new HashSet[MProperty] for mclassdef in mclassdefs do for mpropdef in mclassdef.mpropdefs do if mpropdef.mproperty.intro_mclassdef.mclass == self then continue - if not view.accept_mentity(mpropdef) then continue - set.add(mpropdef.mproperty) + if filter == null or filter.accept_mentity(mpropdef) then + set.add(mpropdef.mproperty) + end end end return set end - # Collect mproperties introduced and redefined in 'self' with `visibility >= min_visibility`. - fun collect_local_mproperties(view: ModelView): Set[MProperty] do + # Collect all properties introduced and redefined in `self` + fun collect_local_mproperties(filter: nullable ModelFilter): Set[MProperty] do var set = new HashSet[MProperty] - set.add_all collect_intro_mproperties(view) - set.add_all collect_redef_mproperties(view) + set.add_all collect_intro_mproperties(filter) + set.add_all collect_redef_mproperties(filter) return set end - # Collect all mproperties inehrited by 'self' with `visibility >= min_visibility`. - fun collect_inherited_mproperties(view: ModelView): Set[MProperty] do + # Collect all properties inehrited by `self` + fun collect_inherited_mproperties(mainmodule: MModule, filter: nullable ModelFilter): Set[MProperty] do var set = new HashSet[MProperty] - for parent in collect_parents(view) do - set.add_all(parent.collect_intro_mproperties(view)) - set.add_all(parent.collect_inherited_mproperties(view)) + for parent in collect_parents(mainmodule, filter) do + set.add_all(parent.collect_intro_mproperties(filter)) + set.add_all(parent.collect_inherited_mproperties(mainmodule, filter)) 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(view: ModelView): Set[MProperty] do + # This include introduced, redefined, inherited properties. + fun collect_accessible_mproperties(mainmodule: MModule, filter: nullable ModelFilter): Set[MProperty] do var set = new HashSet[MProperty] - set.add_all(collect_intro_mproperties(view)) - set.add_all(collect_redef_mproperties(view)) - set.add_all(collect_inherited_mproperties(view)) + set.add_all(collect_intro_mproperties(filter)) + set.add_all(collect_redef_mproperties(filter)) + set.add_all(collect_inherited_mproperties(mainmodule, filter)) return set end - # Collect mmethods introduced in 'self' with `visibility >= min_visibility`. - fun collect_intro_mmethods(view: ModelView): Set[MMethod] do + # Collect all methods introduced in `self` + fun collect_intro_mmethods(filter: nullable ModelFilter): Set[MMethod] do var res = new HashSet[MMethod] - for mproperty in collect_intro_mproperties(view) do + for mproperty in collect_intro_mproperties(filter) 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(view: ModelView): Set[MMethod] do + # Collect all methods redefined in `self` + fun collect_redef_mmethods(filter: nullable ModelFilter): Set[MMethod] do var res = new HashSet[MMethod] - for mproperty in collect_redef_mproperties(view) do + for mproperty in collect_redef_mproperties(filter) 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(view: ModelView): Set[MMethod] do + # Collect all methods introduced and redefined in `self` + fun collect_local_mmethods(filter: nullable ModelFilter): 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_intro_mmethods(filter) + set.add_all collect_redef_mmethods(filter) return set end - # Collect mmethods inherited by 'self' if accepted by `view`. - fun collect_inherited_mmethods(view: ModelView): Set[MMethod] do + # Collect all methods inherited by `self` + fun collect_inherited_mmethods(mainmodule: MModule, filter: nullable ModelFilter): Set[MMethod] do var res = new HashSet[MMethod] - for mproperty in collect_inherited_mproperties(view) do + for mproperty in collect_inherited_mproperties(mainmodule, filter) do if mproperty isa MMethod then res.add(mproperty) end return res end - # Collect mattributes introduced in 'self' with `visibility >= min_visibility`. - fun collect_intro_mattributes(view: ModelView): Set[MAttribute] do + # Collect all methods accessible by `self` + # + # This include introduced, redefined, inherited methods. + fun collect_accessible_mmethods(mainmodule: MModule, filter: nullable ModelFilter): Set[MMethod] do + var set = new HashSet[MMethod] + set.add_all(collect_intro_mmethods(filter)) + set.add_all(collect_redef_mmethods(filter)) + set.add_all(collect_inherited_mmethods(mainmodule, filter)) + return set + end + + # Collect all attributes introduced in `self` + fun collect_intro_mattributes(filter: nullable ModelFilter): Set[MAttribute] do var res = new HashSet[MAttribute] - for mproperty in collect_intro_mproperties(view) do + for mproperty in collect_intro_mproperties(filter) 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(view: ModelView): Set[MAttribute] do + # Collect all attributes redefined in `self` + fun collect_redef_mattributes(filter: nullable ModelFilter): Set[MAttribute] do var res = new HashSet[MAttribute] - for mproperty in collect_redef_mproperties(view) do + for mproperty in collect_redef_mproperties(filter) 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(view: ModelView): Set[MAttribute] do + # Collect all attributes introduced and redefined in `self` + fun collect_local_mattributes(filter: nullable ModelFilter): Set[MAttribute] do var set = new HashSet[MAttribute] - set.add_all collect_intro_mattributes(view) - set.add_all collect_redef_mattributes(view) + set.add_all collect_intro_mattributes(filter) + set.add_all collect_redef_mattributes(filter) return set end - # Collect mattributes inherited by 'self' with `visibility >= min_visibility`. - fun collect_inherited_mattributes(view: ModelView): Set[MAttribute] do + # Collect all attributes inherited by `self` + fun collect_inherited_mattributes(mainmodule: MModule, filter: nullable ModelFilter): Set[MAttribute] do var res = new HashSet[MAttribute] - for mproperty in collect_inherited_mproperties(view) do + for mproperty in collect_inherited_mproperties(mainmodule, filter) 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(view: ModelView): Set[MAttribute] do + fun collect_accessible_mattributes(mainmodule: MModule, filter: nullable ModelFilter): Set[MAttribute] do var set = new HashSet[MAttribute] - set.add_all(collect_intro_mattributes(view)) - set.add_all(collect_redef_mattributes(view)) - set.add_all(collect_inherited_mattributes(view)) + set.add_all(collect_intro_mattributes(filter)) + set.add_all(collect_redef_mattributes(filter)) + set.add_all(collect_inherited_mattributes(mainmodule, filter)) return set end - # Collect init mmethods introduced in 'self' if accepted by `view`. - fun collect_intro_inits(view: ModelView): Set[MMethod] do + # Collect all init methods introduced in `self` + fun collect_intro_inits(filter: nullable ModelFilter): Set[MMethod] do var res = new HashSet[MMethod] - for mproperty in collect_intro_mmethods(view) do + for mproperty in collect_intro_mmethods(filter) do if mproperty.is_init then res.add(mproperty) end return res end - # Collect init mmethods redefined in 'self' if accepted by `view`. - fun collect_redef_inits(view: ModelView): Set[MMethod] do + # Collect all init methods redefined in `self` + fun collect_redef_inits(filter: nullable ModelFilter): Set[MMethod] do var res = new HashSet[MMethod] - for mproperty in collect_redef_mmethods(view) do + for mproperty in collect_redef_mmethods(filter) do if mproperty.is_init then res.add(mproperty) end return res end - # Collect init mmethods introduced and redefined in 'self' if accepted by `view`. - fun collect_local_inits(view: ModelView): Set[MMethod] do + # Collect all init methods introduced and redefined in `self` + fun collect_local_inits(filter: nullable ModelFilter): 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_intro_inits(filter) + set.add_all collect_redef_inits(filter) return set end - # Collect init mmethods inherited by 'self' if accepted by `view`. - fun collect_inherited_inits(view: ModelView): Set[MMethod] do + # Collect all init methods inherited by `self` + fun collect_inherited_inits(mainmodule: MModule, filter: nullable ModelFilter): Set[MMethod] do var res = new HashSet[MMethod] - for mproperty in collect_inherited_mmethods(view) do + for mproperty in collect_inherited_mmethods(mainmodule, filter) do if mproperty.is_init then res.add(mproperty) end return res end - # Collect all init mmethods accessible by 'self' if accepted by `view`. + # Collect all init methods accessible by `self` # # This include introduced, redefined, inherited inits. - fun collect_accessible_inits(view: ModelView): Set[MMethod] do + fun collect_accessible_inits(mainmodule: MModule, filter: nullable ModelFilter): 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)) + set.add_all(collect_intro_inits(filter)) + set.add_all(collect_redef_inits(filter)) + set.add_all(collect_inherited_inits(mainmodule, filter)) + return set + end + + # Collect all virtual types introduced in `self` + fun collect_intro_vts(filter: nullable ModelFilter): Set[MVirtualTypeProp] do + var res = new HashSet[MVirtualTypeProp] + for mproperty in collect_intro_mproperties(filter) do + if mproperty isa MVirtualTypeProp then res.add(mproperty) + end + return res + end + + # Collect all virtual types redefined in `self` + fun collect_redef_vts(filter: nullable ModelFilter): Set[MVirtualTypeProp] do + var res = new HashSet[MVirtualTypeProp] + for mproperty in collect_intro_mproperties(filter) 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(filter: nullable ModelFilter): Set[MVirtualTypeProp] do + var set = new HashSet[MVirtualTypeProp] + set.add_all collect_intro_vts(filter) + set.add_all collect_redef_vts(filter) + return set + end + + # Collect all virtual types inherited by `self` + fun collect_inherited_vts(mainmodule: MModule, filter: nullable ModelFilter): Set[MVirtualTypeProp] do + var res = new HashSet[MVirtualTypeProp] + for mproperty in collect_inherited_mproperties(mainmodule, filter) 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(mainmodule: MModule, filter: nullable ModelFilter): Set[MVirtualTypeProp] do + var set = new HashSet[MVirtualTypeProp] + for mproperty in collect_accessible_mproperties(mainmodule, filter) do + if mproperty isa MVirtualTypeProp then set.add mproperty + end return set end end redef class MClassDef - # Collect mpropdefs in 'self' with `visibility >= min_visibility`. - fun collect_mpropdefs(view: ModelView): Set[MPropDef] do + redef fun collect_modifiers do + var res = super + if not is_intro then + res.add "redef" + else + if mclass.visibility != public_visibility then + res.add mclass.visibility.to_s + end + end + res.add mclass.kind.to_s + return res + end + + 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_parents(mainmodule, filter) 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 then continue + if filter == null or filter.accept_mentity(parent) then res.add parent + end + return res + end + + redef fun collect_children(mainmodule, filter) 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 then continue + if filter == null or filter.accept_mentity(child) then res.add child + end + return res + end + + # Collect all property definitions in `self` + fun collect_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do var res = new HashSet[MPropDef] for mpropdef in mpropdefs do - if not view.accept_mentity(mpropdef) then continue + if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef + end + return res + end + + # Collect all attribute definitions in `self` + fun collect_mattributedefs(filter: nullable ModelFilter): Set[MAttributeDef] do + var res = new HashSet[MAttributeDef] + for mpropdef in collect_mpropdefs(filter) do + if not mpropdef isa MAttributeDef then continue res.add mpropdef end return res end - # Collect mpropdefs introduced in 'self' with `visibility >= min_visibility`. - 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 not view.accept_mentity(mpropdef) then continue + # Collect all methods definitions in `self` + fun collect_mmethoddefs(filter: nullable ModelFilter): Set[MMethodDef] do + var res = new HashSet[MMethodDef] + for mpropdef in collect_mpropdefs(filter) do + if not mpropdef isa MMethodDef then continue res.add mpropdef end return res end - # Collect mpropdefs redefined in 'self' with `visibility >= min_visibility`. - fun collect_redef_mpropdefs(view: ModelView): Set[MPropDef] do + # Collect all virtual types definitions in `self` + fun collect_mtypedefs(filter: nullable ModelFilter): Set[MVirtualTypeDef] do + var res = new HashSet[MVirtualTypeDef] + for mpropdef in collect_mpropdefs(filter) 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(filter: nullable ModelFilter): Set[MPropDef] do var res = new HashSet[MPropDef] for mpropdef in mpropdefs do - if mpropdef.is_intro then continue - if not view.accept_mentity(mpropdef) then continue - res.add mpropdef + if not mpropdef.is_intro then continue + if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef end return res end - redef fun collect_modifiers do - var res = super - if not is_intro then - res.add "redef" - else - res.add mclass.visibility.to_s + # Collect all property definitions that are redefinition in `self` + fun collect_redef_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do + var res = new HashSet[MPropDef] + for mpropdef in mpropdefs do + if mpropdef.is_intro then continue + if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef end - res.add mclass.kind.to_s return res end 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 all property definitions of `self` + fun collect_mpropdefs(filter: nullable ModelFilter): Set[MPropDef] do + var res = new HashSet[MPropDef] + for mpropdef in mpropdefs do + if filter == null or filter.accept_mentity(mpropdef) then res.add mpropdef + end + return res + end + + # Collect all direct super definitions of `self` + redef fun collect_parents(mainmodule, filter) do + var res = new HashSet[MENTITY] + for mpropdef in mpropdefs do + for parent in mpropdef.collect_parents(mainmodule, filter) do + var mprop = parent.mproperty + if filter == null or filter.accept_mentity(mprop) then res.add mprop + end + end + return res + end + + # Collection all definitions that have `self` as a direct super definition + redef fun collect_children(mainmodule, filter) do + var res = new HashSet[MENTITY] + for mpropdef in mpropdefs do + for child in mpropdef.collect_parents(mainmodule, filter) do + var mprop = child.mproperty + if filter == null or filter.accept_mentity(mprop) then res.add mprop + end + end + return res + end end redef class MPropDef + redef fun collect_modifiers do var res = super if not is_intro then res.add "redef" else - res.add mproperty.visibility.to_s + if mproperty.visibility != public_visibility then + res.add mproperty.visibility.to_s + end end var mprop = self if mprop isa MVirtualTypeDef then @@ -488,4 +1144,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 + + # Collect only the next definition of `self` + redef fun collect_parents(mainmodule, filter) 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(mainmodule, filter) do + var res = new HashSet[MENTITY] + for mpropdef in mproperty.collect_mpropdefs(filter) do + if mpropdef.collect_parents(mainmodule, filter).has(self) then res.add mpropdef + end + return res + end end