build_properties(mclassdef2nclassdef[superclassdef])
end
+ mclassdef.build_self_type(self, nclassdef)
for nclassdef2 in nclassdef.all_defs do
for npropdef in nclassdef2.n_propdefs do
npropdef.build_property(self, mclassdef)
# What is the `APropdef` associated to a `MProperty`?
# Used to check multiple definition of a property.
var mprop2npropdef: Map[MProperty, APropdef] = new HashMap[MProperty, APropdef]
+
+ # Build the virtual type `SELF` only for introduction `MClassDef`
+ fun build_self_type(modelbuilder: ModelBuilder, nclassdef: AClassdef)
+ do
+ if not is_intro then return
+
+ var name = "SELF"
+ var mprop = modelbuilder.try_get_mproperty_by_name(nclassdef, self, name)
+
+ # If SELF type is declared nowherer?
+ if mprop == null then return
+
+ # SELF is not a virtual type? it is weird but we ignore it
+ if not mprop isa MVirtualTypeProp then return
+
+ # Is this the intro of SELF in the library?
+ var intro = mprop.intro
+ var intro_mclassdef = intro.mclassdef
+ if intro_mclassdef == self then
+ var nintro = modelbuilder.mpropdef2npropdef[intro]
+
+ # SELF must be declared in Object, otherwise this will create conflicts
+ if intro_mclassdef.mclass.name != "Object" then
+ modelbuilder.error(nintro, "Error: the virtual type SELF must be declared in Object.")
+ end
+
+ # SELF must be public
+ if mprop.visibility != public_visibility then
+ modelbuilder.error(nintro, "Error: the virtual type SELF must be public.")
+ end
+
+ # SELF must not be fixed
+ if intro.is_fixed then
+ modelbuilder.error(nintro, "Error: the virtual type SELF cannot be fixed.")
+ end
+
+ return
+ end
+
+ # This class introduction inherits a SELF
+ # We insert an artificial property to update it
+ var mpropdef = new MVirtualTypeDef(self, mprop, self.location)
+ mpropdef.bound = mclass.mclass_type
+ end
end
redef class APropdef
# Can self be used as a root init?
- private fun look_like_a_root_init(modelbuilder: ModelBuilder): Bool
+ private fun look_like_a_root_init(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool
do
# Need the `init` keyword
if n_kwinit == null then return false
# Need to by anonymous
if self.n_methid != null then return false
- # No parameters
- if self.n_signature.n_params.length > 0 then return false
- # Cannot be private or something
- if not self.n_visibility isa APublicVisibility then return false
# No annotation on itself
if get_single_annotation("old_style_init", modelbuilder) != null then return false
# Nor on its module
var old = amoddecl.get_single_annotation("old_style_init", modelbuilder)
if old != null then return false
end
+ # No parameters
+ if self.n_signature.n_params.length > 0 then
+ modelbuilder.advice(self, "old-init", "Warning: init with signature in {mclassdef}")
+ return false
+ end
+ # Cannot be private or something
+ if not self.n_visibility isa APublicVisibility then
+ modelbuilder.advice(self, "old-init", "Warning: non-public init in {mclassdef}")
+ return false
+ end
return true
end
end
end
+ var look_like_a_root_init = look_like_a_root_init(modelbuilder, mclassdef)
var mprop: nullable MMethod = null
if not is_init or n_kwredef != null then mprop = modelbuilder.try_get_mproperty_by_name(name_node, mclassdef, name).as(nullable MMethod)
- if mprop == null and look_like_a_root_init(modelbuilder) then
+ if mprop == null and look_like_a_root_init then
mprop = modelbuilder.the_root_init_mmethod
var nb = n_block
if nb isa ABlockExpr and nb.n_expr.is_empty and n_doc == null then
if mprop == null then
var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
mprop = new MMethod(mclassdef, name, mvisibility)
- if look_like_a_root_init(modelbuilder) and modelbuilder.the_root_init_mmethod == null then
+ if look_like_a_root_init and modelbuilder.the_root_init_mmethod == null then
modelbuilder.the_root_init_mmethod = mprop
mprop.is_root_init = true
end
self.mpropdef = mpropdef
modelbuilder.mpropdef2npropdef[mpropdef] = self
if mpropdef.is_intro then
- modelbuilder.toolcontext.info("{mpropdef} introduces new method {mprop.full_name}", 3)
+ modelbuilder.toolcontext.info("{mpropdef} introduces new method {mprop.full_name}", 4)
else
- modelbuilder.toolcontext.info("{mpropdef} redefines method {mprop.full_name}", 3)
+ modelbuilder.toolcontext.info("{mpropdef} redefines method {mprop.full_name}", 4)
end
end