From 13c83f90ac0031b71bea8aa14d967b47647498bb Mon Sep 17 00:00:00 2001 From: Dorian Scheidt Date: Fri, 22 Jul 2022 19:06:14 -0500 Subject: [PATCH] fix: Don't add braces to 'if' completion in match guard position When the cursor is in a match arm, but before the fat arrow (=>) token, don't add braces when autocompleting "if". fixes #12823 --- crates/ide-completion/src/completions/expr.rs | 7 +- .../ide-completion/src/completions/keyword.rs | 71 +++++++++++++++++++ crates/ide-completion/src/context.rs | 3 + crates/ide-completion/src/context/analysis.rs | 8 +++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs index d4544dd1d12..bdf6e64f096 100644 --- a/crates/ide-completion/src/completions/expr.rs +++ b/crates/ide-completion/src/completions/expr.rs @@ -21,6 +21,7 @@ pub(crate) fn complete_expr_path( ref is_func_update, ref innermost_ret_ty, ref impl_, + in_match_guard, .. }: &ExprCtx, ) { @@ -195,7 +196,11 @@ pub(crate) fn complete_expr_path( add_keyword("while", "while $1 {\n $0\n}"); add_keyword("while let", "while let $1 = $2 {\n $0\n}"); add_keyword("loop", "loop {\n $0\n}"); - add_keyword("if", "if $1 {\n $0\n}"); + if in_match_guard { + add_keyword("if", "if $0"); + } else { + add_keyword("if", "if $1 {\n $0\n}"); + } add_keyword("if let", "if let $1 = $2 {\n $0\n}"); add_keyword("for", "for $1 in $2 {\n $0\n}"); add_keyword("true", "true"); diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs index 0089958ff1d..3989a451bde 100644 --- a/crates/ide-completion/src/completions/keyword.rs +++ b/crates/ide-completion/src/completions/keyword.rs @@ -163,4 +163,75 @@ fn main() { "#, ); } + + #[test] + fn if_completion_in_match_guard() { + check_edit( + "if", + r" +fn main() { + match () { + () $0 + } +} +", + r" +fn main() { + match () { + () if $0 + } +} +", + ) + } + + #[test] + fn if_completion_in_match_arm_expr() { + check_edit( + "if", + r" +fn main() { + match () { + () => $0 + } +} +", + r" +fn main() { + match () { + () => if $1 { + $0 +} + } +} +", + ) + } + + #[test] + fn if_completion_in_match_arm_expr_block() { + check_edit( + "if", + r" +fn main() { + match () { + () => { + $0 + } + } +} +", + r" +fn main() { + match () { + () => { + if $1 { + $0 +} + } + } +} +", + ) + } } diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index 6a2079b1266..93b6ad5d145 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -138,6 +138,9 @@ pub(crate) struct ExprCtx { pub(crate) self_param: Option, pub(crate) innermost_ret_ty: Option, pub(crate) impl_: Option, + /// Whether this expression occurs in match arm guard position: before the + /// fat arrow token + pub(crate) in_match_guard: bool, } /// Original file ast nodes diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 0c8b569b66a..c71ffa0ed86 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -763,6 +763,13 @@ impl<'a> CompletionContext<'a> { .map_or(false, |it| it.semicolon_token().is_none()); let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax()); + let in_match_guard = match it.parent().and_then(ast::MatchArm::cast) { + Some(arm) => arm + .fat_arrow_token() + .map_or(true, |arrow| it.text_range().start() < arrow.text_range().start()), + None => false, + }; + PathKind::Expr { expr_ctx: ExprCtx { in_block_expr, @@ -775,6 +782,7 @@ impl<'a> CompletionContext<'a> { self_param, incomplete_let, impl_, + in_match_guard, }, } };