comparison trunk/src/docgen/graphutils/primitives.d @ 729:ec8dd7b8bf0c

Updated graph type.
author Jari-Matti M?kel? <jmjm@iki.fi>
date Sun, 03 Feb 2008 19:43:53 +0200
parents b7503e02fbe7
children
comparison
equal deleted inserted replaced
728:41cad5ca4863 729:ec8dd7b8bf0c
2 * Author: Aziz Köksal & Jari-Matti Mäkelä 2 * Author: Aziz Köksal & Jari-Matti Mäkelä
3 * License: GPL3 3 * License: GPL3
4 */ 4 */
5 module docgen.graphutils.primitives; 5 module docgen.graphutils.primitives;
6 6
7 enum EdgeType { 7 /**
8 Unspecified, 8 * Extendible graph class. Should support separation of concerns now better with mixins.
9 Aggregation, 9 * Provides a method for cycle marking.
10 Association, 10 */
11 Composition, 11 class Graph(alias V, alias E, int capacity = 1) {
12 Dependency, 12 static class Edge {
13 Generalization, 13 Vertex outgoing, incoming;
14 Inheritance, 14 //bool cyclic = true;
15 PublicDependency
16 }
17 15
18 enum CycleType { 16 this(Vertex o, Vertex i) {
19 Unspecified, 17 outgoing = o;
20 Cyclefree, 18 incoming = i;
21 Cyclic, 19 o.outgoingEdges ~= this;
22 Reserved 20 i.incomingEdges ~= this;
23 } 21 }
24 22
25 class Edge { 23 bool cyclic() {
26 Vertex outgoing; 24 return outgoing.cyclic && incoming.cyclic;
27 Vertex incoming; 25 }
28 EdgeType type;
29 CycleType cycleType; // used by the cycle algorithm
30 26
31 this(Vertex o, Vertex i, EdgeType type = EdgeType.Unspecified) { 27 mixin E;
32 this.outgoing = o;
33 this.incoming = i;
34 this.type = type;
35 } 28 }
36 29
37 bool isCyclic() { 30 static class Vertex {
38 return cycleType == CycleType.Cyclic; 31 Edge[] incomingEdges;
32 Edge[] outgoingEdges;
33 bool cyclic = true;
34
35 Edge addChild(Vertex v) {
36 return new Edge(v, this);
37 }
38
39 Edge addParent(Vertex v) {
40 return v.addChild(this);
41 }
42
43 Vertex[] incoming() {
44 Vertex[] tmp;
45
46 foreach(edge; incomingEdges)
47 tmp ~= edge.outgoing;
48
49 return tmp;
50 }
51
52 Vertex[] outgoing() {
53 Vertex[] tmp;
54
55 foreach(edge; outgoingEdges)
56 tmp ~= edge.incoming;
57
58 return tmp;
59 }
60
61 mixin V;
62 }
63
64 Vertex[] vertices;
65 Edge[] edges;
66
67 this() {
68 vertices.length = capacity;
69 vertices.length = 0;
70 edges.length = capacity;
71 edges.length = 0;
72 }
73
74 void add(Vertex vertex) { vertices ~= vertex; }
75
76 void add(Edge edge) { edges ~= edge; }
77
78 void connect(Vertex from, Vertex to) { edges ~= from.addParent(to); }
79
80 void connect(int from, int to) { connect(vertices[from], vertices[to]); }
81
82 /**
83 * Starts from non-cyclic nodes and propagates two both directions.
84 * Bugs: marks non-cyclic imports between two cycles as cyclic. Could be fixed later if it's really needed (slow)
85 */
86 void markCycles() {
87 void mark(Vertex v) {
88 v.cyclic = false;
89 foreach(o; v.outgoing) {
90 if (!o.cyclic) continue;
91
92 // propagate
93 bool cyclic = false;
94 foreach(p; o.incoming) if (p.cyclic) { cyclic = true; break; }
95 if (!cyclic) mark(o);
96 }
97 }
98
99 void mark2(Vertex v) {
100 v.cyclic = false;
101 foreach(o; v.incoming) {
102 if (!o.cyclic) continue;
103
104 // propagate
105 bool cyclic = false;
106 foreach(p; o.outgoing) if (p.cyclic) { cyclic = true; break; }
107 if (!cyclic) mark2(o);
108 }
109 }
110
111 foreach(e; vertices)
112 if (e.cyclic) {
113 if (!e.incoming.length) mark(e);
114 if (!e.outgoing.length) mark2(e);
115 }
39 } 116 }
40 } 117 }
41 118
42 enum VertexType { 119 template Empty() {}
43 Module, 120
44 UnlocatableModule, 121
45 Package, 122 // graph elements used in dep graphs
46 Class, 123
47 Interface, 124
48 Trait 125 template DepEdge() {
126 bool isPublic; /// Public import.
127 bool isStatic; /// Static import.
49 } 128 }
50 129
51 class Vertex { 130 template DepVertex() {
52 char[] name; 131 char[] name;
53 char[] location; 132 char[] location;
54 uint id; 133 uint id;
55
56 Edge[] incomingEdges;
57 Edge[] outgoingEdges;
58 VertexType type;
59 134
60 this(char[] name, char[] location, uint id = 0) { 135 this(char[] name, char[] location, uint id = 0) {
61 this.name = name; 136 this.name = name;
62 this.location = location; 137 this.location = location;
63 this.id = id; 138 this.id = id;
64 } 139 }
140 }
65 141
66 Edge addChild(Vertex v, EdgeType type = EdgeType.Unspecified) { 142 alias Graph!(DepVertex, DepEdge, 100) DepGraph;
67 auto edge = new Edge(v, this, type);
68 incomingEdges ~= edge;
69 v.outgoingEdges ~= edge;
70 return edge;
71 }
72
73 Edge addParent(Vertex v, EdgeType type = EdgeType.Unspecified) {
74 return v.addChild(this, type);
75 }
76
77 Vertex[] incoming() {
78 Vertex[] tmp;
79
80 foreach(edge; incomingEdges)
81 tmp ~= edge.outgoing;
82
83 return tmp;
84 }
85
86 Vertex[] outgoing() {
87 Vertex[] tmp;
88
89 foreach(edge; outgoingEdges)
90 tmp ~= edge.incoming;
91
92 return tmp;
93 }
94
95 bool isCyclic() {
96 foreach(edge; outgoingEdges)
97 if (edge.isCyclic)
98 return true;
99
100 return false;
101 }
102 }