Skip to content

Commit 8261599

Browse files
committed
Refactoring
1 parent 15dcb5b commit 8261599

File tree

1 file changed

+70
-67
lines changed

1 file changed

+70
-67
lines changed

src/librustc/ast_map/mod.rs

Lines changed: 70 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,14 @@ pub enum Node<'ast> {
121121
NodeLifetime(&'ast Lifetime),
122122
}
123123

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.
126125
/// The odd layout is to bring down the total size.
127126
#[derive(Copy, Debug)]
128127
enum MapEntry<'ast> {
129128
/// Placeholder for holes in the map.
130129
NotPresent,
131130

132-
/// All the node types, with a parent and scope ID.
131+
/// All the node types, with a parent ID.
133132
EntryItem(NodeId, &'ast Item),
134133
EntryForeignItem(NodeId, &'ast ForeignItem),
135134
EntryTraitItem(NodeId, &'ast TraitItem),
@@ -162,21 +161,21 @@ struct InlinedParent {
162161
}
163162

164163
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> {
166165
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)
180179
}
181180
}
182181

@@ -284,83 +283,87 @@ impl<'ast> Map<'ast> {
284283
self.find_entry(id).and_then(|x| x.to_node())
285284
}
286285

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;
291307
loop {
292308
let parent_node = self.get_parent_node(id);
293309
if parent_node == 0 {
294-
return parent_node;
310+
return Ok(0);
295311
}
296312
if parent_node == id {
297-
return id;
313+
return Err(id);
298314
}
299315

300316
let node = self.find_entry(parent_node);
301317
if node.is_none() {
302-
return id;
318+
return Err(id);
303319
}
304320
let node = node.unwrap().to_node();
305321
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);
312325
}
313-
_ => {}
314-
},
326+
}
315327
None => {
316-
return parent_node;
328+
return Err(parent_node);
317329
}
318330
}
319331
id = parent_node;
320332
}
321333
}
322334

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+
}
333350
}
334351

335352
/// Returns the nearest enclosing scope. A scope is an item or block.
336353
/// FIXME it is not clear to me that all items qualify as scopes - statics
337354
/// and associated types probably shouldn't, for example. Behaviour in this
338355
/// regard should be expected to be highly unstable.
339356
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,
364367
}
365368
}
366369

0 commit comments

Comments
 (0)