ni: fix imported classes list in module view
[nit.git] / src / modelbuilder.nit
index a55f02e..3f39d6d 100644 (file)
@@ -381,6 +381,7 @@ class ModelBuilder
        private fun build_module_importation(nmodule: AModule)
        do
                if nmodule.is_importation_done then return
+               nmodule.is_importation_done = true
                var mmodule = nmodule.mmodule.as(not null)
                var stdimport = true
                var imported_modules = new Array[MModule]
@@ -406,7 +407,6 @@ class ModelBuilder
                end
                self.toolcontext.info("{mmodule} imports {imported_modules.join(", ")}", 3)
                mmodule.set_imported_mmodules(imported_modules)
-               nmodule.is_importation_done = true
        end
 
        # All the loaded modules
@@ -458,6 +458,9 @@ class ModelBuilder
                if mclass == null then
                        mclass = new MClass(mmodule, name, arity, mkind, mvisibility)
                        #print "new class {mclass}"
+               else if nclassdef isa AStdClassdef and nmodule.mclass2nclassdef.has_key(mclass) then
+                       error(nclassdef, "Error: A class {name} is already defined at line {nmodule.mclass2nclassdef[mclass].location.line_start}.")
+                       return
                else if nclassdef isa AStdClassdef and nclassdef.n_kwredef == null then
                        error(nclassdef, "Redef error: {name} is an imported class. Add the redef keyword to refine it.")
                        return
@@ -470,6 +473,7 @@ class ModelBuilder
                        error(nvisibility, "Error: refinement changed the visibility from a {mclass.visibility} to a {mvisibility}")
                end
                nclassdef.mclass = mclass
+               nmodule.mclass2nclassdef[mclass] = nclassdef
        end
 
        # Visit the AST and create the MClassDef objects
@@ -477,7 +481,8 @@ class ModelBuilder
        do
                var mmodule = nmodule.mmodule.as(not null)
                var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
-               var mclass = nclassdef.mclass.as(not null)
+               var mclass = nclassdef.mclass
+               if mclass == null then return # Skip error
                #var mclassdef = nclassdef.mclassdef.as(not null)
 
                var names = new Array[String]
@@ -499,7 +504,7 @@ class ModelBuilder
                                var nfd = nclassdef.n_formaldefs[i]
                                var nfdt = nfd.n_type
                                if nfdt != null then
-                                       var bound = resolve_mtype(nclassdef, nfdt)
+                                       var bound = resolve_mtype_unchecked(nclassdef, nfdt)
                                        if bound == null then return # Forward error
                                        if bound.need_anchor then
                                                # No F-bounds!
@@ -512,7 +517,7 @@ class ModelBuilder
                                        bounds.add(objectclass.mclass_type.as_nullable)
                                else
                                        # Inherit the bound
-                                       bounds.add(mclass.mclassdefs.first.bound_mtype.as(MGenericType).arguments[i])
+                                       bounds.add(mclass.intro.bound_mtype.arguments[i])
                                end
                        end
                end
@@ -529,8 +534,8 @@ class ModelBuilder
                end
        end
 
-       # Visit the AST and set the super-types of the MClass objects (ie compute the inheritance)
-       private fun build_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
+       # Visit the AST and set the super-types of the MClassdef objects
+       private fun collect_a_mclassdef_inheritance(nmodule: AModule, nclassdef: AClassdef)
        do
                var mmodule = nmodule.mmodule.as(not null)
                var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
@@ -543,7 +548,7 @@ class ModelBuilder
                        for nsc in nclassdef.n_superclasses do
                                specobject = false
                                var ntype = nsc.n_type
-                               var mtype = resolve_mtype(nclassdef, ntype)
+                               var mtype = resolve_mtype_unchecked(nclassdef, ntype)
                                if mtype == null then continue # Skip because of error
                                if not mtype isa MClassType then
                                        error(ntype, "Error: supertypes cannot be a formal type")
@@ -562,13 +567,18 @@ class ModelBuilder
        end
 
        # Check the validity of the specialization heirarchy
-       # FIXME Stub implementation
        private fun check_supertypes(nmodule: AModule, nclassdef: AClassdef)
        do
                var mmodule = nmodule.mmodule.as(not null)
                var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
                var mclass = nclassdef.mclass.as(not null)
                var mclassdef = nclassdef.mclassdef.as(not null)
+
+               for s in mclassdef.supertypes do
+                       if s.is_subtype(mmodule, mclassdef.bound_mtype, mclassdef.bound_mtype) then
+                               error(nclassdef, "Error: Inheritance loop for class {mclass} with type {s}")
+                       end
+               end
        end
 
        # Build the classes of the module `nmodule'.
@@ -577,8 +587,10 @@ class ModelBuilder
        do
                # Force building recursively
                if nmodule.build_classes_is_done then return
+               nmodule.build_classes_is_done = true
                var mmodule = nmodule.mmodule.as(not null)
                for imp in mmodule.in_importation.direct_greaters do
+
                        build_classes(mmodule2nmodule[imp])
                end
 
@@ -592,9 +604,47 @@ class ModelBuilder
                        self.build_a_mclassdef(nmodule, nclassdef)
                end
 
+               for nclassdef in nmodule.n_classdefs do
+                       if nclassdef.mclassdef == null then return # forward error
+               end
+
                # Create inheritance on all classdefs
                for nclassdef in nmodule.n_classdefs do
-                       self.build_a_mclassdef_inheritance(nmodule, nclassdef)
+                       self.collect_a_mclassdef_inheritance(nmodule, nclassdef)
+               end
+
+               # Create the mclassdef hierarchy
+               for nclassdef in nmodule.n_classdefs do
+                       var mclassdef = nclassdef.mclassdef.as(not null)
+                       mclassdef.add_in_hierarchy
+               end
+
+               # Check inheritance
+               for nclassdef in nmodule.n_classdefs do
+                       self.check_supertypes(nmodule, nclassdef)
+               end
+
+               # Check unchecked ntypes
+               for nclassdef in nmodule.n_classdefs do
+                       if nclassdef isa AStdClassdef then
+                               # check bound of formal parameter
+                               for nfd in  nclassdef.n_formaldefs do
+                                       var nfdt = nfd.n_type
+                                       if nfdt != null and nfdt.mtype != null then
+                                               var bound = resolve_mtype(nclassdef, nfdt)
+                                               if bound == null then return # Forward error
+                                       end
+                               end
+                               # check declared super types
+                               for nsc in nclassdef.n_superclasses do
+                                       var ntype = nsc.n_type
+                                       if ntype.mtype != null then
+                                               var mtype = resolve_mtype(nclassdef, ntype)
+                                               if mtype == null then return # Forward error
+                                       end
+                               end
+                       end
+
                end
 
                # TODO: Check that the super-class is not intrusive
@@ -604,8 +654,6 @@ class ModelBuilder
                for nclassdef in nmodule.n_classdefs do
                        self.build_properties(nclassdef)
                end
-
-               nmodule.build_classes_is_done = true
        end
 
        # Register the nmodule associated to each mmodule
@@ -624,6 +672,7 @@ class ModelBuilder
        do
                # Force building recursively
                if nclassdef.build_properties_is_done then return
+               nclassdef.build_properties_is_done = true
                var mclassdef = nclassdef.mclassdef.as(not null)
                if mclassdef.in_hierarchy == null then return # Skip error
                for superclassdef in mclassdef.in_hierarchy.direct_greaters do
@@ -640,7 +689,6 @@ class ModelBuilder
                        npropdef.check_signature(self, nclassdef)
                end
                process_default_constructors(nclassdef)
-               nclassdef.build_properties_is_done = true
        end
 
        # Introduce or inherit default constructor
@@ -680,7 +728,7 @@ class ModelBuilder
                        if inhc2 == null then inhc2 = c
                        if inhc2 == inhc then continue
                        if inhc != null then
-                               self.error(nclassdef, "Cannot provide a defaut constructor: conflict for {inhc} and {c}")
+                               self.error(nclassdef, "Error: Cannot provide a defaut constructor: conflict for {inhc} and {c}")
                        else
                                inhc = inhc2
                        end
@@ -692,7 +740,7 @@ class ModelBuilder
                        return
                end
                if not combine.is_empty and inhc != null then
-                       self.error(nclassdef, "Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}")
+                       self.error(nclassdef, "Error: Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}")
                        return
                end
 
@@ -700,9 +748,8 @@ class ModelBuilder
                        nclassdef.super_inits = combine
                        var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
                        var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
-                       var param_names = new Array[String]
-                       var param_types = new Array[MType]
-                       var msignature = new MSignature(param_names, param_types, null, -1)
+                       var mparameters = new Array[MParameter]
+                       var msignature = new MSignature(mparameters, null)
                        mpropdef.msignature = msignature
                        mprop.is_init = true
                        nclassdef.mfree_init = mpropdef
@@ -711,20 +758,21 @@ class ModelBuilder
                end
 
                # Collect undefined attributes
-               var param_names = new Array[String]
-               var param_types = new Array[MType]
+               var mparameters = new Array[MParameter]
                for npropdef in nclassdef.n_propdefs do
                        if npropdef isa AAttrPropdef and npropdef.n_expr == null then
-                               param_names.add(npropdef.mpropdef.mproperty.name.substring_from(1))
+                               if npropdef.mpropdef == null then return # Skip broken attribute
+                               var paramname = npropdef.mpropdef.mproperty.name.substring_from(1)
                                var ret_type = npropdef.mpropdef.static_mtype
                                if ret_type == null then return
-                               param_types.add(ret_type)
+                               var mparameter = new MParameter(paramname, ret_type, false)
+                               mparameters.add(mparameter)
                        end
                end
 
                var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
                var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
-               var msignature = new MSignature(param_names, param_types, null, -1)
+               var msignature = new MSignature(mparameters, null)
                mpropdef.msignature = msignature
                mprop.is_init = true
                nclassdef.mfree_init = mpropdef
@@ -736,7 +784,7 @@ class ModelBuilder
        # The mmodule used as context is `nclassdef.mmodule'
        # In case of problem, an error is displayed on `ntype' and null is returned.
        # FIXME: the name "resolve_mtype" is awful
-       fun resolve_mtype(nclassdef: AClassdef, ntype: AType): nullable MType
+       fun resolve_mtype_unchecked(nclassdef: AClassdef, ntype: AType): nullable MType
        do
                var name = ntype.n_id.text
                var mclassdef = nclassdef.mclassdef
@@ -752,6 +800,7 @@ class ModelBuilder
                                end
                                res = prop.mvirtualtype
                                if ntype.n_kwnullable != null then res = res.as_nullable
+                               ntype.mtype = res
                                return res
                        end
                end
@@ -763,8 +812,9 @@ class ModelBuilder
                        end
                        for i in [0..mclassdef.parameter_names.length[ do
                                if mclassdef.parameter_names[i] == name then
-                                       res = mclassdef.mclass.mclass_type.as(MGenericType).arguments[i]
+                                       res = mclassdef.mclass.mclass_type.arguments[i]
                                        if ntype.n_kwnullable != null then res = res.as_nullable
+                                       ntype.mtype = res
                                        return res
                                end
                        end
@@ -788,16 +838,18 @@ class ModelBuilder
                        if arity == 0 then
                                res = mclass.mclass_type
                                if ntype.n_kwnullable != null then res = res.as_nullable
+                               ntype.mtype = res
                                return res
                        else
                                var mtypes = new Array[MType]
                                for nt in ntype.n_types do
-                                       var mt = resolve_mtype(nclassdef, nt)
+                                       var mt = resolve_mtype_unchecked(nclassdef, nt)
                                        if mt == null then return null # Forward error
                                        mtypes.add(mt)
                                end
                                res = mclass.get_mtype(mtypes)
                                if ntype.n_kwnullable != null then res = res.as_nullable
+                               ntype.mtype = res
                                return res
                        end
                end
@@ -807,6 +859,37 @@ class ModelBuilder
                return null
        end
 
+       # Return the static type associated to the node `ntype'.
+       # `classdef' is the context where the call is made (used to understand formal types)
+       # The mmodule used as context is `nclassdef.mmodule'
+       # In case of problem, an error is displayed on `ntype' and null is returned.
+       # FIXME: the name "resolve_mtype" is awful
+       fun resolve_mtype(nclassdef: AClassdef, ntype: AType): nullable MType
+       do
+               var mtype = ntype.mtype
+               if mtype == null then mtype = resolve_mtype_unchecked(nclassdef, ntype)
+               if mtype == null then return null # Forward error
+
+               if ntype.checked_mtype then return mtype
+               if mtype isa MGenericType then
+                       var mmodule = nclassdef.parent.as(AModule).mmodule.as(not null)
+                       var mclassdef = nclassdef.mclassdef
+                       var mclass = mtype.mclass
+                       for i in [0..mclass.arity[ do
+                               var bound = mclass.intro.bound_mtype.arguments[i]
+                               var nt = ntype.n_types[i]
+                               var mt = resolve_mtype(nclassdef, nt)
+                               if mt == null then return null # forward error
+                               if not mt.is_subtype(mmodule, mclassdef.bound_mtype, bound) then
+                                       error(nt, "Type error: expected {bound}, got {mt}")
+                                       return null
+                               end
+                       end
+               end
+               ntype.checked_mtype = true
+               return mtype
+       end
+
        # Helper function to display an error on a node.
        # Alias for `self.toolcontext.error(n.hot_location, text)'
        fun error(n: ANode, text: String)
@@ -820,6 +903,17 @@ class ModelBuilder
        do
                self.toolcontext.warning(n.hot_location, text)
        end
+
+       # Force to get the primitive method named `name' on the type `recv' or do a fatal error on `n'
+       fun force_get_primitive_method(n: ANode, name: String, recv: MType, mmodule: MModule): MMethod
+       do
+               var res = mmodule.try_get_primitive_method(name, recv)
+               if res == null then
+                       self.toolcontext.fatal_error(n.hot_location, "Fatal Error: {recv} must have a property named {name}.")
+                       abort
+               end
+               return res
+       end
 end
 
 redef class AModule
@@ -829,6 +923,10 @@ redef class AModule
        var is_importation_done: Bool = false
        # Flag that indicate if the class and prop building is already completed
        var build_classes_is_done: Bool = false
+       # What is the AClassdef associated to a MClass?
+       # Used to check multiple definition of a class.
+       var mclass2nclassdef: Map[MClass, AClassdef] = new HashMap[MClass, AClassdef]
+
 end
 
 redef class MClass
@@ -849,6 +947,10 @@ redef class AClassdef
 
        # The free init (implicitely constructed by the class if required)
        var mfree_init: nullable MMethodDef = null
+
+       # 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]
 end
 
 redef class AClasskind
@@ -888,6 +990,13 @@ redef class APrivateVisibility
        redef fun mvisibility do return private_visibility
 end
 
+redef class AType
+       # The mtype associated to the node
+       var mtype: nullable MType = null
+
+       # Is the mtype a valid one?
+       var checked_mtype: Bool = false
+end
 
 #
 
@@ -950,17 +1059,98 @@ redef class APropdef
                end
        end
 
-       private fun check_redef_keyword(modelbuilder: ModelBuilder, nclassdef: AClassdef, kwredef: nullable Token, need_redef: Bool, mprop: MProperty)
+       private fun check_redef_keyword(modelbuilder: ModelBuilder, nclassdef: AClassdef, kwredef: nullable Token, need_redef: Bool, mprop: MProperty): Bool
        do
+               if nclassdef.mprop2npropdef.has_key(mprop) then
+                       modelbuilder.error(self, "Error: A property {mprop} is already defined in class {nclassdef.mclassdef.mclass}.")
+                       return false
+               end
                if kwredef == null then
                        if need_redef then
                                modelbuilder.error(self, "Redef error: {nclassdef.mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.")
+                               return false
                        end
                else
                        if not need_redef then
                                modelbuilder.error(self, "Error: No property {nclassdef.mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.")
+                               return false
+                       end
+               end
+               return true
+       end
+
+end
+
+redef class ASignature
+       # Is the model builder has correctly visited the signature
+       var is_visited = false
+       # Names of parameters from the AST
+       # REQUIRE: is_visited
+       var param_names = new Array[String]
+       # Types of parameters from the AST
+       # REQUIRE: is_visited
+       var param_types = new Array[MType]
+       # Rank of the vararg (of -1 if none)
+       # REQUIRE: is_visited
+       var vararg_rank: Int = -1
+       # Return type
+       var ret_type: nullable MType = null
+
+       # Visit and fill information about a signature
+       private fun visit_signature(modelbuilder: ModelBuilder, nclassdef: AClassdef): Bool
+       do
+               var param_names = self.param_names
+               var param_types = self.param_types
+               for np in self.n_params do
+                       param_names.add(np.n_id.text)
+                       var ntype = np.n_type
+                       if ntype != null then
+                               var mtype = modelbuilder.resolve_mtype(nclassdef, ntype)
+                               if mtype == null then return false # Skip error
+                               for i in [0..param_names.length-param_types.length[ do
+                                       param_types.add(mtype)
+                               end
+                               if np.n_dotdotdot != null then
+                                       if self.vararg_rank != -1 then
+                                               modelbuilder.error(np, "Error: {param_names[self.vararg_rank]} is already a vararg")
+                                               return false
+                                       else
+                                               self.vararg_rank = param_names.length - 1
+                                       end
+                               end
                        end
                end
+               var ntype = self.n_type
+               if ntype != null then
+                       self.ret_type = modelbuilder.resolve_mtype(nclassdef, ntype)
+                       if self.ret_type == null then return false # Skip errir
+               end
+
+               for nclosure in self.n_closure_decls do
+                       if not nclosure.n_signature.visit_signature(modelbuilder, nclassdef) then return false
+               end
+
+               self.is_visited = true
+               return true
+       end
+
+       # Build a visited signature
+       fun build_signature(modelbuilder: ModelBuilder, nclassdef: AClassdef): nullable MSignature
+       do
+               if param_names.length != param_types.length then
+                       # Some parameters are typed, other parameters are not typed.
+                       modelbuilder.error(self.n_params[param_types.length], "Error: Untyped parameter `{param_names[param_types.length]}'.")
+                       return null
+               end
+
+               var mparameters = new Array[MParameter]
+               for i in [0..param_names.length[ do
+                       var mparameter = new MParameter(param_names[i], param_types[i], i == vararg_rank)
+                       mparameters.add(mparameter)
+               end
+
+               var msignature = new MSignature(mparameters, ret_type)
+               return msignature
        end
 end
 
@@ -985,7 +1175,7 @@ redef class AMethPropdef
                                name = "init"
                                name_node = self.n_kwinit
                        else if self isa AExternInitPropdef then
-                               name = "new"
+                               name = "init"
                                name_node = self.n_kwnew
                        else
                                abort
@@ -1010,17 +1200,18 @@ redef class AMethPropdef
                        mprop = new MMethod(mclassdef, name, mvisibility)
                        mprop.is_init = is_init
                        mprop.is_new = self isa AExternInitPropdef
-                       self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mprop)
+                       if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mprop) then return
                else
                        if n_kwredef == null then
                                if self isa AMainMethPropdef then
                                        # no warning
                                else
-                                       self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mprop)
+                                       if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mprop) then return
                                end
                        end
                        check_redef_property_visibility(modelbuilder, nclassdef, self.n_visibility, mprop)
                end
+               nclassdef.mprop2npropdef[mprop] = self
 
                var mpropdef = new MMethodDef(mclassdef, mprop, self.location)
 
@@ -1046,29 +1237,11 @@ redef class AMethPropdef
                var vararg_rank = -1
                var ret_type: nullable MType = null # Return type from the AST
                if nsig != null then
-                       for np in nsig.n_params do
-                               param_names.add(np.n_id.text)
-                               var ntype = np.n_type
-                               if ntype != null then
-                                       var mtype = modelbuilder.resolve_mtype(nclassdef, ntype)
-                                       if mtype == null then return # Skip error
-                                       for i in [0..param_names.length-param_types.length[ do
-                                               param_types.add(mtype)
-                                       end
-                                       if np.n_dotdotdot != null then
-                                               if vararg_rank != -1 then
-                                                       modelbuilder.error(np, "Error: {param_names[vararg_rank]} is already a vararg")
-                                               else
-                                                       vararg_rank = param_names.length - 1
-                                               end
-                                       end
-                               end
-                       end
-                       var ntype = nsig.n_type
-                       if ntype != null then
-                               ret_type = modelbuilder.resolve_mtype(nclassdef, ntype)
-                               if ret_type == null then return # Skip errir
-                       end
+                       if not nsig.visit_signature(modelbuilder, nclassdef) then return
+                       param_names = nsig.param_names
+                       param_types = nsig.param_types
+                       vararg_rank = nsig.vararg_rank
+                       ret_type = nsig.ret_type
                end
 
                # Look for some signature to inherit
@@ -1077,6 +1250,14 @@ redef class AMethPropdef
                if not mpropdef.is_intro then
                        msignature = mpropdef.mproperty.intro.msignature
                        if msignature == null then return # Skip error
+
+                       # Check inherited signature arity
+                       if param_names.length != msignature.arity then
+                               var node: ANode
+                               if nsig != null then node = nsig else node = self
+                               modelbuilder.error(node, "Redef error: {mpropdef} redefines {mpropdef.mproperty.intro} with {param_names.length} parameter(s), {msignature.arity} expected. Signature is {mpropdef}{msignature}")
+                               return
+                       end
                else if mpropdef.mproperty.is_init then
                        # FIXME UGLY: inherit signature from a super-constructor
                        for msupertype in nclassdef.mclassdef.supertypes do
@@ -1090,10 +1271,14 @@ redef class AMethPropdef
                        end
                end
 
+
                # Inherit the signature
                if msignature != null and param_names.length != param_types.length and param_names.length == msignature.arity and param_types.length == 0 then
                        # Parameters are untyped, thus inherit them
-                       param_types = msignature.parameter_mtypes
+                       param_types = new Array[MType]
+                       for mparameter in msignature.mparameters do
+                               param_types.add(mparameter.mtype)
+                       end
                        vararg_rank = msignature.vararg_rank
                end
                if msignature != null and ret_type == null then
@@ -1102,12 +1287,28 @@ redef class AMethPropdef
 
                if param_names.length != param_types.length then
                        # Some parameters are typed, other parameters are not typed.
-                       modelbuilder.warning(nsig.n_params[param_types.length], "Error: Untyped parameter `{param_names[param_types.length]}'.")
+                       modelbuilder.error(nsig.n_params[param_types.length], "Error: Untyped parameter `{param_names[param_types.length]}'.")
                        return
                end
 
-               msignature = new MSignature(param_names, param_types, ret_type, vararg_rank)
+               var mparameters = new Array[MParameter]
+               for i in [0..param_names.length[ do
+                       var mparameter = new MParameter(param_names[i], param_types[i], i == vararg_rank)
+                       mparameters.add(mparameter)
+               end
+
+               msignature = new MSignature(mparameters, ret_type)
                mpropdef.msignature = msignature
+
+               if nsig != null then
+                       for nclosure in nsig.n_closure_decls do
+                               var clos_signature = nclosure.n_signature.build_signature(modelbuilder, nclassdef)
+                               if clos_signature == null then return
+                               var mparameter = new MParameter(nclosure.n_id.text, clos_signature, false)
+                               msignature.mclosures.add(mparameter)
+                       end
+               end
+
        end
 
        redef fun check_signature(modelbuilder, nclassdef)
@@ -1125,12 +1326,6 @@ redef class AMethPropdef
                        var msignature = mpropdef.mproperty.intro.msignature
                        if msignature == null then return
 
-                       if mysignature.arity != msignature.arity then
-                               var node: ANode
-                               if nsig != null then node = nsig else node = self
-                               modelbuilder.error(node, "Redef Error: {mysignature.arity} parameters found, {msignature.arity} expected. Signature is {mpropdef}{msignature}")
-                               return
-                       end
                        var precursor_ret_type = msignature.return_mtype
                        var ret_type = mysignature.return_mtype
                        if ret_type != null and precursor_ret_type == null then
@@ -1141,11 +1336,11 @@ redef class AMethPropdef
                        if mysignature.arity > 0 then
                                # Check parameters types
                                for i in [0..mysignature.arity[ do
-                                       var myt = mysignature.parameter_mtypes[i]
-                                       var prt = msignature.parameter_mtypes[i]
+                                       var myt = mysignature.mparameters[i].mtype
+                                       var prt = msignature.mparameters[i].mtype
                                        if not myt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, prt) and
                                                        not prt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, myt) then
-                                               modelbuilder.error(nsig.n_params[i], "Redef Error: Wrong type for parameter `{mysignature.parameter_names[i]}'. found {myt}, expected {prt}.")
+                                               modelbuilder.error(nsig.n_params[i], "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
                                        end
                                end
                        end
@@ -1184,6 +1379,8 @@ redef class AAttrPropdef
                        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 nid = self.n_id
@@ -1193,12 +1390,14 @@ redef class AAttrPropdef
                        if mprop == null then
                                var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
                                mprop = new MAttribute(mclassdef, name, mvisibility)
-                               self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop)
+                               if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop) then return
                        else
                                assert mprop isa MAttribute
                                check_redef_property_visibility(modelbuilder, nclassdef, self.n_visibility, mprop)
-                               self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop)
+                               if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop) then return
                        end
+                       nclassdef.mprop2npropdef[mprop] = self
+
                        var mpropdef = new MAttributeDef(mclassdef, mprop, self.location)
                        self.mpropdef = mpropdef
                        modelbuilder.mpropdef2npropdef[mpropdef] = self
@@ -1210,11 +1409,13 @@ redef class AAttrPropdef
                                if mreadprop == null then
                                        var mvisibility = new_property_visibility(modelbuilder, nclassdef, nreadable.n_visibility)
                                        mreadprop = new MMethod(mclassdef, readname, mvisibility)
-                                       self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, false, mreadprop)
+                                       if not self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, false, mreadprop) then return
                                else
-                                       self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, true, mreadprop)
+                                       if not self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, true, mreadprop) then return
                                        check_redef_property_visibility(modelbuilder, nclassdef, nreadable.n_visibility, mreadprop)
                                end
+                               nclassdef.mprop2npropdef[mreadprop] = self
+
                                var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location)
                                self.mreadpropdef = mreadpropdef
                                modelbuilder.mpropdef2npropdef[mreadpropdef] = self
@@ -1227,11 +1428,13 @@ redef class AAttrPropdef
                                if mwriteprop == null then
                                        var mvisibility = new_property_visibility(modelbuilder, nclassdef, nwritable.n_visibility)
                                        mwriteprop = new MMethod(mclassdef, writename, mvisibility)
-                                       self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, false, mwriteprop)
+                                       if not self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, false, mwriteprop) then return
                                else
-                                       self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, true, mwriteprop)
+                                       if not self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, true, mwriteprop) then return
                                        check_redef_property_visibility(modelbuilder, nclassdef, nwritable.n_visibility, mwriteprop)
                                end
+                               nclassdef.mprop2npropdef[mwriteprop] = self
+
                                var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
                                self.mwritepropdef = mwritepropdef
                                modelbuilder.mpropdef2npropdef[mwritepropdef] = self
@@ -1249,11 +1452,13 @@ redef class AAttrPropdef
                        if mreadprop == null then
                                var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
                                mreadprop = new MMethod(mclassdef, readname, mvisibility)
-                               self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mreadprop)
+                               if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mreadprop) then return
                        else
-                               self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mreadprop)
+                               if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mreadprop) then return
                                check_redef_property_visibility(modelbuilder, nclassdef, self.n_visibility, mreadprop)
                        end
+                       nclassdef.mprop2npropdef[mreadprop] = self
+
                        var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location)
                        self.mreadpropdef = mreadpropdef
                        modelbuilder.mpropdef2npropdef[mreadpropdef] = self
@@ -1271,13 +1476,15 @@ redef class AAttrPropdef
                                        mvisibility = private_visibility
                                end
                                mwriteprop = new MMethod(mclassdef, writename, mvisibility)
-                               self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, false, mwriteprop)
+                               if not self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, false, mwriteprop) then return
                        else
-                               self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, true, mwriteprop)
+                               if not self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, true, mwriteprop) then return
                                if nwritable != null then
                                        check_redef_property_visibility(modelbuilder, nclassdef, nwritable.n_visibility, mwriteprop)
                                end
                        end
+                       nclassdef.mprop2npropdef[mwriteprop] = self
+
                        var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
                        self.mwritepropdef = mwritepropdef
                        modelbuilder.mpropdef2npropdef[mwritepropdef] = self
@@ -1335,7 +1542,7 @@ redef class AAttrPropdef
 
                var mreadpropdef = self.mreadpropdef
                if mreadpropdef != null then
-                       var msignature = new MSignature(new Array[String], new Array[MType], mtype, -1)
+                       var msignature = new MSignature(new Array[MParameter], mtype)
                        mreadpropdef.msignature = msignature
                end
 
@@ -1347,7 +1554,8 @@ redef class AAttrPropdef
                        else
                                name = n_id2.text
                        end
-                       var msignature = new MSignature([name], [mtype], null, -1)
+                       var mparameter = new MParameter(name, mtype, false)
+                       var msignature = new MSignature([mparameter], null)
                        mwritepropdef.msignature = msignature
                end
        end
@@ -1373,7 +1581,65 @@ redef class AAttrPropdef
                        end
                end
 
-               # FIXME: Check getter ans setter
+               # Check getter and setter
+               var meth = self.mreadpropdef
+               if meth != null then self.check_method_signature(modelbuilder, nclassdef, meth)
+               meth = self.mwritepropdef
+               if meth != null then self.check_method_signature(modelbuilder, nclassdef, meth)
+       end
+
+       private fun check_method_signature(modelbuilder: ModelBuilder, nclassdef: AClassdef, mpropdef: MMethodDef)
+       do
+               var mmodule = mpropdef.mclassdef.mmodule
+               var nsig = self.n_type
+               var mysignature = mpropdef.msignature
+               if mysignature == null then return # Error thus skiped
+
+               # Lookup for signature in the precursor
+               # FIXME all precursors should be considered
+               if not mpropdef.is_intro then
+                       var msignature = mpropdef.mproperty.intro.msignature
+                       if msignature == null then return
+
+                       if mysignature.arity != msignature.arity then
+                               var node: ANode
+                               if nsig != null then node = nsig else node = self
+                               modelbuilder.error(node, "Redef Error: {mysignature.arity} parameters found, {msignature.arity} expected. Signature is {mpropdef}{msignature}")
+                               return
+                       end
+                       var precursor_ret_type = msignature.return_mtype
+                       var ret_type = mysignature.return_mtype
+                       if ret_type != null and precursor_ret_type == null then
+                               var node: ANode
+                               if nsig != null then node = nsig else node = self
+                               modelbuilder.error(node, "Redef Error: {mpropdef.mproperty} is a procedure, not a function.")
+                               return
+                       end
+
+                       if mysignature.arity > 0 then
+                               # Check parameters types
+                               for i in [0..mysignature.arity[ do
+                                       var myt = mysignature.mparameters[i].mtype
+                                       var prt = msignature.mparameters[i].mtype
+                                       if not myt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, prt) and
+                                                       not prt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, myt) then
+                                               var node: ANode
+                                               if nsig != null then node = nsig else node = self
+                                               modelbuilder.error(node, "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
+                                       end
+                               end
+                       end
+                       if precursor_ret_type != null then
+                               if ret_type == null then
+                                       # Inherit the return type
+                                       ret_type = precursor_ret_type
+                               else if not ret_type.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, precursor_ret_type) then
+                                       var node: ANode
+                                       if nsig != null then node = nsig else node = self
+                                       modelbuilder.error(node, "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type}.")
+                               end
+                       end
+               end
        end
 end
 
@@ -1388,12 +1654,14 @@ redef class ATypePropdef
                if mprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
                        mprop = new MVirtualTypeProp(mclassdef, name, mvisibility)
-                       self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop)
+                       if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop) then return
                else
-                       self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop)
+                       if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop) then return
                        assert mprop isa MVirtualTypeProp
                        check_redef_property_visibility(modelbuilder, nclassdef, self.n_visibility, mprop)
                end
+               nclassdef.mprop2npropdef[mprop] = self
+
                var mpropdef = new MVirtualTypeDef(mclassdef, mprop, self.location)
                self.mpropdef = mpropdef
        end