model: intro `MModule::first_real_mmodule` to get the first non-fictive module
[nit.git] / src / loader.nit
index a046815..492584b 100644 (file)
@@ -330,8 +330,21 @@ redef class ModelBuilder
 
        # Return the mgroup associated to a directory path.
        # If the directory is not a group null is returned.
+       #
+       # Note: `paths` is also used to look for mgroups
        fun get_mgroup(dirpath: String): nullable MGroup
        do
+               if not dirpath.file_exists then do
+                       for p in paths do
+                               var try = p / dirpath
+                               if try.file_exists then
+                                       dirpath = try
+                                       break label
+                               end
+                       end
+                       return null
+               end label
+
                var rdp = module_absolute_path(dirpath)
                if mgroups.has_key(rdp) then
                        return mgroups[rdp]
@@ -372,11 +385,7 @@ redef class ModelBuilder
                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
+                       var mdoc = load_markdown(readme)
                        mgroup.mdoc = mdoc
                        mdoc.original_mentity = mgroup
                end
@@ -385,6 +394,17 @@ redef class ModelBuilder
                return mgroup
        end
 
+       # Load a markdown file as a documentation object
+       fun load_markdown(filepath: String): MDoc
+       do
+               var mdoc = new MDoc(new Location(new SourceFile.from_string(filepath, ""),0,0,0,0))
+               var s = new FileReader.open(filepath)
+               while not s.eof do
+                       mdoc.content.add(s.read_line)
+               end
+               return mdoc
+       end
+
        # Force the identification of all ModulePath of the group and sub-groups.
        fun visit_group(mgroup: MGroup) do
                var p = mgroup.filepath
@@ -417,7 +437,7 @@ redef class ModelBuilder
                self.toolcontext.info("load module {filename}", 2)
 
                # Load the file
-               var file = new IFStream.open(filename)
+               var file = new FileReader.open(filename)
                var lexer = new Lexer(new SourceFile(filename, file))
                var parser = new Parser(lexer)
                var tree = parser.parse
@@ -435,6 +455,26 @@ redef class ModelBuilder
                return nmodule
        end
 
+       # Remove Nit source files from a list of arguments.
+       #
+       # Items of `args` that can be loaded as a nit file will be removed from `args` and returned.
+       fun filter_nit_source(args: Array[String]): Array[String]
+       do
+               var keep = new Array[String]
+               var res = new Array[String]
+               for a in args do
+                       var l = identify_file(a)
+                       if l == null then
+                               keep.add a
+                       else
+                               res.add a
+                       end
+               end
+               args.clear
+               args.add_all(keep)
+               return res
+       end
+
        # Try to load a module using a path.
        # Display an error if there is a problem (IO / lexer / parser) and return null.
        # Note: usually, you do not need this method, use `get_mmodule_by_name` instead.
@@ -446,7 +486,11 @@ redef class ModelBuilder
                # Look for the module
                var file = identify_file(filename)
                if file == null then
-                       toolcontext.error(null, "Error: cannot find module `{filename}`.")
+                       if filename.file_exists then
+                               toolcontext.error(null, "Error: `{filename}` is not a Nit source file.")
+                       else
+                               toolcontext.error(null, "Error: cannot find module `{filename}`.")
+                       end
                        return null
                end
 
@@ -527,6 +571,12 @@ redef class ModelBuilder
                nmodules.add(nmodule)
                self.mmodule2nmodule[mmodule] = nmodule
 
+               var source = nmodule.location.file
+               if source != null then
+                       assert source.mmodule == null
+                       source.mmodule = mmodule
+               end
+
                if decl != null then
                        # Extract documentation
                        var ndoc = decl.n_doc
@@ -673,6 +723,11 @@ redef class MGroup
 
 end
 
+redef class SourceFile
+       # Associated mmodule, once created
+       var mmodule: nullable MModule = null
+end
+
 redef class AStdImport
        # The imported module once determined
        var mmodule: nullable MModule = null