X-Git-Url: http://nitlanguage.org diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index 4b1c129..28e6a03 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -82,8 +82,6 @@ redef class ModelBuilder # Are we a refinement if not mclassdef.is_intro then return - var mmodule = nclassdef.mclassdef.mmodule - # Look for the init in Object, or create it if mclassdef.mclass.name == "Object" and the_root_init_mmethod == null then # Create the implicit root-init method @@ -112,46 +110,38 @@ redef class ModelBuilder if mpropdef.mproperty.is_root_init then assert defined_init == null defined_init = mpropdef - else - # An explicit old-style init, so return + else if mpropdef.mproperty.name == "init" then + # An explicit old-style init named "init", so return return end end if not nclassdef isa AStdClassdef then return - # Do we inherit a old-style constructor? - var combine = new Array[MMethod] # old-style constructors without arguments - var inhc: nullable MClass = null # single super-class with a constructor with arguments - if defined_init == null then for st in mclassdef.supertypes do - var c = st.mclass - if not c.kind.need_init then continue - st = st.anchor_to(mmodule, mclassdef.bound_mtype) - var candidate = self.try_get_mproperty_by_name2(nclassdef, mmodule, st, "init").as(nullable MMethod) - if candidate != null then - if candidate.is_root_init then continue - if candidate.intro.msignature != null then - if candidate.intro.msignature.arity == 0 then - combine.add(candidate) - continue - end - end - end - var inhc2 = c.inherit_init_from - if inhc2 == null then inhc2 = c - if inhc2 == inhc then continue - if inhc != null then - self.error(nclassdef, "Error: Cannot provide a defaut constructor: conflict for {inhc} and {c}") - else - inhc = inhc2 - end - end - # Collect undefined attributes var mparameters = new Array[MParameter] var initializers = new Array[MProperty] - var anode: nullable ANode = null for npropdef in nclassdef.n_propdefs do + if npropdef isa AMethPropdef then + if npropdef.mpropdef == null then return # Skip broken attribute + var at = npropdef.get_single_annotation("autoinit", self) + if at == null then continue # Skip non tagged init + + var sig = npropdef.mpropdef.msignature + if sig == null then continue # Skip broken method + + if not npropdef.mpropdef.is_intro then + self.error(at, "Error: `autoinit` cannot be set on redefinitions") + continue + end + + for param in sig.mparameters do + var ret_type = param.mtype + var mparameter = new MParameter(param.name, ret_type, false) + mparameters.add(mparameter) + end + initializers.add(npropdef.mpropdef.mproperty) + end if npropdef isa AAttrPropdef then if npropdef.mpropdef == null then return # Skip broken attribute var at = npropdef.get_single_annotation("noinit", self) @@ -176,49 +166,12 @@ redef class ModelBuilder # Add the setter to the list initializers.add(msetter.mproperty) end - if anode == null then anode = npropdef end end - if anode == null then anode = nclassdef - - if combine.is_empty and inhc != null then - if not mparameters.is_empty then - self.error(anode,"Error: {mclassdef} cannot inherit constructors from {inhc} because there is attributes without initial values: {mparameters.join(", ")}") - return - end - - # TODO: actively inherit the consturctor - self.toolcontext.info("{mclassdef} inherits all constructors from {inhc}", 3) - #mclassdef.mclass.inherit_init_from = inhc - #return - end - - if not combine.is_empty and inhc != null then - self.error(nclassdef, "Error: Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}") - return - end - if not combine.is_empty then - if mparameters.is_empty and combine.length == 1 then - # No need to create a local init, the inherited one is enough - inhc = combine.first.intro_mclassdef.mclass - mclassdef.mclass.inherit_init_from = inhc - self.toolcontext.info("{mclassdef} inherits all constructors from {inhc}", 3) - return - end - nclassdef.super_inits = combine - var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility) - var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location) - var msignature = new MSignature(mparameters, null) - mpropdef.msignature = msignature - mprop.is_init = true - nclassdef.mfree_init = mpropdef - self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3) - return - end if the_root_init_mmethod == null then return - # Look for nost-specific new-stype init definitions + # Look for most-specific new-stype init definitions var spropdefs = the_root_init_mmethod.lookup_super_definitions(mclassdef.mmodule, mclassdef.bound_mtype) if spropdefs.is_empty then toolcontext.fatal_error(nclassdef.location, "Fatal error: {mclassdef} does not specialize {the_root_init_mmethod.intro_mclassdef}. Possible duplication of the root class `Object`?") @@ -328,23 +281,14 @@ redef class ModelBuilder end end -redef class MClass - # The class whose self inherit all the constructors. - # FIXME: this is needed to implement the crazy constructor mixin thing of the of old compiler. We need to think what to do with since this cannot stay in the modelbuilder - var inherit_init_from: nullable MClass = null -end - redef class MPropDef # Does the MPropDef contains a call to super or a call of a super-constructor? # Subsequent phases of the frontend (esp. typing) set it if required - var has_supercall: Bool writable = false + var has_supercall: Bool = false is writable end redef class AClassdef var build_properties_is_done: Bool = false - # The list of super-constructor to call at the start of the free constructor - # FIXME: this is needed to implement the crazy constructor thing of the of old compiler. We need to think what to do with since this cannot stay in the modelbuilder - var super_inits: nullable Collection[MMethod] = null # The free init (implicitely constructed by the class if required) var mfree_init: nullable MMethodDef = null @@ -383,7 +327,7 @@ redef class APropdef type MPROPDEF: MPropDef # The associated propdef once build by a `ModelBuilder` - var mpropdef: nullable MPROPDEF writable + var mpropdef: nullable MPROPDEF is writable private fun build_property(modelbuilder: ModelBuilder, mclassdef: MClassDef) is abstract private fun build_signature(modelbuilder: ModelBuilder) is abstract @@ -404,8 +348,7 @@ redef class APropdef modelbuilder.error(nvisibility, "Error: The only legal visibility for properties in a private class is private.") else if mvisibility == private_visibility then assert nvisibility != null - # Not yet - # modelbuilder.warning(nvisibility, "Warning: private is unrequired since the only legal visibility for properties in a private class is private.") + modelbuilder.advice(nvisibility, "useless-visibility", "Warning: private is superfluous since the only legal visibility for properties in a private class is private.") end mvisibility = private_visibility end @@ -419,6 +362,8 @@ redef class APropdef var mdoc = ndoc.to_mdoc mpropdef.mdoc = mdoc mdoc.original_mentity = mpropdef + else if mpropdef.is_intro and mpropdef.mproperty.visibility >= protected_visibility then + modelbuilder.advice(self, "missing-doc", "Documentation warning: Undocumented property `{mpropdef.mproperty}`") end var at_deprecated = get_single_annotation("deprecated", modelbuilder) @@ -616,6 +561,10 @@ redef class AMethPropdef 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 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 + modelbuilder.advice(self, "useless-init", "Warning: useless empty init in {mclassdef}") + end end if mprop == null then var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) @@ -724,9 +673,9 @@ redef class AMethPropdef msignature = new MSignature(mparameters, ret_type) mpropdef.msignature = msignature - mpropdef.is_abstract = self isa ADeferredMethPropdef - mpropdef.is_intern = self isa AInternMethPropdef - mpropdef.is_extern = self isa AExternPropdef + mpropdef.is_abstract = self.get_single_annotation("abstract", modelbuilder) != null + mpropdef.is_intern = self.get_single_annotation("intern", modelbuilder) != null + mpropdef.is_extern = self.n_extern_code_block != null or self.get_single_annotation("extern", modelbuilder) != null end redef fun check_signature(modelbuilder) @@ -801,20 +750,16 @@ redef class AAttrPropdef var mlazypropdef: nullable MAttributeDef # The associated getter (read accessor) if any - var mreadpropdef: nullable MMethodDef writable + var mreadpropdef: nullable MMethodDef is writable # The associated setter (write accessor) if any - var mwritepropdef: nullable MMethodDef writable + var mwritepropdef: nullable MMethodDef is writable redef fun build_property(modelbuilder, mclassdef) do var mclass = mclassdef.mclass var name: String - if self.n_id != null then - name = self.n_id.text - else - name = self.n_id2.text - end + name = self.n_id2.text if mclass.kind == interface_kind or mclassdef.mclass.kind == enum_kind then modelbuilder.error(self, "Error: Attempt to define attribute {name} in the interface {mclass}.") @@ -824,116 +769,84 @@ redef class AAttrPropdef modelbuilder.error(self, "Error: Attempt to define attribute {name} in the extern class {mclass}.") end - var nid = self.n_id - if nid != null then - # Old attribute style - var mprop = modelbuilder.try_get_mproperty_by_name(nid, mclassdef, name) - if mprop == null then - var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) - mprop = new MAttribute(mclassdef, name, mvisibility) - if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, false, mprop) then return - else - assert mprop isa MAttribute - check_redef_property_visibility(modelbuilder, self.n_visibility, mprop) - if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, true, mprop) then return - end - mclassdef.mprop2npropdef[mprop] = self - - var mpropdef = new MAttributeDef(mclassdef, mprop, self.location) - self.mpropdef = mpropdef - modelbuilder.mpropdef2npropdef[mpropdef] = self - set_doc(mpropdef, modelbuilder) + # New attribute style + var nid2 = self.n_id2 + var mprop = new MAttribute(mclassdef, "_" + name, private_visibility) + var mpropdef = new MAttributeDef(mclassdef, mprop, self.location) + self.mpropdef = mpropdef + modelbuilder.mpropdef2npropdef[mpropdef] = self + set_doc(mpropdef, modelbuilder) - var nreadable = self.n_readable - if nreadable != null then modelbuilder.error(nreadable, "Error: old-style getter no more supported") - var nwritable = self.n_writable - if nwritable != null then modelbuilder.error(nwritable, "Error: old-style setter no more supported") + var readname = name + var mreadprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, readname).as(nullable MMethod) + if mreadprop == null then + var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) + mreadprop = new MMethod(mclassdef, readname, mvisibility) + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then return + mreadprop.deprecation = mprop.deprecation else - # New attribute style - var nid2 = self.n_id2.as(not null) - var mprop = new MAttribute(mclassdef, "_" + name, private_visibility) - var mpropdef = new MAttributeDef(mclassdef, mprop, self.location) - self.mpropdef = mpropdef - modelbuilder.mpropdef2npropdef[mpropdef] = self - set_doc(mpropdef, modelbuilder) - - var readname = name - var mreadprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, readname).as(nullable MMethod) - if mreadprop == null then - var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) - mreadprop = new MMethod(mclassdef, readname, mvisibility) - if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then return - mreadprop.deprecation = mprop.deprecation - else - if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, true, mreadprop) then return - check_redef_property_visibility(modelbuilder, self.n_visibility, mreadprop) - end - mclassdef.mprop2npropdef[mreadprop] = self + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, true, mreadprop) then return + check_redef_property_visibility(modelbuilder, self.n_visibility, mreadprop) + end + mclassdef.mprop2npropdef[mreadprop] = self - var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location) - self.mreadpropdef = mreadpropdef - modelbuilder.mpropdef2npropdef[mreadpropdef] = self - mreadpropdef.mdoc = mpropdef.mdoc + var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location) + self.mreadpropdef = mreadpropdef + modelbuilder.mpropdef2npropdef[mreadpropdef] = self + mreadpropdef.mdoc = mpropdef.mdoc - var atlazy = self.get_single_annotation("lazy", modelbuilder) - if atlazy != null then - if n_expr == null then - modelbuilder.error(atlazy, "Error: a lazy attribute needs a value") - end - is_lazy = true - var mlazyprop = new MAttribute(mclassdef, "lazy _" + name, none_visibility) - var mlazypropdef = new MAttributeDef(mclassdef, mlazyprop, self.location) - self.mlazypropdef = mlazypropdef + var atlazy = self.get_single_annotation("lazy", modelbuilder) + if atlazy != null then + if n_expr == null then + modelbuilder.error(atlazy, "Error: a lazy attribute needs a value") end + is_lazy = true + var mlazyprop = new MAttribute(mclassdef, "lazy _" + name, none_visibility) + var mlazypropdef = new MAttributeDef(mclassdef, mlazyprop, self.location) + self.mlazypropdef = mlazypropdef + end - var atreadonly = self.get_single_annotation("readonly", modelbuilder) - if atreadonly != null then - if n_expr == null then - modelbuilder.error(atreadonly, "Error: a readonly attribute needs a value") - end - # No setter, so just leave - return + var atreadonly = self.get_single_annotation("readonly", modelbuilder) + if atreadonly != null then + if n_expr == null then + modelbuilder.error(atreadonly, "Error: a readonly attribute needs a value") end + # No setter, so just leave + return + end - var writename = name + "=" - var nwritable = self.n_writable - var atwritable = self.get_single_annotation("writable", modelbuilder) - if atwritable != null then - if not atwritable.n_args.is_empty then - writename = atwritable.arg_as_id(modelbuilder) or else writename - end + var writename = name + "=" + var atwritable = self.get_single_annotation("writable", modelbuilder) + if atwritable != null then + if not atwritable.n_args.is_empty then + writename = atwritable.arg_as_id(modelbuilder) or else writename end - var mwriteprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, writename).as(nullable MMethod) - var nwkwredef: nullable Token = null - if nwritable != null then nwkwredef = nwritable.n_kwredef - if atwritable != null then nwkwredef = atwritable.n_kwredef - if mwriteprop == null then - var mvisibility - if nwritable != null then - mvisibility = new_property_visibility(modelbuilder, mclassdef, nwritable.n_visibility) - else if atwritable != null then - mvisibility = new_property_visibility(modelbuilder, mclassdef, atwritable.n_visibility) - else - mvisibility = private_visibility - end - mwriteprop = new MMethod(mclassdef, writename, mvisibility) - if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then return - mwriteprop.deprecation = mprop.deprecation + end + var mwriteprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, writename).as(nullable MMethod) + var nwkwredef: nullable Token = null + if atwritable != null then nwkwredef = atwritable.n_kwredef + if mwriteprop == null then + var mvisibility + if atwritable != null then + mvisibility = new_property_visibility(modelbuilder, mclassdef, atwritable.n_visibility) else - if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef or else n_kwredef, true, mwriteprop) then return - if nwritable != null then - check_redef_property_visibility(modelbuilder, nwritable.n_visibility, mwriteprop) - else if atwritable != null then - check_redef_property_visibility(modelbuilder, atwritable.n_visibility, mwriteprop) - end + mvisibility = private_visibility + end + mwriteprop = new MMethod(mclassdef, writename, mvisibility) + if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then return + mwriteprop.deprecation = mprop.deprecation + else + if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef or else n_kwredef, true, mwriteprop) then return + if atwritable != null then + check_redef_property_visibility(modelbuilder, atwritable.n_visibility, mwriteprop) end - mclassdef.mprop2npropdef[mwriteprop] = self - - var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location) - self.mwritepropdef = mwritepropdef - modelbuilder.mpropdef2npropdef[mwritepropdef] = self - mwritepropdef.mdoc = mpropdef.mdoc end + mclassdef.mprop2npropdef[mwriteprop] = self + + var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location) + self.mwritepropdef = mwritepropdef + modelbuilder.mpropdef2npropdef[mwritepropdef] = self + mwritepropdef.mdoc = mpropdef.mdoc end redef fun build_signature(modelbuilder) @@ -991,8 +904,8 @@ redef class AAttrPropdef else if ntype != null then if nexpr isa ANewExpr then var xmtype = modelbuilder.resolve_mtype(mmodule, mclassdef, nexpr.n_type) - if xmtype == mtype and modelbuilder.toolcontext.opt_warn.value >= 2 then - modelbuilder.warning(ntype, "Warning: useless type definition") + if xmtype == mtype then + modelbuilder.advice(ntype, "useless-type", "Warning: useless type definition") end end end @@ -1012,11 +925,7 @@ redef class AAttrPropdef var mwritepropdef = self.mwritepropdef if mwritepropdef != null then var name: String - if n_id != null then - name = n_id.text.substring_from(1) - else - name = n_id2.text - end + name = n_id2.text var mparameter = new MParameter(name, mtype, false) var msignature = new MSignature([mparameter], null) mwritepropdef.msignature = msignature @@ -1134,7 +1043,7 @@ redef class ATypePropdef var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) mprop = new MVirtualTypeProp(mclassdef, name, mvisibility) for c in name.chars do if c >= 'a' and c<= 'z' then - modelbuilder.warning(n_id, "Warning: lowercase in the virtual type {name}") + modelbuilder.warning(n_id, "bad-type-name", "Warning: lowercase in the virtual type {name}") break end if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, false, mprop) then return @@ -1213,7 +1122,7 @@ redef class ATypePropdef end if p.mclassdef.mclass == mclassdef.mclass then # Still a warning to pass existing bad code - modelbuilder.warning(n_type, "Redef Error: a virtual type cannot be refined.") + modelbuilder.warning(n_type, "refine-type", "Redef Error: a virtual type cannot be refined.") break end if not bound.is_subtype(mmodule, anchor, supbound) then