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
if name == "Bool" and self.model.get_mclasses_by_name("Object") != null then
# Bool is injected because it is needed by engine to code the result
# of the implicit casts.
- var c = new MClass(self, name, null, enum_kind, public_visibility)
- var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0))
+ var loc = model.no_location
+ var c = new MClass(self, name, loc, null, enum_kind, public_visibility)
+ var cladef = new MClassDef(self, c.mclass_type, loc)
cladef.set_supertypes([object_type])
cladef.add_in_hierarchy
return c
var props = self.model.get_mproperties_by_name(name)
if props == null then return null
var res: nullable MMethod = null
+ var recvtype = recv.intro.bound_mtype
for mprop in props do
assert mprop isa MMethod
- var intro = mprop.intro_mclassdef
- for mclassdef in recv.mclassdefs do
- if not self.in_importation.greaters.has(mclassdef.mmodule) then continue
- if not mclassdef.in_hierarchy.greaters.has(intro) then continue
- if res == null then
- res = mprop
- else if res != mprop then
- print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
- abort
- end
+ if not recvtype.has_mproperty(self, mprop) then continue
+ if res == null then
+ res = mprop
+ else if res != mprop then
+ print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
+ abort
end
end
return res
# 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
#
# 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
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
redef fun model do return self.mclass.intro_mmodule.model
+ redef fun location do return mclass.location
+
# TODO: private init because strongly bounded to its mclass. see `mclass.mclass_type`
# The formal arguments of the type
# 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]]"`
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
# Its the definitions of this property that determine the bound or the virtual type.
var mproperty: MVirtualTypeProp
+ redef fun location do return mproperty.location
+
redef fun model do return self.mproperty.intro_mclassdef.mmodule.model
redef fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
redef fun model do return self.mclass.intro_mmodule.model
+ redef fun location do return mclass.location
+
# The position of the parameter (0 for the first parameter)
# FIXME: is `position` a better name?
var rank: Int
# The base type
var mtype: MType
+ redef fun location do return mtype.location
+
redef fun model do return self.mtype.model
redef fun need_anchor do return mtype.need_anchor
redef fun as_nullable do return mtype.as_nullable
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}"
# 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"
# 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"
super MEntity
# The name of the parameter
- redef var name: String
+ redef var name
# The static type of the parameter
var mtype: MType
var intro_mclassdef: MClassDef
# The (short) name of the property
- redef var name: String
+ redef var name
+
+ redef var location
# 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
# The associated global property
var mproperty: MPROPERTY
- # The origin of the definition
- var location: Location
+ redef var location: Location
init
do
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`
# * 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
# 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,
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
# 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