diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs index 76d708ae51a..7a02a3b3333 100644 --- a/crates/ide-completion/src/completions/flyimport.rs +++ b/crates/ide-completion/src/completions/flyimport.rs @@ -161,10 +161,10 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) (_, ItemInNs::Types(hir::ModuleDef::Module(_))) => true, // and so are macros(except for attributes) ( - PathKind::Expr | PathKind::Type | PathKind::Mac | PathKind::Pat, + PathKind::Expr | PathKind::Type | PathKind::Item | PathKind::Pat, ItemInNs::Macros(mac), ) => mac.is_fn_like(ctx.db), - (PathKind::Mac, _) => true, + (PathKind::Item, _) => true, (PathKind::Expr, ItemInNs::Types(_) | ItemInNs::Values(_)) => true, diff --git a/crates/ide-completion/src/completions/unqualified_path.rs b/crates/ide-completion/src/completions/unqualified_path.rs index 94142e274ae..53262ae267b 100644 --- a/crates/ide-completion/src/completions/unqualified_path.rs +++ b/crates/ide-completion/src/completions/unqualified_path.rs @@ -19,7 +19,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC Some(PathCompletionCtx { is_absolute_path: false, qualifier: None, - kind: None | Some(PathKind::Expr | PathKind::Type | PathKind::Mac), + kind: None | Some(PathKind::Expr | PathKind::Type | PathKind::Item), .. }) => (), _ => return, diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index f75aa8f9ff8..a41d89859a9 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -47,12 +47,17 @@ pub(crate) enum Visible { pub(super) enum PathKind { Expr, Type, - Attr { kind: AttrKind, annotated_item_kind: Option }, + Attr { + kind: AttrKind, + annotated_item_kind: Option, + }, Derive, - // This should be removed in favor of `has_macro_bang` in PathCompletionContext - Mac, + /// Path in item position, that is inside an (Assoc)ItemList + Item, Pat, - Vis { has_in_token: bool }, + Vis { + has_in_token: bool, + }, Use, } @@ -60,6 +65,8 @@ pub(super) enum PathKind { pub(crate) struct PathCompletionCtx { /// If this is a call with () already there (or {} in case of record patterns) pub(super) has_call_parens: bool, + /// If this has a macro call bang ! + pub(super) has_macro_bang: bool, /// Whether this path stars with a `::`. pub(super) is_absolute_path: bool, /// The qualifier of the current path if it exists. @@ -942,6 +949,7 @@ impl<'a> CompletionContext<'a> { has_type_args: false, can_be_stmt: false, in_loop_body: false, + has_macro_bang: false, kind: None, }; let mut pat_ctx = None; @@ -970,7 +978,21 @@ impl<'a> CompletionContext<'a> { pat_ctx = Some(pattern_context_for(original_file, it.into())); Some(PathKind::Pat) }, - ast::MacroCall(it) => it.excl_token().and(Some(PathKind::Mac)), + ast::MacroCall(it) => { + path_ctx.has_macro_bang = it.excl_token().is_some(); + match it.syntax().parent().map(|it| it.kind()) { + Some(SyntaxKind::MACRO_PAT) => Some(PathKind::Pat), + Some(SyntaxKind::MACRO_TYPE) => Some(PathKind::Type), + Some(SyntaxKind::MACRO_EXPR) => Some(PathKind::Expr), + Some( + SyntaxKind::ITEM_LIST + | SyntaxKind::ASSOC_ITEM_LIST + | SyntaxKind::EXTERN_ITEM_LIST + | SyntaxKind::SOURCE_FILE + ) => Some(PathKind::Item), + _ => return Some(None), + } + }, ast::Meta(meta) => (|| { let attr = meta.parent_attr()?; let kind = attr.kind(); @@ -989,6 +1011,10 @@ impl<'a> CompletionContext<'a> { })(), ast::Visibility(it) => Some(PathKind::Vis { has_in_token: it.in_token().is_some() }), ast::UseTree(_) => Some(PathKind::Use), + ast::ItemList(_) => Some(PathKind::Item), + ast::AssocItemList(_) => Some(PathKind::Item), + ast::ExternItemList(_) => Some(PathKind::Item), + ast::SourceFile(_) => Some(PathKind::Item), _ => return None, } }; diff --git a/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs index ba18e5d2165..cbf51af7cc0 100644 --- a/crates/ide-completion/src/render/macro_.rs +++ b/crates/ide-completion/src/render/macro_.rs @@ -5,7 +5,7 @@ use ide_db::SymbolKind; use syntax::SmolStr; use crate::{ - context::PathKind, + context::{PathCompletionCtx, PathKind}, item::{Builder, CompletionItem}, render::RenderContext, }; @@ -33,8 +33,12 @@ fn render( let is_fn_like = macro_.is_fn_like(completion.db); let (bra, ket) = if is_fn_like { guess_macro_braces(&name, docs_str) } else { ("", "") }; - let needs_bang = - is_fn_like && !matches!(completion.path_kind(), Some(PathKind::Mac | PathKind::Use)); + let needs_bang = match completion.path_context { + Some(PathCompletionCtx { kind, has_macro_bang, .. }) => { + is_fn_like && kind != Some(PathKind::Use) && !has_macro_bang + } + _ => is_fn_like, + }; let mut item = CompletionItem::new( SymbolKind::from(macro_.kind(completion.db)),