Skip to content

Commit 793389b

Browse files
bors[bot]Veykril
andauthored
Merge #10030
10030: fix: Fix multiple derives in one attribute not expanding all in expand_macro r=Veykril a=Veykril It's probably better to only expand the exact derive the cursor is on(if possible) instead of all derives in the attribute the cursor is one. follow up to #10029 bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents 49763c3 + 0f3617f commit 793389b

File tree

6 files changed

+59
-19
lines changed

6 files changed

+59
-19
lines changed

crates/hir/src/semantics.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
148148
self.imp.expand_attr_macro(item)
149149
}
150150

151-
pub fn expand_derive_macro(&self, derive: &ast::Attr) -> Option<SyntaxNode> {
151+
pub fn expand_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<SyntaxNode>> {
152152
self.imp.expand_derive_macro(derive)
153153
}
154154

@@ -389,16 +389,29 @@ impl<'db> SemanticsImpl<'db> {
389389
Some(node)
390390
}
391391

392-
fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
392+
fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<SyntaxNode>> {
393393
let item = attr.syntax().parent().and_then(ast::Item::cast)?;
394394
let sa = self.analyze(item.syntax());
395395
let item = InFile::new(sa.file_id, &item);
396396
let src = InFile::new(sa.file_id, attr.clone());
397-
let macro_call_id = self.with_ctx(|ctx| ctx.attr_to_derive_macro_call(item, src))?;
398-
let file_id = macro_call_id.as_file();
399-
let node = self.db.parse_or_expand(file_id)?;
400-
self.cache(node.clone(), file_id);
401-
Some(node)
397+
self.with_ctx(|ctx| {
398+
let macro_call_ids = ctx.attr_to_derive_macro_call(item, src)?;
399+
400+
let expansions: Vec<_> = macro_call_ids
401+
.iter()
402+
.map(|call| call.as_file())
403+
.flat_map(|file_id| {
404+
let node = self.db.parse_or_expand(file_id)?;
405+
self.cache(node.clone(), file_id);
406+
Some(node)
407+
})
408+
.collect();
409+
if expansions.is_empty() {
410+
None
411+
} else {
412+
Some(expansions)
413+
}
414+
})
402415
}
403416

404417
fn is_attr_macro_call(&self, item: &ast::Item) -> bool {

crates/hir/src/semantics/source_to_def.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,9 @@ impl SourceToDefCtx<'_, '_> {
246246
&mut self,
247247
item: InFile<&ast::Item>,
248248
src: InFile<ast::Attr>,
249-
) -> Option<MacroCallId> {
249+
) -> Option<&[MacroCallId]> {
250250
let map = self.dyn_map(item)?;
251-
map[keys::DERIVE_MACRO].get(&src).copied()
251+
map[keys::DERIVE_MACRO].get(&src).map(AsRef::as_ref)
252252
}
253253

254254
fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(

crates/hir_def/src/child_by_source.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
use either::Either;
88
use hir_expand::HirFileId;
9+
use itertools::Itertools;
910
use syntax::ast::AttrsOwner;
1011

1112
use crate::{
@@ -109,10 +110,13 @@ impl ChildBySource for ItemScope {
109110
let item = ast_id.with_value(ast_id.to_node(db.upcast()));
110111
res[keys::ATTR_MACRO].insert(item, call_id);
111112
});
112-
self.derive_macro_invocs().for_each(|(ast_id, (attr_id, call_id))| {
113+
self.derive_macro_invocs().for_each(|(ast_id, calls)| {
113114
let item = ast_id.to_node(db.upcast());
114-
if let Some(attr) = item.attrs().nth(attr_id.ast_index as usize) {
115-
res[keys::DERIVE_MACRO].insert(ast_id.with_value(attr), call_id);
115+
let grouped = calls.iter().copied().into_group_map();
116+
for (attr_id, calls) in grouped {
117+
if let Some(attr) = item.attrs().nth(attr_id.ast_index as usize) {
118+
res[keys::DERIVE_MACRO].insert(ast_id.with_value(attr), calls.into());
119+
}
116120
}
117121
});
118122

crates/hir_def/src/item_scope.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@ impl ItemScope {
195195

196196
pub(crate) fn derive_macro_invocs(
197197
&self,
198-
) -> impl Iterator<Item = (AstId<ast::Item>, (AttrId, MacroCallId))> + '_ {
199-
self.derive_macros.iter().flat_map(|(k, v)| v.iter().map(move |v| (*k, *v)))
198+
) -> impl Iterator<Item = (AstId<ast::Item>, &[(AttrId, MacroCallId)])> + '_ {
199+
self.derive_macros.iter().map(|(k, v)| (*k, v.as_ref()))
200200
}
201201

202202
pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {

crates/hir_def/src/keys.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
3333

3434
pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
3535
pub const ATTR_MACRO: Key<ast::Item, MacroCallId> = Key::new();
36-
pub const DERIVE_MACRO: Key<ast::Attr, MacroCallId> = Key::new();
36+
pub const DERIVE_MACRO: Key<ast::Attr, Box<[MacroCallId]>> = Key::new();
3737

3838
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
3939
/// equal if they point to exactly the same object.

crates/ide/src/expand_macro.rs

+27-4
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
3737
if path == "derive" {
3838
let mut tt = tt.syntax().children_with_tokens().skip(1).join("");
3939
tt.pop();
40-
return sema
41-
.expand_derive_macro(&attr)
42-
.map(insert_whitespaces)
43-
.map(|expansion| ExpandedMacro { name: tt, expansion });
40+
let expansions = sema.expand_derive_macro(&attr)?;
41+
return Some(ExpandedMacro {
42+
name: tt,
43+
expansion: expansions.into_iter().map(insert_whitespaces).join(""),
44+
});
4445
}
4546
}
4647
}
@@ -382,4 +383,26 @@ struct Foo {}
382383
"#]],
383384
);
384385
}
386+
387+
#[test]
388+
fn macro_expand_derive_multi() {
389+
check(
390+
r#"
391+
#[rustc_builtin_macro]
392+
pub macro Clone {}
393+
#[rustc_builtin_macro]
394+
pub macro Copy {}
395+
396+
#[derive(Cop$0y, Clone)]
397+
struct Foo {}
398+
"#,
399+
expect![[r#"
400+
Copy, Clone
401+
impl< >crate::marker::Copy for Foo< >{}
402+
403+
impl< >crate::clone::Clone for Foo< >{}
404+
405+
"#]],
406+
);
407+
}
385408
}

0 commit comments

Comments
 (0)