11use petgraph:: stable_graph:: EdgeIndex ;
22use petgraph:: stable_graph:: NodeIndex ;
33use petgraph:: stable_graph:: StableDiGraph ;
4+ use petgraph:: visit:: EdgeRef ;
45use petgraph:: Direction ;
56
67use std:: {
@@ -53,20 +54,27 @@ impl CachedStableGraph {
5354 }
5455 }
5556
57+ // Returns the `PathBuf` for a given `NodeIndex`
5658 pub fn get_node ( & self , node : NodeIndex ) -> PathBuf {
5759 PathBuf :: from_str ( & self . graph [ node] ) . unwrap ( )
5860 }
5961
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 ( )
7078 }
7179
7280 pub fn add_node ( & mut self , name : & Path ) -> NodeIndex {
@@ -83,61 +91,36 @@ impl CachedStableGraph {
8391 self . graph . add_edge ( parent, child, meta)
8492 }
8593
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 ) {
10595 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) ) ;
113100 }
114101
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+ } )
117108 }
118109
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)
134112 }
135113
136114 pub fn collect_root_ancestors ( & self , node : NodeIndex ) -> Vec < NodeIndex > {
137115 let mut visited = HashSet :: new ( ) ;
138116 self . get_root_ancestors ( node, node, & mut visited)
139117 }
140118
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+
141124 fn get_root_ancestors ( & self , initial : NodeIndex , node : NodeIndex , visited : & mut HashSet < NodeIndex > ) -> Vec < NodeIndex > {
142125 if node == initial && !visited. is_empty ( ) {
143126 return vec ! [ ] ;
@@ -163,10 +146,36 @@ impl CachedStableGraph {
163146 }
164147}
165148
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+
166173#[ cfg( test) ]
167174mod graph_test {
168175 use std:: path:: PathBuf ;
169176
177+ use petgraph:: graph:: NodeIndex ;
178+
170179 use crate :: { graph:: CachedStableGraph , IncludePosition } ;
171180
172181 #[ test]
@@ -182,7 +191,7 @@ mod graph_test {
182191 assert_eq ! ( children. len( ) , 1 ) ;
183192 assert_eq ! ( children[ 0 ] , Into :: <PathBuf >:: into( "banana" . to_string( ) ) ) ;
184193
185- let children = graph. child_node_indexes ( idx1) ;
194+ let children: Vec < NodeIndex > = graph. child_node_indexes ( idx1) . collect ( ) ;
186195 assert_eq ! ( children. len( ) , 1 ) ;
187196 assert_eq ! ( children[ 0 ] , idx2) ;
188197
@@ -207,10 +216,33 @@ mod graph_test {
207216 graph. remove_node ( & PathBuf :: from ( "sample" ) ) ;
208217 assert_eq ! ( graph. graph. node_count( ) , 1 ) ;
209218 assert ! ( graph. find_node( & PathBuf :: from( "sample" ) ) . is_none( ) ) ;
219+
210220 let neighbors = graph. child_node_names ( idx2) ;
211221 assert_eq ! ( neighbors. len( ) , 0 ) ;
212222 }
213223
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+
214246 #[ test]
215247 #[ logging_macro:: log_scope]
216248 fn test_collect_root_ancestors ( ) {
@@ -287,10 +319,8 @@ mod graph_test {
287319 graph. add_edge ( idx1, idx3, IncludePosition { line : 5 , start : 0 , end : 0 } ) ;
288320
289321 // 0
290- // |
291- // 1
292- // \
293- // 2 \
322+ // \
323+ // 2 1
294324 // \ /
295325 // 3
296326
0 commit comments