@@ -121,15 +121,14 @@ pub enum Node<'ast> {
121
121
NodeLifetime ( & ' ast Lifetime ) ,
122
122
}
123
123
124
- /// Represents an entry and its parent NodeID and parent_node NodeID, see
125
- /// get_parent_node for the distinction.
124
+ /// Represents an entry and its parent NodeID.
126
125
/// The odd layout is to bring down the total size.
127
126
#[ derive( Copy , Debug ) ]
128
127
enum MapEntry < ' ast > {
129
128
/// Placeholder for holes in the map.
130
129
NotPresent ,
131
130
132
- /// All the node types, with a parent and scope ID.
131
+ /// All the node types, with a parent ID.
133
132
EntryItem ( NodeId , & ' ast Item ) ,
134
133
EntryForeignItem ( NodeId , & ' ast ForeignItem ) ,
135
134
EntryTraitItem ( NodeId , & ' ast TraitItem ) ,
@@ -162,21 +161,21 @@ struct InlinedParent {
162
161
}
163
162
164
163
impl < ' ast > MapEntry < ' ast > {
165
- fn from_node ( s : NodeId , node : Node < ' ast > ) -> MapEntry < ' ast > {
164
+ fn from_node ( p : NodeId , node : Node < ' ast > ) -> MapEntry < ' ast > {
166
165
match node {
167
- NodeItem ( n) => EntryItem ( s , n) ,
168
- NodeForeignItem ( n) => EntryForeignItem ( s , n) ,
169
- NodeTraitItem ( n) => EntryTraitItem ( s , n) ,
170
- NodeImplItem ( n) => EntryImplItem ( s , n) ,
171
- NodeVariant ( n) => EntryVariant ( s , n) ,
172
- NodeExpr ( n) => EntryExpr ( s , n) ,
173
- NodeStmt ( n) => EntryStmt ( s , n) ,
174
- NodeArg ( n) => EntryArg ( s , n) ,
175
- NodeLocal ( n) => EntryLocal ( s , n) ,
176
- NodePat ( n) => EntryPat ( s , n) ,
177
- NodeBlock ( n) => EntryBlock ( s , n) ,
178
- NodeStructCtor ( n) => EntryStructCtor ( s , n) ,
179
- NodeLifetime ( n) => EntryLifetime ( s , n)
166
+ NodeItem ( n) => EntryItem ( p , n) ,
167
+ NodeForeignItem ( n) => EntryForeignItem ( p , n) ,
168
+ NodeTraitItem ( n) => EntryTraitItem ( p , n) ,
169
+ NodeImplItem ( n) => EntryImplItem ( p , n) ,
170
+ NodeVariant ( n) => EntryVariant ( p , n) ,
171
+ NodeExpr ( n) => EntryExpr ( p , n) ,
172
+ NodeStmt ( n) => EntryStmt ( p , n) ,
173
+ NodeArg ( n) => EntryArg ( p , n) ,
174
+ NodeLocal ( n) => EntryLocal ( p , n) ,
175
+ NodePat ( n) => EntryPat ( p , n) ,
176
+ NodeBlock ( n) => EntryBlock ( p , n) ,
177
+ NodeStructCtor ( n) => EntryStructCtor ( p , n) ,
178
+ NodeLifetime ( n) => EntryLifetime ( p , n)
180
179
}
181
180
}
182
181
@@ -284,83 +283,87 @@ impl<'ast> Map<'ast> {
284
283
self . find_entry ( id) . and_then ( |x| x. to_node ( ) )
285
284
}
286
285
287
- /// Retrieve the parent NodeId for `id`, or `id` itself if no
288
- /// parent is registered in this map.
289
- pub fn get_parent ( & self , id : NodeId ) -> NodeId {
290
- let mut id = id;
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;
291
307
loop {
292
308
let parent_node = self . get_parent_node ( id) ;
293
309
if parent_node == 0 {
294
- return parent_node ;
310
+ return Ok ( 0 ) ;
295
311
}
296
312
if parent_node == id {
297
- return id ;
313
+ return Err ( id ) ;
298
314
}
299
315
300
316
let node = self . find_entry ( parent_node) ;
301
317
if node. is_none ( ) {
302
- return id ;
318
+ return Err ( id ) ;
303
319
}
304
320
let node = node. unwrap ( ) . to_node ( ) ;
305
321
match node {
306
- Some ( node) => match node {
307
- NodeItem ( _) |
308
- NodeForeignItem ( _) |
309
- NodeTraitItem ( _) |
310
- NodeImplItem ( _) => {
311
- return parent_node;
322
+ Some ( ref node) => {
323
+ if found ( node) {
324
+ return Ok ( parent_node) ;
312
325
}
313
- _ => { }
314
- } ,
326
+ }
315
327
None => {
316
- return parent_node;
328
+ return Err ( parent_node) ;
317
329
}
318
330
}
319
331
id = parent_node;
320
332
}
321
333
}
322
334
323
- /// Similar to get_parent, returns the parent node id or id if there is no
324
- /// parent.
325
- /// This function returns the most direct parent in the AST, whereas get_parent
326
- /// returns the enclosing item. Note that this might not be the actual parent
327
- /// node in the AST - some kinds of nodes are not in the map and these will
328
- /// never appear as the parent_node. So you can always walk the parent_nodes
329
- /// from a node to the root of the ast (unless you get the same id back here
330
- /// that can happen if the id is not in the map itself or is just weird).
331
- pub fn get_parent_node ( & self , id : NodeId ) -> NodeId {
332
- self . find_entry ( id) . and_then ( |x| x. parent_node ( ) ) . unwrap_or ( id)
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.
339
+ pub fn get_parent ( & self , id : NodeId ) -> NodeId {
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
+ }
333
350
}
334
351
335
352
/// Returns the nearest enclosing scope. A scope is an item or block.
336
353
/// FIXME it is not clear to me that all items qualify as scopes - statics
337
354
/// and associated types probably shouldn't, for example. Behaviour in this
338
355
/// regard should be expected to be highly unstable.
339
356
pub fn get_enclosing_scope ( & self , id : NodeId ) -> Option < NodeId > {
340
- let mut last_id = id;
341
- // Walk up the chain of parents until we find a 'scope'.
342
- loop {
343
- let cur_id = self . get_parent_node ( last_id) ;
344
- if cur_id == last_id {
345
- return None ;
346
- }
347
-
348
- if cur_id == 0 {
349
- return Some ( 0 ) ;
350
- }
351
-
352
- match self . get ( cur_id) {
353
- NodeItem ( _) |
354
- NodeForeignItem ( _) |
355
- NodeTraitItem ( _) |
356
- NodeImplItem ( _) |
357
- NodeBlock ( _) => {
358
- return Some ( cur_id) ;
359
- }
360
- _ => { }
361
- }
362
-
363
- last_id = cur_id;
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 ,
364
367
}
365
368
}
366
369
0 commit comments