comparison trunk/src/cmd/ImportGraph.d @ 702:e10838e0b182

Fixed filter delegate in cmd.ImportGraph. Added members isPublic and isStatic to class Edge.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 27 Jan 2008 18:21:42 +0100
parents 4c0ea78a7f8b
children bf10602159c1
comparison
equal deleted inserted replaced
701:65ad2f96df1f 702:e10838e0b182
58 { 58 {
59 vertex.id = vertices.length; 59 vertex.id = vertices.length;
60 vertices ~= vertex; 60 vertices ~= vertex;
61 } 61 }
62 62
63 void addEdge(Vertex from, Vertex to) 63 Edge addEdge(Vertex from, Vertex to)
64 { 64 {
65 edges ~= new Edge(from, to); 65 auto edge = new Edge(from, to);
66 edges ~= edge;
66 from.outgoing ~= to; 67 from.outgoing ~= to;
67 to.incoming ~= from; 68 to.incoming ~= from;
69 return edge;
68 } 70 }
69 71
70 /// Walks the graph and marks cyclic vertices and edges. 72 /// Walks the graph and marks cyclic vertices and edges.
71 void detectCycles() 73 void detectCycles()
72 { // Cycles could also be detected in the GraphBuilder, 74 { // Cycles could also be detected in the GraphBuilder,
73 // but having the code here makes things much clearer. 75 // but having the code here makes things much clearer.
76
77 // Returns true if the vertex is in status Visiting.
74 bool visit(Vertex vertex) 78 bool visit(Vertex vertex)
75 { 79 {
76 if (vertex.status == Vertex.Status.Visiting) 80 switch (vertex.status)
77 { 81 {
82 case Vertex.Status.Visiting:
78 vertex.isCyclic = true; 83 vertex.isCyclic = true;
79 return true; 84 return true;
80 } 85 case Vertex.Status.None:
81 if (vertex.status == Vertex.Status.Visited) 86 vertex.status = Vertex.Status.Visiting; // Flag as visiting.
82 return false; 87 foreach (outVertex; vertex.outgoing) // Visit successors.
83 // Flag as visiting. 88 vertex.isCyclic |= visit(outVertex);
84 vertex.status = Vertex.Status.Visiting; 89 vertex.status = Vertex.Status.Visited; // Flag as visited.
85 // Visit successors. 90 break;
86 foreach (outVertex; vertex.outgoing) 91 case Vertex.Status.Visited:
87 vertex.isCyclic |= visit(outVertex); 92 break;
88 // Flag as visited. 93 default:
89 vertex.status = Vertex.Status.Visited; 94 assert(0, "unknown vertex status");
90 return false; 95 }
96 return false; // return (vertex.status == Vertex.Status.Visiting);
91 } 97 }
92 // Start visiting vertices. 98 // Start visiting vertices.
93 visit(vertices[0]); 99 visit(vertices[0]);
94 100
95 foreach (edge; edges) 101 foreach (edge; edges)
99 } 105 }
100 106
101 /// Represents a directed connection between two vertices. 107 /// Represents a directed connection between two vertices.
102 class Edge 108 class Edge
103 { 109 {
104 Vertex from; /// Coming from vertex. 110 Vertex from; /// Coming from vertex.
105 Vertex to; /// Going to vertex. 111 Vertex to; /// Going to vertex.
106 bool isCyclic; 112 bool isCyclic; /// Edge connects cyclic vertices.
113 bool isPublic; /// Public import.
114 bool isStatic; /// Static import.
107 115
108 this(Vertex from, Vertex to) 116 this(Vertex from, Vertex to)
109 { 117 {
110 this.from = from; 118 this.from = from;
111 this.to = to; 119 this.to = to;
113 } 121 }
114 122
115 /// Represents a module in the graph. 123 /// Represents a module in the graph.
116 class Vertex 124 class Vertex
117 { 125 {
118 Module modul; /// The module represented by this vertex. 126 Module modul; /// The module represented by this vertex.
119 uint id; /// The nth vertex in the graph. 127 uint id; /// The nth vertex in the graph.
120 Vertex[] incoming; /// Also called predecessors. 128 Vertex[] incoming; /// Also called predecessors.
121 Vertex[] outgoing; /// Also called successors. 129 Vertex[] outgoing; /// Also called successors.
122 bool isCyclic; /// Whether this vertex is in a cyclic relationship with other vertices. 130 bool isCyclic; /// Whether this vertex is in a cyclic relationship with other vertices.
123 131
124 enum Status : ubyte 132 enum Status : ubyte
125 { None, Visiting, Visited } 133 { None, Visiting, Visited }
126 Status status; /// Used by the cycle detection algorithm. 134 Status status; /// Used by the cycle detection algorithm.
127 } 135 }
151 Params: 159 Params:
152 moduleFQNPath = e.g.: dil/ast/Node (module FQN = dil.ast.Node) 160 moduleFQNPath = e.g.: dil/ast/Node (module FQN = dil.ast.Node)
153 +/ 161 +/
154 Vertex loadModule(string moduleFQNPath) 162 Vertex loadModule(string moduleFQNPath)
155 { 163 {
156 // Filter out modules.
157 if (filterPredicate(moduleFQNPath))
158 return null;
159
160 // Look up in table if the module is already loaded. 164 // Look up in table if the module is already loaded.
161 auto pVertex = moduleFQNPath in loadedModulesTable; 165 auto pVertex = moduleFQNPath in loadedModulesTable;
162 if (pVertex !is null) 166 if (pVertex !is null)
163 return *pVertex; // Return already loaded module. 167 return *pVertex; // Returns null for filtered or unlocatable modules.
168
169 // Filter out modules.
170 if (filterPredicate && filterPredicate(moduleFQNPath))
171 { // Store null for filtered modules.
172 loadedModulesTable[moduleFQNPath] = null;
173 return null;
174 }
164 175
165 // Locate the module in the file system. 176 // Locate the module in the file system.
166 auto moduleFilePath = findModulePath(moduleFQNPath, importPaths); 177 auto moduleFilePath = findModulePath(moduleFQNPath, importPaths);
167 178
168 Vertex vertex; 179 Vertex vertex;
173 { // Include module nevertheless. 184 { // Include module nevertheless.
174 vertex = new Vertex; 185 vertex = new Vertex;
175 vertex.modul = new Module(""); 186 vertex.modul = new Module("");
176 vertex.modul.setFQN(replace(moduleFQNPath, dirSep, '.')); 187 vertex.modul.setFQN(replace(moduleFQNPath, dirSep, '.'));
177 graph.addVertex(vertex); 188 graph.addVertex(vertex);
178 loadedModulesTable[moduleFQNPath] = vertex; 189 }
179 } 190 // Store vertex in the table (vertex may be null.)
191 loadedModulesTable[moduleFQNPath] = vertex;
180 } 192 }
181 else 193 else
182 { 194 {
183 auto modul = new Module(moduleFilePath); 195 auto modul = new Module(moduleFilePath);
184 // Use lightweight ImportParser. 196 // Use lightweight ImportParser.
188 vertex = new Vertex; 200 vertex = new Vertex;
189 vertex.modul = modul; 201 vertex.modul = modul;
190 202
191 graph.addVertex(vertex); 203 graph.addVertex(vertex);
192 loadedModulesTable[modul.getFQNPath()] = vertex; 204 loadedModulesTable[modul.getFQNPath()] = vertex;
193 // Load modules which this module depends on. 205
194 foreach (moduleFQNPath_; modul.getImportPaths()) 206 // Load the modules which this module depends on.
195 { 207 foreach (importDecl; modul.imports)
196 auto loaded = loadModule(moduleFQNPath_); 208 {
197 if (loaded !is null) 209 foreach (moduleFQNPath2; importDecl.getModuleFQNs(dirSep))
198 graph.addEdge(vertex, loaded); 210 {
211 auto loaded = loadModule(moduleFQNPath2);
212 if (loaded !is null)
213 {
214 auto edge = graph.addEdge(vertex, loaded);
215 edge.isPublic = importDecl.isPublic();
216 edge.isStatic = importDecl.isStatic();
217 }
218 }
199 } 219 }
200 } 220 }
201 return vertex; 221 return vertex;
202 } 222 }
203 } 223 }
222 gbuilder.importPaths = importPaths; 242 gbuilder.importPaths = importPaths;
223 gbuilder.options = options; 243 gbuilder.options = options;
224 gbuilder.filterPredicate = (string moduleFQNPath) { 244 gbuilder.filterPredicate = (string moduleFQNPath) {
225 foreach (rx; regexps) 245 foreach (rx; regexps)
226 // Replace slashes: dil/ast/Node -> dil.ast.Node 246 // Replace slashes: dil/ast/Node -> dil.ast.Node
227 if (rx.test(replace(moduleFQNPath, dirSep, '.'))) 247 if (rx.test(replace(moduleFQNPath.dup, dirSep, '.')))
228 return true; 248 return true;
229 return false; 249 return false;
230 }; 250 };
231 251
232 auto graph = gbuilder.start(filePath.name()); 252 auto graph = gbuilder.start(filePath.name());