fix: don't complete derive macros as fn-like macros

This commit is contained in:
Jonas Schievink 2021-06-08 17:31:47 +02:00
parent 16e142cd39
commit ee374ff1ee
4 changed files with 88 additions and 4 deletions

View file

@ -1351,6 +1351,13 @@ impl MacroDef {
MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::FuncLike, _) => MacroKind::ProcMacro, MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::FuncLike, _) => MacroKind::ProcMacro,
} }
} }
pub fn is_fn_like(&self) -> bool {
match self.kind() {
MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
MacroKind::Attr | MacroKind::Derive => false,
}
}
} }
/// Invariant: `inner.as_assoc_item(db).is_some()` /// Invariant: `inner.as_assoc_item(db).is_some()`

View file

@ -39,7 +39,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
| hir::ModuleDef::Module(..) => refutable, | hir::ModuleDef::Module(..) => refutable,
_ => false, _ => false,
}, },
hir::ScopeDef::MacroDef(_) => true, hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
hir::ScopeDef::ImplSelfType(impl_) => match impl_.self_ty(ctx.db).as_adt() { hir::ScopeDef::ImplSelfType(impl_) => match impl_.self_ty(ctx.db).as_adt() {
Some(hir::Adt::Struct(strukt)) => { Some(hir::Adt::Struct(strukt)) => {
acc.add_struct_pat(ctx, strukt, Some(name.clone())); acc.add_struct_pat(ctx, strukt, Some(name.clone()));
@ -101,6 +101,28 @@ fn foo() {
); );
} }
#[test]
fn does_not_complete_non_fn_macros() {
check(
r#"
macro_rules! m { ($e:expr) => { $e } }
enum E { X }
#[rustc_builtin_macro]
macro Clone {}
fn foo() {
match E::X { $0 }
}
"#,
expect![[r#"
ev E::X ()
en E
ma m!() macro_rules! m
"#]],
);
}
#[test] #[test]
fn completes_in_simple_macro_call() { fn completes_in_simple_macro_call() {
check( check(

View file

@ -26,8 +26,10 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
let module_scope = module.scope(ctx.db, context_module); let module_scope = module.scope(ctx.db, context_module);
for (name, def) in module_scope { for (name, def) in module_scope {
if let hir::ScopeDef::MacroDef(macro_def) = def { if let hir::ScopeDef::MacroDef(macro_def) = def {
if macro_def.is_fn_like() {
acc.add_macro(ctx, Some(name.clone()), macro_def); acc.add_macro(ctx, Some(name.clone()), macro_def);
} }
}
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def { if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
acc.add_resolution(ctx, name, &def); acc.add_resolution(ctx, name, &def);
} }
@ -58,6 +60,13 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
} }
} }
if let hir::ScopeDef::MacroDef(macro_def) = def {
if !macro_def.is_fn_like() {
// Don't suggest attribute macros and derives.
continue;
}
}
acc.add_resolution(ctx, name, &def); acc.add_resolution(ctx, name, &def);
} }
} }

View file

@ -13,8 +13,10 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
// only show macros in {Assoc}ItemList // only show macros in {Assoc}ItemList
ctx.scope.process_all_names(&mut |name, res| { ctx.scope.process_all_names(&mut |name, res| {
if let hir::ScopeDef::MacroDef(mac) = res { if let hir::ScopeDef::MacroDef(mac) = res {
if mac.is_fn_like() {
acc.add_macro(ctx, Some(name.clone()), mac); acc.add_macro(ctx, Some(name.clone()), mac);
} }
}
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res { if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
acc.add_resolution(ctx, name, &res); acc.add_resolution(ctx, name, &res);
} }
@ -46,7 +48,13 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
cov_mark::hit!(skip_lifetime_completion); cov_mark::hit!(skip_lifetime_completion);
return; return;
} }
let add_resolution = match res {
ScopeDef::MacroDef(mac) => mac.is_fn_like(),
_ => true,
};
if add_resolution {
acc.add_resolution(ctx, name, &res); acc.add_resolution(ctx, name, &res);
}
}); });
} }
@ -426,6 +434,44 @@ mod macros {
); );
} }
#[test]
fn does_not_complete_non_fn_macros() {
check(
r#"
#[rustc_builtin_macro]
pub macro Clone {}
fn f() {$0}
"#,
expect![[r#"
fn f() fn()
"#]],
);
check(
r#"
#[rustc_builtin_macro]
pub macro Clone {}
struct S;
impl S {
$0
}
"#,
expect![[r#""#]],
);
check(
r#"
mod m {
#[rustc_builtin_macro]
pub macro Clone {}
}
fn f() {m::$0}
"#,
expect![[r#""#]],
);
}
#[test] #[test]
fn completes_std_prelude_if_core_is_defined() { fn completes_std_prelude_if_core_is_defined() {
check( check(