Skip to content

Commit 69e5bd5

Browse files
bors[bot]Veykril
andauthored
Merge #11676
11676: internal: Expand into pseudo-derive attribute expansions in completions r=Veykril a=Veykril With this we now properly handle qualified path completions in derives bors r+ Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
2 parents e963443 + 6c8c02f commit 69e5bd5

File tree

26 files changed

+478
-384
lines changed

26 files changed

+478
-384
lines changed

crates/hir/src/display.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use syntax::SmolStr;
1818

1919
use crate::{
2020
Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
21-
LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeOrConstParam,
22-
TypeParam, Union, Variant,
21+
LifetimeParam, Macro, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias,
22+
TypeOrConstParam, TypeParam, Union, Variant,
2323
};
2424

2525
impl HirDisplay for Function {
@@ -509,3 +509,14 @@ impl HirDisplay for Module {
509509
}
510510
}
511511
}
512+
513+
impl HirDisplay for Macro {
514+
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
515+
match self.id {
516+
hir_def::MacroId::Macro2Id(_) => write!(f, "macro"),
517+
hir_def::MacroId::MacroRulesId(_) => write!(f, "macro_rules!"),
518+
hir_def::MacroId::ProcMacroId(_) => write!(f, "proc_macro"),
519+
}?;
520+
write!(f, " {}", self.name(f.db))
521+
}
522+
}

crates/hir/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,10 @@ impl Macro {
18111811
pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
18121812
matches!(self.kind(db), MacroKind::Attr)
18131813
}
1814+
1815+
pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
1816+
matches!(self.kind(db), MacroKind::Derive)
1817+
}
18141818
}
18151819

18161820
impl HasVisibility for Macro {

crates/hir/src/semantics.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
151151
self.imp.expand_attr_macro(item)
152152
}
153153

154+
pub fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
155+
self.imp.expand_derive_as_pseudo_attr_macro(attr)
156+
}
157+
154158
pub fn resolve_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<Option<Macro>>> {
155159
self.imp.resolve_derive_macro(derive)
156160
}
@@ -185,6 +189,19 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
185189
self.imp.speculative_expand_attr(actual_macro_call, speculative_args, token_to_map)
186190
}
187191

192+
pub fn speculative_expand_derive_as_pseudo_attr_macro(
193+
&self,
194+
actual_macro_call: &ast::Attr,
195+
speculative_args: &ast::Attr,
196+
token_to_map: SyntaxToken,
197+
) -> Option<(SyntaxNode, SyntaxToken)> {
198+
self.imp.speculative_expand_derive_as_pseudo_attr_macro(
199+
actual_macro_call,
200+
speculative_args,
201+
token_to_map,
202+
)
203+
}
204+
188205
/// Descend the token into macrocalls to its first mapped counterpart.
189206
pub fn descend_into_macros_single(&self, token: SyntaxToken) -> SyntaxToken {
190207
self.imp.descend_into_macros_single(token)
@@ -438,9 +455,16 @@ impl<'db> SemanticsImpl<'db> {
438455
fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> {
439456
let src = self.wrap_node_infile(item.clone());
440457
let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src))?;
441-
let file_id = macro_call_id.as_file();
442-
let node = self.parse_or_expand(file_id)?;
443-
Some(node)
458+
self.parse_or_expand(macro_call_id.as_file())
459+
}
460+
461+
fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
462+
let src = self.wrap_node_infile(attr.clone());
463+
let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
464+
let call_id = self.with_ctx(|ctx| {
465+
ctx.attr_to_derive_macro_call(src.with_value(&adt), src).map(|(_, it, _)| it)
466+
})?;
467+
self.parse_or_expand(call_id.as_file())
444468
}
445469

446470
fn resolve_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<Option<Macro>>> {
@@ -533,6 +557,25 @@ impl<'db> SemanticsImpl<'db> {
533557
)
534558
}
535559

560+
fn speculative_expand_derive_as_pseudo_attr_macro(
561+
&self,
562+
actual_macro_call: &ast::Attr,
563+
speculative_args: &ast::Attr,
564+
token_to_map: SyntaxToken,
565+
) -> Option<(SyntaxNode, SyntaxToken)> {
566+
let attr = self.wrap_node_infile(actual_macro_call.clone());
567+
let adt = actual_macro_call.syntax().parent().and_then(ast::Adt::cast)?;
568+
let macro_call_id = self.with_ctx(|ctx| {
569+
ctx.attr_to_derive_macro_call(attr.with_value(&adt), attr).map(|(_, it, _)| it)
570+
})?;
571+
hir_expand::db::expand_speculative(
572+
self.db.upcast(),
573+
macro_call_id,
574+
speculative_args.syntax(),
575+
token_to_map,
576+
)
577+
}
578+
536579
// This might not be the correct way to do this, but it works for now
537580
fn descend_node_into_attributes<N: AstNode>(&self, node: N) -> SmallVec<[N; 1]> {
538581
let mut res = smallvec![];

crates/hir_expand/src/builtin_attr_macro.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
//! Builtin attributes.
22
3-
use itertools::Itertools;
4-
53
use crate::{db::AstDatabase, name, ExpandResult, MacroCallId, MacroCallKind};
64

75
macro_rules! register_builtin {
@@ -98,10 +96,16 @@ fn derive_attr_expand(
9896
) -> ExpandResult<tt::Subtree> {
9997
let loc = db.lookup_intern_macro_call(id);
10098
let derives = match &loc.kind {
101-
MacroCallKind::Attr { attr_args, .. } => &attr_args.0,
102-
_ => return ExpandResult::ok(tt.clone()),
99+
MacroCallKind::Attr { attr_args, is_derive: true, .. } => &attr_args.0,
100+
_ => return ExpandResult::ok(Default::default()),
103101
};
102+
pseudo_derive_attr_expansion(tt, derives)
103+
}
104104

105+
pub fn pseudo_derive_attr_expansion(
106+
tt: &tt::Subtree,
107+
args: &tt::Subtree,
108+
) -> ExpandResult<tt::Subtree> {
105109
let mk_leaf = |char| {
106110
tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
107111
char,
@@ -111,21 +115,12 @@ fn derive_attr_expand(
111115
};
112116

113117
let mut token_trees = Vec::new();
114-
for (comma, group) in &derives
115-
.token_trees
116-
.iter()
117-
.filter_map(|tt| match tt {
118-
tt::TokenTree::Leaf(l) => Some(l),
119-
tt::TokenTree::Subtree(_) => None,
120-
})
121-
.group_by(|l| matches!(l, tt::Leaf::Punct(tt::Punct { char: ',', .. })))
118+
for tt in (&args.token_trees)
119+
.split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', .. }))))
122120
{
123-
if comma {
124-
continue;
125-
}
126121
token_trees.push(mk_leaf('#'));
127122
token_trees.push(mk_leaf('['));
128-
token_trees.extend(group.cloned().map(tt::TokenTree::Leaf));
123+
token_trees.extend(tt.iter().cloned());
129124
token_trees.push(mk_leaf(']'));
130125
}
131126
token_trees.push(mk_leaf('('));

crates/hir_expand/src/db.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ use syntax::{
1414
};
1515

1616
use crate::{
17-
ast_id_map::AstIdMap, fixup, hygiene::HygieneFrame, BuiltinAttrExpander, BuiltinDeriveExpander,
18-
BuiltinFnLikeExpander, ExpandError, ExpandResult, ExpandTo, HirFileId, HirFileIdRepr,
19-
MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile,
20-
ProcMacroExpander,
17+
ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion, fixup,
18+
hygiene::HygieneFrame, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander,
19+
ExpandError, ExpandResult, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind,
20+
MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
2121
};
2222

2323
/// Total limit on the number of tokens produced by any macro invocation.
@@ -161,14 +161,16 @@ pub fn expand_speculative(
161161
);
162162

163163
let (attr_arg, token_id) = match loc.kind {
164-
MacroCallKind::Attr { invoc_attr_index, .. } => {
165-
// Attributes may have an input token tree, build the subtree and map for this as well
166-
// then try finding a token id for our token if it is inside this input subtree.
167-
let item = ast::Item::cast(speculative_args.clone())?;
168-
let attr = item
169-
.doc_comments_and_attrs()
170-
.nth(invoc_attr_index as usize)
171-
.and_then(Either::left)?;
164+
MacroCallKind::Attr { invoc_attr_index, is_derive, .. } => {
165+
let attr = if is_derive {
166+
// for pseudo-derive expansion we actually pass the attribute itself only
167+
ast::Attr::cast(speculative_args.clone())
168+
} else {
169+
// Attributes may have an input token tree, build the subtree and map for this as well
170+
// then try finding a token id for our token if it is inside this input subtree.
171+
let item = ast::Item::cast(speculative_args.clone())?;
172+
item.doc_comments_and_attrs().nth(invoc_attr_index as usize).and_then(Either::left)
173+
}?;
172174
match attr.token_tree() {
173175
Some(token_tree) => {
174176
let (mut tree, map) = syntax_node_to_token_tree(attr.token_tree()?.syntax());
@@ -205,11 +207,15 @@ pub fn expand_speculative(
205207

206208
// Do the actual expansion, we need to directly expand the proc macro due to the attribute args
207209
// Otherwise the expand query will fetch the non speculative attribute args and pass those instead.
208-
let mut speculative_expansion = if let MacroDefKind::ProcMacro(expander, ..) = loc.def.kind {
209-
tt.delimiter = None;
210-
expander.expand(db, loc.krate, &tt, attr_arg.as_ref())
211-
} else {
212-
macro_def.expand(db, actual_macro_call, &tt)
210+
let mut speculative_expansion = match loc.def.kind {
211+
MacroDefKind::ProcMacro(expander, ..) => {
212+
tt.delimiter = None;
213+
expander.expand(db, loc.krate, &tt, attr_arg.as_ref())
214+
}
215+
MacroDefKind::BuiltInAttr(BuiltinAttrExpander::Derive, _) => {
216+
pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?)
217+
}
218+
_ => macro_def.expand(db, actual_macro_call, &tt),
213219
};
214220

215221
let expand_to = macro_expand_to(db, actual_macro_call);

crates/ide/src/hover/render.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use std::fmt::Display;
33

44
use either::Either;
5-
use hir::{AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
5+
use hir::{AsAssocItem, AttributeTemplate, HasAttrs, HirDisplay, Semantics, TypeInfo};
66
use ide_db::{
77
base_db::SourceDatabase,
88
defs::Definition,
@@ -13,9 +13,7 @@ use ide_db::{
1313
use itertools::Itertools;
1414
use stdx::format_to;
1515
use syntax::{
16-
algo, ast,
17-
display::{fn_as_proc_macro_label, macro_label},
18-
match_ast, AstNode, Direction,
16+
algo, ast, match_ast, AstNode, Direction,
1917
SyntaxKind::{LET_EXPR, LET_STMT},
2018
SyntaxToken, T,
2119
};
@@ -342,14 +340,8 @@ pub(super) fn definition(
342340
) -> Option<Markup> {
343341
let mod_path = definition_mod_path(db, &def);
344342
let (label, docs) = match def {
345-
Definition::Macro(it) => (
346-
match &it.source(db)?.value {
347-
Either::Left(mac) => macro_label(mac),
348-
Either::Right(mac_fn) => fn_as_proc_macro_label(mac_fn),
349-
},
350-
it.attrs(db).docs(),
351-
),
352-
Definition::Field(def) => label_and_docs(db, def),
343+
Definition::Macro(it) => label_and_docs(db, it),
344+
Definition::Field(it) => label_and_docs(db, it),
353345
Definition::Module(it) => label_and_docs(db, it),
354346
Definition::Function(it) => label_and_docs(db, it),
355347
Definition::Adt(it) => label_and_docs(db, it),

crates/ide/src/hover/tests.rs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4102,16 +4102,16 @@ identity!{
41024102
}
41034103
"#,
41044104
expect![[r#"
4105-
*Copy*
4105+
*Copy*
41064106
4107-
```rust
4108-
test
4109-
```
4107+
```rust
4108+
test
4109+
```
41104110
4111-
```rust
4112-
pub macro Copy
4113-
```
4114-
"#]],
4111+
```rust
4112+
macro Copy
4113+
```
4114+
"#]],
41154115
);
41164116
}
41174117

@@ -4126,16 +4126,16 @@ pub macro Copy {}
41264126
struct Foo;
41274127
"#,
41284128
expect![[r#"
4129-
*Copy*
4129+
*Copy*
41304130
4131-
```rust
4132-
test
4133-
```
4131+
```rust
4132+
test
4133+
```
41344134
4135-
```rust
4136-
pub macro Copy
4137-
```
4138-
"#]],
4135+
```rust
4136+
macro Copy
4137+
```
4138+
"#]],
41394139
);
41404140
check(
41414141
r#"
@@ -4148,16 +4148,16 @@ mod foo {
41484148
struct Foo;
41494149
"#,
41504150
expect![[r#"
4151-
*Copy*
4151+
*Copy*
41524152
4153-
```rust
4154-
test::foo
4155-
```
4153+
```rust
4154+
test::foo
4155+
```
41564156
4157-
```rust
4158-
pub macro Copy
4159-
```
4160-
"#]],
4157+
```rust
4158+
macro Copy
4159+
```
4160+
"#]],
41614161
);
41624162
}
41634163

crates/ide_assists/src/handlers/remove_dbg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
3232
}
3333

3434
let mac_input = tt.syntax().children_with_tokens().skip(1).take_while(|it| *it != r_delim);
35-
let input_expressions = mac_input.into_iter().group_by(|tok| tok.kind() == T![,]);
35+
let input_expressions = mac_input.group_by(|tok| tok.kind() == T![,]);
3636
let input_expressions = input_expressions
3737
.into_iter()
3838
.filter_map(|(is_sep, group)| (!is_sep).then(|| group))

crates/ide_completion/src/completions/attribute.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ mod derive;
2929
mod lint;
3030
mod repr;
3131

32+
pub(crate) use self::derive::complete_derive;
33+
3234
/// Complete inputs to known builtin attributes as well as derive attributes
3335
pub(crate) fn complete_known_attribute_input(
3436
acc: &mut Completions,
@@ -46,7 +48,6 @@ pub(crate) fn complete_known_attribute_input(
4648

4749
match path.text().as_str() {
4850
"repr" => repr::complete_repr(acc, ctx, tt),
49-
"derive" => derive::complete_derive(acc, ctx, ctx.attr.as_ref()?),
5051
"feature" => lint::complete_lint(acc, ctx, &parse_tt_as_comma_sep_paths(tt)?, FEATURES),
5152
"allow" | "warn" | "deny" | "forbid" => {
5253
let existing_lints = parse_tt_as_comma_sep_paths(tt)?;
@@ -62,9 +63,7 @@ pub(crate) fn complete_known_attribute_input(
6263

6364
lint::complete_lint(acc, ctx, &existing_lints, &lints);
6465
}
65-
"cfg" => {
66-
cfg::complete_cfg(acc, ctx);
67-
}
66+
"cfg" => cfg::complete_cfg(acc, ctx),
6867
_ => (),
6968
}
7069
Some(())
@@ -347,7 +346,7 @@ fn parse_comma_sep_expr(input: ast::TokenTree) -> Option<Vec<ast::Expr>> {
347346
.children_with_tokens()
348347
.skip(1)
349348
.take_while(|it| it.as_token() != Some(&r_paren));
350-
let input_expressions = tokens.into_iter().group_by(|tok| tok.kind() == T![,]);
349+
let input_expressions = tokens.group_by(|tok| tok.kind() == T![,]);
351350
Some(
352351
input_expressions
353352
.into_iter()

0 commit comments

Comments
 (0)