Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / modelize / modelize_class.nit
index 5cf3e20..853d8ff 100644 (file)
@@ -250,13 +250,31 @@ redef class ModelBuilder
        do
                var mmodule = nmodule.mmodule
                if mmodule == null then return
-               var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
-               var pointerclass = try_get_mclass_by_name(nmodule, mmodule, "Pointer")
                var mclass = nclassdef.mclass
                if mclass == null then return
                var mclassdef = nclassdef.mclassdef
                if mclassdef == null then return
 
+               var supertypes = collect_supertypes(nmodule, nclassdef, mclassdef.is_intro)
+               mclassdef.set_supertypes(supertypes)
+               if not supertypes.is_empty then self.toolcontext.info("{mclassdef} new super-types: {supertypes.join(", ")}", 3)
+       end
+
+       # List the supertypes specified or implied by `nclassdef`.
+       #
+       # REQUIRE: `nmodule.mmodule != null`
+       # REQUIRE: `nclassdef.mclass != null`
+       private fun collect_supertypes(nmodule: AModule, nclassdef: AClassdef,
+                       is_intro: Bool): Array[MClassType]
+       do
+               var mmodule = nmodule.mmodule.as(not null)
+               var mclass = nclassdef.mclass.as(not null)
+               var name = mclass.name
+               var kind = mclass.kind
+
+               var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")
+               var pointerclass = try_get_mclass_by_name(nmodule, mmodule, "Pointer")
+
                # Do we need to specify Object as a super class?
                var specobject = true
 
@@ -273,39 +291,39 @@ redef class ModelBuilder
                                                ntype, false)
                                if mtype == null then continue # Skip because of error
                                if not mtype isa MClassType then
-                                       error(ntype, "Error: supertypes cannot be a formal type.")
-                                       return
+                                       error(ntype, "Error: a supertype cannot be a formal type.")
+                                       continue
                                end
-                               if not mclass.kind.can_specialize(mtype.mclass.kind) then
-                                       error(ntype, "Error: {mclass.kind} `{mclass}` cannot specialize {mtype.mclass.kind} `{mtype.mclass}`.")
+                               var superclass = mtype.mclass
+                               var super_kind = superclass.kind
+                               if not kind.can_specialize(super_kind) then
+                                       error(ntype, "Error: {kind} `{mclass}` cannot specialize {super_kind} `{superclass}`.")
                                end
                                supertypes.add mtype
                                #print "new super : {mclass} < {mtype}"
-                               if mtype.mclass.kind == extern_kind then specpointer = false
+                               if super_kind == extern_kind then specpointer = false
                        end
                end
 
-               if mclassdef.is_intro and objectclass != null then
-                       if mclass.kind == extern_kind and mclass.name != "Pointer" then
+               if is_intro and objectclass != null then
+                       if kind == extern_kind and name != "Pointer" then
                                # it is an extern class, but not a Pointer
                                if pointerclass == null then
                                        error(nclassdef, "Error: `Pointer` must be defined first.")
-                                       return
+                                       return supertypes
                                end
                                if specpointer then supertypes.add pointerclass.mclass_type
                        else if specobject then
-                               if mclass.name != "Object" then
+                               if name != "Object" then
                                        # it is a standard class without super class (but is not Object)
                                        supertypes.add objectclass.mclass_type
-                               else if mclass.kind != interface_kind then
+                               else if kind != interface_kind then
                                        error(nclassdef, "Error: `Object` must be an {interface_kind}.")
-                                       return
                                end
                        end
                end
 
-               mclassdef.set_supertypes(supertypes)
-               if not supertypes.is_empty then self.toolcontext.info("{mclassdef} new super-types: {supertypes.join(", ")}", 3)
+               return supertypes
        end
 
        # Check the validity of the specialization heirarchy
@@ -452,8 +470,11 @@ redef class ModelBuilder
                        for nsc in nclassdef.n_superclasses do
                                var ntype = nsc.n_type
                                var mtype = ntype.mtype
-                               if mtype == null then continue
-                               assert mtype isa MClassType
+
+                               # If the supertype is `null` or don’t refer to a class, we
+                               # already raised an error.
+                               if not mtype isa MClassType then continue
+
                                var sc = mtype.mclass
                                if not parents.has(sc) or sc == objectclass then
                                        # Skip the warning on generated code
@@ -517,6 +538,9 @@ end
 redef class AExternClasskind
        redef fun mkind do return extern_kind
 end
+redef class ASubsetClasskind
+       redef fun mkind do return subset_kind
+end
 
 redef class AFormaldef
        # The associated parameter type