Skip to content

Commit ee374ff

Browse files
fix: don't complete derive macros as fn-like macros
1 parent 16e142c commit ee374ff

File tree

4 files changed

+88
-4
lines changed

4 files changed

+88
-4
lines changed

crates/hir/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,13 @@ impl MacroDef {
13511351
MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::FuncLike, _) => MacroKind::ProcMacro,
13521352
}
13531353
}
1354+
1355+
pub fn is_fn_like(&self) -> bool {
1356+
match self.kind() {
1357+
MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
1358+
MacroKind::Attr | MacroKind::Derive => false,
1359+
}
1360+
}
13541361
}
13551362

13561363
/// Invariant: `inner.as_assoc_item(db).is_some()`

crates/ide_completion/src/completions/pattern.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
3939
| hir::ModuleDef::Module(..) => refutable,
4040
_ => false,
4141
},
42-
hir::ScopeDef::MacroDef(_) => true,
42+
hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
4343
hir::ScopeDef::ImplSelfType(impl_) => match impl_.self_ty(ctx.db).as_adt() {
4444
Some(hir::Adt::Struct(strukt)) => {
4545
acc.add_struct_pat(ctx, strukt, Some(name.clone()));
@@ -101,6 +101,28 @@ fn foo() {
101101
);
102102
}
103103

104+
#[test]
105+
fn does_not_complete_non_fn_macros() {
106+
check(
107+
r#"
108+
macro_rules! m { ($e:expr) => { $e } }
109+
enum E { X }
110+
111+
#[rustc_builtin_macro]
112+
macro Clone {}
113+
114+
fn foo() {
115+
match E::X { $0 }
116+
}
117+
"#,
118+
expect![[r#"
119+
ev E::X ()
120+
en E
121+
ma m!(…) macro_rules! m
122+
"#]],
123+
);
124+
}
125+
104126
#[test]
105127
fn completes_in_simple_macro_call() {
106128
check(

crates/ide_completion/src/completions/qualified_path.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
2626
let module_scope = module.scope(ctx.db, context_module);
2727
for (name, def) in module_scope {
2828
if let hir::ScopeDef::MacroDef(macro_def) = def {
29-
acc.add_macro(ctx, Some(name.clone()), macro_def);
29+
if macro_def.is_fn_like() {
30+
acc.add_macro(ctx, Some(name.clone()), macro_def);
31+
}
3032
}
3133
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
3234
acc.add_resolution(ctx, name, &def);
@@ -58,6 +60,13 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
5860
}
5961
}
6062

63+
if let hir::ScopeDef::MacroDef(macro_def) = def {
64+
if !macro_def.is_fn_like() {
65+
// Don't suggest attribute macros and derives.
66+
continue;
67+
}
68+
}
69+
6170
acc.add_resolution(ctx, name, &def);
6271
}
6372
}

crates/ide_completion/src/completions/unqualified_path.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
1313
// only show macros in {Assoc}ItemList
1414
ctx.scope.process_all_names(&mut |name, res| {
1515
if let hir::ScopeDef::MacroDef(mac) = res {
16-
acc.add_macro(ctx, Some(name.clone()), mac);
16+
if mac.is_fn_like() {
17+
acc.add_macro(ctx, Some(name.clone()), mac);
18+
}
1719
}
1820
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
1921
acc.add_resolution(ctx, name, &res);
@@ -46,7 +48,13 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
4648
cov_mark::hit!(skip_lifetime_completion);
4749
return;
4850
}
49-
acc.add_resolution(ctx, name, &res);
51+
let add_resolution = match res {
52+
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
53+
_ => true,
54+
};
55+
if add_resolution {
56+
acc.add_resolution(ctx, name, &res);
57+
}
5058
});
5159
}
5260

@@ -426,6 +434,44 @@ mod macros {
426434
);
427435
}
428436

437+
#[test]
438+
fn does_not_complete_non_fn_macros() {
439+
check(
440+
r#"
441+
#[rustc_builtin_macro]
442+
pub macro Clone {}
443+
444+
fn f() {$0}
445+
"#,
446+
expect![[r#"
447+
fn f() fn()
448+
"#]],
449+
);
450+
check(
451+
r#"
452+
#[rustc_builtin_macro]
453+
pub macro Clone {}
454+
455+
struct S;
456+
impl S {
457+
$0
458+
}
459+
"#,
460+
expect![[r#""#]],
461+
);
462+
check(
463+
r#"
464+
mod m {
465+
#[rustc_builtin_macro]
466+
pub macro Clone {}
467+
}
468+
469+
fn f() {m::$0}
470+
"#,
471+
expect![[r#""#]],
472+
);
473+
}
474+
429475
#[test]
430476
fn completes_std_prelude_if_core_is_defined() {
431477
check(

0 commit comments

Comments
 (0)