mainmodule = mmodules.first
else
# We need a main module, so we build it by importing all modules
- mainmodule = new MModule(modelbuilder.model, null, "<main>", new Location(null, 0, 0, 0, 0))
+ mainmodule = new MModule(modelbuilder.model, null, mmodules.first.name, new Location(mmodules.first.location.file, 0, 0, 0, 0))
+ mainmodule.is_fictive = true
mainmodule.set_imported_mmodules(mmodules)
end
for phase in phases_list do
# Called by the `ToolContext::run_global_phases`.
#
# `mainmodule` is the main module of the program.
- # It could be an implicit module (called "<main>").
+ # It could be an implicit module (called like the first given_mmodules).
#
# `given_modules` is the list of explicitely requested modules.
# from the command-line for instance.
paths.append(path_env.split_with(':'))
end
- path_env = "NIT_DIR".environ
- if not path_env.is_empty then
- var libname = "{path_env}/lib"
+ 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 = "{sys.program_name.dirname}/../lib"
- if libname.file_exists then paths.add(libname.simplify_path)
end
# Load a bunch of modules.
if not mmodule.is_visible(mprop.intro_mclassdef.mmodule, mprop.visibility) then continue
if res == null then
res = mprop
- else
+ continue
+ end
+
+ # Two global properties?
+ # First, special case for init, keep the most specific ones
+ if res isa MMethod and mprop isa MMethod and res.is_init and mprop.is_init then
var restype = res.intro_mclassdef.bound_mtype
var mproptype = mprop.intro_mclassdef.bound_mtype
- if restype.is_subtype(mmodule, null, mproptype) then
- # we keep res
- else if mproptype.is_subtype(mmodule, null, restype) then
+ if mproptype.is_subtype(mmodule, null, restype) then
+ # found a most specific constructor, so keep it
res = mprop
- else
- if ress == null then ress = new Array[MProperty]
- ress.add(mprop)
+ continue
end
end
+
+ # Ok, just keep all prop in the ress table
+ if ress == null then
+ ress = new Array[MProperty]
+ ress.add(res)
+ end
+ ress.add(mprop)
end
- if ress != null then
+
+ # There is conflict?
+ if ress != null and res isa MMethod and res.is_init then
+ # special case forinit again
var restype = res.intro_mclassdef.bound_mtype
+ var ress2 = new Array[MProperty]
for mprop in ress do
var mproptype = mprop.intro_mclassdef.bound_mtype
if not restype.is_subtype(mmodule, null, mproptype) then
- self.error(anode, "Ambigous property name '{name}' for {mtype}; conflict between {mprop.full_name} and {res.full_name}")
- return null
+ ress2.add(mprop)
+ else if not mprop isa MMethod or not mprop.is_init then
+ ress2.add(mprop)
end
end
+ if ress2.is_empty then
+ ress = null
+ else
+ ress = ress2
+ ress.add(res)
+ end
+ end
+
+ if ress != null then
+ assert ress.length > 1
+ var s = new Array[String]
+ for mprop in ress do s.add mprop.full_name
+ self.error(anode, "Ambigous property name '{name}' for {mtype}; conflict between {s.join(" and ")}")
end
self.try_get_mproperty_by_name2_cache[mmodule, mtype, name] = res
# The list is initially set with :
# * the toolcontext --path option
# * the NIT_PATH environment variable
- # * some heuristics including the NIT_DIR environment variable and the progname of the process
+ # * `toolcontext.nit_dir`
# Path can be added (or removed) by the client
var paths: Array[String] = new Array[String]
return mgroups[rdp]
end
- # Hack, a dir is determined by the presence of a honomymous nit file
+ # Hack, a group is determined by:
+ # * the presence of a honomymous nit file
+ # * the fact that the directory is named `src`
var pn = rdp.basename(".nit")
var mp = dirpath.join_path(pn + ".nit").simplify_path
- if not mp.file_exists then return null
+ var dirpath2 = dirpath
+ if not mp.file_exists then
+ if pn == "src" then
+ # With a src directory, the group name is the name of the parent directory
+ dirpath2 = rdp.dirname
+ pn = dirpath2.basename("")
+ else
+ return null
+ end
+ end
# check parent directory
var parentpath = dirpath.join_path("..").simplify_path
mgroup = new MGroup(pn, parent.mproject, parent)
toolcontext.info("found sub group `{mgroup.full_name}` at {dirpath}", 2)
end
+ var readme = dirpath2.join_path("README.md")
+ if not readme.file_exists then readme = dirpath2.join_path("README")
+ if readme.file_exists then
+ var mdoc = new MDoc
+ var s = new IFStream.open(readme)
+ while not s.eof do
+ mdoc.content.add(s.read_line)
+ end
+ mgroup.mdoc = mdoc
+ mdoc.original_mentity = mgroup
+ end
mgroup.filepath = dirpath
mgroups[rdp] = mgroup
return mgroup
if decl != null then
var ndoc = decl.n_doc
- if ndoc != null then mmodule.mdoc = ndoc.to_mdoc
+ if ndoc != null then
+ var mdoc = ndoc.to_mdoc
+ mmodule.mdoc = mdoc
+ mdoc.original_mentity = mmodule
+ end
end
return mmodule
end
self.toolcontext.info("{mmodule} imports {imported_modules.join(", ")}", 3)
mmodule.set_imported_mmodules(imported_modules)
+
+ # 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
# All the loaded modules