X-Git-Url: http://nitlanguage.org diff --git a/src/loader.nit b/src/loader.nit index a046815..312d02b 100644 --- a/src/loader.nit +++ b/src/loader.nit @@ -72,8 +72,9 @@ redef class ModelBuilder if nmodule == null then continue # Skip error # Load imported module build_module_importation(nmodule) - - mmodules.add(nmodule.mmodule.as(not null)) + var mmodule = nmodule.mmodule + if mmodule == null then continue # skip error + mmodules.add mmodule end var time1 = get_time self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2) @@ -100,16 +101,28 @@ redef class ModelBuilder if nmodule == null then continue # Skip error # Load imported module build_module_importation(nmodule) - - res.add(nmodule.mmodule.as(not null)) + var mmodule = nmodule.mmodule + if mmodule == null then continue # Skip error + res.add mmodule end end return res end # Load a bunch of modules and groups. - # Each name can be a module or a group. - # If it is a group then recursively all its modules are parsed. + # + # Each name can be: + # + # * a path to a module, a group or a directory of projects. + # * a short name of a module or a group that are looked in the `paths` (-I) + # + # Then, for each entry, if it is: + # + # * a module, then is it parser and returned. + # * a group then recursively all its modules are parsed. + # * a directory of projects then all the modules of all projects are parsed. + # * else an error is displayed. + # # See `parse` for details. fun parse_full(names: Sequence[String]): Array[MModule] do @@ -118,17 +131,48 @@ redef class ModelBuilder self.toolcontext.info("*** PARSE ***", 1) var mmodules = new ArraySet[MModule] for a in names do + # Case of a group var mgroup = self.get_mgroup(a) if mgroup != null then mmodules.add_all parse_group(mgroup) continue end + + # Case of a directory that is not a group + var stat = a.to_path.stat + if stat != null and stat.is_dir then + self.toolcontext.info("look in directory {a}", 2) + var fs = a.files + # Try each entry as a group or a module + for f in fs do + var af = a/f + mgroup = get_mgroup(af) + if mgroup != null then + mmodules.add_all parse_group(mgroup) + continue + end + var mp = identify_file(af) + if mp != null then + var nmodule = self.load_module(af) + if nmodule == null then continue # Skip error + build_module_importation(nmodule) + var mmodule = nmodule.mmodule + if mmodule == null then continue # Skip error + mmodules.add mmodule + else + self.toolcontext.info("ignore file {af}", 2) + end + end + continue + end + var nmodule = self.load_module(a) if nmodule == null then continue # Skip error # Load imported module build_module_importation(nmodule) - - mmodules.add(nmodule.mmodule.as(not null)) + var mmodule = nmodule.mmodule + if mmodule == null then continue # Skip error + mmodules.add mmodule end var time1 = get_time self.toolcontext.info("*** END PARSE: {time1-time0} ***", 2) @@ -222,7 +266,7 @@ redef class ModelBuilder if res == null then return null # Forward error # Load imported module build_module_importation(res) - return res.mmodule.as(not null) + return res.mmodule end # Search a module `name` from path `lookpaths`. @@ -330,19 +374,35 @@ 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] end - # Hack, a group is determined by: + # Hack, a group is determined by one of the following: # * the presence of a honomymous nit file # * the fact that the directory is named `src` + # * the fact that there is a sub-directory named `src` var pn = rdp.basename(".nit") var mp = dirpath.join_path(pn + ".nit").simplify_path + # dirpath2 is the root directory + # dirpath is the src subdirectory directory, if any, else it is the same that dirpath2 var dirpath2 = dirpath if not mp.file_exists then if pn == "src" then @@ -350,12 +410,17 @@ redef class ModelBuilder dirpath2 = rdp.dirname pn = dirpath2.basename("") else - return null + # Check a `src` subdirectory + dirpath = dirpath2 / "src" + if not dirpath.file_exists then + # All rules failed, so return null + return null + end end end # check parent directory - var parentpath = dirpath.join_path("..").simplify_path + var parentpath = dirpath2.join_path("..").simplify_path var parent = get_mgroup(parentpath) var mgroup @@ -369,22 +434,36 @@ redef class ModelBuilder 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") + + # search documentation + # in src first so the documentation of the project code can be distinct for the documentation of the project usage + var readme = dirpath.join_path("README.md") + if not readme.file_exists then readme = dirpath.join_path("README") + if not readme.file_exists then 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 + mgroup.filepath = dirpath - mgroups[rdp] = mgroup + mgroups[module_absolute_path(dirpath)] = mgroup + mgroups[module_absolute_path(dirpath2)] = mgroup 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 +496,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 +514,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 +545,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 +630,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 +782,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