@@ -121,7 +121,7 @@ pub enum Node<'ast> {
121
121
NodeLifetime ( & ' ast Lifetime ) ,
122
122
}
123
123
124
- /// Represents an entry and its parent Node ID
124
+ /// Represents an entry and its parent NodeID.
125
125
/// The odd layout is to bring down the total size.
126
126
#[ derive( Copy , Debug ) ]
127
127
enum MapEntry < ' ast > {
@@ -179,7 +179,7 @@ impl<'ast> MapEntry<'ast> {
179
179
}
180
180
}
181
181
182
- fn parent ( self ) -> Option < NodeId > {
182
+ fn parent_node ( self ) -> Option < NodeId > {
183
183
Some ( match self {
184
184
EntryItem ( id, _) => id,
185
185
EntryForeignItem ( id, _) => id,
@@ -283,10 +283,88 @@ impl<'ast> Map<'ast> {
283
283
self . find_entry ( id) . and_then ( |x| x. to_node ( ) )
284
284
}
285
285
286
- /// Retrieve the parent NodeId for `id`, or `id` itself if no
287
- /// parent is registered in this map.
286
+ /// Similar to get_parent, returns the parent node id or id if there is no
287
+ /// parent.
288
+ /// This function returns the immediate parent in the AST, whereas get_parent
289
+ /// returns the enclosing item. Note that this might not be the actual parent
290
+ /// node in the AST - some kinds of nodes are not in the map and these will
291
+ /// never appear as the parent_node. So you can always walk the parent_nodes
292
+ /// from a node to the root of the ast (unless you get the same id back here
293
+ /// that can happen if the id is not in the map itself or is just weird).
294
+ pub fn get_parent_node ( & self , id : NodeId ) -> NodeId {
295
+ self . find_entry ( id) . and_then ( |x| x. parent_node ( ) ) . unwrap_or ( id)
296
+ }
297
+
298
+ /// If there is some error when walking the parents (e.g., a node does not
299
+ /// have a parent in the map or a node can't be found), then we return the
300
+ /// last good node id we found. Note that reaching the crate root (id == 0),
301
+ /// is not an error, since items in the crate module have the crate root as
302
+ /// parent.
303
+ fn walk_parent_nodes < F > ( & self , start_id : NodeId , found : F ) -> Result < NodeId , NodeId >
304
+ where F : Fn ( & Node < ' ast > ) -> bool
305
+ {
306
+ let mut id = start_id;
307
+ loop {
308
+ let parent_node = self . get_parent_node ( id) ;
309
+ if parent_node == 0 {
310
+ return Ok ( 0 ) ;
311
+ }
312
+ if parent_node == id {
313
+ return Err ( id) ;
314
+ }
315
+
316
+ let node = self . find_entry ( parent_node) ;
317
+ if node. is_none ( ) {
318
+ return Err ( id) ;
319
+ }
320
+ let node = node. unwrap ( ) . to_node ( ) ;
321
+ match node {
322
+ Some ( ref node) => {
323
+ if found ( node) {
324
+ return Ok ( parent_node) ;
325
+ }
326
+ }
327
+ None => {
328
+ return Err ( parent_node) ;
329
+ }
330
+ }
331
+ id = parent_node;
332
+ }
333
+ }
334
+
335
+ /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
336
+ /// parent item is in this map. The "parent item" is the closest parent node
337
+ /// in the AST which is recorded by the map and is an item, either an item
338
+ /// in a module, trait, or impl.
288
339
pub fn get_parent ( & self , id : NodeId ) -> NodeId {
289
- self . find_entry ( id) . and_then ( |x| x. parent ( ) ) . unwrap_or ( id)
340
+ match self . walk_parent_nodes ( id, |node| match * node {
341
+ NodeItem ( _) |
342
+ NodeForeignItem ( _) |
343
+ NodeTraitItem ( _) |
344
+ NodeImplItem ( _) => true ,
345
+ _ => false ,
346
+ } ) {
347
+ Ok ( id) => id,
348
+ Err ( id) => id,
349
+ }
350
+ }
351
+
352
+ /// Returns the nearest enclosing scope. A scope is an item or block.
353
+ /// FIXME it is not clear to me that all items qualify as scopes - statics
354
+ /// and associated types probably shouldn't, for example. Behaviour in this
355
+ /// regard should be expected to be highly unstable.
356
+ pub fn get_enclosing_scope ( & self , id : NodeId ) -> Option < NodeId > {
357
+ match self . walk_parent_nodes ( id, |node| match * node {
358
+ NodeItem ( _) |
359
+ NodeForeignItem ( _) |
360
+ NodeTraitItem ( _) |
361
+ NodeImplItem ( _) |
362
+ NodeBlock ( _) => true ,
363
+ _ => false ,
364
+ } ) {
365
+ Ok ( id) => Some ( id) ,
366
+ Err ( _) => None ,
367
+ }
290
368
}
291
369
292
370
pub fn get_parent_did ( & self , id : NodeId ) -> DefId {
@@ -590,15 +668,15 @@ impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
590
668
return None ;
591
669
}
592
670
self . idx += 1 ;
593
- let ( p , name) = match self . map . find_entry ( idx) {
594
- Some ( EntryItem ( p , n) ) => ( p , n. name ( ) ) ,
595
- Some ( EntryForeignItem ( p , n) ) => ( p , n. name ( ) ) ,
596
- Some ( EntryTraitItem ( p , n) ) => ( p , n. name ( ) ) ,
597
- Some ( EntryImplItem ( p , n) ) => ( p , n. name ( ) ) ,
598
- Some ( EntryVariant ( p , n) ) => ( p , n. name ( ) ) ,
671
+ let name = match self . map . find_entry ( idx) {
672
+ Some ( EntryItem ( _ , n) ) => n. name ( ) ,
673
+ Some ( EntryForeignItem ( _ , n) ) => n. name ( ) ,
674
+ Some ( EntryTraitItem ( _ , n) ) => n. name ( ) ,
675
+ Some ( EntryImplItem ( _ , n) ) => n. name ( ) ,
676
+ Some ( EntryVariant ( _ , n) ) => n. name ( ) ,
599
677
_ => continue ,
600
678
} ;
601
- if self . matches_names ( p , name) {
679
+ if self . matches_names ( self . map . get_parent ( idx ) , name) {
602
680
return Some ( idx)
603
681
}
604
682
}
@@ -647,8 +725,7 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
647
725
/// A Visitor that walks over an AST and collects Node's into an AST Map.
648
726
struct NodeCollector < ' ast > {
649
727
map : Vec < MapEntry < ' ast > > ,
650
- /// The node in which we are currently mapping (an item or a method).
651
- parent : NodeId
728
+ parent_node : NodeId ,
652
729
}
653
730
654
731
impl < ' ast > NodeCollector < ' ast > {
@@ -662,7 +739,7 @@ impl<'ast> NodeCollector<'ast> {
662
739
}
663
740
664
741
fn insert ( & mut self , id : NodeId , node : Node < ' ast > ) {
665
- let entry = MapEntry :: from_node ( self . parent , node) ;
742
+ let entry = MapEntry :: from_node ( self . parent_node , node) ;
666
743
self . insert_entry ( id, entry) ;
667
744
}
668
745
@@ -676,8 +753,10 @@ impl<'ast> NodeCollector<'ast> {
676
753
impl < ' ast > Visitor < ' ast > for NodeCollector < ' ast > {
677
754
fn visit_item ( & mut self , i : & ' ast Item ) {
678
755
self . insert ( i. id , NodeItem ( i) ) ;
679
- let parent = self . parent ;
680
- self . parent = i. id ;
756
+
757
+ let parent_node = self . parent_node ;
758
+ self . parent_node = i. id ;
759
+
681
760
match i. node {
682
761
ItemImpl ( _, _, _, _, _, ref impl_items) => {
683
762
for ii in impl_items {
@@ -727,21 +806,23 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
727
806
_ => { }
728
807
}
729
808
visit:: walk_item ( self , i) ;
730
- self . parent = parent ;
809
+ self . parent_node = parent_node ;
731
810
}
732
811
733
812
fn visit_trait_item ( & mut self , ti : & ' ast TraitItem ) {
734
- let parent = self . parent ;
735
- self . parent = ti. id ;
813
+ let parent_node = self . parent_node ;
814
+ self . parent_node = ti. id ;
736
815
visit:: walk_trait_item ( self , ti) ;
737
- self . parent = parent ;
816
+ self . parent_node = parent_node ;
738
817
}
739
818
740
819
fn visit_impl_item ( & mut self , ii : & ' ast ImplItem ) {
741
- let parent = self . parent ;
742
- self . parent = ii. id ;
820
+ let parent_node = self . parent_node ;
821
+ self . parent_node = ii. id ;
822
+
743
823
visit:: walk_impl_item ( self , ii) ;
744
- self . parent = parent;
824
+
825
+ self . parent_node = parent_node;
745
826
}
746
827
747
828
fn visit_pat ( & mut self , pat : & ' ast Pat ) {
@@ -750,38 +831,58 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
750
831
PatIdent ( ..) => NodeLocal ( pat) ,
751
832
_ => NodePat ( pat)
752
833
} ) ;
834
+
835
+ let parent_node = self . parent_node ;
836
+ self . parent_node = pat. id ;
753
837
visit:: walk_pat ( self , pat) ;
838
+ self . parent_node = parent_node;
754
839
}
755
840
756
841
fn visit_expr ( & mut self , expr : & ' ast Expr ) {
757
842
self . insert ( expr. id , NodeExpr ( expr) ) ;
843
+ let parent_node = self . parent_node ;
844
+ self . parent_node = expr. id ;
758
845
visit:: walk_expr ( self , expr) ;
846
+ self . parent_node = parent_node;
759
847
}
760
848
761
849
fn visit_stmt ( & mut self , stmt : & ' ast Stmt ) {
762
- self . insert ( ast_util:: stmt_id ( stmt) , NodeStmt ( stmt) ) ;
850
+ let id = ast_util:: stmt_id ( stmt) ;
851
+ self . insert ( id, NodeStmt ( stmt) ) ;
852
+ let parent_node = self . parent_node ;
853
+ self . parent_node = id;
763
854
visit:: walk_stmt ( self , stmt) ;
855
+ self . parent_node = parent_node;
764
856
}
765
857
766
858
fn visit_fn ( & mut self , fk : visit:: FnKind < ' ast > , fd : & ' ast FnDecl ,
767
- b : & ' ast Block , s : Span , _: NodeId ) {
859
+ b : & ' ast Block , s : Span , id : NodeId ) {
860
+ let parent_node = self . parent_node ;
861
+ self . parent_node = id;
768
862
self . visit_fn_decl ( fd) ;
769
863
visit:: walk_fn ( self , fk, fd, b, s) ;
864
+ self . parent_node = parent_node;
770
865
}
771
866
772
867
fn visit_ty ( & mut self , ty : & ' ast Ty ) {
868
+ let parent_node = self . parent_node ;
869
+ self . parent_node = ty. id ;
773
870
match ty. node {
774
871
TyBareFn ( ref fd) => {
775
872
self . visit_fn_decl ( & * fd. decl ) ;
776
873
}
777
874
_ => { }
778
875
}
779
876
visit:: walk_ty ( self , ty) ;
877
+ self . parent_node = parent_node;
780
878
}
781
879
782
880
fn visit_block ( & mut self , block : & ' ast Block ) {
783
881
self . insert ( block. id , NodeBlock ( block) ) ;
882
+ let parent_node = self . parent_node ;
883
+ self . parent_node = block. id ;
784
884
visit:: walk_block ( self , block) ;
885
+ self . parent_node = parent_node;
785
886
}
786
887
787
888
fn visit_lifetime_ref ( & mut self , lifetime : & ' ast Lifetime ) {
@@ -809,7 +910,7 @@ pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map
809
910
810
911
let mut collector = NodeCollector {
811
912
map : vec ! [ ] ,
812
- parent : CRATE_NODE_ID
913
+ parent_node : CRATE_NODE_ID ,
813
914
} ;
814
915
collector. insert_entry ( CRATE_NODE_ID , RootCrate ) ;
815
916
visit:: walk_crate ( & mut collector, & forest. krate ) ;
@@ -864,11 +965,11 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
864
965
ii : ii
865
966
} ) ;
866
967
968
+ let ii_parent_id = fld. new_id ( DUMMY_NODE_ID ) ;
867
969
let mut collector = NodeCollector {
868
970
map : mem:: replace ( & mut * map. map . borrow_mut ( ) , vec ! [ ] ) ,
869
- parent : fld . new_id ( DUMMY_NODE_ID )
971
+ parent_node : ii_parent_id ,
870
972
} ;
871
- let ii_parent_id = collector. parent ;
872
973
collector. insert_entry ( ii_parent_id, RootInlinedParent ( ii_parent) ) ;
873
974
visit:: walk_inlined_item ( & mut collector, & ii_parent. ii ) ;
874
975
0 commit comments