2016-04-13 19:14:03 -05:00
|
|
|
// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT
|
2015-09-10 14:53:08 -05:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
2016-11-28 13:00:26 -06:00
|
|
|
use hir::intravisit::{Visitor, NestedVisitorMap};
|
2015-09-10 14:53:08 -05:00
|
|
|
use std::iter::repeat;
|
2016-04-13 19:14:03 -05:00
|
|
|
use syntax::ast::{NodeId, CRATE_NODE_ID};
|
2016-06-21 17:08:13 -05:00
|
|
|
use syntax_pos::Span;
|
2015-09-10 14:53:08 -05:00
|
|
|
|
2015-12-21 15:24:15 -06:00
|
|
|
/// A Visitor that walks over the HIR and collects Nodes into a HIR map
|
2017-01-25 19:21:50 -06:00
|
|
|
pub struct NodeCollector<'hir> {
|
2015-12-21 15:24:15 -06:00
|
|
|
/// The crate
|
2017-01-25 19:21:50 -06:00
|
|
|
pub krate: &'hir Crate,
|
2015-12-21 15:24:15 -06:00
|
|
|
/// The node map
|
2017-01-25 19:21:50 -06:00
|
|
|
pub(super) map: Vec<MapEntry<'hir>>,
|
2015-12-21 15:24:15 -06:00
|
|
|
/// The parent of this node
|
2015-09-10 14:53:08 -05:00
|
|
|
pub parent_node: NodeId,
|
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
impl<'hir> NodeCollector<'hir> {
|
|
|
|
pub fn root(krate: &'hir Crate) -> NodeCollector<'hir> {
|
2016-04-13 18:55:34 -05:00
|
|
|
let mut collector = NodeCollector {
|
2017-07-03 13:19:51 -05:00
|
|
|
krate,
|
2016-04-13 18:55:34 -05:00
|
|
|
map: vec![],
|
|
|
|
parent_node: CRATE_NODE_ID,
|
|
|
|
};
|
|
|
|
collector.insert_entry(CRATE_NODE_ID, RootCrate);
|
|
|
|
|
|
|
|
collector
|
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
|
|
|
|
debug!("hir_map: {:?} => {:?}", id, entry);
|
2016-04-13 18:55:34 -05:00
|
|
|
let len = self.map.len();
|
2016-08-31 06:00:29 -05:00
|
|
|
if id.as_usize() >= len {
|
|
|
|
self.map.extend(repeat(NotPresent).take(id.as_usize() - len + 1));
|
2015-09-10 14:53:08 -05:00
|
|
|
}
|
2016-08-31 06:00:29 -05:00
|
|
|
self.map[id.as_usize()] = entry;
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn insert(&mut self, id: NodeId, node: Node<'hir>) {
|
2016-04-13 18:55:34 -05:00
|
|
|
let entry = MapEntry::from_node(self.parent_node, node);
|
|
|
|
self.insert_entry(id, entry);
|
|
|
|
}
|
2016-04-14 00:24:30 -05:00
|
|
|
|
|
|
|
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
|
|
|
|
let parent_node = self.parent_node;
|
|
|
|
self.parent_node = parent_id;
|
|
|
|
f(self);
|
|
|
|
self.parent_node = parent_node;
|
|
|
|
}
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
|
2016-04-13 18:55:34 -05:00
|
|
|
/// Because we want to track parent items and so forth, enable
|
|
|
|
/// deep walking so that we walk nested items in the context of
|
|
|
|
/// their outer items.
|
2016-11-09 15:45:26 -06:00
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
|
2016-11-09 15:45:26 -06:00
|
|
|
panic!("visit_nested_xxx must be manually implemented in this visitor")
|
|
|
|
}
|
|
|
|
|
2016-04-13 18:55:34 -05:00
|
|
|
fn visit_nested_item(&mut self, item: ItemId) {
|
|
|
|
debug!("visit_nested_item: {:?}", item);
|
2017-01-03 20:01:58 -06:00
|
|
|
self.visit_item(self.krate.item(item.id));
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
|
|
|
|
2016-12-03 20:21:06 -06:00
|
|
|
fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
|
2017-01-03 20:01:58 -06:00
|
|
|
self.visit_trait_item(self.krate.trait_item(item_id));
|
2016-12-03 20:21:06 -06:00
|
|
|
}
|
|
|
|
|
2016-11-04 17:20:15 -05:00
|
|
|
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
|
2017-01-03 20:01:58 -06:00
|
|
|
self.visit_impl_item(self.krate.impl_item(item_id));
|
2016-11-04 17:20:15 -05:00
|
|
|
}
|
|
|
|
|
2016-12-21 04:32:59 -06:00
|
|
|
fn visit_nested_body(&mut self, id: BodyId) {
|
2017-01-03 20:01:58 -06:00
|
|
|
self.visit_body(self.krate.body(id));
|
2016-10-28 15:58:32 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_item(&mut self, i: &'hir Item) {
|
2016-04-13 18:55:34 -05:00
|
|
|
debug!("visit_item: {:?}", i);
|
|
|
|
|
|
|
|
self.insert(i.id, NodeItem(i));
|
|
|
|
|
2016-04-14 00:24:30 -05:00
|
|
|
self.with_parent(i.id, |this| {
|
|
|
|
match i.node {
|
|
|
|
ItemStruct(ref struct_def, _) => {
|
|
|
|
// If this is a tuple-like struct, register the constructor.
|
|
|
|
if !struct_def.is_struct() {
|
|
|
|
this.insert(struct_def.id(), NodeStructCtor(struct_def));
|
|
|
|
}
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
2016-04-14 00:24:30 -05:00
|
|
|
_ => {}
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
2016-04-14 00:24:30 -05:00
|
|
|
intravisit::walk_item(this, i);
|
|
|
|
});
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem) {
|
2016-04-13 18:55:34 -05:00
|
|
|
self.insert(foreign_item.id, NodeForeignItem(foreign_item));
|
|
|
|
|
2016-04-14 00:24:30 -05:00
|
|
|
self.with_parent(foreign_item.id, |this| {
|
|
|
|
intravisit::walk_foreign_item(this, foreign_item);
|
|
|
|
});
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_generics(&mut self, generics: &'hir Generics) {
|
2016-04-13 18:55:34 -05:00
|
|
|
for ty_param in generics.ty_params.iter() {
|
|
|
|
self.insert(ty_param.id, NodeTyParam(ty_param));
|
|
|
|
}
|
|
|
|
|
|
|
|
intravisit::walk_generics(self, generics);
|
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
|
2016-04-13 18:55:34 -05:00
|
|
|
self.insert(ti.id, NodeTraitItem(ti));
|
|
|
|
|
2016-04-14 00:24:30 -05:00
|
|
|
self.with_parent(ti.id, |this| {
|
|
|
|
intravisit::walk_trait_item(this, ti);
|
|
|
|
});
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
|
2016-04-13 18:55:34 -05:00
|
|
|
self.insert(ii.id, NodeImplItem(ii));
|
|
|
|
|
2016-04-14 00:24:30 -05:00
|
|
|
self.with_parent(ii.id, |this| {
|
|
|
|
intravisit::walk_impl_item(this, ii);
|
|
|
|
});
|
2016-04-13 18:55:34 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_pat(&mut self, pat: &'hir Pat) {
|
2016-03-06 06:54:44 -06:00
|
|
|
let node = if let PatKind::Binding(..) = pat.node {
|
2017-08-18 01:00:57 -05:00
|
|
|
NodeBinding(pat)
|
2016-04-17 17:30:55 -05:00
|
|
|
} else {
|
|
|
|
NodePat(pat)
|
|
|
|
};
|
|
|
|
self.insert(pat.id, node);
|
2015-09-10 14:53:08 -05:00
|
|
|
|
2016-04-14 00:24:30 -05:00
|
|
|
self.with_parent(pat.id, |this| {
|
|
|
|
intravisit::walk_pat(this, pat);
|
|
|
|
});
|
2015-09-10 14:53:08 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_expr(&mut self, expr: &'hir Expr) {
|
2015-09-10 14:53:08 -05:00
|
|
|
self.insert(expr.id, NodeExpr(expr));
|
|
|
|
|
2016-04-14 00:24:30 -05:00
|
|
|
self.with_parent(expr.id, |this| {
|
|
|
|
intravisit::walk_expr(this, expr);
|
|
|
|
});
|
2015-09-10 14:53:08 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_stmt(&mut self, stmt: &'hir Stmt) {
|
2016-03-29 01:32:58 -05:00
|
|
|
let id = stmt.node.id();
|
2015-09-10 14:53:08 -05:00
|
|
|
self.insert(id, NodeStmt(stmt));
|
2016-04-14 00:24:30 -05:00
|
|
|
|
|
|
|
self.with_parent(id, |this| {
|
|
|
|
intravisit::walk_stmt(this, stmt);
|
|
|
|
});
|
2015-09-10 14:53:08 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_ty(&mut self, ty: &'hir Ty) {
|
2016-08-05 19:12:20 -05:00
|
|
|
self.insert(ty.id, NodeTy(ty));
|
|
|
|
|
|
|
|
self.with_parent(ty.id, |this| {
|
|
|
|
intravisit::walk_ty(this, ty);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_trait_ref(&mut self, tr: &'hir TraitRef) {
|
2016-10-30 01:04:52 -05:00
|
|
|
self.insert(tr.ref_id, NodeTraitRef(tr));
|
|
|
|
|
|
|
|
self.with_parent(tr.ref_id, |this| {
|
|
|
|
intravisit::walk_trait_ref(this, tr);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_fn(&mut self, fk: intravisit::FnKind<'hir>, fd: &'hir FnDecl,
|
2016-12-21 04:32:59 -06:00
|
|
|
b: BodyId, s: Span, id: NodeId) {
|
2015-09-29 05:47:33 -05:00
|
|
|
assert_eq!(self.parent_node, id);
|
2016-07-28 04:58:45 -05:00
|
|
|
intravisit::walk_fn(self, fk, fd, b, s, id);
|
2015-09-10 14:53:08 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_block(&mut self, block: &'hir Block) {
|
2015-09-10 14:53:08 -05:00
|
|
|
self.insert(block.id, NodeBlock(block));
|
2016-04-14 00:24:30 -05:00
|
|
|
self.with_parent(block.id, |this| {
|
|
|
|
intravisit::walk_block(this, block);
|
|
|
|
});
|
2015-09-10 14:53:08 -05:00
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
|
2015-09-10 14:53:08 -05:00
|
|
|
self.insert(lifetime.id, NodeLifetime(lifetime));
|
|
|
|
}
|
2016-10-28 01:52:45 -05:00
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_vis(&mut self, visibility: &'hir Visibility) {
|
2016-10-30 01:04:52 -05:00
|
|
|
match *visibility {
|
|
|
|
Visibility::Public |
|
|
|
|
Visibility::Crate |
|
|
|
|
Visibility::Inherited => {}
|
|
|
|
Visibility::Restricted { id, .. } => {
|
|
|
|
self.insert(id, NodeVisibility(visibility));
|
|
|
|
self.with_parent(id, |this| {
|
|
|
|
intravisit::walk_vis(this, visibility);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_macro_def(&mut self, macro_def: &'hir MacroDef) {
|
2016-10-28 01:52:45 -05:00
|
|
|
self.insert_entry(macro_def.id, NotPresent);
|
|
|
|
}
|
2016-11-09 12:57:48 -06:00
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: NodeId) {
|
2016-12-21 04:32:59 -06:00
|
|
|
let id = v.node.data.id();
|
|
|
|
self.insert(id, NodeVariant(v));
|
|
|
|
self.with_parent(id, |this| {
|
|
|
|
intravisit::walk_variant(this, v, g, item_id);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-01-25 19:21:50 -06:00
|
|
|
fn visit_struct_field(&mut self, field: &'hir StructField) {
|
2016-11-09 12:57:48 -06:00
|
|
|
self.insert(field.id, NodeField(field));
|
|
|
|
self.with_parent(field.id, |this| {
|
|
|
|
intravisit::walk_struct_field(this, field);
|
|
|
|
});
|
|
|
|
}
|
2015-09-10 14:53:08 -05:00
|
|
|
}
|