1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use super::MapEntry::*;
14 use rustc_front::hir::*;
15 use rustc_front::util;
16 use rustc_front::visit::{self, Visitor};
17 use std::iter::repeat;
18 use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
19 use syntax::codemap::Span;
20 use util::nodemap::NodeSet;
22 /// A Visitor that walks over an AST and collects Node's into an AST
24 pub struct NodeCollector<'ast> {
25 pub map: Vec<MapEntry<'ast>>,
26 pub definitions_map: NodeSet,
27 pub parent_node: NodeId,
30 impl<'ast> NodeCollector<'ast> {
31 pub fn root() -> NodeCollector<'ast> {
32 let mut collector = NodeCollector {
34 definitions_map: NodeSet(),
35 parent_node: CRATE_NODE_ID,
37 collector.insert_entry(CRATE_NODE_ID, RootCrate);
38 collector.create_def(CRATE_NODE_ID);
39 collector.create_def(DUMMY_NODE_ID);
43 pub fn extend(parent: &'ast InlinedParent,
45 map: Vec<MapEntry<'ast>>,
46 definitions_map: NodeSet)
47 -> NodeCollector<'ast> {
48 let mut collector = NodeCollector {
50 definitions_map: definitions_map,
51 parent_node: parent_node
53 collector.insert_entry(parent_node, RootInlinedParent(parent));
58 fn create_def(&mut self, node: NodeId) {
59 let is_new = self.definitions_map.insert(node);
61 "two entries for node id `{}` -- previous is `{:?}`",
65 fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
66 debug!("ast_map: {:?} => {:?}", id, entry);
67 let len = self.map.len();
68 if id as usize >= len {
69 self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
71 self.map[id as usize] = entry;
74 fn insert(&mut self, id: NodeId, node: Node<'ast>) {
75 let entry = MapEntry::from_node(self.parent_node, node);
76 self.insert_entry(id, entry);
79 fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
80 for a in &decl.inputs {
81 self.insert(a.id, NodeArg(&*a.pat));
86 impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
87 fn visit_item(&mut self, i: &'ast Item) {
88 self.insert(i.id, NodeItem(i));
90 let parent_node = self.parent_node;
91 self.parent_node = i.id;
93 self.create_def(i.id);
97 ItemEnum(ref enum_definition, _) => {
98 for v in &enum_definition.variants {
99 self.insert(v.node.id, NodeVariant(&**v));
100 self.create_def(v.node.id);
103 TupleVariantKind(ref args) => {
105 self.create_def(arg.id);
108 StructVariantKind(ref def) => {
109 for field in &def.fields {
110 self.create_def(field.node.id);
116 ItemForeignMod(..) => {}
117 ItemStruct(ref struct_def, _) => {
118 // If this is a tuple-like struct, register the constructor.
119 match struct_def.ctor_id {
121 self.insert(ctor_id, NodeStructCtor(&**struct_def));
122 self.create_def(ctor_id);
127 for field in &struct_def.fields {
128 self.create_def(field.node.id);
131 ItemTrait(_, _, ref bounds, _) => {
132 for b in bounds.iter() {
133 if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
134 self.insert(t.trait_ref.ref_id, NodeItem(i));
138 ItemUse(ref view_path) => {
139 match view_path.node {
140 ViewPathList(_, ref paths) => {
142 self.insert(path.node.id(), NodeItem(i));
150 visit::walk_item(self, i);
151 self.parent_node = parent_node;
154 fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
155 self.insert(foreign_item.id, NodeForeignItem(foreign_item));
156 self.create_def(foreign_item.id);
158 let parent_node = self.parent_node;
159 self.parent_node = foreign_item.id;
160 visit::walk_foreign_item(self, foreign_item);
161 self.parent_node = parent_node;
164 fn visit_generics(&mut self, generics: &'ast Generics) {
165 for ty_param in generics.ty_params.iter() {
166 self.create_def(ty_param.id);
167 self.insert(ty_param.id, NodeTyParam(ty_param));
170 visit::walk_generics(self, generics);
173 fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
174 self.insert(ti.id, NodeTraitItem(ti));
175 self.create_def(ti.id);
178 ConstTraitItem(_, Some(ref expr)) => {
179 self.create_def(expr.id);
184 let parent_node = self.parent_node;
185 self.parent_node = ti.id;
186 visit::walk_trait_item(self, ti);
187 self.parent_node = parent_node;
190 fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
191 self.insert(ii.id, NodeImplItem(ii));
192 self.create_def(ii.id);
195 ConstImplItem(_, ref expr) => {
196 self.create_def(expr.id);
201 let parent_node = self.parent_node;
202 self.parent_node = ii.id;
203 visit::walk_impl_item(self, ii);
204 self.parent_node = parent_node;
207 fn visit_pat(&mut self, pat: &'ast Pat) {
208 let maybe_binding = match pat.node {
209 PatIdent(..) => true,
214 if maybe_binding {NodeLocal(pat)} else {NodePat(pat)});
217 self.create_def(pat.id);
220 let parent_node = self.parent_node;
221 self.parent_node = pat.id;
222 visit::walk_pat(self, pat);
223 self.parent_node = parent_node;
226 fn visit_expr(&mut self, expr: &'ast Expr) {
227 self.insert(expr.id, NodeExpr(expr));
230 ExprClosure(..) => self.create_def(expr.id),
234 let parent_node = self.parent_node;
235 self.parent_node = expr.id;
236 visit::walk_expr(self, expr);
237 self.parent_node = parent_node;
240 fn visit_stmt(&mut self, stmt: &'ast Stmt) {
241 let id = util::stmt_id(stmt);
242 self.insert(id, NodeStmt(stmt));
243 let parent_node = self.parent_node;
244 self.parent_node = id;
245 visit::walk_stmt(self, stmt);
246 self.parent_node = parent_node;
249 fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
250 b: &'ast Block, s: Span, id: NodeId) {
251 assert_eq!(self.parent_node, id);
252 self.visit_fn_decl(fd);
253 visit::walk_fn(self, fk, fd, b, s);
256 fn visit_ty(&mut self, ty: &'ast Ty) {
258 TyBareFn(ref fd) => {
259 self.visit_fn_decl(&*fd.decl);
263 visit::walk_ty(self, ty);
266 fn visit_block(&mut self, block: &'ast Block) {
267 self.insert(block.id, NodeBlock(block));
268 let parent_node = self.parent_node;
269 self.parent_node = block.id;
270 visit::walk_block(self, block);
271 self.parent_node = parent_node;
274 fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
275 self.insert(lifetime.id, NodeLifetime(lifetime));
278 fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
279 self.create_def(def.lifetime.id);
280 self.visit_lifetime(&def.lifetime);
283 fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
284 self.create_def(macro_def.id);