diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs index d4544dd1d1..bdf6e64f09 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 0089958ff1..3989a451bd 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 6a2079b126..93b6ad5d14 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 0c8b569b66..c71ffa0ed8 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, }, } };