From c0d2b44250528a847782abf984bf2c15c017abd8 Mon Sep 17 00:00:00 2001 From: unexge Date: Thu, 26 Aug 2021 19:44:46 +0300 Subject: [PATCH 1/2] fix: correctly complete macro call if cursor at `!` --- .../src/completions/unqualified_path.rs | 27 +++++++++++++++++++ crates/ide_completion/src/context.rs | 15 ++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index d81cb5391cb0..8d421fc78d78 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -304,4 +304,31 @@ pub mod prelude { "#]], ); } + + #[test] + fn completes_macro_call_if_cursor_at_bang_token() { + // Regression test for https://github.com/rust-analyzer/rust-analyzer/issues/9904 + cov_mark::check!(completes_macro_call_if_cursor_at_bang_token); + check_edit( + "foo!", + r#" +macro_rules! foo { + () => {} +} + +fn main() { + foo!$0 +} +"#, + r#" +macro_rules! foo { + () => {} +} + +fn main() { + foo!($0) +} +"#, + ); + } } diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 6c6f8f8512bf..d9024157ce45 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -236,14 +236,21 @@ impl<'a> CompletionContext<'a> { let kind = self.token.kind(); if kind == IDENT || kind == LIFETIME_IDENT || kind == UNDERSCORE || kind.is_keyword() { cov_mark::hit!(completes_if_prefix_is_keyword); - self.original_token.text_range() + return self.original_token.text_range(); } else if kind == CHAR { // assume we are completing a lifetime but the user has only typed the ' cov_mark::hit!(completes_if_lifetime_without_idents); - TextRange::at(self.original_token.text_range().start(), TextSize::from(1)) - } else { - TextRange::empty(self.position.offset) + return TextRange::at(self.original_token.text_range().start(), TextSize::from(1)); + } else if kind == BANG { + if let Some(n) = self.token.parent() { + if n.kind() == SyntaxKind::MACRO_CALL { + cov_mark::hit!(completes_macro_call_if_cursor_at_bang_token); + return n.text_range(); + } + } } + + TextRange::empty(self.position.offset) } pub(crate) fn previous_token_is(&self, kind: SyntaxKind) -> bool { From e0e7f0c1702063552f090b20aa980454ac61f02b Mon Sep 17 00:00:00 2001 From: unexge Date: Wed, 1 Sep 2021 09:11:20 +0300 Subject: [PATCH 2/2] Move "complete macro call if cursor at `!` token" logic to `MacroRender` --- .../src/completions/unqualified_path.rs | 27 -------------- crates/ide_completion/src/context.rs | 19 +++++----- crates/ide_completion/src/render/macro_.rs | 36 +++++++++++++++++-- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 8d421fc78d78..d81cb5391cb0 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs @@ -304,31 +304,4 @@ pub mod prelude { "#]], ); } - - #[test] - fn completes_macro_call_if_cursor_at_bang_token() { - // Regression test for https://github.com/rust-analyzer/rust-analyzer/issues/9904 - cov_mark::check!(completes_macro_call_if_cursor_at_bang_token); - check_edit( - "foo!", - r#" -macro_rules! foo { - () => {} -} - -fn main() { - foo!$0 -} -"#, - r#" -macro_rules! foo { - () => {} -} - -fn main() { - foo!($0) -} -"#, - ); - } } diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index d9024157ce45..a112f573918e 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -236,21 +236,14 @@ impl<'a> CompletionContext<'a> { let kind = self.token.kind(); if kind == IDENT || kind == LIFETIME_IDENT || kind == UNDERSCORE || kind.is_keyword() { cov_mark::hit!(completes_if_prefix_is_keyword); - return self.original_token.text_range(); + self.original_token.text_range() } else if kind == CHAR { // assume we are completing a lifetime but the user has only typed the ' cov_mark::hit!(completes_if_lifetime_without_idents); - return TextRange::at(self.original_token.text_range().start(), TextSize::from(1)); - } else if kind == BANG { - if let Some(n) = self.token.parent() { - if n.kind() == SyntaxKind::MACRO_CALL { - cov_mark::hit!(completes_macro_call_if_cursor_at_bang_token); - return n.text_range(); - } - } + TextRange::at(self.original_token.text_range().start(), TextSize::from(1)) + } else { + TextRange::empty(self.position.offset) } - - TextRange::empty(self.position.offset) } pub(crate) fn previous_token_is(&self, kind: SyntaxKind) -> bool { @@ -402,6 +395,10 @@ impl<'a> CompletionContext<'a> { } } + pub(crate) fn is_immediately_after_macro_bang(&self) -> bool { + self.token.kind() == BANG && self.token.parent().map_or(false, |it| it.kind() == MACRO_CALL) + } + /// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items. pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) { self.scope.process_all_names(&mut |name, def| { diff --git a/crates/ide_completion/src/render/macro_.rs b/crates/ide_completion/src/render/macro_.rs index eb9fb4d8bf0a..d1b549df1bb9 100644 --- a/crates/ide_completion/src/render/macro_.rs +++ b/crates/ide_completion/src/render/macro_.rs @@ -41,8 +41,13 @@ impl<'a> MacroRender<'a> { } fn render(&self, import_to_add: Option) -> Option { - let mut item = - CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label()); + let source_range = if self.ctx.completion.is_immediately_after_macro_bang() { + cov_mark::hit!(completes_macro_call_if_cursor_at_bang_token); + self.ctx.completion.token.parent().map(|it| it.text_range()) + } else { + Some(self.ctx.source_range()) + }?; + let mut item = CompletionItem::new(CompletionKind::Reference, source_range, &self.label()); item.kind(SymbolKind::Macro) .set_documentation(self.docs.clone()) .set_deprecated(self.ctx.is_deprecated(self.macro_)) @@ -230,4 +235,31 @@ fn main() { foo! {$0} } "#, ) } + + #[test] + fn completes_macro_call_if_cursor_at_bang_token() { + // Regression test for https://github.com/rust-analyzer/rust-analyzer/issues/9904 + cov_mark::check!(completes_macro_call_if_cursor_at_bang_token); + check_edit( + "foo!", + r#" +macro_rules! foo { + () => {} +} + +fn main() { + foo!$0 +} +"#, + r#" +macro_rules! foo { + () => {} +} + +fn main() { + foo!($0) +} +"#, + ); + } }