diff options
Diffstat (limited to 'crates/ra_hir_def/src/data.rs')
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 184 |
1 files changed, 81 insertions, 103 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index ccb682f9a..e7eb2bb11 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -9,12 +9,13 @@ use hir_expand::{ | |||
9 | }; | 9 | }; |
10 | use ra_prof::profile; | 10 | use ra_prof::profile; |
11 | use ra_syntax::ast::{ | 11 | use ra_syntax::ast::{ |
12 | self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, | 12 | self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, |
13 | VisibilityOwner, | 13 | VisibilityOwner, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use crate::{ | 16 | use crate::{ |
17 | attr::Attrs, | 17 | attr::Attrs, |
18 | body::LowerCtx, | ||
18 | db::DefDatabase, | 19 | db::DefDatabase, |
19 | path::{path, AssociatedTypeBinding, GenericArgs, Path}, | 20 | path::{path, AssociatedTypeBinding, GenericArgs, Path}, |
20 | src::HasSource, | 21 | src::HasSource, |
@@ -40,13 +41,14 @@ impl FunctionData { | |||
40 | pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { | 41 | pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { |
41 | let loc = func.lookup(db); | 42 | let loc = func.lookup(db); |
42 | let src = loc.source(db); | 43 | let src = loc.source(db); |
44 | let ctx = LowerCtx::new(db, src.file_id); | ||
43 | let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); | 45 | let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); |
44 | let mut params = Vec::new(); | 46 | let mut params = Vec::new(); |
45 | let mut has_self_param = false; | 47 | let mut has_self_param = false; |
46 | if let Some(param_list) = src.value.param_list() { | 48 | if let Some(param_list) = src.value.param_list() { |
47 | if let Some(self_param) = param_list.self_param() { | 49 | if let Some(self_param) = param_list.self_param() { |
48 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { | 50 | let self_type = if let Some(type_ref) = self_param.ascribed_type() { |
49 | TypeRef::from_ast(type_ref) | 51 | TypeRef::from_ast(&ctx, type_ref) |
50 | } else { | 52 | } else { |
51 | let self_type = TypeRef::Path(name![Self].into()); | 53 | let self_type = TypeRef::Path(name![Self].into()); |
52 | match self_param.kind() { | 54 | match self_param.kind() { |
@@ -63,14 +65,14 @@ impl FunctionData { | |||
63 | has_self_param = true; | 65 | has_self_param = true; |
64 | } | 66 | } |
65 | for param in param_list.params() { | 67 | for param in param_list.params() { |
66 | let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); | 68 | let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type()); |
67 | params.push(type_ref); | 69 | params.push(type_ref); |
68 | } | 70 | } |
69 | } | 71 | } |
70 | let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); | 72 | let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); |
71 | 73 | ||
72 | let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { | 74 | let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { |
73 | TypeRef::from_ast(type_ref) | 75 | TypeRef::from_ast(&ctx, type_ref) |
74 | } else { | 76 | } else { |
75 | TypeRef::unit() | 77 | TypeRef::unit() |
76 | }; | 78 | }; |
@@ -122,7 +124,8 @@ impl TypeAliasData { | |||
122 | let loc = typ.lookup(db); | 124 | let loc = typ.lookup(db); |
123 | let node = loc.source(db); | 125 | let node = loc.source(db); |
124 | let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); | 126 | let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); |
125 | let type_ref = node.value.type_ref().map(TypeRef::from_ast); | 127 | let lower_ctx = LowerCtx::new(db, node.file_id); |
128 | let type_ref = node.value.type_ref().map(|it| TypeRef::from_ast(&lower_ctx, it)); | ||
126 | let vis_default = RawVisibility::default_for_container(loc.container); | 129 | let vis_default = RawVisibility::default_for_container(loc.container); |
127 | let visibility = RawVisibility::from_ast_with_default( | 130 | let visibility = RawVisibility::from_ast_with_default( |
128 | db, | 131 | db, |
@@ -130,7 +133,7 @@ impl TypeAliasData { | |||
130 | node.as_ref().map(|n| n.visibility()), | 133 | node.as_ref().map(|n| n.visibility()), |
131 | ); | 134 | ); |
132 | let bounds = if let Some(bound_list) = node.value.type_bound_list() { | 135 | let bounds = if let Some(bound_list) = node.value.type_bound_list() { |
133 | bound_list.bounds().map(TypeBound::from_ast).collect() | 136 | bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect() |
134 | } else { | 137 | } else { |
135 | Vec::new() | 138 | Vec::new() |
136 | }; | 139 | }; |
@@ -147,51 +150,31 @@ pub struct TraitData { | |||
147 | 150 | ||
148 | impl TraitData { | 151 | impl TraitData { |
149 | pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { | 152 | pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { |
150 | let src = tr.lookup(db).source(db); | 153 | let tr_loc = tr.lookup(db); |
154 | let src = tr_loc.source(db); | ||
151 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 155 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
152 | let auto = src.value.auto_token().is_some(); | 156 | let auto = src.value.auto_token().is_some(); |
153 | let ast_id_map = db.ast_id_map(src.file_id); | 157 | let module_id = tr_loc.container.module(db); |
154 | 158 | ||
155 | let container = AssocContainerId::TraitId(tr); | 159 | let container = AssocContainerId::TraitId(tr); |
156 | let items = if let Some(item_list) = src.value.item_list() { | 160 | let mut items = Vec::new(); |
157 | item_list | 161 | |
158 | .impl_items() | 162 | if let Some(item_list) = src.value.item_list() { |
159 | .map(|item_node| match item_node { | 163 | let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id); |
160 | ast::ImplItem::FnDef(it) => { | 164 | items.extend(collect_items( |
161 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 165 | db, |
162 | let def = FunctionLoc { | 166 | &mut expander, |
163 | container, | 167 | item_list.assoc_items(), |
164 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | 168 | src.file_id, |
165 | } | 169 | container, |
166 | .intern(db) | 170 | )); |
167 | .into(); | 171 | items.extend(collect_items_in_macros( |
168 | (name, def) | 172 | db, |
169 | } | 173 | &mut expander, |
170 | ast::ImplItem::ConstDef(it) => { | 174 | &src.with_value(item_list), |
171 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 175 | container, |
172 | let def = ConstLoc { | 176 | )); |
173 | container, | 177 | } |
174 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | ||
175 | } | ||
176 | .intern(db) | ||
177 | .into(); | ||
178 | (name, def) | ||
179 | } | ||
180 | ast::ImplItem::TypeAliasDef(it) => { | ||
181 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | ||
182 | let def = TypeAliasLoc { | ||
183 | container, | ||
184 | ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), | ||
185 | } | ||
186 | .intern(db) | ||
187 | .into(); | ||
188 | (name, def) | ||
189 | } | ||
190 | }) | ||
191 | .collect() | ||
192 | } else { | ||
193 | Vec::new() | ||
194 | }; | ||
195 | Arc::new(TraitData { name, items, auto }) | 178 | Arc::new(TraitData { name, items, auto }) |
196 | } | 179 | } |
197 | 180 | ||
@@ -223,29 +206,28 @@ impl ImplData { | |||
223 | let _p = profile("impl_data_query"); | 206 | let _p = profile("impl_data_query"); |
224 | let impl_loc = id.lookup(db); | 207 | let impl_loc = id.lookup(db); |
225 | let src = impl_loc.source(db); | 208 | let src = impl_loc.source(db); |
209 | let lower_ctx = LowerCtx::new(db, src.file_id); | ||
226 | 210 | ||
227 | let target_trait = src.value.target_trait().map(TypeRef::from_ast); | 211 | let target_trait = src.value.target_trait().map(|it| TypeRef::from_ast(&lower_ctx, it)); |
228 | let target_type = TypeRef::from_ast_opt(src.value.target_type()); | 212 | let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type()); |
229 | let is_negative = src.value.excl_token().is_some(); | 213 | let is_negative = src.value.excl_token().is_some(); |
230 | let module_id = impl_loc.container.module(db); | 214 | let module_id = impl_loc.container.module(db); |
215 | let container = AssocContainerId::ImplId(id); | ||
231 | 216 | ||
232 | let mut items = Vec::new(); | 217 | let mut items: Vec<AssocItemId> = Vec::new(); |
233 | 218 | ||
234 | if let Some(item_list) = src.value.item_list() { | 219 | if let Some(item_list) = src.value.item_list() { |
235 | let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); | 220 | let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); |
236 | items.extend(collect_impl_items( | 221 | items.extend( |
237 | db, | 222 | collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container) |
238 | &mut expander, | 223 | .into_iter() |
239 | item_list.impl_items(), | 224 | .map(|(_, item)| item), |
240 | src.file_id, | 225 | ); |
241 | id, | 226 | items.extend( |
242 | )); | 227 | collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container) |
243 | items.extend(collect_impl_items_in_macros( | 228 | .into_iter() |
244 | db, | 229 | .map(|(_, item)| item), |
245 | &mut expander, | 230 | ); |
246 | &src.with_value(item_list), | ||
247 | id, | ||
248 | )); | ||
249 | } | 231 | } |
250 | 232 | ||
251 | let res = ImplData { target_trait, target_type, items, is_negative }; | 233 | let res = ImplData { target_trait, target_type, items, is_negative }; |
@@ -279,57 +261,59 @@ impl ConstData { | |||
279 | vis_default: RawVisibility, | 261 | vis_default: RawVisibility, |
280 | node: InFile<N>, | 262 | node: InFile<N>, |
281 | ) -> ConstData { | 263 | ) -> ConstData { |
264 | let ctx = LowerCtx::new(db, node.file_id); | ||
282 | let name = node.value.name().map(|n| n.as_name()); | 265 | let name = node.value.name().map(|n| n.as_name()); |
283 | let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type()); | 266 | let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type()); |
284 | let visibility = | 267 | let visibility = |
285 | RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); | 268 | RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); |
286 | ConstData { name, type_ref, visibility } | 269 | ConstData { name, type_ref, visibility } |
287 | } | 270 | } |
288 | } | 271 | } |
289 | 272 | ||
290 | fn collect_impl_items_in_macros( | 273 | fn collect_items_in_macros( |
291 | db: &dyn DefDatabase, | 274 | db: &dyn DefDatabase, |
292 | expander: &mut Expander, | 275 | expander: &mut Expander, |
293 | impl_def: &InFile<ast::ItemList>, | 276 | impl_def: &InFile<ast::ItemList>, |
294 | id: ImplId, | 277 | container: AssocContainerId, |
295 | ) -> Vec<AssocItemId> { | 278 | ) -> Vec<(Name, AssocItemId)> { |
296 | let mut res = Vec::new(); | 279 | let mut res = Vec::new(); |
297 | 280 | ||
298 | // We set a limit to protect against infinite recursion | 281 | // We set a limit to protect against infinite recursion |
299 | let limit = 100; | 282 | let limit = 100; |
300 | 283 | ||
301 | for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { | 284 | for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { |
302 | res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) | 285 | res.extend(collect_items_in_macro(db, expander, m, container, limit)) |
303 | } | 286 | } |
304 | 287 | ||
305 | res | 288 | res |
306 | } | 289 | } |
307 | 290 | ||
308 | fn collect_impl_items_in_macro( | 291 | fn collect_items_in_macro( |
309 | db: &dyn DefDatabase, | 292 | db: &dyn DefDatabase, |
310 | expander: &mut Expander, | 293 | expander: &mut Expander, |
311 | m: ast::MacroCall, | 294 | m: ast::MacroCall, |
312 | id: ImplId, | 295 | container: AssocContainerId, |
313 | limit: usize, | 296 | limit: usize, |
314 | ) -> Vec<AssocItemId> { | 297 | ) -> Vec<(Name, AssocItemId)> { |
315 | if limit == 0 { | 298 | if limit == 0 { |
316 | return Vec::new(); | 299 | return Vec::new(); |
317 | } | 300 | } |
318 | 301 | ||
319 | if let Some((mark, items)) = expander.enter_expand(db, None, m) { | 302 | if let Some((mark, items)) = expander.enter_expand(db, None, m) { |
320 | let items: InFile<ast::MacroItems> = expander.to_source(items); | 303 | let items: InFile<ast::MacroItems> = expander.to_source(items); |
321 | let mut res = collect_impl_items( | 304 | let mut res = collect_items( |
322 | db, | 305 | db, |
323 | expander, | 306 | expander, |
324 | items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), | 307 | items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())), |
325 | items.file_id, | 308 | items.file_id, |
326 | id, | 309 | container, |
327 | ); | 310 | ); |
311 | |||
328 | // Recursive collect macros | 312 | // Recursive collect macros |
329 | // Note that ast::ModuleItem do not include ast::MacroCall | 313 | // Note that ast::ModuleItem do not include ast::MacroCall |
330 | // We cannot use ModuleItemOwner::items here | 314 | // We cannot use ModuleItemOwner::items here |
331 | for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { | 315 | for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { |
332 | res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) | 316 | res.extend(collect_items_in_macro(db, expander, it, container, limit - 1)) |
333 | } | 317 | } |
334 | expander.exit(db, mark); | 318 | expander.exit(db, mark); |
335 | res | 319 | res |
@@ -338,44 +322,38 @@ fn collect_impl_items_in_macro( | |||
338 | } | 322 | } |
339 | } | 323 | } |
340 | 324 | ||
341 | fn collect_impl_items( | 325 | fn collect_items( |
342 | db: &dyn DefDatabase, | 326 | db: &dyn DefDatabase, |
343 | expander: &mut Expander, | 327 | expander: &mut Expander, |
344 | impl_items: impl Iterator<Item = ImplItem>, | 328 | assoc_items: impl Iterator<Item = AssocItem>, |
345 | file_id: crate::HirFileId, | 329 | file_id: crate::HirFileId, |
346 | id: ImplId, | 330 | container: AssocContainerId, |
347 | ) -> Vec<AssocItemId> { | 331 | ) -> Vec<(Name, AssocItemId)> { |
348 | let items = db.ast_id_map(file_id); | 332 | let items = db.ast_id_map(file_id); |
349 | 333 | ||
350 | impl_items | 334 | assoc_items |
351 | .filter_map(|item_node| match item_node { | 335 | .filter_map(|item_node| match item_node { |
352 | ast::ImplItem::FnDef(it) => { | 336 | ast::AssocItem::FnDef(it) => { |
353 | let attrs = expander.parse_attrs(&it); | 337 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
354 | if !expander.is_cfg_enabled(&attrs) { | 338 | if !expander.is_cfg_enabled(&it) { |
355 | return None; | 339 | return None; |
356 | } | 340 | } |
357 | let def = FunctionLoc { | 341 | let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
358 | container: AssocContainerId::ImplId(id), | 342 | .intern(db); |
359 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 343 | Some((name, def.into())) |
360 | } | ||
361 | .intern(db); | ||
362 | Some(def.into()) | ||
363 | } | 344 | } |
364 | ast::ImplItem::ConstDef(it) => { | 345 | ast::AssocItem::ConstDef(it) => { |
365 | let def = ConstLoc { | 346 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
366 | container: AssocContainerId::ImplId(id), | 347 | let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
367 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 348 | .intern(db); |
368 | } | 349 | Some((name, def.into())) |
369 | .intern(db); | ||
370 | Some(def.into()) | ||
371 | } | 350 | } |
372 | ast::ImplItem::TypeAliasDef(it) => { | 351 | ast::AssocItem::TypeAliasDef(it) => { |
373 | let def = TypeAliasLoc { | 352 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); |
374 | container: AssocContainerId::ImplId(id), | 353 | let def = |
375 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 354 | TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } |
376 | } | 355 | .intern(db); |
377 | .intern(db); | 356 | Some((name, def.into())) |
378 | Some(def.into()) | ||
379 | } | 357 | } |
380 | }) | 358 | }) |
381 | .collect() | 359 | .collect() |