aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/data.rs
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-06-22 14:07:06 +0100
committerJonas Schievink <[email protected]>2020-06-24 15:53:16 +0100
commit4b03b39d5b4b00daffb120a4d2d9ea4a55a9a7ac (patch)
tree85431e53ce86bbcf16ba9b38fcc5f2ad27378722 /crates/ra_hir_def/src/data.rs
parentb94caeb88b4aab7219d4b2f5c8c6c668199247fb (diff)
draw the rest of the owl
Diffstat (limited to 'crates/ra_hir_def/src/data.rs')
-rw-r--r--crates/ra_hir_def/src/data.rs220
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;
5use hir_expand::{ 5use 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};
10use ra_prof::profile; 10use ra_prof::profile;
11use ra_syntax::ast::{ 11use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, VisibilityOwner};
12 self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner,
13 VisibilityOwner,
14};
15 12
16use crate::{ 13use 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 {
155impl TraitData { 154impl 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
298fn collect_items_in_macros( 286fn 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
316fn 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
350fn 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}