X-Git-Url: http://nitlanguage.org diff --git a/src/loader.nit b/src/loader.nit index 7f5a245..f18d7be 100644 --- a/src/loader.nit +++ b/src/loader.nit @@ -39,6 +39,7 @@ module loader import modelbuilder_base import ini +import picnit_shared redef class ToolContext # Option --path @@ -65,6 +66,11 @@ redef class ModelBuilder # Setup the paths value paths.append(toolcontext.opt_path.value) + # Packages managed by picnit, only use when not testing with tests.sh + if "NIT_TESTING_TESTS_SH".environ != "true" then + paths.add picnit_lib_dir + end + var path_env = "NIT_PATH".environ if not path_env.is_empty then paths.append(path_env.split_with(':')) @@ -135,6 +141,7 @@ redef class ModelBuilder alpha_comparator.sort(fs) # Try each entry as a group or a module for f in fs do + if f.first == '.' then continue var af = a/f mgroup = identify_group(af) if mgroup != null then @@ -375,6 +382,53 @@ redef class ModelBuilder end end + # Found nothing? maybe it is a qualified name + if path.chars.has(':') then + var ids = path.split("::") + var g = identify_group(ids.first) + if g != null then + scan_group(g) + var ms = g.mmodules_by_name(ids.last) + + # Return exact match + for m in ms do + if m.full_name == path then + return m + end + end + + # Where there is only one or two names `foo::bar` + # then accept module that matches `foo::*::bar` + if ids.length <= 2 then + if ms.length == 1 then return ms.first + if ms.length > 1 then + var l = new Array[String] + for m in ms do + var fp = m.filepath + if fp != null then fp = " ({fp})" else fp = "" + l.add "`{m.full_name}`{fp}" + end + last_loader_error = "Error: conflicting module for `{path}`: {l.join(", ")} " + return null + end + end + + var bests = new BestDistance[String](path.length / 2) + # We found nothing. But propose something in the package? + for sg in g.mpackage.mgroups do + for m in sg.mmodules do + var d = path.levenshtein_distance(m.full_name) + bests.update(d, m.full_name) + end + end + var last_loader_error = "Error: cannot find module `{path}`." + if bests.best_items.not_empty then + last_loader_error += " Did you mean " + bests.best_items.join(", ", " or ") + "?" + end + self.last_loader_error = last_loader_error + return null + end + end return null end @@ -589,6 +643,7 @@ redef class ModelBuilder var files = p.files alpha_comparator.sort(files) for f in files do + if f.first == '.' then continue var fp = p/f var g = identify_group(fp) # Recursively scan for groups of the same package @@ -695,7 +750,7 @@ redef class ModelBuilder # Injection of a new module without source. # Used by the interpreter. - fun load_rt_module(parent: nullable MModule, nmodule: AModule, mod_name: String): nullable AModule + fun load_rt_module(parent: nullable MModule, nmodule: AModule, mod_name: String): nullable MModule do # Create the module @@ -712,11 +767,10 @@ redef class ModelBuilder imported_modules.add(parent) mmodule.set_visibility_for(parent, intrude_visibility) mmodule.set_imported_mmodules(imported_modules) - else - build_module_importation(nmodule) end + build_module_importation(nmodule) - return nmodule + return mmodule end # Visit the AST and create the `MModule` object @@ -764,8 +818,8 @@ redef class ModelBuilder mmodule.mdoc = mdoc mdoc.original_mentity = mmodule end - # Is the module a test suite? - mmodule.is_test_suite = not decl.get_annotations("test_suite").is_empty + # Is the module generated? + mmodule.is_generated = not decl.get_annotations("generated").is_empty end end @@ -998,7 +1052,7 @@ redef class ModelBuilder # (and `build_module_importation` that calls it). # # TODO (when the loader will be rewritten): use a better representation and move up rules in the model. - private var conditional_importations = new Array[SequenceRead[MModule]] + var conditional_importations = new Array[SequenceRead[MModule]] # Extends the current importations according to imported rules about conditional importation fun apply_conditional_importations(mmodule: MModule) @@ -1014,7 +1068,7 @@ redef class ModelBuilder for i in [1..ci.length[ do var m = ci[i] # Is imported? - if not mmodule.in_importation.greaters.has(m) then continue label + if mmodule == m or not mmodule.in_importation.greaters.has(m) then continue label end # Still here? It means that all conditions modules are loaded and imported