model: promote location to any `MEntity`
[nit.git] / src / model / model.nit
index b9d6aa2..2de65f5 100644 (file)
@@ -119,7 +119,17 @@ redef class Model
        end
 end
 
-# An OrderedTree that can be easily refined for display purposes
+# An OrderedTree bound to MEntity.
+#
+# We introduce a new class so it can be easily refined by tools working
+# with a Model.
+class MEntityTree
+       super OrderedTree[MEntity]
+end
+
+# A MEntityTree borned to MConcern.
+#
+# TODO remove when nitdoc is fully merged with model_collect
 class ConcernsTree
        super OrderedTree[MConcern]
 end
@@ -374,7 +384,9 @@ class MClass
 
        # The short name of the class
        # In Nit, the name of a class cannot evolve in refinements
-       redef var name: String
+       redef var name
+
+       redef var location
 
        # The canonical name of the class
        #
@@ -578,12 +590,11 @@ class MClassDef
        # ENSURE: `bound_mtype.mclass == self.mclass`
        var bound_mtype: MClassType
 
-       # The origin of the definition
-       var location: Location
+       redef var location: Location
 
        # Internal name combining the module and the class
-       # Example: "mymodule#MyClass"
-       redef var to_s: String is noinit
+       # Example: "mymodule$MyClass"
+       redef var to_s is noinit
 
        init
        do
@@ -594,34 +605,34 @@ class MClassDef
                        assert not isset mclass._intro
                        mclass.intro = self
                end
-               self.to_s = "{mmodule}#{mclass}"
+               self.to_s = "{mmodule}${mclass}"
        end
 
        # Actually the name of the `mclass`
        redef fun name do return mclass.name
 
-       # The module and class name separated by a '#'.
+       # The module and class name separated by a '$'.
        #
        # The short-name of the class is used for introduction.
-       # Example: "my_module#MyClass"
+       # Example: "my_module$MyClass"
        #
        # The full-name of the class is used for refinement.
-       # Example: "my_module#intro_module::MyClass"
+       # Example: "my_module$intro_module::MyClass"
        redef var full_name is lazy do
                if is_intro then
-                       # public gives 'p#A'
-                       # private gives 'p::m#A'
-                       return "{mmodule.namespace_for(mclass.visibility)}#{mclass.name}"
+                       # public gives 'p$A'
+                       # private gives 'p::m$A'
+                       return "{mmodule.namespace_for(mclass.visibility)}${mclass.name}"
                else if mclass.intro_mmodule.mpackage != mmodule.mpackage then
-                       # public gives 'q::n#p::A'
-                       # private gives 'q::n#p::m::A'
-                       return "{mmodule.full_name}#{mclass.full_name}"
+                       # public gives 'q::n$p::A'
+                       # private gives 'q::n$p::m::A'
+                       return "{mmodule.full_name}${mclass.full_name}"
                else if mclass.visibility > private_visibility then
-                       # public gives 'p::n#A'
-                       return "{mmodule.full_name}#{mclass.name}"
+                       # public gives 'p::n$A'
+                       return "{mmodule.full_name}${mclass.name}"
                else
-                       # private gives 'p::n#::m::A' (redundant p is omitted)
-                       return "{mmodule.full_name}#::{mclass.intro_mmodule.name}::{mclass.name}"
+                       # private gives 'p::n$::m::A' (redundant p is omitted)
+                       return "{mmodule.full_name}$::{mclass.intro_mmodule.name}::{mclass.name}"
                end
        end
 
@@ -1277,7 +1288,7 @@ class MGenericType
 
        # The short-name of the class, then the full-name of each type arguments within brackets.
        # Example: `"Map[String, List[Int]]"`
-       redef var to_s: String is noinit
+       redef var to_s is noinit
 
        # The full-name of the class, then the full-name of each type arguments within brackets.
        # Example: `"core::Map[core::String, core::List[core::Int]]"`
@@ -1299,7 +1310,7 @@ class MGenericType
                return res.to_s
        end
 
-       redef var need_anchor: Bool is noinit
+       redef var need_anchor is noinit
 
        redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
        do
@@ -1669,7 +1680,7 @@ class MNullableType
                self.to_s = "nullable {mtype}"
        end
 
-       redef var to_s: String is noinit
+       redef var to_s is noinit
 
        redef var full_name is lazy do return "nullable {mtype.full_name}"
 
@@ -1723,7 +1734,7 @@ end
 # The is only one null type per model, see `MModel::null_type`.
 class MNullType
        super MType
-       redef var model: Model
+       redef var model
        redef fun to_s do return "null"
        redef fun full_name do return "null"
        redef fun c_name do return "null"
@@ -1749,7 +1760,7 @@ end
 # Semantically it is the singleton `null.as_notnull`.
 class MBottomType
        super MType
-       redef var model: Model
+       redef var model
        redef fun to_s do return "bottom"
        redef fun full_name do return "bottom"
        redef fun c_name do return "bottom"
@@ -1885,7 +1896,7 @@ class MParameter
        super MEntity
 
        # The name of the parameter
-       redef var name: String
+       redef var name
 
        # The static type of the parameter
        var mtype: MType
@@ -1939,14 +1950,25 @@ abstract class MProperty
        var intro_mclassdef: MClassDef
 
        # The (short) name of the property
-       redef var name: String
+       redef var name
 
        # The canonical name of the property.
        #
-       # It is the short-`name` prefixed by the short-name of the class and the full-name of the module.
+       # It is currently the short-`name` prefixed by the short-name of the class and the full-name of the module.
        # Example: "my_package::my_module::MyClass::my_method"
+       #
+       # The full-name of the module is needed because two distinct modules of the same package can
+       # still refine the same class and introduce homonym properties.
+       #
+       # For public properties not introduced by refinement, the module name is not used.
+       #
+       # Example: `my_package::MyClass::My_method`
        redef var full_name is lazy do
-               return "{intro_mclassdef.mmodule.namespace_for(visibility)}::{intro_mclassdef.mclass.name}::{name}"
+               if intro_mclassdef.is_intro then
+                       return "{intro_mclassdef.mmodule.namespace_for(visibility)}::{intro_mclassdef.mclass.name}::{name}"
+               else
+                       return "{intro_mclassdef.mmodule.full_name}::{intro_mclassdef.mclass.name}::{name}"
+               end
        end
 
        redef var c_name is lazy do
@@ -2220,8 +2242,7 @@ abstract class MPropDef
        # The associated global property
        var mproperty: MPROPERTY
 
-       # The origin of the definition
-       var location: Location
+       redef var location: Location
 
        init
        do
@@ -2231,7 +2252,7 @@ abstract class MPropDef
                        assert not isset mproperty._intro
                        mproperty.intro = self
                end
-               self.to_s = "{mclassdef}#{mproperty}"
+               self.to_s = "{mclassdef}${mproperty}"
        end
 
        # Actually the name of the `mproperty`
@@ -2245,17 +2266,17 @@ abstract class MPropDef
        #  * a property "p::m::A::x"
        #  * redefined in a refinement of a class "q::n::B"
        #  * in a module "r::o"
-       #  * so "r::o#q::n::B#p::m::A::x"
+       #  * so "r::o$q::n::B$p::m::A::x"
        #
        # Fortunately, the full-name is simplified when entities are repeated.
-       # For the previous case, the simplest form is "p#A#x".
+       # For the previous case, the simplest form is "p$A$x".
        redef var full_name is lazy do
                var res = new FlatBuffer
 
-               # The first part is the mclassdef. Worst case is "r::o#q::n::B"
+               # The first part is the mclassdef. Worst case is "r::o$q::n::B"
                res.append mclassdef.full_name
 
-               res.append "#"
+               res.append "$"
 
                if mclassdef.mclass == mproperty.intro_mclassdef.mclass then
                        # intro are unambiguous in a class
@@ -2264,7 +2285,7 @@ abstract class MPropDef
                        # Just try to simplify each part
                        if mclassdef.mmodule.mpackage != mproperty.intro_mclassdef.mmodule.mpackage then
                                # precise "p::m" only if "p" != "r"
-                               res.append mproperty.intro_mclassdef.mmodule.full_name
+                               res.append mproperty.intro_mclassdef.mmodule.namespace_for(mproperty.visibility)
                                res.append "::"
                        else if mproperty.visibility <= private_visibility then
                                # Same package ("p"=="q"), but private visibility,
@@ -2309,8 +2330,8 @@ abstract class MPropDef
        redef fun model do return mclassdef.model
 
        # Internal name combining the module, the class and the property
-       # Example: "mymodule#MyClass#mymethod"
-       redef var to_s: String is noinit
+       # Example: "mymodule$MyClass$mymethod"
+       redef var to_s is noinit
 
        # Is self the definition that introduce the property?
        fun is_intro: Bool do return isset mproperty._intro and mproperty.intro == self
@@ -2413,7 +2434,7 @@ end
 # Note this class is basically an enum.
 # FIXME: use a real enum once user-defined enums are available
 class MClassKind
-       redef var to_s: String
+       redef var to_s
 
        # Is a constructor required?
        var need_init: Bool