diff trunk/src/docgen/graphutils/writer.d @ 395:ac9cd48151b6

Added couple of docgen modules.
author Jari-Matti M?kel? <jmjm@iki.fi>
date Wed, 19 Sep 2007 23:12:20 +0300
parents
children 49f3afd6a0e8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/docgen/graphutils/writer.d	Wed Sep 19 23:12:20 2007 +0300
@@ -0,0 +1,176 @@
+/**
+ * Author: Jari-Matti Mäkelä
+ * License: GPL3
+ */
+module docgen.graphutils.writer;
+
+public import docgen.misc.misc;
+public import docgen.graphutils.primitives;
+import tango.io.model.IConduit : OutputStream;
+debug import tango.io.Stdout;
+
+enum ImageFormat {
+  PNG,
+  SVG,
+  GIF
+}
+
+const imageFormatExts = [ "png", "svg", "gif" ];
+
+enum GraphFormat {
+  Dot,
+  ModuleNames,
+  ModulePaths
+}
+
+struct GraphOptions {
+  GraphFormat graphFormat;
+  ImageFormat imageFormat;
+  DocFormat docFormat;
+  uint depth;
+  bool IncludeUnlocatableModules;
+  bool HighlightCyclicEdges;
+  bool HighlightCyclicVertices;
+  bool GroupByPackageNames;
+  bool GroupByFullPackageName;
+}
+
+interface GraphWriter {
+  void generateGraph(Vertex[], Edge[]);
+}
+
+alias void delegate(Vertex[], Edge[]) GraphWriterDg;
+
+abstract class AbstractGraphWriter : GraphWriter {
+  protected GraphWriterFactory factory;
+  protected OutputStream[] outputs;
+
+  this(GraphWriterFactory factory, OutputStream[] outputs) {
+    this.factory = factory;
+    this.outputs = outputs;
+  }
+
+  /**
+   * Marks all cycles in the graph.
+   *
+   * May have bugs, but is a bit simpler than the previous version.
+   */
+  protected static void findCycles(Vertex[] vertices, Edge[] edges) {
+    debug void p() {
+      foreach(e; edges) Stderr(e.type)(" "c);
+      Stderr.newline;
+    }
+
+    bool visit(Edge edge) {
+      if (edge.type == EdgeType.Reserved) {
+        edge.type = EdgeType.CyclicDependency;
+        debug p();
+        return true;
+      }
+
+      bool wasCyclic = edge.isCyclic();
+      edge.type = EdgeType.Reserved;
+      debug p();
+
+      foreach(edge2; edge.incoming.outgoingEdges)
+        if (visit(edge2)) {
+          if (edge.isCyclic()) {
+            edge.type = EdgeType.Reserved;
+            wasCyclic = true;
+            debug p();
+            continue;
+          }
+          edge.type = EdgeType.CyclicDependency;
+          return true;
+        }
+
+      edge.type = wasCyclic ? EdgeType.CyclicDependency : EdgeType.Dependency;
+      debug p();
+      return false;
+    }
+
+    foreach(vertex; vertices)
+      foreach(edge; vertex.outgoingEdges)
+        if (edge.type == EdgeType.Unspecified) {
+          visit(edge);
+          debug Stderr("*\n");
+        }
+  }
+
+    /+
+    void analyzeGraph(Vertex[] vertices, Edge[] edges)
+    {
+    void recursive(Vertex[] modules)
+    {
+      foreach (idx, vertex; vertices)
+      {
+        uint outgoing, incoming;
+        foreach (j, edge; edges)
+        {
+          if (edge.outgoing is vertex)
+            outgoing++;
+          if (edge.incoming is vertex)
+            incoming++;
+        }
+
+        if (outgoing == 0)
+        {
+          if (incoming != 0)
+          {
+            // Vertex is a sink.
+            alias outgoing i; // Reuse
+            alias incoming j; // Reuse
+            // Remove edges.
+            for (i=j=0; i < edges.length; i++)
+              if (edges[i].incoming !is vertex)
+                edges[j++] = edges[i];
+            edges.length = j;
+            vertices = vertices[0..idx] ~ vertices[idx+1..$];
+            return recursive(modules);
+          }
+          else
+            assert(0, "orphaned module: "~vertex.getFQN()~" (has no edges in graph)"); // orphaned vertex (module) in graph
+        }
+        else if (incoming == 0)
+        {
+          // Vertex is a source
+          alias outgoing i; // Reuse
+          alias incoming j; // Reuse
+          // Remove edges.
+          for (i=j=0; i < edges.length; i++)
+            if (edges[i].outgoing !is vertex)
+              edges[j++] = edges[i];
+          edges.length = j;
+          vertices = vertices[0..idx] ~ vertices[idx+1..$];
+          return recursive(modules);
+        }
+//         else
+//         {
+//           // source && sink
+//         }
+      }
+
+      // When reaching this point it means only cylic edges and vertices are left.
+      foreach (vertex; vertices)
+        vertex.isCyclic = true;
+      foreach (edge; edges)
+        if (edge)
+          edge.isCyclic = true;
+    }
+    recursive(vertices);
+    }
+    +/
+}
+
+interface GraphWriterFactory {
+  GraphOptions *options();
+  GraphWriterDg createGraphWriter(OutputStream[] outputs);
+}
+
+abstract class AbstractGraphWriterFactory : GraphWriterFactory {
+  protected GraphOptions m_options;
+
+  public GraphOptions *options() {
+    return &m_options;
+  }
+}
\ No newline at end of file