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