Build the classes of the module nmodule.

Property definitions

nitc :: modelize_class $ ModelBuilder :: build_classes
	# Build the classes of the module `nmodule`.
	private fun build_classes(nmodule: AModule)
	do
		# Force building recursively
		if nmodule.build_classes_is_done then return
		nmodule.build_classes_is_done = true
		var mmodule = nmodule.mmodule
		if mmodule == null then return
		for imp in mmodule.in_importation.direct_greaters do
			var nimp = mmodule2node(imp)
			if nimp != null then build_classes(nimp)
		end

		# Create all classes
		# process AStdClassdef before so that non-AStdClassdef classes can be attached to existing ones, if any
		for nclassdef in nmodule.n_classdefs do
			if not nclassdef isa AStdClassdef then continue
			self.build_a_mclass(nmodule, nclassdef)
		end
		for nclassdef in nmodule.n_classdefs do
			if nclassdef isa AStdClassdef then continue
			self.build_a_mclass(nmodule, nclassdef)
		end

		# Create all classdefs
		for nclassdef in nmodule.n_classdefs do
			if not nclassdef isa AStdClassdef then continue
			self.build_a_mclassdef(nmodule, nclassdef)
		end
		for nclassdef in nmodule.n_classdefs do
			if nclassdef isa AStdClassdef then continue
			self.build_a_mclassdef(nmodule, nclassdef)
		end

		# Create inheritance on all classdefs
		for nclassdef in nmodule.n_classdefs do
			self.build_a_mclassdef_inheritance(nmodule, nclassdef)
		end

		# Create the mclassdef hierarchy
		for mclassdef in mmodule.mclassdefs do
			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
				var mclassdef = nclassdef.mclassdef
				var mclass
				var anchor
				if mclassdef == null then
					mclass = null
					anchor = null
				else
					mclass = mclassdef.mclass
					anchor = mclassdef.bound_mtype
				end

				# 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_mtype3(mmodule, mclass, anchor, 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_mtype3(mmodule, mclass, anchor, ntype)
						if mtype == null then return # Forward error
					end
				end
			end
		end

		# Check clash of ancestors
		for nclassdef in nmodule.n_classdefs do
			var mclassdef = nclassdef.mclassdef
			if mclassdef == null then continue
			var superclasses = new HashMap[MClass, MClassType]
			for scd in mclassdef.in_hierarchy.greaters do
				for st in scd.supertypes do
					if not superclasses.has_key(st.mclass) then
						superclasses[st.mclass] = st
					else if superclasses[st.mclass] != st then
						var st1 = superclasses[st.mclass].resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mmodule, false)
						var st2 = st.resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mmodule, false)
						if st1 != st2 then
							error(nclassdef, "Error: incompatible ancestors for `{mclassdef.mclass}`; conflict: `{st1}` and `{st2}`")
						end
					end
				end
			end
		end

		# TODO: Check that the super-class is not intrusive

		# Check that the superclasses are not already known (by transitivity)
		for nclassdef in nmodule.n_classdefs do
			if not nclassdef isa AStdClassdef or nclassdef.is_broken then continue
			var mclassdef = nclassdef.mclassdef
			if mclassdef == null then continue

			# Get the direct superclasses
			# Since we are a mclassdef, just look at the mclassdef hierarchy
			var parents = new Array[MClass]
			for sup in mclassdef.in_hierarchy.direct_greaters do
				parents.add(sup.mclass)
			end

			# Used to track duplicates of superclasses
			var seen_parents = new ArrayMap[MClass, AType]

			# The Object class
			var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object")

			# Check each declared superclass to see if it belong to the direct superclass
			for nsc in nclassdef.n_superclasses do
				var ntype = nsc.n_type
				var mtype = ntype.mtype

				# 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
					if ntype.location.file != null and not ntype.location.file.filename.is_empty then
						warning(ntype, "useless-superclass", "Warning: superfluous super-class `{mtype}` in class `{mclassdef.mclass}`.")
					end
				else if not seen_parents.has_key(sc) then
					seen_parents[sc] = ntype
				else
					warning(ntype, "useless-superclass", "Warning: duplicated super-class `{mtype}` in class `{mclassdef.mclass}`.")
				end
			end
		end
	end
src/modelize/modelize_class.nit:346,2--491,4