Skip to content

Commit 926ba99

Browse files
bors[bot]Veykril
andauthored
Merge #11235
11235: internal: Record attribute calls on assoc items in TraitData and ImplData r=Veykril a=Veykril Fixes #11228 Co-authored-by: Lukas Wirth <[email protected]>
2 parents c17db9f + 8d4f40e commit 926ba99

File tree

5 files changed

+105
-42
lines changed

5 files changed

+105
-42
lines changed

crates/hir/src/semantics/source_to_def.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,7 @@ impl SourceToDefCtx<'_, '_> {
316316
}
317317

318318
pub(super) fn macro_to_def(&mut self, src: InFile<ast::Macro>) -> Option<MacroDefId> {
319-
let makro =
320-
self.dyn_map(src.as_ref()).and_then(|it| it[keys::MACRO_CALL].get(&src).copied());
319+
let makro = self.dyn_map(src.as_ref()).and_then(|it| it[keys::MACRO].get(&src).copied());
321320
if let res @ Some(_) = makro {
322321
return res;
323322
}

crates/hir_def/src/child_by_source.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,31 @@ pub trait ChildBySource {
3030
impl ChildBySource for TraitId {
3131
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
3232
let data = db.trait_data(*self);
33-
// FIXME attribute macros
34-
for &(_, item) in data.items.iter() {
33+
34+
data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
35+
|(ast_id, call_id)| {
36+
let item = ast_id.with_value(ast_id.to_node(db.upcast()));
37+
res[keys::ATTR_MACRO_CALL].insert(item, call_id);
38+
},
39+
);
40+
data.items.iter().for_each(|&(_, item)| {
3541
child_by_source_assoc_items(db, res, file_id, item);
36-
}
42+
});
3743
}
3844
}
3945

4046
impl ChildBySource for ImplId {
4147
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
4248
let data = db.impl_data(*self);
43-
// FIXME attribute macros
44-
for &item in data.items.iter() {
49+
data.attribute_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
50+
|(ast_id, call_id)| {
51+
let item = ast_id.with_value(ast_id.to_node(db.upcast()));
52+
res[keys::ATTR_MACRO_CALL].insert(item, call_id);
53+
},
54+
);
55+
data.items.iter().for_each(|&item| {
4556
child_by_source_assoc_items(db, res, file_id, item);
46-
}
57+
});
4758
}
4859
}
4960

@@ -97,7 +108,7 @@ impl ChildBySource for ItemScope {
97108
// FIXME: Do we need to add proc-macros into a PROCMACRO dynmap here?
98109
Either::Right(_fn) => return,
99110
};
100-
res[keys::MACRO_CALL].insert(src, makro);
111+
res[keys::MACRO].insert(src, makro);
101112
}
102113
});
103114
self.unnamed_consts().for_each(|konst| {

crates/hir_def/src/data.rs

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::sync::Arc;
44

5-
use hir_expand::{name::Name, AstId, ExpandResult, InFile};
5+
use hir_expand::{name::Name, AstId, ExpandResult, InFile, MacroCallId};
66
use syntax::ast;
77

88
use crate::{
@@ -184,6 +184,8 @@ pub struct TraitData {
184184
/// method calls to this trait's methods when the receiver is an array and the crate edition is
185185
/// 2015 or 2018.
186186
pub skip_array_during_method_dispatch: bool,
187+
// box it as the vec is usually empty anyways
188+
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
187189
}
188190

189191
impl TraitData {
@@ -207,15 +209,8 @@ impl TraitData {
207209
.by_key("rustc_skip_array_during_method_dispatch")
208210
.exists();
209211

210-
let items = collect_items(
211-
db,
212-
module_id,
213-
&mut expander,
214-
tr_def.items.iter().copied(),
215-
tr_loc.id.tree_id(),
216-
container,
217-
100,
218-
);
212+
let (items, attribute_calls) =
213+
do_collect(db, module_id, &mut expander, &tr_def.items, tr_loc.id.tree_id(), container);
219214

220215
Arc::new(TraitData {
221216
name,
@@ -224,6 +219,7 @@ impl TraitData {
224219
is_unsafe,
225220
visibility,
226221
skip_array_during_method_dispatch,
222+
attribute_calls,
227223
})
228224
}
229225

@@ -247,6 +243,10 @@ impl TraitData {
247243
_ => None,
248244
})
249245
}
246+
247+
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
248+
self.attribute_calls.iter().flat_map(|it| it.iter()).copied()
249+
}
250250
}
251251

252252
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -255,6 +255,8 @@ pub struct ImplData {
255255
pub self_ty: Interned<TypeRef>,
256256
pub items: Vec<AssocItemId>,
257257
pub is_negative: bool,
258+
// box it as the vec is usually empty anyways
259+
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
258260
}
259261

260262
impl ImplData {
@@ -271,18 +273,21 @@ impl ImplData {
271273
let container = ItemContainerId::ImplId(id);
272274
let mut expander = Expander::new(db, impl_loc.id.file_id(), module_id);
273275

274-
let items = collect_items(
276+
let (items, attribute_calls) = do_collect(
275277
db,
276278
module_id,
277279
&mut expander,
278-
impl_def.items.iter().copied(),
280+
&impl_def.items,
279281
impl_loc.id.tree_id(),
280282
container,
281-
100,
282283
);
283284
let items = items.into_iter().map(|(_, item)| item).collect();
284285

285-
Arc::new(ImplData { target_trait, self_ty, items, is_negative })
286+
Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls })
287+
}
288+
289+
pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
290+
self.attribute_calls.iter().flat_map(|it| it.iter()).copied()
286291
}
287292
}
288293

@@ -333,41 +338,70 @@ impl StaticData {
333338
}
334339
}
335340

341+
fn do_collect(
342+
db: &dyn DefDatabase,
343+
module_id: ModuleId,
344+
expander: &mut Expander,
345+
assoc_items: &[AssocItem],
346+
tree_id: item_tree::TreeId,
347+
container: ItemContainerId,
348+
) -> (Vec<(Name, AssocItemId)>, Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>) {
349+
let mut items = Vec::new();
350+
let mut attribute_calls = Vec::new();
351+
352+
collect_items(
353+
db,
354+
&mut items,
355+
&mut attribute_calls,
356+
module_id,
357+
expander,
358+
assoc_items.iter().copied(),
359+
tree_id,
360+
container,
361+
100,
362+
);
363+
364+
let attribute_calls =
365+
if attribute_calls.is_empty() { None } else { Some(Box::new(attribute_calls)) };
366+
(items, attribute_calls)
367+
}
368+
336369
fn collect_items(
337370
db: &dyn DefDatabase,
371+
items: &mut Vec<(Name, AssocItemId)>,
372+
attr_calls: &mut Vec<(AstId<ast::Item>, MacroCallId)>,
338373
module: ModuleId,
339374
expander: &mut Expander,
340375
assoc_items: impl Iterator<Item = AssocItem>,
341376
tree_id: item_tree::TreeId,
342377
container: ItemContainerId,
343378
limit: usize,
344-
) -> Vec<(Name, AssocItemId)> {
379+
) {
345380
if limit == 0 {
346-
return Vec::new();
381+
return;
347382
}
348383

349384
let item_tree = tree_id.item_tree(db);
350385
let crate_graph = db.crate_graph();
351386
let cfg_options = &crate_graph[module.krate].cfg_options;
352387
let def_map = module.def_map(db);
353388

354-
let mut items = Vec::new();
355389
'items: for item in assoc_items {
356390
let attrs = item_tree.attrs(db, module.krate, ModItem::from(item).into());
357391
if !attrs.is_cfg_enabled(cfg_options) {
358392
continue;
359393
}
360394

361395
for attr in &*attrs {
362-
let ast_id = AstIdWithPath {
363-
path: (*attr.path).clone(),
364-
ast_id: AstId::new(expander.current_file_id(), item.ast_id(&item_tree).upcast()),
365-
};
396+
let ast_id = AstId::new(expander.current_file_id(), item.ast_id(&item_tree).upcast());
397+
let ast_id_with_path = AstIdWithPath { path: (*attr.path).clone(), ast_id };
398+
366399
if let Ok(ResolvedAttr::Macro(call_id)) =
367-
def_map.resolve_attr_macro(db, module.local_id, ast_id, attr)
400+
def_map.resolve_attr_macro(db, module.local_id, ast_id_with_path, attr)
368401
{
402+
attr_calls.push((ast_id, call_id));
369403
let res = expander.enter_expand_id(db, call_id);
370-
items.extend(collect_macro_items(db, module, expander, container, limit, res));
404+
collect_macro_items(db, items, attr_calls, module, expander, container, limit, res);
371405
continue 'items;
372406
}
373407
}
@@ -401,34 +435,32 @@ fn collect_items(
401435
let res = expander.enter_expand(db, call);
402436

403437
if let Ok(res) = res {
404-
items.extend(collect_macro_items(db, module, expander, container, limit, res));
438+
collect_macro_items(
439+
db, items, attr_calls, module, expander, container, limit, res,
440+
);
405441
}
406442
}
407443
}
408444
}
409-
410-
items
411445
}
412446

413447
fn collect_macro_items(
414448
db: &dyn DefDatabase,
449+
items: &mut Vec<(Name, AssocItemId)>,
450+
attr_calls: &mut Vec<(AstId<ast::Item>, MacroCallId)>,
415451
module: ModuleId,
416452
expander: &mut Expander,
417453
container: ItemContainerId,
418454
limit: usize,
419455
res: ExpandResult<Option<(Mark, ast::MacroItems)>>,
420-
) -> Vec<(Name, AssocItemId)> {
456+
) {
421457
if let Some((mark, mac)) = res.value {
422458
let src: InFile<ast::MacroItems> = expander.to_source(mac);
423459
let tree_id = item_tree::TreeId::new(src.file_id, None);
424460
let item_tree = tree_id.item_tree(db);
425461
let iter = item_tree.top_level_items().iter().filter_map(ModItem::as_assoc_item);
426-
let items = collect_items(db, module, expander, iter, tree_id, container, limit - 1);
462+
collect_items(db, items, attr_calls, module, expander, iter, tree_id, container, limit - 1);
427463

428464
expander.exit(db, mark);
429-
430-
return items;
431465
}
432-
433-
Vec::new()
434466
}

crates/hir_def/src/keys.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
3232
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
3333
pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
3434

35-
pub const MACRO_CALL: Key<ast::Macro, MacroDefId> = Key::new();
35+
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
3636
pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
3737
pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, Box<[Option<MacroCallId>]>)> = Key::new();
3838

crates/ide/src/references.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,4 +1514,25 @@ fn func$0() {
15141514
"#]],
15151515
)
15161516
}
1517+
1518+
#[test]
1519+
fn attr_assoc_item() {
1520+
check(
1521+
r#"
1522+
//- proc_macros: identity
1523+
1524+
trait Trait {
1525+
#[proc_macros::identity]
1526+
fn func() {
1527+
Self::func$0();
1528+
}
1529+
}
1530+
"#,
1531+
expect![[r#"
1532+
func Function FileId(0) 48..87 51..55
1533+
1534+
FileId(0) 74..78
1535+
"#]],
1536+
)
1537+
}
15171538
}

0 commit comments

Comments
 (0)