nitmetrics: compute scalar module count
[nit.git] / src / modelbuilder.nit
index 54961fc..18cb12f 100644 (file)
@@ -477,7 +477,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]
@@ -592,6 +593,10 @@ 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)
@@ -680,7 +685,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 +697,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
 
@@ -819,6 +824,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
@@ -961,6 +977,7 @@ redef class APropdef
                        end
                end
        end
+
 end
 
 redef class ASignature
@@ -1008,9 +1025,32 @@ redef class ASignature
                        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
 
 redef class AMethPropdef
@@ -1108,6 +1148,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
@@ -1121,6 +1169,7 @@ 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
@@ -1136,7 +1185,7 @@ 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
 
@@ -1145,8 +1194,19 @@ redef class AMethPropdef
                        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)
@@ -1164,12 +1224,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
@@ -1413,7 +1467,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