# FIXME add missing error checks
module modelbuilder
-import parser
import model
-import poset
-import opts
-import toolcontext
import phase
private import more_collections
redef class ToolContext
# Option --path
- var opt_path: OptionArray = new OptionArray("Set include path for loaders (may be used more than once)", "-I", "--path")
+ var opt_path = new OptionArray("Set include path for loaders (may be used more than once)", "-I", "--path")
# Option --only-metamodel
- var opt_only_metamodel: OptionBool = new OptionBool("Stop after meta-model processing", "--only-metamodel")
+ var opt_only_metamodel = new OptionBool("Stop after meta-model processing", "--only-metamodel")
# Option --only-parse
- var opt_only_parse: OptionBool = new OptionBool("Only proceed to parse step of loaders", "--only-parse")
+ var opt_only_parse = new OptionBool("Only proceed to parse step of loaders", "--only-parse")
# Option --ignore-visibility
- var opt_ignore_visibility: OptionBool = new OptionBool("Do not check, and produce errors, on visibility issues.", "--ignore-visibility")
+ var opt_ignore_visibility = new OptionBool("Do not check, and produce errors, on visibility issues.", "--ignore-visibility")
redef init
do
option_context.add_option(opt_path, opt_only_parse, opt_only_metamodel, opt_ignore_visibility)
end
+ # The modelbuilder 1-to-1 associated with the toolcontext
fun modelbuilder: ModelBuilder do return modelbuilder_real.as(not null)
+
private var modelbuilder_real: nullable ModelBuilder = null
- # Run `process_mainmodule` on all phases
- fun run_global_phases(mmodules: Array[MModule])
+ # Combine module to make a single one if required.
+ fun make_main_module(mmodules: Array[MModule]): MModule
do
assert not mmodules.is_empty
var mainmodule
mainmodule = mmodules.first
else
# We need a main module, so we build it by importing all modules
- mainmodule = new MModule(modelbuilder.model, null, mmodules.first.name, new Location(mmodules.first.location.file, 0, 0, 0, 0))
+ mainmodule = new MModule(modelbuilder.model, null, mmodules.first.name + "-m", new Location(mmodules.first.location.file, 0, 0, 0, 0))
mainmodule.is_fictive = true
mainmodule.set_imported_mmodules(mmodules)
end
+ return mainmodule
+ end
+
+ # Run `process_mainmodule` on all phases
+ fun run_global_phases(mmodules: Array[MModule])
+ do
+ var mainmodule = make_main_module(mmodules)
for phase in phases_list do
if phase.disabled then continue
phase.process_mainmodule(mainmodule, mmodules)
# Instantiate a modelbuilder for a model and a toolcontext
# Important, the options of the toolcontext must be correctly set (parse_option already called)
- init(model: Model, toolcontext: ToolContext)
+ init
do
- self.model = model
- self.toolcontext = toolcontext
assert toolcontext.modelbuilder_real == null
toolcontext.modelbuilder_real = self
end
var nit_dir = toolcontext.nit_dir
- if nit_dir != null then
- var libname = "{nit_dir}/lib"
- if libname.file_exists then paths.add(libname)
- end
+ var libname = "{nit_dir}/lib"
+ if libname.file_exists then paths.add(libname)
end
# Load a bunch of modules.
for mprop in props do
if not mtype.has_mproperty(mmodule, mprop) then continue
if not mmodule.is_visible(mprop.intro_mclassdef.mmodule, mprop.visibility) then continue
+
+ # new-factories are invisible outside of the class
+ if mprop isa MMethod and mprop.is_new and (not mtype isa MClassType or mprop.intro_mclassdef.mclass != mtype.mclass) then
+ continue
+ end
+
if res == null then
res = mprop
continue
return res
end
- private var try_get_mproperty_by_name2_cache: HashMap3[MModule, MType, String, nullable MProperty] = new HashMap3[MModule, MType, String, nullable MProperty]
+ private var try_get_mproperty_by_name2_cache = new HashMap3[MModule, MType, String, nullable MProperty]
# Alias for try_get_mproperty_by_name2(anode, mclassdef.mmodule, mclassdef.mtype, name)
# * the NIT_PATH environment variable
# * `toolcontext.nit_dir`
# Path can be added (or removed) by the client
- var paths: Array[String] = new Array[String]
+ var paths = new Array[String]
# Like (an used by) `get_mmodule_by_name` but just return the ModulePath
private fun search_mmodule_by_name(anode: ANode, mgroup: nullable MGroup, name: String): nullable ModulePath
var parser = new Parser(lexer)
var tree = parser.parse
file.close
- var mod_name = filename.basename(".nit")
# Handle lexer and parser error
var nmodule = tree.n_base
return nmodule
end
- fun load_rt_module(parent: MModule, nmodule: AModule, mod_name: String): nullable AModule
+ # Injection of a new module without source.
+ # Used by the interpreted
+ fun load_rt_module(parent: nullable MModule, nmodule: AModule, mod_name: String): nullable AModule
do
# Create the module
- var mmodule = new MModule(model, parent.mgroup, mod_name, nmodule.location)
+
+ var mgroup = null
+ if parent != null then mgroup = parent.mgroup
+ var mmodule = new MModule(model, mgroup, mod_name, nmodule.location)
nmodule.mmodule = mmodule
nmodules.add(nmodule)
self.mmodule2nmodule[mmodule] = nmodule
- var imported_modules = new Array[MModule]
-
- imported_modules.add(parent)
- mmodule.set_visibility_for(parent, intrude_visibility)
-
- mmodule.set_imported_mmodules(imported_modules)
+ if parent!= null then
+ var imported_modules = new Array[MModule]
+ imported_modules.add(parent)
+ mmodule.set_visibility_for(parent, intrude_visibility)
+ mmodule.set_imported_mmodules(imported_modules)
+ else
+ build_module_importation(nmodule)
+ end
return nmodule
end
var mdoc = ndoc.to_mdoc
mmodule.mdoc = mdoc
mdoc.original_mentity = mmodule
+ else
+ advice(decl, "missing-doc", "Documentation warning: Undocumented module `{mmodule}`")
end
end
self.toolcontext.info("{mmodule} imports {imported_modules.join(", ")}", 3)
mmodule.set_imported_mmodules(imported_modules)
+ # Force standard to be public if imported
+ for sup in mmodule.in_importation.greaters do
+ if sup.name == "standard" 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
end
# All the loaded modules
- var nmodules: Array[AModule] = new Array[AModule]
+ var nmodules = new Array[AModule]
# Register the nmodule associated to each mmodule
# FIXME: why not refine the `MModule` class with a nullable attribute?
- var mmodule2nmodule: HashMap[MModule, AModule] = new HashMap[MModule, AModule]
+ var mmodule2nmodule = new HashMap[MModule, AModule]
# Helper function to display an error on a node.
# Alias for `self.toolcontext.error(n.hot_location, text)`
# Helper function to display a warning on a node.
# Alias for: `self.toolcontext.warning(n.hot_location, text)`
- fun warning(n: ANode, text: String)
+ fun warning(n: ANode, tag, text: String)
+ do
+ self.toolcontext.warning(n.hot_location, tag, text)
+ end
+
+ # Helper function to display an advice on a node.
+ # Alias for: `self.toolcontext.advice(n.hot_location, text)`
+ fun advice(n: ANode, tag, text: String)
do
- self.toolcontext.warning(n.hot_location, text)
+ self.toolcontext.advice(n.hot_location, tag, text)
end
# Force to get the primitive method named `name` on the type `recv` or do a fatal error on `n`
- fun force_get_primitive_method(n: ANode, name: String, recv: MClass, mmodule: MModule): MMethod
+ fun force_get_primitive_method(n: nullable ANode, name: String, recv: MClass, mmodule: MModule): MMethod
do
var res = mmodule.try_get_primitive_method(name, recv)
if res == null then
- self.toolcontext.fatal_error(n.hot_location, "Fatal Error: {recv} must have a property named {name}.")
+ var l = null
+ if n != null then l = n.hot_location
+ self.toolcontext.fatal_error(l, "Fatal Error: {recv} must have a property named {name}.")
abort
end
return res