nitmetrics: refactor self usage metrics computation
[nit.git] / src / typing.nit
index b9ce1f9..6687413 100644 (file)
@@ -171,6 +171,13 @@ private class TypeVisitor
                return self.modelbuilder.resolve_mtype(self.nclassdef, node)
        end
 
+       fun try_get_mclass(node: ANode, name: String): nullable MClass
+       do
+               var mmodule = self.nclassdef.mclassdef.mmodule
+               var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
+               return mclass
+       end
+
        fun get_mclass(node: ANode, name: String): nullable MClass
        do
                var mmodule = self.nclassdef.mclassdef.mmodule
@@ -205,6 +212,11 @@ private class TypeVisitor
                        return null
                end
 
+               if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility then
+                       self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self. {mproperty.intro_mclassdef.mmodule.visibility_for(self.mmodule)}")
+                       return null
+               end
+
                var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
                if propdefs.length == 0 then
                        self.modelbuilder.error(node, "Type error: no definition found for property {name} in {unsafe_type}")
@@ -711,18 +723,14 @@ end
 
 redef class AForExpr
        var coltype: nullable MGenericType
-       redef fun accept_typing(v)
-       do
-               var mtype = v.visit_expr(n_expr)
-               if mtype == null then return
 
-               var colcla = v.get_mclass(self, "Collection")
-               if colcla == null then return
+       private fun do_type_iterator(v: TypeVisitor, mtype: MType)
+       do
                var objcla = v.get_mclass(self, "Object")
                if objcla == null then return
-               var mapcla = v.get_mclass(self, "Map")
-               if mapcla == null then return
-               if v.is_subtype(mtype, colcla.get_mtype([objcla.mclass_type.as_nullable])) then
+
+               var colcla = v.try_get_mclass(self, "Collection")
+               if colcla != null and v.is_subtype(mtype, colcla.get_mtype([objcla.mclass_type.as_nullable])) then
                        var coltype = mtype.supertype_to(v.mmodule, v.anchor, colcla)
                        assert coltype isa MGenericType
                        self.coltype = coltype
@@ -732,7 +740,11 @@ redef class AForExpr
                        else
                                variables.first.declared_type = coltype.arguments.first
                        end
-               else if v.is_subtype(mtype, mapcla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
+                       return
+               end
+
+               var mapcla = v.try_get_mclass(self, "Map")
+               if mapcla != null and v.is_subtype(mtype, mapcla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
                        var coltype = mtype.supertype_to(v.mmodule, v.anchor, mapcla)
                        assert coltype isa MGenericType
                        self.coltype = coltype
@@ -743,10 +755,19 @@ redef class AForExpr
                                variables[0].declared_type = coltype.arguments[0]
                                variables[1].declared_type = coltype.arguments[1]
                        end
-               else
-                       v.modelbuilder.error(self, "TODO: Do 'for' on {mtype}")
+                       return
                end
 
+               v.modelbuilder.error(self, "NOT YET IMPLEMENTED: Do 'for' on {mtype}")
+       end
+
+       redef fun accept_typing(v)
+       do
+               var mtype = v.visit_expr(n_expr)
+               if mtype == null then return
+
+               self.do_type_iterator(v, mtype)
+
                v.visit_stmt(n_block)
                self.is_typed = true
        end
@@ -907,8 +928,11 @@ end
 redef class ARangeExpr
        redef fun accept_typing(v)
        do
-               var t1 = v.visit_expr(self.n_expr)
-               var t2 = v.visit_expr(self.n_expr2)
+               var discrete_class = v.get_mclass(self, "Discrete")
+               if discrete_class == null then return # Forward error
+               var discrete_type = discrete_class.mclassdefs.first.bound_mtype
+               var t1 = v.visit_expr_subtype(self.n_expr, discrete_type)
+               var t2 = v.visit_expr_subtype(self.n_expr2, discrete_type)
                if t1 == null or t2 == null then return
                var mclass = v.get_mclass(self, "Range")
                if mclass == null then return # Forward error
@@ -1020,6 +1044,7 @@ redef class ASendExpr
                msignature = v.resolve_signature_for(msignature, recvtype, for_self)
 
                var args = compute_raw_arguments
+               self.raw_arguments = args
 
                v.check_signature(self, args, name, msignature)
 
@@ -1051,7 +1076,9 @@ redef class ASendExpr
        private fun property_name: String is abstract
 
        # An array of all arguments (excluding self)
-       fun compute_raw_arguments: Array[AExpr] is abstract
+       var raw_arguments: nullable Array[AExpr]
+
+       private fun compute_raw_arguments: Array[AExpr] is abstract
 end
 
 redef class ABinopExpr
@@ -1189,6 +1216,7 @@ redef class ASendReassignFormExpr
                msignature = v.resolve_signature_for(msignature, recvtype, for_self)
 
                var args = compute_raw_arguments
+               self.raw_arguments = args
 
                v.check_signature(self, args, name, msignature)
 
@@ -1209,6 +1237,7 @@ redef class ASendReassignFormExpr
                var wtype = self.resolve_reassignment(v, readtype, wmsignature.mparameters.last.mtype)
                if wtype == null then return
 
+               args = args.to_a # duplicate so raw_arguments keeps only the getter args
                args.add(self.n_value)
                v.check_signature(self, args, name + "=", wmsignature)