nitc: let CC, CXX and NO_STACKTRACE use env value
[nit.git] / src / loader.nit
index 0cd3331..37812f7 100644 (file)
@@ -356,7 +356,7 @@ redef class ModelBuilder
                last_loader_error = null
 
                # special case for not a nit file
-               if not path.has_suffix(".nit") then
+               if not path.has_suffix(".nit") then do
                        # search dirless files in known -I paths
                        if not path.chars.has('/') then
                                var res = search_module_in_paths(null, path, self.paths)
@@ -364,19 +364,66 @@ redef class ModelBuilder
                        end
 
                        # Found nothing? maybe it is a group...
-                       var candidate = null
                        if path.file_exists then
                                var mgroup = identify_group(path)
                                if mgroup != null then
                                        var owner_path = mgroup.filepath.join_path(mgroup.name + ".nit")
-                                       if owner_path.file_exists then candidate = owner_path
+                                       if owner_path.file_exists then
+                                               path = owner_path
+                                               break
+                                       end
                                end
                        end
 
-                       if candidate == null then
-                               return null
+                       # 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
-                       path = candidate
+
+                       return null
                end
 
                # Does the file exists?
@@ -766,6 +813,8 @@ redef class ModelBuilder
                        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 +1047,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 +1063,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