]> git.lizzy.rs Git - rust.git/blob - src/librustc/front/map/collector.rs
track def-id for inlined items
[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::intravisit::{self, Visitor};
17 use middle::def_id::{CRATE_DEF_INDEX, DefId, 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 krate: &'ast Crate,
26     pub map: Vec<MapEntry<'ast>>,
27     pub definitions: Definitions,
28     pub parent_node: NodeId,
29 }
30
31 impl<'ast> NodeCollector<'ast> {
32     pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> {
33         let mut collector = NodeCollector {
34             krate: krate,
35             map: vec![],
36             definitions: Definitions::new(),
37             parent_node: CRATE_NODE_ID,
38         };
39         collector.insert_entry(CRATE_NODE_ID, RootCrate);
40
41         let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
42         assert_eq!(result, CRATE_DEF_INDEX);
43
44         collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
45
46         collector
47     }
48
49     pub fn extend(krate: &'ast Crate,
50                   parent: &'ast InlinedParent,
51                   parent_node: NodeId,
52                   parent_def_path: DefPath,
53                   parent_def_id: DefId,
54                   map: Vec<MapEntry<'ast>>,
55                   definitions: Definitions)
56                   -> NodeCollector<'ast> {
57         let mut collector = NodeCollector {
58             krate: krate,
59             map: map,
60             parent_node: parent_node,
61             definitions: definitions,
62         };
63
64         assert_eq!(parent_def_path.krate, parent_def_id.krate);
65         let root_path = Box::new(InlinedRootPath {
66             data: parent_def_path.data,
67             def_id: parent_def_id,
68         });
69
70         collector.insert_entry(parent_node, RootInlinedParent(parent));
71         collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
72
73         collector
74     }
75
76     fn parent_def(&self) -> Option<DefIndex> {
77         let mut parent_node = Some(self.parent_node);
78         while let Some(p) = parent_node {
79             if let Some(q) = self.definitions.opt_def_index(p) {
80                 return Some(q);
81             }
82             parent_node = self.map[p as usize].parent_node();
83         }
84         None
85     }
86
87     fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
88         let parent_def = self.parent_def();
89         debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
90         self.definitions.create_def_with_parent(parent_def, node_id, data)
91     }
92
93     fn create_def_with_parent(&mut self,
94                               parent: Option<DefIndex>,
95                               node_id: NodeId,
96                               data: DefPathData)
97                               -> DefIndex {
98         self.definitions.create_def_with_parent(parent, node_id, data)
99     }
100
101     fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
102         debug!("ast_map: {:?} => {:?}", id, entry);
103         let len = self.map.len();
104         if id as usize >= len {
105             self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
106         }
107         self.map[id as usize] = entry;
108     }
109
110     fn insert_def(&mut self, id: NodeId, node: Node<'ast>, data: DefPathData) -> DefIndex {
111         self.insert(id, node);
112         self.create_def(id, data)
113     }
114
115     fn insert(&mut self, id: NodeId, node: Node<'ast>) {
116         let entry = MapEntry::from_node(self.parent_node, node);
117         self.insert_entry(id, entry);
118     }
119 }
120
121 impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
122     /// Because we want to track parent items and so forth, enable
123     /// deep walking so that we walk nested items in the context of
124     /// their outer items.
125     fn visit_nested_item(&mut self, item: ItemId) {
126         debug!("visit_nested_item: {:?}", item);
127         self.visit_item(self.krate.item(item.id))
128     }
129
130     fn visit_item(&mut self, i: &'ast Item) {
131         debug!("visit_item: {:?}", i);
132
133         // Pick the def data. This need not be unique, but the more
134         // information we encapsulate into
135         let def_data = match i.node {
136             ItemDefaultImpl(..) | ItemImpl(..) => DefPathData::Impl(i.name),
137             ItemEnum(..) | ItemStruct(..) | ItemTrait(..) => DefPathData::Type(i.name),
138             ItemExternCrate(..) | ItemMod(..) => DefPathData::Mod(i.name),
139             ItemStatic(..) | ItemConst(..) | ItemFn(..) => DefPathData::Value(i.name),
140             _ => DefPathData::Misc,
141         };
142
143         self.insert_def(i.id, NodeItem(i), def_data);
144
145         let parent_node = self.parent_node;
146         self.parent_node = i.id;
147
148         match i.node {
149             ItemImpl(..) => {}
150             ItemEnum(ref enum_definition, _) => {
151                 for v in &enum_definition.variants {
152                     let variant_def_index =
153                         self.insert_def(v.node.data.id(),
154                                         NodeVariant(v),
155                                         DefPathData::EnumVariant(v.node.name));
156
157                     for field in v.node.data.fields() {
158                         self.create_def_with_parent(
159                             Some(variant_def_index),
160                             field.id,
161                             DefPathData::Field(field.name));
162                     }
163                 }
164             }
165             ItemForeignMod(..) => {
166             }
167             ItemStruct(ref struct_def, _) => {
168                 // If this is a tuple-like struct, register the constructor.
169                 if !struct_def.is_struct() {
170                     self.insert_def(struct_def.id(),
171                                     NodeStructCtor(struct_def),
172                                     DefPathData::StructCtor);
173                 }
174
175                 for field in struct_def.fields() {
176                     self.create_def(field.id, DefPathData::Field(field.name));
177                 }
178             }
179             ItemTrait(_, _, ref bounds, _) => {
180                 for b in bounds.iter() {
181                     if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
182                         self.insert(t.trait_ref.ref_id, NodeItem(i));
183                     }
184                 }
185             }
186             ItemUse(ref view_path) => {
187                 match view_path.node {
188                     ViewPathList(_, ref paths) => {
189                         for path in paths {
190                             self.insert(path.node.id(), NodeItem(i));
191                         }
192                     }
193                     _ => ()
194                 }
195             }
196             _ => {}
197         }
198         intravisit::walk_item(self, i);
199         self.parent_node = parent_node;
200     }
201
202     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
203         self.insert_def(foreign_item.id,
204                         NodeForeignItem(foreign_item),
205                         DefPathData::Value(foreign_item.name));
206
207         let parent_node = self.parent_node;
208         self.parent_node = foreign_item.id;
209         intravisit::walk_foreign_item(self, foreign_item);
210         self.parent_node = parent_node;
211     }
212
213     fn visit_generics(&mut self, generics: &'ast Generics) {
214         for ty_param in generics.ty_params.iter() {
215             self.insert_def(ty_param.id,
216                             NodeTyParam(ty_param),
217                             DefPathData::TypeParam(ty_param.name));
218         }
219
220         intravisit::walk_generics(self, generics);
221     }
222
223     fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
224         let def_data = match ti.node {
225             MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::Value(ti.name),
226             TypeTraitItem(..) => DefPathData::Type(ti.name),
227         };
228
229         self.insert(ti.id, NodeTraitItem(ti));
230         self.create_def(ti.id, def_data);
231
232         let parent_node = self.parent_node;
233         self.parent_node = ti.id;
234
235         match ti.node {
236             ConstTraitItem(_, Some(ref expr)) => {
237                 self.create_def(expr.id, DefPathData::Initializer);
238             }
239             _ => { }
240         }
241
242         intravisit::walk_trait_item(self, ti);
243
244         self.parent_node = parent_node;
245     }
246
247     fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
248         let def_data = match ii.node {
249             ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::Value(ii.name),
250             ImplItemKind::Type(..) => DefPathData::Type(ii.name),
251         };
252
253         self.insert_def(ii.id, NodeImplItem(ii), def_data);
254
255         let parent_node = self.parent_node;
256         self.parent_node = ii.id;
257
258         match ii.node {
259             ImplItemKind::Const(_, ref expr) => {
260                 self.create_def(expr.id, DefPathData::Initializer);
261             }
262             _ => { }
263         }
264
265         intravisit::walk_impl_item(self, ii);
266
267         self.parent_node = parent_node;
268     }
269
270     fn visit_pat(&mut self, pat: &'ast Pat) {
271         let maybe_binding = match pat.node {
272             PatKind::Ident(_, id, _) => Some(id.node),
273             _ => None
274         };
275
276         if let Some(id) = maybe_binding {
277             self.insert_def(pat.id, NodeLocal(pat), DefPathData::Binding(id.name));
278         } else {
279             self.insert(pat.id, NodePat(pat));
280         }
281
282         let parent_node = self.parent_node;
283         self.parent_node = pat.id;
284         intravisit::walk_pat(self, pat);
285         self.parent_node = parent_node;
286     }
287
288     fn visit_expr(&mut self, expr: &'ast Expr) {
289         self.insert(expr.id, NodeExpr(expr));
290
291         match expr.node {
292             ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
293             _ => { }
294         }
295
296         let parent_node = self.parent_node;
297         self.parent_node = expr.id;
298         intravisit::walk_expr(self, expr);
299         self.parent_node = parent_node;
300     }
301
302     fn visit_stmt(&mut self, stmt: &'ast Stmt) {
303         let id = util::stmt_id(stmt);
304         self.insert(id, NodeStmt(stmt));
305         let parent_node = self.parent_node;
306         self.parent_node = id;
307         intravisit::walk_stmt(self, stmt);
308         self.parent_node = parent_node;
309     }
310
311     fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
312                 b: &'ast Block, s: Span, id: NodeId) {
313         assert_eq!(self.parent_node, id);
314         intravisit::walk_fn(self, fk, fd, b, s);
315     }
316
317     fn visit_block(&mut self, block: &'ast Block) {
318         self.insert(block.id, NodeBlock(block));
319         let parent_node = self.parent_node;
320         self.parent_node = block.id;
321         intravisit::walk_block(self, block);
322         self.parent_node = parent_node;
323     }
324
325     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
326         self.insert(lifetime.id, NodeLifetime(lifetime));
327     }
328
329     fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
330         self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
331         self.visit_lifetime(&def.lifetime);
332     }
333
334     fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
335         self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
336     }
337 }