Mercurial > projects > dil
diff trunk/src/docgen/misc/parser.d @ 441:13ecfb4278a4
Initial docgen test stuff.
author | Jari-Matti M?kel? <jmjm@iki.fi> |
---|---|
date | Tue, 16 Oct 2007 17:53:59 +0300 |
parents | |
children | 3f44c38bf870 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/misc/parser.d Tue Oct 16 17:53:59 2007 +0300 @@ -0,0 +1,259 @@ +/** + * Author: Aziz Köksal & Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.misc.parser; + +import docgen.graphutils.writers; + +import dil.Parser; +import dil.Module; +import dil.Settings; +import tango.text.Regex : RegExp = Regex; +import tango.io.FilePath; +import tango.io.FileConst; +import tango.text.Util; +import common; +debug import tango.io.Stdout; + +class Parser { + private static string findModulePath(string moduleFQN, string[] importPaths) { + string modulePath; + + foreach (path; importPaths) { + modulePath = path ~ (path[$-1] == dirSep ? "" : [dirSep]) ~ moduleFQN ~ ".d"; + + // TODO: also check for *.di? + + if ((new FilePath(modulePath)).exists()) { + debug Stdout(" * File for ")(moduleFQN)(" found: ")(modulePath).newline; + return modulePath; + } + } + + debug Stdout(" * ")(moduleFQN)(" does not exist in imports")().newline()(); + return null; + } + + /** + * Imports the transitive closure of imports starting from "filePath", + * limited by recursionDepth. + * + * The search can be filtered by providing a list of regexps that match the + * FQNs of modules to be ignored. + * + * Params: + * filePath = Path of the file to parse + * importPaths = Directories to look for imports + * strRegexps = Filter regexps + * IncludeUnlocatableModules = Call the delegate also for unlocatable files + * recursionDepth = How many levels of imports to follow (-1 = no limit) + * mdg = Delegate that gets called for every module found + * idg = Delegate that gets called for every import found + * modules = List of parsed modules + */ + public static void loadModules(string filePath, string[] importPaths, string[] strRegexps, + bool IncludeUnlocatableModules, int recursionDepth, + void delegate (string fqn, string path, Module) mdg, + void delegate (Module imported, Module importer) idg, + out Module[] modules) { + + loadModules([filePath], importPaths, strRegexps, IncludeUnlocatableModules, + recursionDepth, mdg, idg, modules); + } + + /** + * Imports the transitive closure of imports starting from "filePath", + * limited by recursionDepth. + * + * The search can be filtered by providing a list of regexps that match the + * FQNs of modules to be ignored. + * + * Params: + * filePaths = Paths of the files to parse + * importPaths = Directories to look for imports + * strRegexps = Filter regexps + * IncludeUnlocatableModules = Call the delegate also for unlocatable files + * recursionDepth = How many levels of imports to follow (-1 = no limit) + * mdg = Delegate that gets called for every module found + * idg = Delegate that gets called for every import found + * modules = List of parsed modules + */ + public static void loadModules(string[] filePaths, string[] importPaths, string[] strRegexps, + bool IncludeUnlocatableModules, int recursionDepth, + void delegate (string fqn, string path, Module) mdg, + void delegate (Module imported, Module importer) idg, + out Module[] modules) { + // Initialize regular expressions. + RegExp[] regexps; + foreach (strRegexp; strRegexps) + regexps ~= new RegExp(strRegexp); + + // Add directory of file and global directories to import paths. + foreach(filePath; filePaths) { + auto fileDir = (new FilePath(filePath)).folder(); + if (fileDir.length) + importPaths ~= fileDir; + } + + importPaths ~= GlobalSettings.importPaths; + + debug foreach(path; importPaths) { + Stdout("Import path: ")(path).newline; + } + + Module[string] loadedModules; + + Module loadModule(string moduleFQNPath, int depth) { + if (depth == 0) return null; + + debug Stdout("Loading ")(moduleFQNPath).newline; + + // Return already loaded module. + auto mod_ = moduleFQNPath in loadedModules; + if (mod_ !is null) { + debug Stdout(" Already loaded.")(moduleFQNPath).newline; + return *mod_; + } + + auto FQN = replace(moduleFQNPath.dup, dirSep, '.'); + + // Ignore module names matching regular expressions. + foreach (rx; regexps) + if (rx.test(FQN)) return null; + + auto modulePath = findModulePath(moduleFQNPath, importPaths); + //foreach(filePath; filePaths) + //if (moduleFQNPath == filePath) modulePath = filePath; + + debug Stdout(" FQN ")(FQN).newline; + debug Stdout(" Module path ")(modulePath).newline; + + Module mod = null; + + if (modulePath is null) { + if (IncludeUnlocatableModules) + mdg(FQN, moduleFQNPath, null); + } else { + mod = new Module(modulePath); + loadedModules[moduleFQNPath] = mod; + mod.parse(); + + mdg(FQN, moduleFQNPath, mod); + + auto moduleFQNs = mod.getImports(); + + foreach (moduleFQN_; moduleFQNs) { + auto loaded_mod = loadModule(moduleFQN_, depth == -1 ? depth : depth-1); + + if (loaded_mod !is null) + idg(loaded_mod, mod); + } + } + + return mod; + } // loadModule + + foreach(filePath; filePaths) + loadModule(filePath, recursionDepth); + + // Finished loading modules. + + // Ordered list of loaded modules. + modules = loadedModules.values; + } + + + /+ Old version - deprecated + + /** + * Imports the transitive closure of imports starting from "filePath". + * + * The search can be filtered by providing a list of regexps that match the + * FQNs of modules to be ignored. + * + * TODO: integrate better with the docgen stuff - there's no need to + * scan&parse several times + */ + public static void loadModules2(string filePath, string[] importPaths, + string[] strRegexps, + bool IncludeUnlocatableModules, + out Vertex[] vertices, out Edge[] edges, + out Module[] modules) { + // Init regular expressions. + RegExp[] regexps; + foreach (strRegexp; strRegexps) + regexps ~= new RegExp(strRegexp); + + // Add directory of file and global directories to import paths. + auto fileDir = (new FilePath(filePath)).folder(); + if (fileDir.length) + importPaths ~= fileDir; + importPaths ~= GlobalSettings.importPaths; + + Vertex[string] loadedModules; + Edge[] _edges; + Module[] _modules; + + int modCounter = 0; + + void addModule(Vertex mod) { + assert(!(mod.location in loadedModules)); + + mod.id = modCounter++; + loadedModules[mod.location] = mod; + } + + Vertex loadModule(string moduleFQNPath) { + // Return already loaded module. + auto mod_ = moduleFQNPath in loadedModules; + if (mod_ !is null) return *mod_; + + // Ignore module names matching regular expressions. + foreach (rx; regexps) + if (rx.test(replace(moduleFQNPath, dirSep, '.'))) + return null; + + auto modulePath = findModulePath(moduleFQNPath, importPaths); + if (moduleFQNPath == filePath) modulePath = filePath; + auto FQN = replace(moduleFQNPath, dirSep, '.'); + + Vertex mod; + + if (modulePath is null) { + if (IncludeUnlocatableModules) { + mod = new Vertex(FQN, moduleFQNPath); + addModule(mod); + } + } else { + mod = new Vertex(FQN, moduleFQNPath); + addModule(mod); + + auto m = new Module(modulePath); + _modules ~= m; + m.parse(); + + auto moduleFQNs = m.getImports(); + + foreach (moduleFQN_; moduleFQNs) { + auto loaded_mod = loadModule(moduleFQN_); + + if (loaded_mod !is null) + loaded_mod.addChild(mod); + } + } + + return mod; + } // loadModule + + loadModule(filePath); + + // Finished loading modules. + + // Ordered list of loaded modules. + vertices = loadedModules.values; + edges = _edges; + modules = _modules; + } + +/ +} \ No newline at end of file