1
1
use petgraph:: stable_graph:: EdgeIndex ;
2
2
use petgraph:: stable_graph:: NodeIndex ;
3
3
use petgraph:: stable_graph:: StableDiGraph ;
4
+ use petgraph:: visit:: EdgeRef ;
4
5
use petgraph:: Direction ;
5
6
6
7
use std:: {
@@ -53,20 +54,27 @@ impl CachedStableGraph {
53
54
}
54
55
}
55
56
57
+ // Returns the `PathBuf` for a given `NodeIndex`
56
58
pub fn get_node ( & self , node : NodeIndex ) -> PathBuf {
57
59
PathBuf :: from_str ( & self . graph [ node] ) . unwrap ( )
58
60
}
59
61
60
- pub fn get_edge_meta ( & self , parent : NodeIndex , child : NodeIndex ) -> & IncludePosition {
61
- self . graph . edge_weight ( self . graph . find_edge ( parent, child) . unwrap ( ) ) . unwrap ( )
62
- }
63
-
64
- #[ allow( dead_code) ]
65
- pub fn remove_node ( & mut self , name : & Path ) {
66
- let idx = self . cache . remove ( name) ;
67
- if let Some ( idx) = idx {
68
- self . graph . remove_node ( idx) ;
69
- }
62
+ /// returns an iterator over all the `IncludePosition`'s between a parent and its child for all the positions
63
+ /// that the child may be imported into the parent, in order of import.
64
+ pub fn get_edge_metas ( & self , parent : NodeIndex , child : NodeIndex ) -> impl Iterator < Item = IncludePosition > + ' _ {
65
+ let mut edges = self
66
+ . graph
67
+ . edges ( parent)
68
+ . filter_map ( move |edge| {
69
+ let target = self . graph . edge_endpoints ( edge. id ( ) ) . unwrap ( ) . 1 ;
70
+ if target != child {
71
+ return None ;
72
+ }
73
+ Some ( self . graph [ edge. id ( ) ] )
74
+ } )
75
+ . collect :: < Vec < IncludePosition > > ( ) ;
76
+ edges. sort_by ( |x, y| x. line . cmp ( & y. line ) ) ;
77
+ edges. into_iter ( )
70
78
}
71
79
72
80
pub fn add_node ( & mut self , name : & Path ) -> NodeIndex {
@@ -83,61 +91,36 @@ impl CachedStableGraph {
83
91
self . graph . add_edge ( parent, child, meta)
84
92
}
85
93
86
- pub fn remove_edge ( & mut self , parent : NodeIndex , child : NodeIndex ) {
87
- let edge = self . graph . find_edge ( parent, child) . unwrap ( ) ;
88
- self . graph . remove_edge ( edge) ;
89
- }
90
-
91
- #[ allow( dead_code) ]
92
- pub fn edge_weights ( & self , node : NodeIndex ) -> Vec < IncludePosition > {
93
- self . graph . edges ( node) . map ( |e| e. weight ( ) . clone ( ) ) . collect ( )
94
- }
95
-
96
- #[ allow( dead_code) ]
97
- pub fn child_node_names ( & self , node : NodeIndex ) -> Vec < PathBuf > {
98
- self . graph
99
- . neighbors ( node)
100
- . map ( |n| self . reverse_index . get ( & n) . unwrap ( ) . clone ( ) )
101
- . collect ( )
102
- }
103
-
104
- pub fn child_node_meta ( & self , node : NodeIndex ) -> Vec < ( PathBuf , IncludePosition ) > {
94
+ pub fn remove_edge ( & mut self , parent : NodeIndex , child : NodeIndex , position : IncludePosition ) {
105
95
self . graph
106
- . neighbors ( node)
107
- . map ( |n| {
108
- let edge = self . graph . find_edge ( node, n) . unwrap ( ) ;
109
- let edge_meta = self . graph . edge_weight ( edge) . unwrap ( ) ;
110
- return ( self . reverse_index . get ( & n) . unwrap ( ) . clone ( ) , edge_meta. clone ( ) ) ;
111
- } )
112
- . collect ( )
96
+ . edges ( parent)
97
+ . find ( |edge| self . graph . edge_endpoints ( edge. id ( ) ) . unwrap ( ) . 1 == child && * edge. weight ( ) == position)
98
+ . map ( |edge| edge. id ( ) )
99
+ . and_then ( |edge| self . graph . remove_edge ( edge) ) ;
113
100
}
114
101
115
- pub fn child_node_indexes ( & self , node : NodeIndex ) -> Vec < NodeIndex > {
116
- self . graph . neighbors ( node) . collect ( )
102
+ pub fn child_node_metas ( & self , node : NodeIndex ) -> impl Iterator < Item = ( PathBuf , IncludePosition ) > + ' _ {
103
+ self . graph . neighbors ( node) . map ( move |n| {
104
+ let edge = self . graph . find_edge ( node, n) . unwrap ( ) ;
105
+ let edge_meta = self . graph . edge_weight ( edge) . unwrap ( ) ;
106
+ return ( self . reverse_index . get ( & n) . unwrap ( ) . clone ( ) , * edge_meta) ;
107
+ } )
117
108
}
118
109
119
- #[ allow( dead_code) ]
120
- pub fn parent_node_names ( & self , node : NodeIndex ) -> Vec < PathBuf > {
121
- self . graph
122
- . neighbors_directed ( node, Direction :: Incoming )
123
- . map ( |n| self . reverse_index . get ( & n) . unwrap ( ) . clone ( ) )
124
- . collect ( )
125
- }
126
-
127
- pub fn parent_node_indexes ( & self , node : NodeIndex ) -> Vec < NodeIndex > {
128
- self . graph . neighbors_directed ( node, Direction :: Incoming ) . collect ( )
129
- }
130
-
131
- #[ allow( dead_code) ]
132
- pub fn get_include_meta ( & self , node : NodeIndex ) -> Vec < IncludePosition > {
133
- self . graph . edges ( node) . map ( |e| e. weight ( ) . clone ( ) ) . collect ( )
110
+ pub fn child_node_indexes ( & self , node : NodeIndex ) -> impl Iterator < Item = NodeIndex > + ' _ {
111
+ self . graph . neighbors ( node)
134
112
}
135
113
136
114
pub fn collect_root_ancestors ( & self , node : NodeIndex ) -> Vec < NodeIndex > {
137
115
let mut visited = HashSet :: new ( ) ;
138
116
self . get_root_ancestors ( node, node, & mut visited)
139
117
}
140
118
119
+ // TODO: impl Iterator
120
+ fn parent_node_indexes ( & self , node : NodeIndex ) -> Vec < NodeIndex > {
121
+ self . graph . neighbors_directed ( node, Direction :: Incoming ) . collect ( )
122
+ }
123
+
141
124
fn get_root_ancestors ( & self , initial : NodeIndex , node : NodeIndex , visited : & mut HashSet < NodeIndex > ) -> Vec < NodeIndex > {
142
125
if node == initial && !visited. is_empty ( ) {
143
126
return vec ! [ ] ;
@@ -163,10 +146,36 @@ impl CachedStableGraph {
163
146
}
164
147
}
165
148
149
+ #[ cfg( test) ]
150
+ impl CachedStableGraph {
151
+ fn parent_node_names ( & self , node : NodeIndex ) -> Vec < PathBuf > {
152
+ self . graph
153
+ . neighbors_directed ( node, Direction :: Incoming )
154
+ . map ( |n| self . reverse_index . get ( & n) . unwrap ( ) . clone ( ) )
155
+ . collect ( )
156
+ }
157
+
158
+ fn child_node_names ( & self , node : NodeIndex ) -> Vec < PathBuf > {
159
+ self . graph
160
+ . neighbors ( node)
161
+ . map ( |n| self . reverse_index . get ( & n) . unwrap ( ) . clone ( ) )
162
+ . collect ( )
163
+ }
164
+
165
+ fn remove_node ( & mut self , name : & Path ) {
166
+ let idx = self . cache . remove ( name) ;
167
+ if let Some ( idx) = idx {
168
+ self . graph . remove_node ( idx) ;
169
+ }
170
+ }
171
+ }
172
+
166
173
#[ cfg( test) ]
167
174
mod graph_test {
168
175
use std:: path:: PathBuf ;
169
176
177
+ use petgraph:: graph:: NodeIndex ;
178
+
170
179
use crate :: { graph:: CachedStableGraph , IncludePosition } ;
171
180
172
181
#[ test]
@@ -182,7 +191,7 @@ mod graph_test {
182
191
assert_eq ! ( children. len( ) , 1 ) ;
183
192
assert_eq ! ( children[ 0 ] , Into :: <PathBuf >:: into( "banana" . to_string( ) ) ) ;
184
193
185
- let children = graph. child_node_indexes ( idx1) ;
194
+ let children: Vec < NodeIndex > = graph. child_node_indexes ( idx1) . collect ( ) ;
186
195
assert_eq ! ( children. len( ) , 1 ) ;
187
196
assert_eq ! ( children[ 0 ] , idx2) ;
188
197
@@ -207,10 +216,33 @@ mod graph_test {
207
216
graph. remove_node ( & PathBuf :: from ( "sample" ) ) ;
208
217
assert_eq ! ( graph. graph. node_count( ) , 1 ) ;
209
218
assert ! ( graph. find_node( & PathBuf :: from( "sample" ) ) . is_none( ) ) ;
219
+
210
220
let neighbors = graph. child_node_names ( idx2) ;
211
221
assert_eq ! ( neighbors. len( ) , 0 ) ;
212
222
}
213
223
224
+ #[ test]
225
+ #[ logging_macro:: log_scope]
226
+ fn test_double_import ( ) {
227
+ let mut graph = CachedStableGraph :: new ( ) ;
228
+
229
+ let idx0 = graph. add_node ( & PathBuf :: from ( "0" ) ) ;
230
+ let idx1 = graph. add_node ( & PathBuf :: from ( "1" ) ) ;
231
+
232
+ graph. add_edge ( idx0, idx1, IncludePosition { line : 2 , start : 0 , end : 0 } ) ;
233
+ graph. add_edge ( idx0, idx1, IncludePosition { line : 4 , start : 0 , end : 0 } ) ;
234
+
235
+ // 0
236
+ // / \
237
+ // 1 1
238
+
239
+ assert_eq ! ( 2 , graph. get_edge_metas( idx0, idx1) . count( ) ) ;
240
+
241
+ let mut edge_metas = graph. get_edge_metas ( idx0, idx1) ;
242
+ assert_eq ! ( Some ( IncludePosition { line: 2 , start: 0 , end: 0 } ) , edge_metas. next( ) ) ;
243
+ assert_eq ! ( Some ( IncludePosition { line: 4 , start: 0 , end: 0 } ) , edge_metas. next( ) ) ;
244
+ }
245
+
214
246
#[ test]
215
247
#[ logging_macro:: log_scope]
216
248
fn test_collect_root_ancestors ( ) {
@@ -287,10 +319,8 @@ mod graph_test {
287
319
graph. add_edge ( idx1, idx3, IncludePosition { line : 5 , start : 0 , end : 0 } ) ;
288
320
289
321
// 0
290
- // |
291
- // 1
292
- // \
293
- // 2 \
322
+ // \
323
+ // 2 1
294
324
// \ /
295
325
// 3
296
326
0 commit comments