]> git.lizzy.rs Git - rust.git/blob - src/librustc/front/map/collector.rs
Merge VariantData and VariantData_
[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.data.id(),
138                                         NodeVariant(&**v),
139                                         DefPathData::EnumVariant(v.node.name));
140
141                     for field in v.node.data.fields() {
142                         self.create_def_with_parent(
143                             Some(variant_def_index),
144                             field.node.id,
145                             DefPathData::Field(field.node.kind));
146                     }
147                 }
148             }
149             ItemForeignMod(..) => {
150             }
151             ItemStruct(ref struct_def, _) => {
152                 // If this is a tuple-like struct, register the constructor.
153                 if !struct_def.is_struct() {
154                     self.insert_def(struct_def.id(),
155                                     NodeStructCtor(&**struct_def),
156                                     DefPathData::StructCtor);
157                 }
158
159                 for field in struct_def.fields() {
160                     self.create_def(field.node.id, DefPathData::Field(field.node.kind));
161                 }
162             }
163             ItemTrait(_, _, ref bounds, _) => {
164                 for b in bounds.iter() {
165                     if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
166                         self.insert(t.trait_ref.ref_id, NodeItem(i));
167                     }
168                 }
169             }
170             ItemUse(ref view_path) => {
171                 match view_path.node {
172                     ViewPathList(_, ref paths) => {
173                         for path in paths {
174                             self.insert(path.node.id(), NodeItem(i));
175                         }
176                     }
177                     _ => ()
178                 }
179             }
180             _ => {}
181         }
182         visit::walk_item(self, i);
183         self.parent_node = parent_node;
184     }
185
186     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
187         self.insert_def(foreign_item.id,
188                         NodeForeignItem(foreign_item),
189                         DefPathData::Value(foreign_item.name));
190
191         let parent_node = self.parent_node;
192         self.parent_node = foreign_item.id;
193         visit::walk_foreign_item(self, foreign_item);
194         self.parent_node = parent_node;
195     }
196
197     fn visit_generics(&mut self, generics: &'ast Generics) {
198         for ty_param in generics.ty_params.iter() {
199             self.insert_def(ty_param.id,
200                             NodeTyParam(ty_param),
201                             DefPathData::TypeParam(ty_param.name));
202         }
203
204         visit::walk_generics(self, generics);
205     }
206
207     fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
208         let def_data = match ti.node {
209             MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::Value(ti.name),
210             TypeTraitItem(..) => DefPathData::Type(ti.name),
211         };
212
213         self.insert(ti.id, NodeTraitItem(ti));
214         self.create_def(ti.id, def_data);
215
216         let parent_node = self.parent_node;
217         self.parent_node = ti.id;
218
219         match ti.node {
220             ConstTraitItem(_, Some(ref expr)) => {
221                 self.create_def(expr.id, DefPathData::Initializer);
222             }
223             _ => { }
224         }
225
226         visit::walk_trait_item(self, ti);
227
228         self.parent_node = parent_node;
229     }
230
231     fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
232         let def_data = match ii.node {
233             MethodImplItem(..) | ConstImplItem(..) => DefPathData::Value(ii.name),
234             TypeImplItem(..) => DefPathData::Type(ii.name),
235         };
236
237         self.insert_def(ii.id, NodeImplItem(ii), def_data);
238
239         let parent_node = self.parent_node;
240         self.parent_node = ii.id;
241
242         match ii.node {
243             ConstImplItem(_, ref expr) => {
244                 self.create_def(expr.id, DefPathData::Initializer);
245             }
246             _ => { }
247         }
248
249         visit::walk_impl_item(self, ii);
250
251         self.parent_node = parent_node;
252     }
253
254     fn visit_pat(&mut self, pat: &'ast Pat) {
255         let maybe_binding = match pat.node {
256             PatIdent(_, id, _) => Some(id.node),
257             _ => None
258         };
259
260         if let Some(id) = maybe_binding {
261             self.insert_def(pat.id, NodeLocal(pat), DefPathData::Binding(id.name));
262         } else {
263             self.insert(pat.id, NodePat(pat));
264         }
265
266         let parent_node = self.parent_node;
267         self.parent_node = pat.id;
268         visit::walk_pat(self, pat);
269         self.parent_node = parent_node;
270     }
271
272     fn visit_expr(&mut self, expr: &'ast Expr) {
273         self.insert(expr.id, NodeExpr(expr));
274
275         match expr.node {
276             ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
277             _ => { }
278         }
279
280         let parent_node = self.parent_node;
281         self.parent_node = expr.id;
282         visit::walk_expr(self, expr);
283         self.parent_node = parent_node;
284     }
285
286     fn visit_stmt(&mut self, stmt: &'ast Stmt) {
287         let id = util::stmt_id(stmt);
288         self.insert(id, NodeStmt(stmt));
289         let parent_node = self.parent_node;
290         self.parent_node = id;
291         visit::walk_stmt(self, stmt);
292         self.parent_node = parent_node;
293     }
294
295     fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
296                 b: &'ast Block, s: Span, id: NodeId) {
297         assert_eq!(self.parent_node, id);
298         self.visit_fn_decl(fd);
299         visit::walk_fn(self, fk, fd, b, s);
300     }
301
302     fn visit_ty(&mut self, ty: &'ast Ty) {
303         match ty.node {
304             TyBareFn(ref fd) => {
305                 self.visit_fn_decl(&*fd.decl);
306             }
307             _ => {}
308         }
309         visit::walk_ty(self, ty);
310     }
311
312     fn visit_block(&mut self, block: &'ast Block) {
313         self.insert(block.id, NodeBlock(block));
314         let parent_node = self.parent_node;
315         self.parent_node = block.id;
316         visit::walk_block(self, block);
317         self.parent_node = parent_node;
318     }
319
320     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
321         self.insert(lifetime.id, NodeLifetime(lifetime));
322     }
323
324     fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
325         self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
326         self.visit_lifetime(&def.lifetime);
327     }
328
329     fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
330         self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
331     }
332 }
333