about summary refs log tree commit diff
diff options
context:
space:
mode:
authorShoyu Vanilla (Flint) <modulo641@gmail.com>2025-09-20 11:57:07 +0000
committerGitHub <noreply@github.com>2025-09-20 11:57:07 +0000
commit36b75b503ece2de745c62e2f6495ce2583076fc0 (patch)
treef33c0e99cf08a93e76828a75257f34fe955b6be4
parentb6eb08532cdf17eaf147ebd1c8555093b37cea0f (diff)
parent024ea0274d0ac4c938712653e2f8e2e7fec619f2 (diff)
downloadrust-36b75b503ece2de745c62e2f6495ce2583076fc0.tar.gz
rust-36b75b503ece2de745c62e2f6495ce2583076fc0.zip
Merge pull request #20702 from A4-Tacks/else-not-before-else
Fix `else` completion before else keyword
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs128
4 files changed, 133 insertions, 3 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
index a7df0ab3863..080875e0163 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
@@ -59,6 +59,7 @@ pub(crate) fn complete_expr_path(
         in_block_expr,
         in_breakable,
         after_if_expr,
+        before_else_kw,
         in_condition,
         incomplete_let,
         after_incomplete_let,
@@ -386,7 +387,7 @@ pub(crate) fn complete_expr_path(
                         add_keyword("let", "let $1 = $0;");
                     }
 
-                    if after_if_expr || after_incomplete_let {
+                    if !before_else_kw && (after_if_expr || after_incomplete_let) {
                         add_keyword("else", "else {\n    $0\n}");
                     }
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index 007475688d2..9deaaf66312 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -144,6 +144,7 @@ pub(crate) struct PathExprCtx<'db> {
     pub(crate) in_block_expr: bool,
     pub(crate) in_breakable: BreakableKind,
     pub(crate) after_if_expr: bool,
+    pub(crate) before_else_kw: bool,
     /// Whether this expression is the direct condition of an if or while expression
     pub(crate) in_condition: bool,
     pub(crate) incomplete_let: bool,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index b33a547dee9..7b78a9700ec 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -1282,11 +1282,12 @@ fn classify_name_ref<'db>(
         let after_incomplete_let = after_incomplete_let(it.clone()).is_some();
         let incomplete_expr_stmt =
             it.parent().and_then(ast::ExprStmt::cast).map(|it| it.semicolon_token().is_none());
+        let before_else_kw = before_else_kw(it);
         let incomplete_let = it
             .parent()
             .and_then(ast::LetStmt::cast)
             .is_some_and(|it| it.semicolon_token().is_none())
-            || after_incomplete_let && incomplete_expr_stmt.unwrap_or(true) && !before_else_kw(it);
+            || after_incomplete_let && incomplete_expr_stmt.unwrap_or(true) && !before_else_kw;
         let in_value = it.parent().and_then(Either::<ast::LetStmt, ast::ArgList>::cast).is_some();
         let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax());
 
@@ -1302,6 +1303,7 @@ fn classify_name_ref<'db>(
                 in_block_expr,
                 in_breakable: in_loop_body,
                 after_if_expr,
+                before_else_kw,
                 in_condition,
                 ref_expr_parent,
                 after_amp,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index 5cc72ef845b..c420953036f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -1673,7 +1673,133 @@ fn foo() { let x = if foo {} $0 else {}; }
             kw async
             kw const
             kw crate::
-            kw else
+            kw else if
+            kw enum
+            kw extern
+            kw false
+            kw fn
+            kw for
+            kw if
+            kw if let
+            kw impl
+            kw impl for
+            kw let
+            kw letm
+            kw loop
+            kw match
+            kw mod
+            kw return
+            kw self::
+            kw static
+            kw struct
+            kw trait
+            kw true
+            kw type
+            kw union
+            kw unsafe
+            kw use
+            kw while
+            kw while let
+            sn macro_rules
+            sn pd
+            sn ppd
+        "#]],
+    );
+    check(
+        r#"
+fn foo() { let x = if foo {} $0 else if true {}; }
+"#,
+        expect![[r#"
+            fn foo    fn()
+            bt u32     u32
+            kw async
+            kw const
+            kw crate::
+            kw else if
+            kw enum
+            kw extern
+            kw false
+            kw fn
+            kw for
+            kw if
+            kw if let
+            kw impl
+            kw impl for
+            kw let
+            kw letm
+            kw loop
+            kw match
+            kw mod
+            kw return
+            kw self::
+            kw static
+            kw struct
+            kw trait
+            kw true
+            kw type
+            kw union
+            kw unsafe
+            kw use
+            kw while
+            kw while let
+            sn macro_rules
+            sn pd
+            sn ppd
+        "#]],
+    );
+    check(
+        r#"
+fn foo() { let x = if foo {} el$0 else if true {} else {}; }
+"#,
+        expect![[r#"
+            fn foo()  fn()
+            lc x        ()
+            bt u32     u32
+            kw async
+            kw const
+            kw crate::
+            kw else if
+            kw enum
+            kw extern
+            kw false
+            kw fn
+            kw for
+            kw if
+            kw if let
+            kw impl
+            kw impl for
+            kw let
+            kw letm
+            kw loop
+            kw match
+            kw mod
+            kw return
+            kw self::
+            kw static
+            kw struct
+            kw trait
+            kw true
+            kw type
+            kw union
+            kw unsafe
+            kw use
+            kw while
+            kw while let
+            sn macro_rules
+            sn pd
+            sn ppd
+        "#]],
+    );
+    check(
+        r#"
+fn foo() { let x = if foo {} $0 else if true {} else {}; }
+"#,
+        expect![[r#"
+            fn foo    fn()
+            bt u32     u32
+            kw async
+            kw const
+            kw crate::
             kw else if
             kw enum
             kw extern