# HG changeset patch # User Jari-Matti M?kel? # Date 1190232740 -10800 # Node ID ac9cd48151b684e67ac74f897436f83aa0f1a696 # Parent 6440da4adb07d97ca1c7bed2cd3a3c7a4e416ec7 Added couple of docgen modules. diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen-tests.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen-tests.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,55 @@ +/** + * Author: Jari-Matti Mäkelä + * License: GPL3 + */ +module trunk.src.tests; + +import docgen.graphutils.writers; +import tango.io.Stdout; +import tango.io.FileConduit; + +/** + * A temporary test program for the docgen package. + * I'll replace this with proper unittests in the future. + * + */ +void main() { + { + auto a = new Vertex("mod_a", "path.to.mod_a", 1); + auto b = new Vertex("mod_b", "path.to.mod_b", 2); + auto c = new Vertex("mod_c", "path.to.mod_c", 3); + + auto d = new Vertex("mod_d", "path.to.mod_d", 4); + auto e = new Vertex("mod_e", "path.to.mod_e", 5); + auto f = new Vertex("mod_f", "path.to.mod_f", 6); + auto g = new Vertex("mod_g", "path.to.mod_g", 7); + + Edge[] edges; + //edges ~= a.addChild(b); + //edges ~= b.addChild(c); + //edges ~= c.addChild(a); + edges ~= d.addChild(a); + //edges ~= e.addChild(a); + edges ~= b.addChild(d); + edges ~= b.addChild(e); + edges ~= g.addChild(a); + edges ~= b.addChild(f); + edges ~= g.addChild(f); + edges ~= a.addChild(g); + + + + GraphOptions test; + test.graphFormat = GraphFormat.Dot; + test.HighlightCyclicVertices = true; + //test.format = GraphOutputFormat.ModuleNames; + //test.format = GraphOutputFormat.ModulePaths; + test.depth = 5; + //test.depth++; + + auto gwf = new DefaultGraphWriterFactory(test); + auto writer = gwf.createGraphWriter([Stdout.stream, new FileConduit("test.dot", FileConduit.WriteCreate)]); + + writer([a,b,c,d,e,f,g], edges); + } +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/archdoc.xmi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/archdoc.xmi Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,1066 @@ + + + + + umbrello uml modeller http://uml.sf.net + 1.5.71 + UnicodeUTF8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/docgen.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/docgen.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,22 @@ +/** + * Author: Jari-Matti Mäkelä + * License: GPL3 + */ +module trunk.src.docgen.docgen; + +import docgen.modulegraph.writer; + +struct DocGeneratorOptions { + GraphWriterOptions graph; + ListingsOptions listings; + CommentFormat commentFormat; +} + +/** + * Main routine for doc generation. + */ +class DocGenerator { + public static void generate() { + + } +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/graphutils/dotwriter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/graphutils/dotwriter.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,97 @@ +/** + * Author: Aziz Köksal & Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.graphutils.dotwriter; +import docgen.graphutils.writer; + +import tango.io.protocol.Writer : Writer; +import tango.io.FileConduit : FileConduit; +import tango.io.Print: Print; +import tango.text.convert.Layout : Layout; + + +/** + * Creates a graph rule file for the dot utility. + * + * TODO: support changing colors / graph style? + */ +class DotWriter : AbstractGraphWriter { + this(GraphWriterFactory factory, OutputStream[] outputs) { + super(factory, outputs); + assert(outputs.length == 2, "Wrong number of outputs"); + } + + void generateGraph(Vertex[] vertices, Edge[] edges) { + auto output2 = new Print!(char)(new Layout!(char), outputs[0]); + auto output = new Print!(char)(new Layout!(char), outputs[1]); + + Vertex[][char[]] verticesByPckgName; + if (factory.options.GroupByFullPackageName) + foreach (module_; vertices) + verticesByPckgName[module_.name] ~= module_; // FIXME: is it name or loc? + + if (factory.options.HighlightCyclicVertices || + factory.options.HighlightCyclicEdges) + findCycles(vertices, edges); + + if (cast(FileConduit)outputs[1]) { + // name of the .dot file + char[] fn = (cast(FileConduit)outputs[1]).toUtf8(); + + // .dot -> .svg/.png/.gif/... + fn = fn[0..$-3] ~ imageFormatExts[factory.options.imageFormat]; + + switch(factory.options.docFormat) { + case DocFormat.LaTeX: + output2.format("\\includegraphics{{{0}}", fn); + break; + case DocFormat.XML: + // TODO + break; + case DocFormat.HTML: + output2.format(``, fn); + break; + case DocFormat.PlainText: + throw new Exception("Dot output is not supported in plain text mode."); + } + } + + output("Digraph ModuleDependencies {\n"); + + if (factory.options.HighlightCyclicVertices) + foreach (module_; vertices) + output.format( + ` n{0} [label="{1}"{2}];`\n, + module_.id, + module_.name, + (module_.isCyclic ? ",style=filled,fillcolor=tomato" : "") + ); + else + foreach (i, module_; vertices) + output.format(` n{0} [label="{1}"];`, i, module_.name); + + foreach (edge; edges) + output.format( + ` n{0} -> n{1}{2};`\n, + edge.outgoing.id, + edge.incoming.id, + (edge.isCyclic ? "[color=red]" : "") + ); + + if (factory.options.GroupByFullPackageName) + foreach (packageName, vertices; verticesByPckgName) { + output.format( + ` subgraph "cluster_{0}" {{`\n` label="{0}";color=blue;`\n` `, + packageName, + packageName + ); + + foreach (module_; vertices) + output.format(`n{0};`, module_.id); + output("\n }\n"); + } + + output("}"); + } +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/graphutils/modulenamewriter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/graphutils/modulenamewriter.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,38 @@ +/** + * Author: Aziz Köksal & Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.graphutils.modulenamewriter; +import docgen.graphutils.writer; + +import tango.io.protocol.Writer : Writer; +import tango.io.FileConduit : FileConduit; +import tango.io.Print: Print; +import tango.text.convert.Layout : Layout; + + +/** + * TODO: add support for html/xml/latex? + */ +class ModuleNameWriter : AbstractGraphWriter { + this(GraphWriterFactory factory, OutputStream[] outputs) { + super(factory, outputs); + assert(outputs.length == 1, "Wrong number of outputs"); + } + + void generateGraph(Vertex[] vertices, Edge[] edges) { + auto output = new Writer(outputs[0]); + + void doList(Vertex[] v, uint level, char[] indent = "") { + if (!level) return; + + foreach (vertex; v) { + output(indent)(vertex.name).newline; + if (vertex.outgoing.length) + doList(vertex.outgoing, level-1, indent ~ " "); + } + } + + doList(vertices, factory.options.depth); + } +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/graphutils/modulepathwriter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/graphutils/modulepathwriter.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,37 @@ +/** + * Author: Aziz Köksal & Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.graphutils.modulepathwriter; +import docgen.graphutils.writer; + +import tango.io.protocol.Writer : Writer; +import tango.io.FileConduit : FileConduit; +import tango.io.Print: Print; +import tango.text.convert.Layout : Layout; + +/** + * TODO: add support for html/xml/latex? + */ +class ModulePathWriter : AbstractGraphWriter { + this(GraphWriterFactory factory, OutputStream[] outputs) { + super(factory, outputs); + assert(outputs.length == 1, "Wrong number of outputs"); + } + + void generateGraph(Vertex[] vertices, Edge[] edges) { + auto output = new Writer(outputs[0]); + + void doPaths(Vertex[] v, uint level, char[] indent = "") { + if (!level) return; + + foreach (vertex; v) { + output(indent)(vertex.location).newline; + if (vertex.outgoing.length) + doPaths(vertex.outgoing, level-1, indent ~ " "); + } + } + + doPaths(vertices, factory.options.depth); + } +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/graphutils/primitives.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/graphutils/primitives.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,94 @@ +/** + * Author: Aziz Köksal & Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.graphutils.primitives; + +enum EdgeType { + Unspecified, + Aggregation, + Association, + Composition, + CyclicDependency, + Dependency, + Generalization, + Inheritance, + Reserved // for the cycle algorithm +} + +class Edge { + Vertex outgoing; + Vertex incoming; + EdgeType type; + + this(Vertex o, Vertex i, EdgeType type = EdgeType.Unspecified) { + this.outgoing = o; + this.incoming = i; + this.type = type; + } + + bool isCyclic() { + return type == EdgeType.CyclicDependency; + } +} + +enum VertexType { + Module, + Package, + Class, + Interface, + Trait +} + +class Vertex { + char[] name; + char[] location; + uint id; + + Edge[] incomingEdges; + Edge[] outgoingEdges; + VertexType type; + + this(char[] name, char[] location, uint id = 0) { + this.name = name; + this.location = location; + this.id = id; + } + + Edge addChild(Vertex v, EdgeType type = EdgeType.Unspecified) { + auto edge = new Edge(v, this, type); + incomingEdges ~= edge; + v.outgoingEdges ~= edge; + return edge; + } + + Edge addParent(Vertex v, EdgeType type = EdgeType.Unspecified) { + return v.addChild(this, type); + } + + Vertex[] incoming() { + Vertex[] tmp; + + foreach(edge; incomingEdges) + tmp ~= edge.outgoing; + + return tmp; + } + + Vertex[] outgoing() { + Vertex[] tmp; + + foreach(edge; outgoingEdges) + tmp ~= edge.incoming; + + return tmp; + } + + bool isCyclic() { + foreach(edge; outgoingEdges) + if (edge.isCyclic) + return true; + + return false; + } +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/graphutils/writer.d --- /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 diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/graphutils/writers.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/graphutils/writers.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,27 @@ +/** + * Author: Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.graphutils.writers; + +public import docgen.graphutils.writer; +import docgen.graphutils.dotwriter; +import docgen.graphutils.modulepathwriter; +import docgen.graphutils.modulenamewriter; + +class DefaultGraphWriterFactory : AbstractGraphWriterFactory { + this(GraphOptions options) { + m_options = options; + } + + GraphWriterDg createGraphWriter(OutputStream[] outputs) { + switch (m_options.graphFormat) { + case GraphFormat.Dot: + return &((new DotWriter(this, outputs)).generateGraph); + case GraphFormat.ModuleNames: + return &((new ModuleNameWriter(this, outputs)).generateGraph); + case GraphFormat.ModulePaths: + return &((new ModulePathWriter(this, outputs)).generateGraph); + } + } +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/lstlang0.sty --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/lstlang0.sty Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,21 @@ +%% +%% D definition (c) 2007 Jari-Matti Mäkelä +%% +\lst@definelanguage{D}% + {morekeywords={abstract,alias,align,asm,assert,auto,body,bool,break,% + byte,case,cast,catch,cdouble,cent,cfloat,char,class,const,continue,% + creal,dchar,debug,default,delegate,delete,deprecated,do,double,% + else,enum,export,extern,false,final,finally,float,for,foreach,% + foreach_reverse,function,goto,idouble,if,ifloat,import,in,inout,% + int,interface,invariant,ireal,is,lazy,long,macro,mixin,module,new,% + null,out,override,package,pragma,private,protected,public,real,ref,% + return,scope,short,static,struct,super,switch,synchronized,template,% + this,throw,true,try,typedef,typeid,typeof,ubyte,ucent,uint,ulong,% + union,unittest,ushort,version,void,volatile,wchar,while,with},% + sensitive,% + morecomment=[s]{/*}{*/},% + morecomment=[n]{/+}{+/},% + morecomment=[l]//,% + morestring=[b]",% + morestring=[b]`% + }[keywords,comments,strings]% \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/misc/misc.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/misc/misc.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,17 @@ +/** + * Author: Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.misc.misc; + +enum DocFormat { + LaTeX, + XML, + HTML, + PlainText +} + +enum CommentFormat { + Ddoc, + Doxygen +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/modulegraph/writer.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/modulegraph/writer.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,143 @@ +/** + * Author: Aziz Köksal & Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.modulegraph.writer; + +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; + +alias FileConst.PathSeparatorChar dirSep; + +class ModuleGraphGenerator { + 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()) + return modulePath; + } + + return null; + } + + /** + * 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 loadModules(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; + } + + /** + * TODO + */ + static void generateGraph(GraphWriterOptions *options) { + auto gwf = new DefaultGraphWriterFactory(*options); + + auto writer = gwf.createGraphWriter([Stdout.stream]); + + Edge[] edges; + Vertex[] vertices; + + loadModules(null, null, null, + gwf.options.IncludeUnlocatableModules, + vertices, edges); + + writer(vertices, edges); + } +} diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/sourcelisting/writer.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/sourcelisting/writer.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,41 @@ +/** + * Author: Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.sourcelisting.writer; + +public import docgen.misc.misc; +import dil.Parser; +import tango.io.model.IConduit : OutputStream, InputStream; + +struct ListingOptions { + DocFormat docFormat; +} + +interface ListingWriter { + void generateListing(Parser parser); + void generateListing(InputStream input); +} + +abstract class AbstractListingWriter : ListingWriter { + protected ListingWriterFactory factory; + protected OutputStream[] outputs; + + this(ListingWriterFactory factory, OutputStream[] outputs) { + this.factory = factory; + this.outputs = outputs; + } +} + +interface ListingWriterFactory { + ListingOptions *options(); + ListingWriter createListingWriter(OutputStream[] outputs); +} + +abstract class AbstractListingWriterFactory : ListingWriterFactory { + protected ListingOptions m_options; + + public ListingOptions *options() { + return &m_options; + } +} \ No newline at end of file diff -r 6440da4adb07 -r ac9cd48151b6 trunk/src/docgen/sourcelisting/writers.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/docgen/sourcelisting/writers.d Wed Sep 19 23:12:20 2007 +0300 @@ -0,0 +1,83 @@ +/** + * Author: Jari-Matti Mäkelä + * License: GPL3 + */ +module docgen.sourcelisting.writers; + +public import docgen.sourcelisting.writer; +import dil.Parser; + +class DefaultListingWriterFactory : AbstractListingWriterFactory { + this(ListingOptions options) { + m_options = options; + } + + ListingWriter createListingWriter(OutputStream[] outputs) { + switch (m_options.docFormat) { + case DocFormat.LaTeX: + return new LaTeXWriter(this, outputs); + case DocFormat.XML: + return new XMLWriter(this, outputs); + case DocFormat.HTML: + return new HTMLWriter(this, outputs); + case DocFormat.PlainText: + return new PlainTextWriter(this, outputs); + } + } +} + + +/** + * TODO + */ +class LaTeXWriter : AbstractListingWriter { + this(ListingWriterFactory factory, OutputStream[] outputs) { + super(factory, outputs); + assert(outputs.length == 2, "Wrong number of outputs"); + } + + void generateListing(Parser parser) { /* TODO */ } + void generateListing(InputStream input) { /* TODO */ } +} + + +/** + * TODO + */ +class XMLWriter : AbstractListingWriter { + this(ListingWriterFactory factory, OutputStream[] outputs) { + super(factory, outputs); + assert(outputs.length == 2, "Wrong number of outputs"); + } + + void generateListing(Parser parser) { /* TODO */ } + void generateListing(InputStream input) { /* TODO */ } +} + + +/** + * TODO: add support for html/xml/latex? + */ +class HTMLWriter : AbstractListingWriter { + this(ListingWriterFactory factory, OutputStream[] outputs) { + super(factory, outputs); + assert(outputs.length == 2, "Wrong number of outputs"); + } + + void generateListing(Parser parser) { /* TODO */ } + void generateListing(InputStream input) { /* TODO */ } +} + + +/** + * TODO + */ +class PlainTextWriter : AbstractListingWriter { + this(ListingWriterFactory factory, OutputStream[] outputs) { + super(factory, outputs); + assert(outputs.length == 2, "Wrong number of outputs"); + } + + void generateListing(Parser parser) { /* TODO */ } + void generateListing(InputStream input) { /* TODO */ } +} \ No newline at end of file