src: reduce warnings and spelling errors
[nit.git] / src / semantize / typing.nit
index 462fe04..25fa0d6 100644 (file)
@@ -101,9 +101,9 @@ private class TypeVisitor
        end
 
        # Check that `sub` is a subtype of `sup`.
-       # If `sub` is not a valud suptype, then display an error on `node` an return null.
+       # If `sub` is not a valid suptype, then display an error on `node` an return null.
        # If `sub` is a safe subtype of `sup` then return `sub`.
-       # If `sub` is an insafe subtype (ie an imlicit cast is required), then return `sup`.
+       # If `sub` is an unsafe subtype (ie an implicit cast is required), then return `sup`.
        #
        # The point of the return type is to determinate the usable type on an expression:
        # If the suptype is safe, then the return type is the one on the expression typed by `sub`.
@@ -112,7 +112,7 @@ private class TypeVisitor
        do
                if self.is_subtype(sub, sup) then return sub
                if self.is_subtype(sub, self.anchor_to(sup)) then
-                       # FIXME workarround to the current unsafe typing policy. To remove once fixed virtual types exists.
+                       # FIXME workaround to the current unsafe typing policy. To remove once fixed virtual types exists.
                        #node.debug("Unsafe typing: expected {sup}, got {sub}")
                        return sup
                end
@@ -188,9 +188,9 @@ private class TypeVisitor
                if sup == null then return null # Forward error
 
                if sup == sub then
-                       self.modelbuilder.warning(node, "Warning: Expression is already a {sup}.")
+                       self.modelbuilder.warning(node, "useless-type-test", "Warning: Expression is already a {sup}.")
                else if self.is_subtype(sub, sup) then
-                       self.modelbuilder.warning(node, "Warning: Expression is already a {sup} since it is a {sub}.")
+                       self.modelbuilder.warning(node, "useless-type-test", "Warning: Expression is already a {sup} since it is a {sub}.")
                end
                return sup
        end
@@ -262,6 +262,16 @@ private class TypeVisitor
                        return null
                end
 
+               var info = mproperty.deprecation
+               if info != null and self.mpropdef.mproperty.deprecation == null then
+                       var mdoc = info.mdoc
+                       if mdoc != null then
+                               self.modelbuilder.warning(node, "deprecated-method", "Deprecation Warning: Method '{name}' is deprecated: {mdoc.content.first}")
+                       else
+                               self.modelbuilder.warning(node, "deprecated-method", "Deprecation Warning: Method '{name}' is deprecated.")
+                       end
+               end
+
                var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
                var mpropdef
                if propdefs.length == 0 then
@@ -270,7 +280,7 @@ private class TypeVisitor
                else if propdefs.length == 1 then
                        mpropdef = propdefs.first
                else
-                       self.modelbuilder.warning(node, "Warning: confliting property definitions for property {name} in {unsafe_type}: {propdefs.join(" ")}")
+                       self.modelbuilder.warning(node, "property-conflict", "Warning: conflicting property definitions for property {name} in {unsafe_type}: {propdefs.join(" ")}")
                        mpropdef = mproperty.intro
                end
 
@@ -294,7 +304,7 @@ private class TypeVisitor
                return callsite
        end
 
-       # Visit the expressions of args and cheik their conformity with the corresponding typi in signature
+       # Visit the expressions of args and check their conformity with the corresponding type in signature
        # The point of this method is to handle varargs correctly
        # Note: The signature must be correctly adapted
        fun check_signature(node: ANode, args: Array[AExpr], name: String, msignature: MSignature): Bool
@@ -399,7 +409,7 @@ end
 
 # A specific method call site with its associated informations.
 class CallSite
-       # The assiciated node for location
+       # The associated node for location
        var node: ANode
 
        # The static type of the receiver (possibly unresolved)
@@ -412,7 +422,7 @@ class CallSite
        var anchor: nullable MClassType
 
        # Is the receiver self?
-       # If "for_self", virtual types of the signature are keeped
+       # If "for_self", virtual types of the signature are kept
        # If "not_for_self", virtual type are erased
        var recv_is_self: Bool
 
@@ -447,7 +457,7 @@ redef class FlowContext
 
        # Adapt the variable to a static type
        # Warning1: do not modify vars directly.
-       # Warning2: sub-flow may have cached a unadapted variabial
+       # Warning2: sub-flow may have cached a unadapted variable
        private fun set_var(variable: Variable, mtype: nullable MType)
        do
                self.vars[variable] = mtype
@@ -491,7 +501,7 @@ redef class APropdef
        do
        end
 
-       # The variable associated to the reciever (if any)
+       # The variable associated to the receiver (if any)
        var selfvariable: nullable Variable
 end
 
@@ -1087,19 +1097,37 @@ redef class AArrayExpr
 
        redef fun accept_typing(v)
        do
+               var mtype: nullable MType = null
+               var ntype = self.n_type
+               if ntype != null then
+                       mtype = v.resolve_mtype(ntype)
+                       if mtype == null then return # Skip error
+               end
                var mtypes = new Array[nullable MType]
+               var useless = false
                for e in self.n_exprs.n_exprs do
                        var t = v.visit_expr(e)
                        if t == null then
                                return # Skip error
                        end
-                       mtypes.add(t)
+                       if mtype != null then
+                               if v.check_subtype(e, t, mtype) == null then return # Skip error
+                               if t == mtype then useless = true
+                       else
+                               mtypes.add(t)
+                       end
+               end
+               if mtype == null then
+                       mtype = v.merge_types(self, mtypes)
                end
-               var mtype = v.merge_types(self, mtypes)
                if mtype == null then
                        v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}")
                        return
                end
+               if useless then
+                       assert ntype != null
+                       v.modelbuilder.warning(ntype, "useless-type", "Warning: useless type declaration `{mtype}` in literal Array since it can be inferred from the elements type.")
+               end
                var mclass = v.get_mclass(self, "Array")
                if mclass == null then return # Forward error
                var array_mtype = mclass.get_mtype([mtype])
@@ -1202,13 +1230,13 @@ redef class AAsNotnullExpr
                self.mtype = mtype
 
                if mtype isa MClassType then
-                       v.modelbuilder.warning(self, "Warning: expression is already not null, since it is a `{mtype}`.")
+                       v.modelbuilder.warning(self, "useless-type-test", "Warning: expression is already not null, since it is a `{mtype}`.")
                        return
                end
                assert mtype.need_anchor
                var u = v.anchor_to(mtype)
                if not u isa MNullableType then
-                       v.modelbuilder.warning(self, "Warning: expression is already not null, since it is a `{mtype}: {u}`.")
+                       v.modelbuilder.warning(self, "useless-type-test", "Warning: expression is already not null, since it is a `{mtype}: {u}`.")
                        return
                end
        end
@@ -1355,6 +1383,9 @@ end
 redef class AStarExpr
        redef fun property_name do return "*"
 end
+redef class AStarstarExpr
+       redef fun property_name do return "**"
+end
 redef class ASlashExpr
        redef fun property_name do return "/"
 end
@@ -1476,14 +1507,16 @@ redef class ASuperExpr
 
        redef fun accept_typing(v)
        do
-               var recvtype = v.anchor
+               var anchor = v.anchor
+               assert anchor != null
+               var recvtype = v.get_variable(self, v.selfvariable)
                assert recvtype != null
                var mproperty = v.mpropdef.mproperty
                if not mproperty isa MMethod then
                        v.error(self, "Error: super only usable in a method")
                        return
                end
-               var superprops = mproperty.lookup_super_definitions(v.mmodule, recvtype)
+               var superprops = mproperty.lookup_super_definitions(v.mmodule, anchor)
                if superprops.length == 0 then
                        if mproperty.is_init and v.mpropdef.is_intro then
                                process_superinit(v)
@@ -1509,18 +1542,20 @@ redef class ASuperExpr
 
        private fun process_superinit(v: TypeVisitor)
        do
-               var recvtype = v.anchor
+               var anchor = v.anchor
+               assert anchor != null
+               var recvtype = v.get_variable(self, v.selfvariable)
                assert recvtype != null
                var mpropdef = v.mpropdef
                assert mpropdef isa MMethodDef
                var mproperty = mpropdef.mproperty
                var superprop: nullable MMethodDef = null
                for msupertype in mpropdef.mclassdef.supertypes do
-                       msupertype = msupertype.anchor_to(v.mmodule, recvtype)
+                       msupertype = msupertype.anchor_to(v.mmodule, anchor)
                        var errcount = v.modelbuilder.toolcontext.error_count
                        var candidate = v.try_get_mproperty_by_name2(self, msupertype, mproperty.name).as(nullable MMethod)
                        if candidate == null then
-                               if v.modelbuilder.toolcontext.error_count > errcount then return # Forard error
+                               if v.modelbuilder.toolcontext.error_count > errcount then return # Forward error
                                continue # Try next super-class
                        end
                        if superprop != null and candidate.is_root_init then
@@ -1530,13 +1565,13 @@ redef class ASuperExpr
                                v.error(self, "Error: conflicting super constructor to call for {mproperty}: {candidate.full_name}, {superprop.mproperty.full_name}")
                                return
                        end
-                       var candidatedefs = candidate.lookup_definitions(v.mmodule, recvtype)
+                       var candidatedefs = candidate.lookup_definitions(v.mmodule, anchor)
                        if superprop != null and superprop.mproperty == candidate then
                                if superprop == candidatedefs.first then continue
                                candidatedefs.add(superprop)
                        end
                        if candidatedefs.length > 1 then
-                               v.error(self, "Error: confliting property definitions for property {mproperty} in {recvtype}: {candidatedefs.join(", ")}")
+                               v.error(self, "Error: conflicting property definitions for property {mproperty} in {recvtype}: {candidatedefs.join(", ")}")
                                return
                        end
                        superprop = candidatedefs.first
@@ -1728,7 +1763,7 @@ redef class ADebugTypeExpr
                var mtype = v.resolve_mtype(ntype)
                if mtype != null and mtype != expr then
                        var umtype = v.anchor_to(mtype)
-                       v.modelbuilder.warning(self, "Found type {expr} (-> {unsafe}), expected {mtype} (-> {umtype})")
+                       v.modelbuilder.warning(self, "debug", "Found type {expr} (-> {unsafe}), expected {mtype} (-> {umtype})")
                end
                self.is_typed = true
        end