]> git.lizzy.rs Git - rust.git/blob - src/librustc/front/map/collector.rs
stop updating `parent_node_id` when there is no corresponding map entry
[rust.git] / src / librustc / front / map / collector.rs
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.
4 //
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.
10
11 use super::*;
12 use super::MapEntry::*;
13
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;
21
22 /// A Visitor that walks over an AST and collects Node's into an AST
23 /// Map.
24 pub struct NodeCollector<'ast> {
25     pub map: Vec<MapEntry<'ast>>,
26     pub definitions_map: NodeSet,
27     pub parent_node: NodeId,
28 }
29
30 impl<'ast> NodeCollector<'ast> {
31     pub fn root() -> NodeCollector<'ast> {
32         let mut collector = NodeCollector {
33             map: vec![],
34             definitions_map: NodeSet(),
35             parent_node: CRATE_NODE_ID,
36         };
37         collector.insert_entry(CRATE_NODE_ID, RootCrate);
38         collector.create_def(CRATE_NODE_ID);
39         collector.create_def(DUMMY_NODE_ID);
40         collector
41     }
42
43     pub fn extend(parent: &'ast InlinedParent,
44                   parent_node: NodeId,
45                   map: Vec<MapEntry<'ast>>,
46                   definitions_map: NodeSet)
47                   -> NodeCollector<'ast> {
48         let mut collector = NodeCollector {
49             map: map,
50             definitions_map: definitions_map,
51             parent_node: parent_node
52         };
53         collector.insert_entry(parent_node, RootInlinedParent(parent));
54
55         collector
56     }
57
58     fn create_def(&mut self, node: NodeId) {
59         let is_new = self.definitions_map.insert(node);
60         assert!(is_new,
61                 "two entries for node id `{}` -- previous is `{:?}`",
62                 node, node);
63     }
64
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));
70         }
71         self.map[id as usize] = entry;
72     }
73
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);
77     }
78
79     fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
80         for a in &decl.inputs {
81             self.insert(a.id, NodeArg(&*a.pat));
82         }
83     }
84 }
85
86 impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
87     fn visit_item(&mut self, i: &'ast Item) {
88         self.insert(i.id, NodeItem(i));
89
90         let parent_node = self.parent_node;
91         self.parent_node = i.id;
92
93         self.create_def(i.id);
94
95         match i.node {
96             ItemImpl(..) => { }
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);
101
102                     match v.node.kind {
103                         TupleVariantKind(ref args) => {
104                             for arg in args {
105                                 self.create_def(arg.id);
106                             }
107                         }
108                         StructVariantKind(ref def) => {
109                             for field in &def.fields {
110                                 self.create_def(field.node.id);
111                             }
112                         }
113                     }
114                 }
115             }
116             ItemForeignMod(..) => {}
117             ItemStruct(ref struct_def, _) => {
118                 // If this is a tuple-like struct, register the constructor.
119                 match struct_def.ctor_id {
120                     Some(ctor_id) => {
121                         self.insert(ctor_id, NodeStructCtor(&**struct_def));
122                         self.create_def(ctor_id);
123                     }
124                     None => {}
125                 }
126
127                 for field in &struct_def.fields {
128                     self.create_def(field.node.id);
129                 }
130             }
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));
135                     }
136                 }
137             }
138             ItemUse(ref view_path) => {
139                 match view_path.node {
140                     ViewPathList(_, ref paths) => {
141                         for path in paths {
142                             self.insert(path.node.id(), NodeItem(i));
143                         }
144                     }
145                     _ => ()
146                 }
147             }
148             _ => {}
149         }
150         visit::walk_item(self, i);
151         self.parent_node = parent_node;
152     }
153
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);
157
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;
162     }
163
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));
168         }
169
170         visit::walk_generics(self, generics);
171     }
172
173     fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
174         self.insert(ti.id, NodeTraitItem(ti));
175         self.create_def(ti.id);
176
177         match ti.node {
178             ConstTraitItem(_, Some(ref expr)) => {
179                 self.create_def(expr.id);
180             }
181             _ => { }
182         }
183
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;
188     }
189
190     fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
191         self.insert(ii.id, NodeImplItem(ii));
192         self.create_def(ii.id);
193
194         match ii.node {
195             ConstImplItem(_, ref expr) => {
196                 self.create_def(expr.id);
197             }
198             _ => { }
199         }
200
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;
205     }
206
207     fn visit_pat(&mut self, pat: &'ast Pat) {
208         let maybe_binding = match pat.node {
209             PatIdent(..) => true,
210             _ => false
211         };
212
213         self.insert(pat.id,
214                     if maybe_binding {NodeLocal(pat)} else {NodePat(pat)});
215
216         if maybe_binding {
217             self.create_def(pat.id);
218         }
219
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;
224     }
225
226     fn visit_expr(&mut self, expr: &'ast Expr) {
227         self.insert(expr.id, NodeExpr(expr));
228
229         match expr.node {
230             ExprClosure(..) => self.create_def(expr.id),
231             _ => (),
232         }
233
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;
238     }
239
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;
247     }
248
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);
254     }
255
256     fn visit_ty(&mut self, ty: &'ast Ty) {
257         match ty.node {
258             TyBareFn(ref fd) => {
259                 self.visit_fn_decl(&*fd.decl);
260             }
261             _ => {}
262         }
263         visit::walk_ty(self, ty);
264     }
265
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;
272     }
273
274     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
275         self.insert(lifetime.id, NodeLifetime(lifetime));
276     }
277
278     fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
279         self.create_def(def.lifetime.id);
280         self.visit_lifetime(&def.lifetime);
281     }
282
283     fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
284         self.create_def(macro_def.id);
285     }
286 }
287