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