Merge: Abstract attribute
[nit.git] / src / modelize / modelize_property.nit
index 35a50c3..a4d1141 100644 (file)
@@ -955,32 +955,31 @@ redef class AAttrPropdef
        redef fun build_property(modelbuilder, mclassdef)
        do
                var mclass = mclassdef.mclass
+               var nid2 = n_id2
+               var name = nid2.text
+
+               var atabstract = self.get_single_annotation("abstract", modelbuilder)
+               if atabstract == null then
+                       if mclass.kind == interface_kind then
+                               modelbuilder.error(self, "Error: Attempt to define attribute {name} in the interface {mclass}.")
+                       else if mclass.kind == enum_kind then
+                               modelbuilder.error(self, "Error: Attempt to define attribute {name} in the enum class {mclass}.")
+                       else if mclass.kind == extern_kind then
+                               modelbuilder.error(self, "Error: Attempt to define attribute {name} in the extern class {mclass}.")
+                       end
 
-               var name: String
-               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}.")
-               else if mclass.kind == enum_kind then
-                       modelbuilder.error(self, "Error: Attempt to define attribute {name} in the enum class {mclass}.")
-               else if mclass.kind == extern_kind then
-                       modelbuilder.error(self, "Error: Attempt to define attribute {name} in the extern class {mclass}.")
+                       var mprop = new MAttribute(mclassdef, "_" + name, private_visibility)
+                       var mpropdef = new MAttributeDef(mclassdef, mprop, self.location)
+                       self.mpropdef = mpropdef
+                       modelbuilder.mpropdef2npropdef[mpropdef] = self
                end
 
-               # 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
-
                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)
@@ -991,10 +990,16 @@ redef class AAttrPropdef
                self.mreadpropdef = mreadpropdef
                modelbuilder.mpropdef2npropdef[mreadpropdef] = self
                set_doc(mreadpropdef, modelbuilder)
-               mpropdef.mdoc = mreadpropdef.mdoc
+               if mpropdef != null then mpropdef.mdoc = mreadpropdef.mdoc
+               if atabstract != null then mreadpropdef.is_abstract = true
 
                has_value = n_expr != null or n_block != null
 
+               if atabstract != null and has_value then
+                       modelbuilder.error(atabstract, "Error: `abstract` attributes cannot have an initial value")
+                       return
+               end
+
                var atnoinit = self.get_single_annotation("noinit", modelbuilder)
                if atnoinit == null then atnoinit = self.get_single_annotation("noautoinit", modelbuilder)
                if atnoinit != null then
@@ -1003,6 +1008,10 @@ redef class AAttrPropdef
                                modelbuilder.error(atnoinit, "Error: `noautoinit` attributes cannot have an initial value")
                                return
                        end
+                       if atabstract != null then
+                               modelbuilder.error(atnoinit, "Error: `noautoinit` attributes cannot be abstract")
+                               return
+                       end
                end
 
                var atlazy = self.get_single_annotation("lazy", modelbuilder)
@@ -1054,7 +1063,7 @@ redef class AAttrPropdef
                        end
                        mwriteprop = new MMethod(mclassdef, writename, mvisibility)
                        if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then return
-                       mwriteprop.deprecation = mprop.deprecation
+                       mwriteprop.deprecation = mreadprop.deprecation
                else
                        if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef or else n_kwredef, true, mwriteprop) then return
                        if atwritable != null then
@@ -1066,18 +1075,19 @@ redef class AAttrPropdef
                var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
                self.mwritepropdef = mwritepropdef
                modelbuilder.mpropdef2npropdef[mwritepropdef] = self
-               mwritepropdef.mdoc = mpropdef.mdoc
+               mwritepropdef.mdoc = mreadpropdef.mdoc
+               if atabstract != null then mwritepropdef.is_abstract = true
        end
 
        redef fun build_signature(modelbuilder)
        do
+               var mreadpropdef = self.mreadpropdef
                var mpropdef = self.mpropdef
-               if mpropdef == null then return # Error thus skipped
-               var mclassdef = mpropdef.mclassdef
+               if mreadpropdef == null then return # Error thus skipped
+               var mclassdef = mreadpropdef.mclassdef
                var mmodule = mclassdef.mmodule
                var mtype: nullable MType = null
 
-               var mreadpropdef = self.mreadpropdef
 
                var ntype = self.n_type
                if ntype != null then
@@ -1087,7 +1097,7 @@ redef class AAttrPropdef
 
                var inherited_type: nullable MType = null
                # Inherit the type from the getter (usually an abstract getter)
-               if mreadpropdef != null and not mreadpropdef.is_intro then
+               if not mreadpropdef.is_intro then
                        var msignature = mreadpropdef.mproperty.intro.msignature
                        if msignature == null then return # Error, thus skipped
                        inherited_type = msignature.return_mtype
@@ -1122,7 +1132,7 @@ redef class AAttrPropdef
                                        var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
                                        if cla != null then mtype = cla.mclass_type
                                else
-                                       modelbuilder.error(self, "Error: Untyped attribute {mpropdef}. Implicit typing allowed only for literals and new.")
+                                       modelbuilder.error(self, "Error: Untyped attribute {mreadpropdef}. Implicit typing allowed only for literals and new.")
                                end
 
                                if mtype == null then return
@@ -1137,13 +1147,15 @@ redef class AAttrPropdef
                end
 
                if mtype == null then
-                       modelbuilder.error(self, "Error: Untyped attribute {mpropdef}")
+                       modelbuilder.error(self, "Error: Untyped attribute {mreadpropdef}")
                        return
                end
 
-               mpropdef.static_mtype = mtype
+               if mpropdef != null then
+                       mpropdef.static_mtype = mtype
+               end
 
-               if mreadpropdef != null then
+               do
                        var msignature = new MSignature(new Array[MParameter], mtype)
                        mreadpropdef.msignature = msignature
                end