diff trunk/src/cmd/ImportGraph.d @ 370:ae4afb66768f

- Renamed findModule() to findModulePath(). - Added struct Edge. - Fix: don't append fileDir to importPaths when it's empty. - Added function findCyclicEdges(). - Added method getFQN() to class ModuleDeclaration. - Added member moduleFQN to class Module. - Renamed Module.fileName to filePath. - Added method setFQN() to class Module. - Fix in Lexer.scanspecialTokenSequence(): corrected MID.
author aziz
date Mon, 03 Sep 2007 16:29:02 +0000
parents 2adf808343d6
children 0bd21b746a04
line wrap: on
line diff
--- a/trunk/src/cmd/ImportGraph.d	Sat Sep 01 19:58:01 2007 +0000
+++ b/trunk/src/cmd/ImportGraph.d	Mon Sep 03 16:29:02 2007 +0000
@@ -13,8 +13,9 @@
 import std.stdio : writefln;
 import std.path : getDirName, dirSep = sep;
 import std.file : exists;
+import std.string : replace;
 
-string findModule(string moduleFQN, string[] importPaths)
+string findModulePath(string moduleFQN, string[] importPaths)
 {
   string modulePath;
   foreach (path; importPaths)
@@ -26,36 +27,66 @@
   return null;
 }
 
+struct Edge
+{
+  Module outgoing;
+  Module incoming;
+  static Edge opCall(Module o, Module i)
+  {
+    Edge e;
+    e.outgoing = o;
+    e.incoming = i;
+    return e;
+  }
+}
+
 void execute(string fileName, string[] importPaths)
 {
   // Add directory of file and global directories to import paths.
-  importPaths ~= getDirName(fileName) ~ GlobalSettings.importPaths;
+  auto fileDir = getDirName(fileName);
+  if (fileDir.length)
+    importPaths ~= fileDir;
+  importPaths ~= GlobalSettings.importPaths;
 
   Module[string] loadedModules;
+  Module[] loadedModulesList; // Ordered list of loaded modules.
+  Edge edges[];
 
-  Module loadModule(string moduleFQN)
+  Module loadModule(string moduleFQNPath)
   {
-    auto mod_ = moduleFQN in loadedModules;
+    auto mod_ = moduleFQNPath in loadedModules;
     if (mod_ !is null)
       return *mod_;
 // writefln(moduleFQN);
-    auto modulePath = findModule(moduleFQN, importPaths);
+    auto modulePath = findModulePath(moduleFQNPath, importPaths);
+    Module mod;
     if (modulePath is null)
-      writefln("Warning: Module %s.d couldn't be found.", moduleFQN);
+    {
+// writefln("Warning: Module %s.d couldn't be found.", moduleFQNPath);
+      mod = new Module(null, true);
+      mod.setFQN(replace(moduleFQNPath, dirSep, "."));
+      loadedModules[moduleFQNPath] = mod;
+      loadedModulesList ~= mod;
+    }
     else
     {
-      auto mod = new Module(modulePath, true);
+      mod = new Module(modulePath, true);
       mod.parse();
 
-      loadedModules[moduleFQN] = mod;
+      loadedModules[moduleFQNPath] = mod;
+      loadedModulesList ~= mod;
 
       auto moduleFQNs = mod.getImports();
 
       foreach (moduleFQN_; moduleFQNs)
-        mod.modules ~= loadModule(moduleFQN_);
+      {
+        auto loaded_mod = loadModule(moduleFQN_);
+        edges ~= Edge(mod, loaded_mod);
+        mod.modules ~= loaded_mod;
+      }
       return mod;
     }
-    return null;
+    return mod;
   }
 
   auto mod = new Module(fileName, true);
@@ -63,6 +94,54 @@
 
   auto moduleFQNs = mod.getImports();
 
+  loadedModules[mod.getFQNPath()] = mod;
+  loadedModulesList ~= mod;
+
   foreach (moduleFQN_; moduleFQNs)
-    mod.modules ~= loadModule(moduleFQN_);
+  {
+    auto loaded_mod = loadModule(moduleFQN_);
+    edges ~= Edge(mod, loaded_mod);
+    mod.modules ~= loaded_mod;
+  }
+
+  writefln("digraph module_dependencies\n{");
+  foreach (edge; edges)
+  {
+    writefln(`  "%s" -> "%s"`, edge.outgoing.getFQN(), edge.incoming.getFQN());
+  }
+  writefln("}");
 }
+
+Edge[] findCyclicEdges(Module[] modules, Edge[] edges)
+{
+  foreach (module_; modules)
+  {
+    uint outgoing, incoming;
+    foreach (edge; edges)
+    {
+      if (edge.outgoing == module_)
+        outgoing++;
+      if (edge.incoming == module_)
+        incoming++;
+    }
+
+    if (outgoing == 0)
+    {
+      if (incoming != 0)
+      {
+        // sink
+      }
+      else
+        assert(0); // orphaned vertex (module) in graph
+    }
+    else if (incoming == 0)
+    {
+      // source
+    }
+    else
+    {
+      // source && sink
+    }
+  }
+  return null;
+}