Add parent_node to ast_map
This commit is contained in:
parent
27975c49a6
commit
bbf0daa192
1 changed files with 133 additions and 67 deletions
|
@ -121,27 +121,28 @@ pub enum Node<'ast> {
|
|||
NodeLifetime(&'ast Lifetime),
|
||||
}
|
||||
|
||||
/// Represents an entry and its parent Node ID
|
||||
/// Represents an entry and its parent NodeID and parent_node NodeID, see
|
||||
/// get_parent_node for the distinction.
|
||||
/// The odd layout is to bring down the total size.
|
||||
#[derive(Copy, Debug)]
|
||||
enum MapEntry<'ast> {
|
||||
/// Placeholder for holes in the map.
|
||||
NotPresent,
|
||||
|
||||
/// All the node types, with a parent ID.
|
||||
EntryItem(NodeId, &'ast Item),
|
||||
EntryForeignItem(NodeId, &'ast ForeignItem),
|
||||
EntryTraitItem(NodeId, &'ast TraitItem),
|
||||
EntryImplItem(NodeId, &'ast ImplItem),
|
||||
EntryVariant(NodeId, &'ast Variant),
|
||||
EntryExpr(NodeId, &'ast Expr),
|
||||
EntryStmt(NodeId, &'ast Stmt),
|
||||
EntryArg(NodeId, &'ast Pat),
|
||||
EntryLocal(NodeId, &'ast Pat),
|
||||
EntryPat(NodeId, &'ast Pat),
|
||||
EntryBlock(NodeId, &'ast Block),
|
||||
EntryStructCtor(NodeId, &'ast StructDef),
|
||||
EntryLifetime(NodeId, &'ast Lifetime),
|
||||
/// All the node types, with a parent and scope ID.
|
||||
EntryItem(NodeId, NodeId, &'ast Item),
|
||||
EntryForeignItem(NodeId, NodeId, &'ast ForeignItem),
|
||||
EntryTraitItem(NodeId, NodeId, &'ast TraitItem),
|
||||
EntryImplItem(NodeId, NodeId, &'ast ImplItem),
|
||||
EntryVariant(NodeId, NodeId, &'ast Variant),
|
||||
EntryExpr(NodeId, NodeId, &'ast Expr),
|
||||
EntryStmt(NodeId, NodeId, &'ast Stmt),
|
||||
EntryArg(NodeId, NodeId, &'ast Pat),
|
||||
EntryLocal(NodeId, NodeId, &'ast Pat),
|
||||
EntryPat(NodeId, NodeId, &'ast Pat),
|
||||
EntryBlock(NodeId, NodeId, &'ast Block),
|
||||
EntryStructCtor(NodeId, NodeId, &'ast StructDef),
|
||||
EntryLifetime(NodeId, NodeId, &'ast Lifetime),
|
||||
|
||||
/// Roots for node trees.
|
||||
RootCrate,
|
||||
|
@ -161,58 +162,77 @@ struct InlinedParent {
|
|||
}
|
||||
|
||||
impl<'ast> MapEntry<'ast> {
|
||||
fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
|
||||
fn from_node(p: NodeId, s: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
|
||||
match node {
|
||||
NodeItem(n) => EntryItem(p, n),
|
||||
NodeForeignItem(n) => EntryForeignItem(p, n),
|
||||
NodeTraitItem(n) => EntryTraitItem(p, n),
|
||||
NodeImplItem(n) => EntryImplItem(p, n),
|
||||
NodeVariant(n) => EntryVariant(p, n),
|
||||
NodeExpr(n) => EntryExpr(p, n),
|
||||
NodeStmt(n) => EntryStmt(p, n),
|
||||
NodeArg(n) => EntryArg(p, n),
|
||||
NodeLocal(n) => EntryLocal(p, n),
|
||||
NodePat(n) => EntryPat(p, n),
|
||||
NodeBlock(n) => EntryBlock(p, n),
|
||||
NodeStructCtor(n) => EntryStructCtor(p, n),
|
||||
NodeLifetime(n) => EntryLifetime(p, n)
|
||||
NodeItem(n) => EntryItem(p, s, n),
|
||||
NodeForeignItem(n) => EntryForeignItem(p, s, n),
|
||||
NodeTraitItem(n) => EntryTraitItem(p, s, n),
|
||||
NodeImplItem(n) => EntryImplItem(p, s, n),
|
||||
NodeVariant(n) => EntryVariant(p, s, n),
|
||||
NodeExpr(n) => EntryExpr(p, s, n),
|
||||
NodeStmt(n) => EntryStmt(p, s, n),
|
||||
NodeArg(n) => EntryArg(p, s, n),
|
||||
NodeLocal(n) => EntryLocal(p, s, n),
|
||||
NodePat(n) => EntryPat(p, s, n),
|
||||
NodeBlock(n) => EntryBlock(p, s, n),
|
||||
NodeStructCtor(n) => EntryStructCtor(p, s, n),
|
||||
NodeLifetime(n) => EntryLifetime(p, s, n)
|
||||
}
|
||||
}
|
||||
|
||||
fn parent(self) -> Option<NodeId> {
|
||||
Some(match self {
|
||||
EntryItem(id, _) => id,
|
||||
EntryForeignItem(id, _) => id,
|
||||
EntryTraitItem(id, _) => id,
|
||||
EntryImplItem(id, _) => id,
|
||||
EntryVariant(id, _) => id,
|
||||
EntryExpr(id, _) => id,
|
||||
EntryStmt(id, _) => id,
|
||||
EntryArg(id, _) => id,
|
||||
EntryLocal(id, _) => id,
|
||||
EntryPat(id, _) => id,
|
||||
EntryBlock(id, _) => id,
|
||||
EntryStructCtor(id, _) => id,
|
||||
EntryLifetime(id, _) => id,
|
||||
EntryItem(id, _, _) => id,
|
||||
EntryForeignItem(id, _, _) => id,
|
||||
EntryTraitItem(id, _, _) => id,
|
||||
EntryImplItem(id, _, _) => id,
|
||||
EntryVariant(id, _, _) => id,
|
||||
EntryExpr(id, _, _) => id,
|
||||
EntryStmt(id, _, _) => id,
|
||||
EntryArg(id, _, _) => id,
|
||||
EntryLocal(id, _, _) => id,
|
||||
EntryPat(id, _, _) => id,
|
||||
EntryBlock(id, _, _) => id,
|
||||
EntryStructCtor(id, _, _) => id,
|
||||
EntryLifetime(id, _, _) => id,
|
||||
_ => return None
|
||||
})
|
||||
}
|
||||
|
||||
fn parent_node(self) -> Option<NodeId> {
|
||||
Some(match self {
|
||||
EntryItem(_, id, _) => id,
|
||||
EntryForeignItem(_, id, _) => id,
|
||||
EntryTraitItem(_, id, _) => id,
|
||||
EntryImplItem(_, id, _) => id,
|
||||
EntryVariant(_, id, _) => id,
|
||||
EntryExpr(_, id, _) => id,
|
||||
EntryStmt(_, id, _) => id,
|
||||
EntryArg(_, id, _) => id,
|
||||
EntryLocal(_, id, _) => id,
|
||||
EntryPat(_, id, _) => id,
|
||||
EntryBlock(_, id, _) => id,
|
||||
EntryStructCtor(_, id, _) => id,
|
||||
EntryLifetime(_, id, _) => id,
|
||||
_ => return None
|
||||
})
|
||||
}
|
||||
|
||||
fn to_node(self) -> Option<Node<'ast>> {
|
||||
Some(match self {
|
||||
EntryItem(_, n) => NodeItem(n),
|
||||
EntryForeignItem(_, n) => NodeForeignItem(n),
|
||||
EntryTraitItem(_, n) => NodeTraitItem(n),
|
||||
EntryImplItem(_, n) => NodeImplItem(n),
|
||||
EntryVariant(_, n) => NodeVariant(n),
|
||||
EntryExpr(_, n) => NodeExpr(n),
|
||||
EntryStmt(_, n) => NodeStmt(n),
|
||||
EntryArg(_, n) => NodeArg(n),
|
||||
EntryLocal(_, n) => NodeLocal(n),
|
||||
EntryPat(_, n) => NodePat(n),
|
||||
EntryBlock(_, n) => NodeBlock(n),
|
||||
EntryStructCtor(_, n) => NodeStructCtor(n),
|
||||
EntryLifetime(_, n) => NodeLifetime(n),
|
||||
EntryItem(_, _, n) => NodeItem(n),
|
||||
EntryForeignItem(_, _, n) => NodeForeignItem(n),
|
||||
EntryTraitItem(_, _, n) => NodeTraitItem(n),
|
||||
EntryImplItem(_, _, n) => NodeImplItem(n),
|
||||
EntryVariant(_, _, n) => NodeVariant(n),
|
||||
EntryExpr(_, _, n) => NodeExpr(n),
|
||||
EntryStmt(_, _, n) => NodeStmt(n),
|
||||
EntryArg(_, _, n) => NodeArg(n),
|
||||
EntryLocal(_, _, n) => NodeLocal(n),
|
||||
EntryPat(_, _, n) => NodePat(n),
|
||||
EntryBlock(_, _, n) => NodeBlock(n),
|
||||
EntryStructCtor(_, _, n) => NodeStructCtor(n),
|
||||
EntryLifetime(_, _, n) => NodeLifetime(n),
|
||||
_ => return None
|
||||
})
|
||||
}
|
||||
|
@ -289,6 +309,18 @@ impl<'ast> Map<'ast> {
|
|||
self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
|
||||
}
|
||||
|
||||
/// Similar to get_parent, returns the parent node id or id if there is no
|
||||
/// parent.
|
||||
/// This function returns the most direct parent in the AST, whereas get_parent
|
||||
/// returns the enclosing item. Note that this might not be the actual parent
|
||||
/// node in the AST - some kinds of nodes are not in the map and these will
|
||||
/// never appear as the parent_node. So you can always walk the parent_nodes
|
||||
/// from a node to the root of the ast (unless you get the same id back here
|
||||
/// that can happen if the id is not in the map itself or is just weird).
|
||||
pub fn get_parent_node(&self, id: NodeId) -> NodeId {
|
||||
self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
|
||||
}
|
||||
|
||||
pub fn get_parent_did(&self, id: NodeId) -> DefId {
|
||||
let parent = self.get_parent(id);
|
||||
match self.find_entry(parent) {
|
||||
|
@ -301,7 +333,7 @@ impl<'ast> Map<'ast> {
|
|||
pub fn get_foreign_abi(&self, id: NodeId) -> abi::Abi {
|
||||
let parent = self.get_parent(id);
|
||||
let abi = match self.find_entry(parent) {
|
||||
Some(EntryItem(_, i)) => {
|
||||
Some(EntryItem(_, _, i)) => {
|
||||
match i.node {
|
||||
ItemForeignMod(ref nm) => Some(nm.abi),
|
||||
_ => None
|
||||
|
@ -591,11 +623,11 @@ impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
|
|||
}
|
||||
self.idx += 1;
|
||||
let (p, name) = match self.map.find_entry(idx) {
|
||||
Some(EntryItem(p, n)) => (p, n.name()),
|
||||
Some(EntryForeignItem(p, n))=> (p, n.name()),
|
||||
Some(EntryTraitItem(p, n)) => (p, n.name()),
|
||||
Some(EntryImplItem(p, n)) => (p, n.name()),
|
||||
Some(EntryVariant(p, n)) => (p, n.name()),
|
||||
Some(EntryItem(p, _, n)) => (p, n.name()),
|
||||
Some(EntryForeignItem(p, _, n))=> (p, n.name()),
|
||||
Some(EntryTraitItem(p, _, n)) => (p, n.name()),
|
||||
Some(EntryImplItem(p, _, n)) => (p, n.name()),
|
||||
Some(EntryVariant(p, _, n)) => (p, n.name()),
|
||||
_ => continue,
|
||||
};
|
||||
if self.matches_names(p, name) {
|
||||
|
@ -648,7 +680,8 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
|
|||
struct NodeCollector<'ast> {
|
||||
map: Vec<MapEntry<'ast>>,
|
||||
/// The node in which we are currently mapping (an item or a method).
|
||||
parent: NodeId
|
||||
parent: NodeId,
|
||||
parent_node: NodeId,
|
||||
}
|
||||
|
||||
impl<'ast> NodeCollector<'ast> {
|
||||
|
@ -662,7 +695,7 @@ impl<'ast> NodeCollector<'ast> {
|
|||
}
|
||||
|
||||
fn insert(&mut self, id: NodeId, node: Node<'ast>) {
|
||||
let entry = MapEntry::from_node(self.parent, node);
|
||||
let entry = MapEntry::from_node(self.parent, self.parent_node, node);
|
||||
self.insert_entry(id, entry);
|
||||
}
|
||||
|
||||
|
@ -678,6 +711,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
|||
self.insert(i.id, NodeItem(i));
|
||||
let parent = self.parent;
|
||||
self.parent = i.id;
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = i.id;
|
||||
match i.node {
|
||||
ItemImpl(_, _, _, _, _, ref impl_items) => {
|
||||
for ii in impl_items {
|
||||
|
@ -728,48 +763,70 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
|||
}
|
||||
visit::walk_item(self, i);
|
||||
self.parent = parent;
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
|
||||
let parent = self.parent;
|
||||
self.parent = ti.id;
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = ti.id;
|
||||
visit::walk_trait_item(self, ti);
|
||||
self.parent = parent;
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
|
||||
let parent = self.parent;
|
||||
self.parent = ii.id;
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = ii.id;
|
||||
visit::walk_impl_item(self, ii);
|
||||
self.parent = parent;
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &'ast Pat) {
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = pat.id;
|
||||
self.insert(pat.id, match pat.node {
|
||||
// Note: this is at least *potentially* a pattern...
|
||||
PatIdent(..) => NodeLocal(pat),
|
||||
_ => NodePat(pat)
|
||||
});
|
||||
visit::walk_pat(self, pat);
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'ast Expr) {
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = expr.id;
|
||||
self.insert(expr.id, NodeExpr(expr));
|
||||
visit::walk_expr(self, expr);
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, stmt: &'ast Stmt) {
|
||||
self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
|
||||
let id = ast_util::stmt_id(stmt);
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = id;
|
||||
self.insert(id, NodeStmt(stmt));
|
||||
visit::walk_stmt(self, stmt);
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
|
||||
b: &'ast Block, s: Span, _: NodeId) {
|
||||
b: &'ast Block, s: Span, id: NodeId) {
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = id;
|
||||
self.visit_fn_decl(fd);
|
||||
visit::walk_fn(self, fk, fd, b, s);
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'ast Ty) {
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = ty.id;
|
||||
match ty.node {
|
||||
TyBareFn(ref fd) => {
|
||||
self.visit_fn_decl(&*fd.decl);
|
||||
|
@ -777,15 +834,22 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
|||
_ => {}
|
||||
}
|
||||
visit::walk_ty(self, ty);
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, block: &'ast Block) {
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = block.id;
|
||||
self.insert(block.id, NodeBlock(block));
|
||||
visit::walk_block(self, block);
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_lifetime_ref(&mut self, lifetime: &'ast Lifetime) {
|
||||
let parent_node = self.parent_node;
|
||||
self.parent_node = lifetime.id;
|
||||
self.insert(lifetime.id, NodeLifetime(lifetime));
|
||||
self.parent_node = parent_node;
|
||||
}
|
||||
|
||||
fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
|
||||
|
@ -809,7 +873,8 @@ pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map
|
|||
|
||||
let mut collector = NodeCollector {
|
||||
map: vec![],
|
||||
parent: CRATE_NODE_ID
|
||||
parent: CRATE_NODE_ID,
|
||||
parent_node: CRATE_NODE_ID,
|
||||
};
|
||||
collector.insert_entry(CRATE_NODE_ID, RootCrate);
|
||||
visit::walk_crate(&mut collector, &forest.krate);
|
||||
|
@ -866,7 +931,8 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
|
|||
|
||||
let mut collector = NodeCollector {
|
||||
map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
|
||||
parent: fld.new_id(DUMMY_NODE_ID)
|
||||
parent: fld.new_id(DUMMY_NODE_ID),
|
||||
parent_node: fld.new_id(DUMMY_NODE_ID),
|
||||
};
|
||||
let ii_parent_id = collector.parent;
|
||||
collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue