Analyze the module importation and fill the module_importation_hierarchy

If the importation was already done (nmodule.is_importation_done), this method does a no-op.

REQUIRE nmodule.mmodule != null

ENSURE nmodule.is_importation_done

Property definitions

nitc :: loader $ ModelBuilder :: build_module_importation
	# Analyze the module importation and fill the module_importation_hierarchy
	#
	# If the importation was already done (`nmodule.is_importation_done`), this method does a no-op.
	#
	# REQUIRE `nmodule.mmodule != null`
	# ENSURE `nmodule.is_importation_done`
	fun build_module_importation(nmodule: AModule)
	do
		if nmodule.is_importation_done then return
		nmodule.is_importation_done = true
		var mmodule = nmodule.mmodule.as(not null)
		var stdimport = true
		var imported_modules = new Array[MModule]
		for aimport in nmodule.n_imports do
			# Do not imports conditional
			var atconditionals = aimport.get_annotations("conditional")
			if atconditionals.not_empty then continue

			stdimport = false
			if not aimport isa AStdImport then
				continue
			end

			# Load the imported module
			var sup = search_module_by_amodule_name(aimport.n_name, mmodule.mgroup)
			if sup == null then
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
				continue # Skip error
			end
			var ast = sup.load(self)
			if ast == null then
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
				continue # Skip error
			end

			aimport.mmodule = sup
			imported_modules.add(sup)
			var mvisibility = aimport.n_visibility.mvisibility
			if mvisibility == protected_visibility then
				mmodule.is_broken = true
				error(aimport.n_visibility, "Error: only properties can be protected.")
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
				return
			end
			if sup == mmodule then
				error(aimport.n_name, "Error: dependency loop in module {mmodule}.")
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
			end
			if sup.in_importation < mmodule then
				error(aimport.n_name, "Error: dependency loop between modules {mmodule} and {sup}.")
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
				return
			end
			mmodule.set_visibility_for(sup, mvisibility)
		end
		if stdimport then
			var mod_name = "core"
			var sup = self.get_mmodule_by_name(nmodule, null, mod_name)
			if sup == null then
				mmodule.is_broken = true
				nmodule.mmodule = null # invalidate the module
			else # Skip error
				imported_modules.add(sup)
				mmodule.set_visibility_for(sup, public_visibility)
			end
		end

		# Declare conditional importation
		for aimport in nmodule.n_imports do
			if not aimport isa AStdImport then continue
			var atconditionals = aimport.get_annotations("conditional")
			if atconditionals.is_empty then continue

			var suppath = search_module_by_amodule_name(aimport.n_name, mmodule.mgroup)
			if suppath == null then continue # skip error

			for atconditional in atconditionals do
				var nargs = atconditional.n_args
				if nargs.is_empty then
					error(atconditional, "Syntax Error: `conditional` expects module identifiers as arguments.")
					continue
				end

				# The rule
				var rule = new Array[MModule]

				# First element is the goal, thus
				rule.add suppath

				# Second element is the first condition, that is to be a client of the current module
				rule.add mmodule

				# Other condition are to be also a client of each modules indicated as arguments of the annotation
				for narg in nargs do
					var id = narg.as_id
					if id == null then
						error(narg, "Syntax Error: `conditional` expects module identifier as arguments.")
						continue
					end

					var mp = search_mmodule_by_name(narg, mmodule.mgroup, id)
					if mp == null then continue

					rule.add mp
				end

				conditional_importations.add rule
			end
		end

		mmodule.set_imported_mmodules(imported_modules)

		apply_conditional_importations(mmodule)

		self.toolcontext.info("{mmodule} imports {mmodule.in_importation.direct_greaters.join(", ")}", 3)

		# Force `core` to be public if imported
		for sup in mmodule.in_importation.greaters do
			if sup.name == "core" then
				mmodule.set_visibility_for(sup, public_visibility)
			end
		end

		# TODO: Correctly check for useless importation
		# It is even doable?
		var directs = mmodule.in_importation.direct_greaters
		for nim in nmodule.n_imports do
			if not nim isa AStdImport then continue
			var im = nim.mmodule
			if im == null then continue
			if directs.has(im) then continue
			# This generates so much noise that it is simpler to just comment it
			#warning(nim, "Warning: possible useless importation of {im}")
		end
	end
src/loader.nit:921,2--1060,4