From ee374ff1ee7ad1af6bc0624f98b2028cef6ed4a8 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 8 Jun 2021 17:31:47 +0200 Subject: fix: don't complete derive macros as fn-like macros --- crates/ide_completion/src/completions/pattern.rs | 24 ++++++++++- .../src/completions/qualified_path.rs | 11 ++++- .../src/completions/unqualified_path.rs | 50 +++++++++++++++++++++- 3 files changed, 81 insertions(+), 4 deletions(-) (limited to 'crates/ide_completion/src') diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs index 8a728c67e..1daa8595a 100644 --- a/crates/ide_completion/src/completions/pattern.rs +++ b/crates/ide_completion/src/completions/pattern.rs @@ -39,7 +39,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | hir::ModuleDef::Module(..) => refutable, _ => 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() { Some(hir::Adt::Struct(strukt)) => { 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] fn completes_in_simple_macro_call() { check( diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index d58745fb4..4dfdc5ced 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -26,7 +26,9 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon let module_scope = module.scope(ctx.db, context_module); for (name, def) in module_scope { if let hir::ScopeDef::MacroDef(macro_def) = def { - acc.add_macro(ctx, Some(name.clone()), macro_def); + if macro_def.is_fn_like() { + acc.add_macro(ctx, Some(name.clone()), macro_def); + } } if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = 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); } } diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 8b22933e0..52f40d496 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -13,7 +13,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC // only show macros in {Assoc}ItemList ctx.scope.process_all_names(&mut |name, res| { if let hir::ScopeDef::MacroDef(mac) = res { - acc.add_macro(ctx, Some(name.clone()), mac); + if mac.is_fn_like() { + acc.add_macro(ctx, Some(name.clone()), mac); + } } if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = 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); return; } - acc.add_resolution(ctx, name, &res); + let add_resolution = match res { + ScopeDef::MacroDef(mac) => mac.is_fn_like(), + _ => true, + }; + if add_resolution { + 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] fn completes_std_prelude_if_core_is_defined() { check( -- cgit v1.2.3