diff options
Diffstat (limited to 'crates/ra_hir_def/src/data.rs')
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 220 |
1 files changed, 96 insertions, 124 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 53599e74a..697fde3d2 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -5,24 +5,23 @@ use std::sync::Arc; | |||
5 | use hir_expand::{ | 5 | use hir_expand::{ |
6 | hygiene::Hygiene, | 6 | hygiene::Hygiene, |
7 | name::{name, AsName, Name}, | 7 | name::{name, AsName, Name}, |
8 | AstId, InFile, | 8 | InFile, |
9 | }; | 9 | }; |
10 | use ra_prof::profile; | 10 | use ra_prof::profile; |
11 | use ra_syntax::ast::{ | 11 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, VisibilityOwner}; |
12 | self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, | ||
13 | VisibilityOwner, | ||
14 | }; | ||
15 | 12 | ||
16 | use crate::{ | 13 | use crate::{ |
17 | attr::Attrs, | 14 | attr::Attrs, |
15 | body::Expander, | ||
18 | body::LowerCtx, | 16 | body::LowerCtx, |
19 | db::DefDatabase, | 17 | db::DefDatabase, |
18 | item_tree::{AssocItem, ItemTreeId, ModItem}, | ||
20 | path::{path, AssociatedTypeBinding, GenericArgs, Path}, | 19 | path::{path, AssociatedTypeBinding, GenericArgs, Path}, |
21 | src::HasSource, | 20 | src::HasSource, |
22 | type_ref::{Mutability, TypeBound, TypeRef}, | 21 | type_ref::{Mutability, TypeBound, TypeRef}, |
23 | visibility::RawVisibility, | 22 | visibility::RawVisibility, |
24 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, | 23 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
25 | ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 24 | Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
26 | }; | 25 | }; |
27 | 26 | ||
28 | #[derive(Debug, Clone, PartialEq, Eq)] | 27 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -155,30 +154,24 @@ pub struct TraitData { | |||
155 | impl TraitData { | 154 | impl TraitData { |
156 | pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { | 155 | pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { |
157 | let tr_loc = tr.lookup(db); | 156 | let tr_loc = tr.lookup(db); |
158 | let src = tr_loc.source(db); | 157 | let item_tree = db.item_tree(tr_loc.id.file_id); |
159 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 158 | let tr_def = &item_tree[tr_loc.id.value]; |
160 | let auto = src.value.auto_token().is_some(); | 159 | let name = tr_def.name.clone(); |
160 | let auto = tr_def.auto; | ||
161 | let module_id = tr_loc.container.module(db); | 161 | let module_id = tr_loc.container.module(db); |
162 | |||
163 | let container = AssocContainerId::TraitId(tr); | 162 | let container = AssocContainerId::TraitId(tr); |
164 | let mut items = Vec::new(); | 163 | let mut expander = Expander::new(db, tr_loc.id.file_id, module_id); |
165 | 164 | ||
166 | if let Some(item_list) = src.value.item_list() { | 165 | let items = collect_items( |
167 | let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id); | 166 | db, |
168 | items.extend(collect_items( | 167 | module_id, |
169 | db, | 168 | &mut expander, |
170 | &mut expander, | 169 | tr_def.items.iter().copied(), |
171 | item_list.assoc_items(), | 170 | tr_loc.id.file_id, |
172 | src.file_id, | 171 | container, |
173 | container, | 172 | 100, |
174 | )); | 173 | ); |
175 | items.extend(collect_items_in_macros( | 174 | |
176 | db, | ||
177 | &mut expander, | ||
178 | &src.with_value(item_list), | ||
179 | container, | ||
180 | )); | ||
181 | } | ||
182 | Arc::new(TraitData { name, items, auto }) | 175 | Arc::new(TraitData { name, items, auto }) |
183 | } | 176 | } |
184 | 177 | ||
@@ -209,33 +202,28 @@ impl ImplData { | |||
209 | pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> { | 202 | pub(crate) fn impl_data_query(db: &dyn DefDatabase, id: ImplId) -> Arc<ImplData> { |
210 | let _p = profile("impl_data_query"); | 203 | let _p = profile("impl_data_query"); |
211 | let impl_loc = id.lookup(db); | 204 | let impl_loc = id.lookup(db); |
212 | let src = impl_loc.source(db); | ||
213 | let lower_ctx = LowerCtx::new(db, src.file_id); | ||
214 | 205 | ||
215 | let target_trait = src.value.target_trait().map(|it| TypeRef::from_ast(&lower_ctx, it)); | 206 | let item_tree = db.item_tree(impl_loc.id.file_id); |
216 | let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type()); | 207 | let impl_def = &item_tree[impl_loc.id.value]; |
217 | let is_negative = src.value.excl_token().is_some(); | 208 | let target_trait = impl_def.target_trait.clone(); |
209 | let target_type = impl_def.target_type.clone(); | ||
210 | let is_negative = impl_def.is_negative; | ||
218 | let module_id = impl_loc.container.module(db); | 211 | let module_id = impl_loc.container.module(db); |
219 | let container = AssocContainerId::ImplId(id); | 212 | let container = AssocContainerId::ImplId(id); |
213 | let mut expander = Expander::new(db, impl_loc.id.file_id, module_id); | ||
220 | 214 | ||
221 | let mut items: Vec<AssocItemId> = Vec::new(); | 215 | let items = collect_items( |
222 | 216 | db, | |
223 | if let Some(item_list) = src.value.item_list() { | 217 | module_id, |
224 | let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); | 218 | &mut expander, |
225 | items.extend( | 219 | impl_def.items.iter().copied(), |
226 | collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container) | 220 | impl_loc.id.file_id, |
227 | .into_iter() | 221 | container, |
228 | .map(|(_, item)| item), | 222 | 100, |
229 | ); | 223 | ); |
230 | items.extend( | 224 | let items = items.into_iter().map(|(_, item)| item).collect(); |
231 | collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container) | ||
232 | .into_iter() | ||
233 | .map(|(_, item)| item), | ||
234 | ); | ||
235 | } | ||
236 | 225 | ||
237 | let res = ImplData { target_trait, target_type, items, is_negative }; | 226 | Arc::new(ImplData { target_trait, target_type, items, is_negative }) |
238 | Arc::new(res) | ||
239 | } | 227 | } |
240 | } | 228 | } |
241 | 229 | ||
@@ -295,28 +283,12 @@ impl StaticData { | |||
295 | } | 283 | } |
296 | } | 284 | } |
297 | 285 | ||
298 | fn collect_items_in_macros( | 286 | fn collect_items( |
299 | db: &dyn DefDatabase, | ||
300 | expander: &mut Expander, | ||
301 | impl_def: &InFile<ast::ItemList>, | ||
302 | container: AssocContainerId, | ||
303 | ) -> Vec<(Name, AssocItemId)> { | ||
304 | let mut res = Vec::new(); | ||
305 | |||
306 | // We set a limit to protect against infinite recursion | ||
307 | let limit = 100; | ||
308 | |||
309 | for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { | ||
310 | res.extend(collect_items_in_macro(db, expander, m, container, limit)) | ||
311 | } | ||
312 | |||
313 | res | ||
314 | } | ||
315 | |||
316 | fn collect_items_in_macro( | ||
317 | db: &dyn DefDatabase, | 287 | db: &dyn DefDatabase, |
288 | module: ModuleId, | ||
318 | expander: &mut Expander, | 289 | expander: &mut Expander, |
319 | m: ast::MacroCall, | 290 | assoc_items: impl Iterator<Item = AssocItem>, |
291 | file_id: crate::HirFileId, | ||
320 | container: AssocContainerId, | 292 | container: AssocContainerId, |
321 | limit: usize, | 293 | limit: usize, |
322 | ) -> Vec<(Name, AssocItemId)> { | 294 | ) -> Vec<(Name, AssocItemId)> { |
@@ -324,62 +296,62 @@ fn collect_items_in_macro( | |||
324 | return Vec::new(); | 296 | return Vec::new(); |
325 | } | 297 | } |
326 | 298 | ||
327 | if let Some((mark, items)) = expander.enter_expand(db, None, m) { | 299 | let item_tree = db.item_tree(file_id); |
328 | let items: InFile<ast::MacroItems> = expander.to_source(items); | 300 | let cfg_options = db.crate_graph()[module.krate].cfg_options.clone(); |
329 | let mut res = collect_items( | ||
330 | db, | ||
331 | expander, | ||
332 | items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())), | ||
333 | items.file_id, | ||
334 | container, | ||
335 | ); | ||
336 | |||
337 | // Recursive collect macros | ||
338 | // Note that ast::ModuleItem do not include ast::MacroCall | ||
339 | // We cannot use ModuleItemOwner::items here | ||
340 | for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { | ||
341 | res.extend(collect_items_in_macro(db, expander, it, container, limit - 1)) | ||
342 | } | ||
343 | expander.exit(db, mark); | ||
344 | res | ||
345 | } else { | ||
346 | Vec::new() | ||
347 | } | ||
348 | } | ||
349 | 301 | ||
350 | fn collect_items( | 302 | let mut items = Vec::new(); |
351 | db: &dyn DefDatabase, | 303 | for item in assoc_items { |
352 | expander: &mut Expander, | 304 | match item { |
353 | assoc_items: impl Iterator<Item = AssocItem>, | 305 | AssocItem::Function(id) => { |
354 | file_id: crate::HirFileId, | 306 | let item = &item_tree[id]; |
355 | container: AssocContainerId, | 307 | if !item.attrs.is_cfg_enabled(&cfg_options) { |
356 | ) -> Vec<(Name, AssocItemId)> { | 308 | continue; |
357 | let items = db.ast_id_map(file_id); | ||
358 | |||
359 | assoc_items | ||
360 | .filter_map(|item_node| match item_node { | ||
361 | ast::AssocItem::FnDef(it) => { | ||
362 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | ||
363 | if !expander.is_cfg_enabled(&it) { | ||
364 | return None; | ||
365 | } | 309 | } |
366 | let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } | 310 | let def = FunctionLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db); |
367 | .intern(db); | 311 | items.push((item.name.clone(), def.into())); |
368 | Some((name, def.into())) | ||
369 | } | 312 | } |
370 | ast::AssocItem::ConstDef(it) => { | 313 | // FIXME: cfg? |
371 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 314 | AssocItem::Const(id) => { |
372 | let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } | 315 | let item = &item_tree[id]; |
373 | .intern(db); | 316 | let name = if let Some(name) = item.name.clone() { |
374 | Some((name, def.into())) | 317 | name |
318 | } else { | ||
319 | continue; | ||
320 | }; | ||
321 | let def = ConstLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db); | ||
322 | items.push((name, def.into())); | ||
375 | } | 323 | } |
376 | ast::AssocItem::TypeAliasDef(it) => { | 324 | AssocItem::TypeAlias(id) => { |
377 | let name = it.name().map_or_else(Name::missing, |it| it.as_name()); | 325 | let item = &item_tree[id]; |
378 | let def = | 326 | let def = TypeAliasLoc { container, id: ItemTreeId::new(file_id, id) }.intern(db); |
379 | TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) } | 327 | items.push((item.name.clone(), def.into())); |
380 | .intern(db); | ||
381 | Some((name, def.into())) | ||
382 | } | 328 | } |
383 | }) | 329 | AssocItem::MacroCall(call) => { |
384 | .collect() | 330 | let call = &item_tree[call]; |
331 | let ast_id_map = db.ast_id_map(file_id); | ||
332 | let root = db.parse_or_expand(file_id).unwrap(); | ||
333 | let call = ast_id_map.get(call.ast_id).to_node(&root); | ||
334 | |||
335 | if let Some((mark, mac)) = expander.enter_expand(db, None, call) { | ||
336 | let src: InFile<ast::MacroItems> = expander.to_source(mac); | ||
337 | let item_tree = db.item_tree(src.file_id); | ||
338 | let iter = | ||
339 | item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item); | ||
340 | items.extend(collect_items( | ||
341 | db, | ||
342 | module, | ||
343 | expander, | ||
344 | iter, | ||
345 | src.file_id, | ||
346 | container, | ||
347 | limit - 1, | ||
348 | )); | ||
349 | |||
350 | expander.exit(db, mark); | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | } | ||
355 | |||
356 | items | ||
385 | } | 357 | } |