]> git.lizzy.rs Git - rust.git/blob - src/librustc/front/map/collector.rs
Auto merge of #28789 - rkruppe:rm-unused-probes, r=alexcrichton
[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 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;
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: Definitions,
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: Definitions::new(),
35             parent_node: CRATE_NODE_ID,
36         };
37         collector.insert_entry(CRATE_NODE_ID, RootCrate);
38
39         let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
40         assert_eq!(result, CRATE_DEF_INDEX);
41
42         collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
43
44         collector
45     }
46
47     pub fn extend(parent: &'ast InlinedParent,
48                   parent_node: NodeId,
49                   parent_def_path: DefPath,
50                   map: Vec<MapEntry<'ast>>,
51                   definitions: Definitions)
52                   -> NodeCollector<'ast> {
53         let mut collector = NodeCollector {
54             map: map,
55             parent_node: parent_node,
56             definitions: definitions,
57         };
58
59         collector.insert_entry(parent_node, RootInlinedParent(parent));
60         collector.create_def(parent_node, DefPathData::InlinedRoot(parent_def_path));
61
62         collector
63     }
64
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) {
69                 return Some(q);
70             }
71             parent_node = self.map[p as usize].parent_node();
72         }
73         None
74     }
75
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)
79     }
80
81     fn create_def_with_parent(&mut self,
82                               parent: Option<DefIndex>,
83                               node_id: NodeId,
84                               data: DefPathData)
85                               -> DefIndex {
86         self.definitions.create_def_with_parent(parent, node_id, data)
87     }
88
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));
94         }
95         self.map[id as usize] = entry;
96     }
97
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)
101     }
102
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);
106     }
107
108     fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
109         for a in &decl.inputs {
110             self.insert(a.id, NodeArg(&*a.pat));
111         }
112     }
113 }
114
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,
125         };
126
127         self.insert_def(i.id, NodeItem(i), def_data);
128
129         let parent_node = self.parent_node;
130         self.parent_node = i.id;
131
132         match i.node {
133             ItemImpl(..) => {}
134             ItemEnum(ref enum_definition, _) => {
135                 for v in &enum_definition.variants {
136                     let variant_def_index =
137                         self.insert_def(v.node.id,
138                                         NodeVariant(&**v),
139                                         DefPathData::EnumVariant(v.node.name));
140
141                     match v.node.kind {
142                         TupleVariantKind(ref args) => {
143                             for arg in args {
144                                 self.create_def_with_parent(Some(variant_def_index),
145                                                             arg.id,
146                                                             DefPathData::PositionalField);
147                             }
148                         }
149                         StructVariantKind(ref def) => {
150                             for field in &def.fields {
151                                 self.create_def_with_parent(
152                                     Some(variant_def_index),
153                                     field.node.id,
154                                     DefPathData::Field(field.node.kind));
155                             }
156                         }
157                     }
158                 }
159             }
160             ItemForeignMod(..) => {
161             }
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);
168                 }
169
170                 for field in &struct_def.fields {
171                     self.create_def(field.node.id, DefPathData::Field(field.node.kind));
172                 }
173             }
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));
178                     }
179                 }
180             }
181             ItemUse(ref view_path) => {
182                 match view_path.node {
183                     ViewPathList(_, ref paths) => {
184                         for path in paths {
185                             self.insert(path.node.id(), NodeItem(i));
186                         }
187                     }
188                     _ => ()
189                 }
190             }
191             _ => {}
192         }
193         visit::walk_item(self, i);
194         self.parent_node = parent_node;
195     }
196
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));
201
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;
206     }
207
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));
213         }
214
215         visit::walk_generics(self, generics);
216     }
217
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),
222         };
223
224         self.insert(ti.id, NodeTraitItem(ti));
225         self.create_def(ti.id, def_data);
226
227         let parent_node = self.parent_node;
228         self.parent_node = ti.id;
229
230         match ti.node {
231             ConstTraitItem(_, Some(ref expr)) => {
232                 self.create_def(expr.id, DefPathData::Initializer);
233             }
234             _ => { }
235         }
236
237         visit::walk_trait_item(self, ti);
238
239         self.parent_node = parent_node;
240     }
241
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),
246         };
247
248         self.insert_def(ii.id, NodeImplItem(ii), def_data);
249
250         let parent_node = self.parent_node;
251         self.parent_node = ii.id;
252
253         match ii.node {
254             ConstImplItem(_, ref expr) => {
255                 self.create_def(expr.id, DefPathData::Initializer);
256             }
257             _ => { }
258         }
259
260         visit::walk_impl_item(self, ii);
261
262         self.parent_node = parent_node;
263     }
264
265     fn visit_pat(&mut self, pat: &'ast Pat) {
266         let maybe_binding = match pat.node {
267             PatIdent(_, id, _) => Some(id.node),
268             _ => None
269         };
270
271         if let Some(id) = maybe_binding {
272             self.insert_def(pat.id, NodeLocal(pat), DefPathData::Binding(id.name));
273         } else {
274             self.insert(pat.id, NodePat(pat));
275         }
276
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;
281     }
282
283     fn visit_expr(&mut self, expr: &'ast Expr) {
284         self.insert(expr.id, NodeExpr(expr));
285
286         match expr.node {
287             ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
288             _ => { }
289         }
290
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;
295     }
296
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;
304     }
305
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);
311     }
312
313     fn visit_ty(&mut self, ty: &'ast Ty) {
314         match ty.node {
315             TyBareFn(ref fd) => {
316                 self.visit_fn_decl(&*fd.decl);
317             }
318             _ => {}
319         }
320         visit::walk_ty(self, ty);
321     }
322
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;
329     }
330
331     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
332         self.insert(lifetime.id, NodeLifetime(lifetime));
333     }
334
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);
338     }
339
340     fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
341         self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
342     }
343 }
344