X-Git-Url: http://nitlanguage.org diff --git a/src/model/mmodule.nit b/src/model/mmodule.nit index d2750ed..d88a0ba 100644 --- a/src/model/mmodule.nit +++ b/src/model/mmodule.nit @@ -17,7 +17,6 @@ # modules and module hierarchies in the metamodel module mmodule -import poset import location import mproject private import more_collections @@ -26,19 +25,13 @@ private import more_collections # A model knows modules, classes and properties and can retrieve them. redef class Model # All known modules - var mmodules: Array[MModule] = new Array[MModule] - - # placebo for old module nesting hierarchy. - # where mainmodule < mainmodule::nestedmodule - # - # TODO REMOVE, rely on mgroup instead - var mmodule_nesting_hierarchy: POSet[MModule] = new POSet[MModule] + var mmodules = new Array[MModule] # Full module importation hierarchy including private or nested links. - var mmodule_importation_hierarchy: POSet[MModule] = new POSet[MModule] + var mmodule_importation_hierarchy = new POSet[MModule] # Collections of modules grouped by their short names - private var mmodules_by_name: MultiHashMap[String, MModule] = new MultiHashMap[String, MModule] + private var mmodules_by_name = new MultiHashMap[String, MModule] # Return all module named `name` # If such a module does not exist, null is returned (instead of an empty array) @@ -58,31 +51,41 @@ redef class MGroup # The loaded modules of this group var mmodules = new Array[MModule] - # Placebo stuff to find the owner (module with same name) - # null is returned if there is no owner, or if it is not loaded yet - fun fuzzy_owner: nullable MModule + # The default module of a group (if any, and if loaded) + # + # The default module of a group is the one that has the same name. + # Return `null` if the group has no default module or if the default + # module is not loaded. + var default_mmodule: nullable MModule = null + + redef fun mdoc_or_fallback do - for m in mmodules do if m.name == name then return m - return null + if mdoc != null then return mdoc + if default_mmodule == null then return null + return default_mmodule.mdoc_or_fallback end end # A Nit module is usually associated with a Nit source file. class MModule - # The model considered - var model: Model + super MConcern - # placebo for old module nesting hierarchy - # return null if self is not nested (ie. is a top-level module) - # - # TODO REMOVE, rely on mgroup instead - var direct_owner: nullable MModule + # The model considered + redef var model: Model # The group of module in the project if any var mgroup: nullable MGroup + # The project of the module if any + # Safe alias for `mgroup.mproject` + fun mproject: nullable MProject + do + var g = mgroup + if g == null then return null else return g.mproject + end + # The short name of the module - var name: String + redef var name: String # The origin of the definition var location: Location @@ -90,19 +93,17 @@ class MModule # Alias for `name` redef fun to_s do return self.name - # placebo for old module nesting hierarchy - # The view of the module in the `model.mmodule_nesting_hierarchy` - # - # TODO REMOVE, rely on mgroup instead - var in_nesting: POSetElement[MModule] - # The view of the module in the `model.mmodule_importation_hierarchy` - var in_importation: POSetElement[MModule] + var in_importation: POSetElement[MModule] is noinit - # The canonical name of the module + # The canonical name of the module. + # + # It is usually the `name` prefixed by the project's name. # Example: `"project::name"` - fun full_name: String - do + # + # If both names are the same (of if the module is project-less), then + # the short-name is used alone. + redef var full_name is lazy do var mgroup = self.mgroup if mgroup == null or mgroup.mproject.name == self.name then return self.name @@ -111,33 +112,59 @@ class MModule end end + # The namespace used for entities according to their visibility `v`. + # + # Public entities use only the project as a namespace. + # Private entities use the `full_name` (i.e. "project::module") + # + # This method is used by entities to implement their `full_name`. + fun namespace_for(v: MVisibility): String do + if v <= private_visibility then return full_name + var mgroup = self.mgroup + if mgroup == null then + return full_name + else + return mgroup.mproject.full_name + end + end + + # Return the name of the global C identifier associated to `self`. + # This name is used to prefix files and other C identifiers associated with `self`. + redef var c_name: String is lazy do + var g = mgroup + var res + if g != null and g.mproject.name != name then + res = g.mproject.name.to_cmangle + "__" + name.to_cmangle + else + res = name.to_cmangle + end + return res + end + + # C identifier version of `namespace_for`. + # See `c_name` + # + # This method is used by entities to implement their `c_name`. + fun c_namespace_for(v: MVisibility): String do + if v <= private_visibility then return c_name + var mgroup = self.mgroup + if mgroup == null then + return c_name + else + return mgroup.mproject.c_name + end + end + # Create a new empty module and register it to a model - init(model: Model, mgroup: nullable MGroup, name: String, location: Location) + init do - self.model = model - self.name = name - self.location = location model.mmodules_by_name.add_one(name, self) model.mmodules.add(self) - self.in_nesting = model.mmodule_nesting_hierarchy.add_node(self) - self.mgroup = mgroup if mgroup != null then mgroup.mmodules.add(self) - # placebo for old module nesting hierarchy - var direct_owner = mgroup.fuzzy_owner - if direct_owner == self then - # The module is the new owner of its own group, thus adopt the other modules - for m in mgroup.mmodules do - if m == self then continue - m.direct_owner = self - model.mmodule_nesting_hierarchy.add_edge(self, m) - end - # The potential owner is the the fuzzy_owner of the parent group - if mgroup.parent != null then direct_owner = mgroup.parent.fuzzy_owner - end - if direct_owner != self and direct_owner != null then - self.direct_owner = direct_owner - model.mmodule_nesting_hierarchy.add_edge(direct_owner, self) + if mgroup.name == name then + assert mgroup.default_mmodule == null + mgroup.default_mmodule = self end end self.in_importation = model.mmodule_importation_hierarchy.add_node(self) @@ -154,9 +181,9 @@ class MModule end end - private var intrude_mmodules: HashSet[MModule] = new HashSet[MModule] - private var public_mmodules: HashSet[MModule] = new HashSet[MModule] - private var private_mmodules: HashSet[MModule] = new HashSet[MModule] + private var intrude_mmodules = new HashSet[MModule] + private var public_mmodules = new HashSet[MModule] + private var private_mmodules = new HashSet[MModule] # Return the visibility level of an imported module `m` fun visibility_for(m: MModule): MVisibility @@ -191,18 +218,6 @@ class MModule end end - # placebo for old module nesting hierarchy - fun public_owner: nullable MModule - do - var mgroup = self.mgroup - if mgroup == null then return null - mgroup = mgroup.mproject.root - if mgroup.mmodules.is_empty then return null - var res = mgroup.fuzzy_owner - if res == self then return null - return res - end - # Return true if a class or a property introduced in `intro_mmodule` with a visibility of `visibility` is visible in self. fun is_visible(intro_mmodule: MModule, visibility: MVisibility): Bool do @@ -219,4 +234,14 @@ class MModule abort end end + + # Is `self` created for internal purpose? + # Fictive modules are instantiated internally but they should not be + # exposed to the final user. + var is_fictive: Bool = false is writable + + # Is `self` a unit test module used by `nitunit`? + var is_test_suite: Bool = false is writable + + redef fun parent_concern do return mgroup end