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 middle::def_id::{CRATE_DEF_INDEX, DefIndex};
18 use std::iter::repeat;
19 use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
20 use syntax::codemap::Span;
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: Definitions,
27 pub parent_node: NodeId,
30 impl<'ast> NodeCollector<'ast> {
31 pub fn root() -> NodeCollector<'ast> {
32 let mut collector = NodeCollector {
34 definitions: Definitions::new(),
35 parent_node: CRATE_NODE_ID,
37 collector.insert_entry(CRATE_NODE_ID, RootCrate);
39 let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
40 assert_eq!(result, CRATE_DEF_INDEX);
42 collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
47 pub fn extend(parent: &'ast InlinedParent,
49 parent_def_path: DefPath,
50 map: Vec<MapEntry<'ast>>,
51 definitions: Definitions)
52 -> NodeCollector<'ast> {
53 let mut collector = NodeCollector {
55 parent_node: parent_node,
56 definitions: definitions,
59 collector.insert_entry(parent_node, RootInlinedParent(parent));
60 collector.create_def(parent_node, DefPathData::InlinedRoot(parent_def_path));
65 fn parent_def(&self) -> Option<DefIndex> {
66 let mut parent_node = Some(self.parent_node);
67 while let Some(p) = parent_node {
68 if let Some(q) = self.definitions.opt_def_index(p) {
71 parent_node = self.map[p as usize].parent_node();
76 fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
77 let parent_def = self.parent_def();
78 self.definitions.create_def_with_parent(parent_def, node_id, data)
81 fn create_def_with_parent(&mut self,
82 parent: Option<DefIndex>,
86 self.definitions.create_def_with_parent(parent, node_id, data)
89 fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
90 debug!("ast_map: {:?} => {:?}", id, entry);
91 let len = self.map.len();
92 if id as usize >= len {
93 self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
95 self.map[id as usize] = entry;
98 fn insert_def(&mut self, id: NodeId, node: Node<'ast>, data: DefPathData) -> DefIndex {
99 self.insert(id, node);
100 self.create_def(id, data)
103 fn insert(&mut self, id: NodeId, node: Node<'ast>) {
104 let entry = MapEntry::from_node(self.parent_node, node);
105 self.insert_entry(id, entry);
108 fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
109 for a in &decl.inputs {
110 self.insert(a.id, NodeArg(&*a.pat));
115 impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
116 fn visit_item(&mut self, i: &'ast Item) {
117 // Pick the def data. This need not be unique, but the more
118 // information we encapsulate into
119 let def_data = match i.node {
120 ItemDefaultImpl(..) | ItemImpl(..) => DefPathData::Impl,
121 ItemEnum(..) | ItemStruct(..) | ItemTrait(..) => DefPathData::Type(i.name),
122 ItemExternCrate(..) | ItemMod(..) => DefPathData::Mod(i.name),
123 ItemStatic(..) | ItemConst(..) | ItemFn(..) => DefPathData::Value(i.name),
124 _ => DefPathData::Misc,
127 self.insert_def(i.id, NodeItem(i), def_data);
129 let parent_node = self.parent_node;
130 self.parent_node = i.id;
134 ItemEnum(ref enum_definition, _) => {
135 for v in &enum_definition.variants {
136 let variant_def_index =
137 self.insert_def(v.node.id,
139 DefPathData::EnumVariant(v.node.name));
142 TupleVariantKind(ref args) => {
144 self.create_def_with_parent(Some(variant_def_index),
146 DefPathData::PositionalField);
149 StructVariantKind(ref def) => {
150 for field in &def.fields {
151 self.create_def_with_parent(
152 Some(variant_def_index),
154 DefPathData::Field(field.node.kind));
160 ItemForeignMod(..) => {
162 ItemStruct(ref struct_def, _) => {
163 // If this is a tuple-like struct, register the constructor.
164 if let Some(ctor_id) = struct_def.ctor_id {
165 self.insert_def(ctor_id,
166 NodeStructCtor(&**struct_def),
167 DefPathData::StructCtor);
170 for field in &struct_def.fields {
171 self.create_def(field.node.id, DefPathData::Field(field.node.kind));
174 ItemTrait(_, _, ref bounds, _) => {
175 for b in bounds.iter() {
176 if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
177 self.insert(t.trait_ref.ref_id, NodeItem(i));
181 ItemUse(ref view_path) => {
182 match view_path.node {
183 ViewPathList(_, ref paths) => {
185 self.insert(path.node.id(), NodeItem(i));
193 visit::walk_item(self, i);
194 self.parent_node = parent_node;
197 fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
198 self.insert_def(foreign_item.id,
199 NodeForeignItem(foreign_item),
200 DefPathData::Value(foreign_item.name));
202 let parent_node = self.parent_node;
203 self.parent_node = foreign_item.id;
204 visit::walk_foreign_item(self, foreign_item);
205 self.parent_node = parent_node;
208 fn visit_generics(&mut self, generics: &'ast Generics) {
209 for ty_param in generics.ty_params.iter() {
210 self.insert_def(ty_param.id,
211 NodeTyParam(ty_param),
212 DefPathData::TypeParam(ty_param.name));
215 visit::walk_generics(self, generics);
218 fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
219 let def_data = match ti.node {
220 MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::Value(ti.name),
221 TypeTraitItem(..) => DefPathData::Type(ti.name),
224 self.insert(ti.id, NodeTraitItem(ti));
225 self.create_def(ti.id, def_data);
227 let parent_node = self.parent_node;
228 self.parent_node = ti.id;
231 ConstTraitItem(_, Some(ref expr)) => {
232 self.create_def(expr.id, DefPathData::Initializer);
237 visit::walk_trait_item(self, ti);
239 self.parent_node = parent_node;
242 fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
243 let def_data = match ii.node {
244 MethodImplItem(..) | ConstImplItem(..) => DefPathData::Value(ii.name),
245 TypeImplItem(..) => DefPathData::Type(ii.name),
248 self.insert_def(ii.id, NodeImplItem(ii), def_data);
250 let parent_node = self.parent_node;
251 self.parent_node = ii.id;
254 ConstImplItem(_, ref expr) => {
255 self.create_def(expr.id, DefPathData::Initializer);
260 visit::walk_impl_item(self, ii);
262 self.parent_node = parent_node;
265 fn visit_pat(&mut self, pat: &'ast Pat) {
266 let maybe_binding = match pat.node {
267 PatIdent(_, id, _) => Some(id.node),
271 if let Some(id) = maybe_binding {
272 self.insert_def(pat.id, NodeLocal(pat), DefPathData::Binding(id.name));
274 self.insert(pat.id, NodePat(pat));
277 let parent_node = self.parent_node;
278 self.parent_node = pat.id;
279 visit::walk_pat(self, pat);
280 self.parent_node = parent_node;
283 fn visit_expr(&mut self, expr: &'ast Expr) {
284 self.insert(expr.id, NodeExpr(expr));
287 ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
291 let parent_node = self.parent_node;
292 self.parent_node = expr.id;
293 visit::walk_expr(self, expr);
294 self.parent_node = parent_node;
297 fn visit_stmt(&mut self, stmt: &'ast Stmt) {
298 let id = util::stmt_id(stmt);
299 self.insert(id, NodeStmt(stmt));
300 let parent_node = self.parent_node;
301 self.parent_node = id;
302 visit::walk_stmt(self, stmt);
303 self.parent_node = parent_node;
306 fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
307 b: &'ast Block, s: Span, id: NodeId) {
308 assert_eq!(self.parent_node, id);
309 self.visit_fn_decl(fd);
310 visit::walk_fn(self, fk, fd, b, s);
313 fn visit_ty(&mut self, ty: &'ast Ty) {
315 TyBareFn(ref fd) => {
316 self.visit_fn_decl(&*fd.decl);
320 visit::walk_ty(self, ty);
323 fn visit_block(&mut self, block: &'ast Block) {
324 self.insert(block.id, NodeBlock(block));
325 let parent_node = self.parent_node;
326 self.parent_node = block.id;
327 visit::walk_block(self, block);
328 self.parent_node = parent_node;
331 fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
332 self.insert(lifetime.id, NodeLifetime(lifetime));
335 fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
336 self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
337 self.visit_lifetime(&def.lifetime);
340 fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
341 self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));