]>
Commit | Line | Data |
---|---|---|
a7813a04 XL |
1 | // Copyright 2016 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 | ||
476ff2be | 11 | use hir::map::definitions::*; |
cc61c64b | 12 | use hir::def_id::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace}; |
a7813a04 XL |
13 | |
14 | use syntax::ast::*; | |
c30ab7b3 | 15 | use syntax::ext::hygiene::Mark; |
a7813a04 | 16 | use syntax::visit; |
7cac9316 | 17 | use syntax::symbol::keywords; |
041b39d2 | 18 | use syntax::symbol::Symbol; |
a7813a04 | 19 | |
cc61c64b XL |
20 | use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE}; |
21 | ||
32a655c1 | 22 | /// Creates def ids for nodes in the AST. |
c30ab7b3 | 23 | pub struct DefCollector<'a> { |
c30ab7b3 | 24 | definitions: &'a mut Definitions, |
a7813a04 | 25 | parent_def: Option<DefIndex>, |
7cac9316 | 26 | expansion: Mark, |
c30ab7b3 | 27 | pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>, |
a7813a04 XL |
28 | } |
29 | ||
c30ab7b3 SL |
30 | pub struct MacroInvocationData { |
31 | pub mark: Mark, | |
32 | pub def_index: DefIndex, | |
32a655c1 | 33 | pub const_expr: bool, |
c30ab7b3 SL |
34 | } |
35 | ||
36 | impl<'a> DefCollector<'a> { | |
7cac9316 | 37 | pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self { |
9e0c209e | 38 | DefCollector { |
041b39d2 XL |
39 | definitions, |
40 | expansion, | |
a7813a04 | 41 | parent_def: None, |
c30ab7b3 | 42 | visit_macro_invoc: None, |
9e0c209e | 43 | } |
a7813a04 XL |
44 | } |
45 | ||
cc61c64b XL |
46 | pub fn collect_root(&mut self, crate_name: &str, crate_disambiguator: &str) { |
47 | let root = self.definitions.create_root_def(crate_name, | |
48 | crate_disambiguator); | |
9e0c209e SL |
49 | assert_eq!(root, CRATE_DEF_INDEX); |
50 | self.parent_def = Some(root); | |
a7813a04 XL |
51 | } |
52 | ||
cc61c64b XL |
53 | fn create_def(&mut self, |
54 | node_id: NodeId, | |
55 | data: DefPathData, | |
56 | address_space: DefIndexAddressSpace) | |
57 | -> DefIndex { | |
58 | let parent_def = self.parent_def.unwrap(); | |
a7813a04 | 59 | debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); |
7cac9316 XL |
60 | self.definitions |
61 | .create_def_with_parent(parent_def, node_id, data, address_space, self.expansion) | |
a7813a04 XL |
62 | } |
63 | ||
c30ab7b3 | 64 | pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) { |
a7813a04 XL |
65 | let parent = self.parent_def; |
66 | self.parent_def = Some(parent_def); | |
67 | f(self); | |
68 | self.parent_def = parent; | |
69 | } | |
70 | ||
32a655c1 | 71 | pub fn visit_const_expr(&mut self, expr: &Expr) { |
c30ab7b3 SL |
72 | match expr.node { |
73 | // Find the node which will be used after lowering. | |
32a655c1 | 74 | ExprKind::Paren(ref inner) => return self.visit_const_expr(inner), |
c30ab7b3 SL |
75 | ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, true), |
76 | // FIXME(eddyb) Closures should have separate | |
77 | // function definition IDs and expression IDs. | |
78 | ExprKind::Closure(..) => return, | |
79 | _ => {} | |
a7813a04 XL |
80 | } |
81 | ||
cc61c64b | 82 | self.create_def(expr.id, DefPathData::Initializer, REGULAR_SPACE); |
a7813a04 XL |
83 | } |
84 | ||
32a655c1 | 85 | fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) { |
c30ab7b3 SL |
86 | if let Some(ref mut visit) = self.visit_macro_invoc { |
87 | visit(MacroInvocationData { | |
cc61c64b | 88 | mark: id.placeholder_to_mark(), |
041b39d2 | 89 | const_expr, |
c30ab7b3 SL |
90 | def_index: self.parent_def.unwrap(), |
91 | }) | |
92 | } | |
93 | } | |
a7813a04 XL |
94 | } |
95 | ||
476ff2be SL |
96 | impl<'a> visit::Visitor<'a> for DefCollector<'a> { |
97 | fn visit_item(&mut self, i: &'a Item) { | |
a7813a04 XL |
98 | debug!("visit_item: {:?}", i); |
99 | ||
100 | // Pick the def data. This need not be unique, but the more | |
101 | // information we encapsulate into | |
102 | let def_data = match i.node { | |
103 | ItemKind::DefaultImpl(..) | ItemKind::Impl(..) => | |
104 | DefPathData::Impl, | |
9e0c209e | 105 | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) | |
a7813a04 | 106 | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => |
ea8adc8c | 107 | DefPathData::TypeNs(i.ident.name.as_str()), |
c30ab7b3 SL |
108 | ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { |
109 | return visit::walk_item(self, i); | |
110 | } | |
ea8adc8c | 111 | ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()), |
a7813a04 | 112 | ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => |
ea8adc8c XL |
113 | DefPathData::ValueNs(i.ident.name.as_str()), |
114 | ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()), | |
c30ab7b3 | 115 | ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false), |
cc61c64b | 116 | ItemKind::GlobalAsm(..) => DefPathData::Misc, |
476ff2be SL |
117 | ItemKind::Use(ref view_path) => { |
118 | match view_path.node { | |
119 | ViewPathGlob(..) => {} | |
120 | ||
121 | // FIXME(eddyb) Should use the real name. Which namespace? | |
122 | ViewPathSimple(..) => {} | |
123 | ViewPathList(_, ref imports) => { | |
124 | for import in imports { | |
cc61c64b XL |
125 | self.create_def(import.node.id, |
126 | DefPathData::Misc, | |
127 | ITEM_LIKE_SPACE); | |
476ff2be SL |
128 | } |
129 | } | |
130 | } | |
131 | DefPathData::Misc | |
132 | } | |
a7813a04 | 133 | }; |
cc61c64b | 134 | let def = self.create_def(i.id, def_data, ITEM_LIKE_SPACE); |
a7813a04 XL |
135 | |
136 | self.with_parent(def, |this| { | |
137 | match i.node { | |
138 | ItemKind::Enum(ref enum_definition, _) => { | |
139 | for v in &enum_definition.variants { | |
140 | let variant_def_index = | |
141 | this.create_def(v.node.data.id(), | |
ea8adc8c | 142 | DefPathData::EnumVariant(v.node.name.name.as_str()), |
cc61c64b | 143 | REGULAR_SPACE); |
a7813a04 XL |
144 | this.with_parent(variant_def_index, |this| { |
145 | for (index, field) in v.node.data.fields().iter().enumerate() { | |
041b39d2 XL |
146 | let name = field.ident.map(|ident| ident.name) |
147 | .unwrap_or_else(|| Symbol::intern(&index.to_string())); | |
ea8adc8c XL |
148 | this.create_def(field.id, |
149 | DefPathData::Field(name.as_str()), | |
150 | REGULAR_SPACE); | |
a7813a04 XL |
151 | } |
152 | ||
153 | if let Some(ref expr) = v.node.disr_expr { | |
32a655c1 | 154 | this.visit_const_expr(expr); |
a7813a04 XL |
155 | } |
156 | }); | |
157 | } | |
158 | } | |
9e0c209e | 159 | ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { |
a7813a04 XL |
160 | // If this is a tuple-like struct, register the constructor. |
161 | if !struct_def.is_struct() { | |
162 | this.create_def(struct_def.id(), | |
cc61c64b XL |
163 | DefPathData::StructCtor, |
164 | REGULAR_SPACE); | |
a7813a04 XL |
165 | } |
166 | ||
167 | for (index, field) in struct_def.fields().iter().enumerate() { | |
041b39d2 XL |
168 | let name = field.ident.map(|ident| ident.name) |
169 | .unwrap_or_else(|| Symbol::intern(&index.to_string())); | |
ea8adc8c | 170 | this.create_def(field.id, DefPathData::Field(name.as_str()), REGULAR_SPACE); |
a7813a04 XL |
171 | } |
172 | } | |
173 | _ => {} | |
174 | } | |
175 | visit::walk_item(this, i); | |
176 | }); | |
177 | } | |
178 | ||
476ff2be | 179 | fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { |
5bcae85e | 180 | let def = self.create_def(foreign_item.id, |
ea8adc8c | 181 | DefPathData::ValueNs(foreign_item.ident.name.as_str()), |
cc61c64b | 182 | REGULAR_SPACE); |
a7813a04 XL |
183 | |
184 | self.with_parent(def, |this| { | |
185 | visit::walk_foreign_item(this, foreign_item); | |
186 | }); | |
187 | } | |
188 | ||
476ff2be | 189 | fn visit_generics(&mut self, generics: &'a Generics) { |
a7813a04 | 190 | for ty_param in generics.ty_params.iter() { |
cc61c64b | 191 | self.create_def(ty_param.id, |
ea8adc8c | 192 | DefPathData::TypeParam(ty_param.ident.name.as_str()), |
cc61c64b | 193 | REGULAR_SPACE); |
a7813a04 XL |
194 | } |
195 | ||
196 | visit::walk_generics(self, generics); | |
197 | } | |
198 | ||
476ff2be | 199 | fn visit_trait_item(&mut self, ti: &'a TraitItem) { |
a7813a04 XL |
200 | let def_data = match ti.node { |
201 | TraitItemKind::Method(..) | TraitItemKind::Const(..) => | |
ea8adc8c XL |
202 | DefPathData::ValueNs(ti.ident.name.as_str()), |
203 | TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()), | |
c30ab7b3 | 204 | TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false), |
a7813a04 XL |
205 | }; |
206 | ||
cc61c64b | 207 | let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE); |
a7813a04 XL |
208 | self.with_parent(def, |this| { |
209 | if let TraitItemKind::Const(_, Some(ref expr)) = ti.node { | |
32a655c1 | 210 | this.visit_const_expr(expr); |
a7813a04 XL |
211 | } |
212 | ||
213 | visit::walk_trait_item(this, ti); | |
214 | }); | |
215 | } | |
216 | ||
476ff2be | 217 | fn visit_impl_item(&mut self, ii: &'a ImplItem) { |
a7813a04 XL |
218 | let def_data = match ii.node { |
219 | ImplItemKind::Method(..) | ImplItemKind::Const(..) => | |
ea8adc8c XL |
220 | DefPathData::ValueNs(ii.ident.name.as_str()), |
221 | ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()), | |
c30ab7b3 | 222 | ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false), |
a7813a04 XL |
223 | }; |
224 | ||
cc61c64b | 225 | let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE); |
a7813a04 XL |
226 | self.with_parent(def, |this| { |
227 | if let ImplItemKind::Const(_, ref expr) = ii.node { | |
32a655c1 | 228 | this.visit_const_expr(expr); |
a7813a04 XL |
229 | } |
230 | ||
231 | visit::walk_impl_item(this, ii); | |
232 | }); | |
233 | } | |
234 | ||
476ff2be | 235 | fn visit_pat(&mut self, pat: &'a Pat) { |
c30ab7b3 SL |
236 | match pat.node { |
237 | PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false), | |
ea8adc8c | 238 | _ => visit::walk_pat(self, pat), |
a7813a04 | 239 | } |
a7813a04 XL |
240 | } |
241 | ||
476ff2be | 242 | fn visit_expr(&mut self, expr: &'a Expr) { |
a7813a04 XL |
243 | let parent_def = self.parent_def; |
244 | ||
c30ab7b3 SL |
245 | match expr.node { |
246 | ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false), | |
32a655c1 | 247 | ExprKind::Repeat(_, ref count) => self.visit_const_expr(count), |
c30ab7b3 | 248 | ExprKind::Closure(..) => { |
cc61c64b XL |
249 | let def = self.create_def(expr.id, |
250 | DefPathData::ClosureExpr, | |
251 | REGULAR_SPACE); | |
c30ab7b3 SL |
252 | self.parent_def = Some(def); |
253 | } | |
254 | _ => {} | |
a7813a04 XL |
255 | } |
256 | ||
257 | visit::walk_expr(self, expr); | |
258 | self.parent_def = parent_def; | |
259 | } | |
260 | ||
476ff2be | 261 | fn visit_ty(&mut self, ty: &'a Ty) { |
c30ab7b3 SL |
262 | match ty.node { |
263 | TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false), | |
32a655c1 | 264 | TyKind::Array(_, ref length) => self.visit_const_expr(length), |
c30ab7b3 | 265 | TyKind::ImplTrait(..) => { |
cc61c64b | 266 | self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE); |
c30ab7b3 | 267 | } |
32a655c1 | 268 | TyKind::Typeof(ref expr) => self.visit_const_expr(expr), |
c30ab7b3 | 269 | _ => {} |
5bcae85e | 270 | } |
a7813a04 XL |
271 | visit::walk_ty(self, ty); |
272 | } | |
273 | ||
476ff2be | 274 | fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) { |
cc61c64b | 275 | self.create_def(def.lifetime.id, |
ea8adc8c | 276 | DefPathData::LifetimeDef(def.lifetime.ident.name.as_str()), |
cc61c64b | 277 | REGULAR_SPACE); |
a7813a04 XL |
278 | } |
279 | ||
476ff2be | 280 | fn visit_stmt(&mut self, stmt: &'a Stmt) { |
c30ab7b3 SL |
281 | match stmt.node { |
282 | StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false), | |
283 | _ => visit::walk_stmt(self, stmt), | |
284 | } | |
285 | } | |
a7813a04 | 286 | } |