about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-01-27 11:35:33 +0000
committerbors <bors@rust-lang.org>2023-01-27 11:35:33 +0000
commit2935a89f3f4434bcff11f4c738e5a5f7666ebb9a (patch)
treee02892606ee7e3f4482317337d07afc9cd6fc16c
parent9814d798411a4b1b258c710f86626bd1997e406f (diff)
parent68291906116feef3e74d9f4c8c5641eebd8dd9da (diff)
downloadrust-2935a89f3f4434bcff11f4c738e5a5f7666ebb9a.tar.gz
rust-2935a89f3f4434bcff11f4c738e5a5f7666ebb9a.zip
Auto merge of #14037 - Veykril:if-let-match, r=Veykril
Handle boolean scrutinees in match <-> if let replacement assists better
-rw-r--r--crates/ide-assists/src/handlers/replace_if_let_with_match.rs183
1 files changed, 159 insertions, 24 deletions
diff --git a/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
index 484c27387da..457559656a4 100644
--- a/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
@@ -13,7 +13,7 @@ use syntax::{
         edit::{AstNodeEdit, IndentLevel},
         make, HasName,
     },
-    AstNode, TextRange,
+    AstNode, TextRange, T,
 };
 
 use crate::{
@@ -96,8 +96,9 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
         cond_bodies.push((cond, body));
     }
 
-    if !pat_seen {
-        // Don't offer turning an if (chain) without patterns into a match
+    if !pat_seen && cond_bodies.len() != 1 {
+        // Don't offer turning an if (chain) without patterns into a match,
+        // unless its a simple `if cond { .. } (else { .. })`
         return None;
     }
 
@@ -114,6 +115,11 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
                         Either::Left(pat) => {
                             make::match_arm(iter::once(pat), None, unwrap_trivial_block(body))
                         }
+                        Either::Right(_) if !pat_seen => make::match_arm(
+                            iter::once(make::literal_pat("true").into()),
+                            None,
+                            unwrap_trivial_block(body),
+                        ),
                         Either::Right(expr) => make::match_arm(
                             iter::once(make::wildcard_pat().into()),
                             Some(expr),
@@ -144,31 +150,36 @@ fn make_else_arm(
     else_block: Option<ast::BlockExpr>,
     conditionals: &[(Either<ast::Pat, ast::Expr>, ast::BlockExpr)],
 ) -> ast::MatchArm {
-    if let Some(else_block) = else_block {
-        let pattern = if let [(Either::Left(pat), _)] = conditionals {
-            ctx.sema
+    let (pattern, expr) = if let Some(else_block) = else_block {
+        let pattern = match conditionals {
+            [(Either::Right(_), _)] => make::literal_pat("false").into(),
+            [(Either::Left(pat), _)] => match ctx
+                .sema
                 .type_of_pat(pat)
                 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.adjusted()))
-                .zip(Some(pat))
-        } else {
-            None
-        };
-        let pattern = match pattern {
-            Some((it, pat)) => {
-                if does_pat_match_variant(pat, &it.sad_pattern()) {
-                    it.happy_pattern_wildcard()
-                } else if does_nested_pattern(pat) {
-                    make::wildcard_pat().into()
-                } else {
-                    it.sad_pattern()
+            {
+                Some(it) => {
+                    if does_pat_match_variant(pat, &it.sad_pattern()) {
+                        it.happy_pattern_wildcard()
+                    } else if does_nested_pattern(pat) {
+                        make::wildcard_pat().into()
+                    } else {
+                        it.sad_pattern()
+                    }
                 }
-            }
-            None => make::wildcard_pat().into(),
+                None => make::wildcard_pat().into(),
+            },
+            _ => make::wildcard_pat().into(),
         };
-        make::match_arm(iter::once(pattern), None, unwrap_trivial_block(else_block))
+        (pattern, unwrap_trivial_block(else_block))
     } else {
-        make::match_arm(iter::once(make::wildcard_pat().into()), None, make::expr_unit())
-    }
+        let pattern = match conditionals {
+            [(Either::Right(_), _)] => make::literal_pat("false").into(),
+            _ => make::wildcard_pat().into(),
+        };
+        (pattern, make::expr_unit())
+    };
+    make::match_arm(iter::once(pattern), None, expr)
 }
 
 // Assist: replace_match_with_if_let
@@ -231,7 +242,19 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
                 }
             }
 
-            let condition = make::expr_let(if_let_pat, scrutinee);
+            let condition = match if_let_pat {
+                ast::Pat::LiteralPat(p)
+                    if p.literal().map_or(false, |it| it.token().kind() == T![true]) =>
+                {
+                    scrutinee
+                }
+                ast::Pat::LiteralPat(p)
+                    if p.literal().map_or(false, |it| it.token().kind() == T![false]) =>
+                {
+                    make::expr_prefix(T![!], scrutinee)
+                }
+                _ => make::expr_let(if_let_pat, scrutinee).into(),
+            };
             let then_block = make_block_expr(then_expr.reset_indent());
             let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) };
             let if_let_expr = make::expr_if(
@@ -328,6 +351,58 @@ fn main() {
     }
 
     #[test]
+    fn test_if_with_match_no_else() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+pub fn foo(foo: bool) {
+    if foo$0 {
+        self.foo();
+    }
+}
+"#,
+            r#"
+pub fn foo(foo: bool) {
+    match foo {
+        true => {
+            self.foo();
+        }
+        false => (),
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn test_if_with_match_with_else() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+pub fn foo(foo: bool) {
+    if foo$0 {
+        self.foo();
+    } else {
+        self.bar();
+    }
+}
+"#,
+            r#"
+pub fn foo(foo: bool) {
+    match foo {
+        true => {
+            self.foo();
+        }
+        false => {
+            self.bar();
+        }
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
     fn test_if_let_with_match_no_else() {
         check_assist(
             replace_if_let_with_match,
@@ -996,4 +1071,64 @@ fn main() {
 "#,
         )
     }
+
+    #[test]
+    fn test_replace_match_with_if_bool() {
+        check_assist(
+            replace_match_with_if_let,
+            r#"
+fn main() {
+    match$0 b {
+        true => (),
+        _ => code(),
+    }
+}
+"#,
+            r#"
+fn main() {
+    if b {
+        ()
+    } else {
+        code()
+    }
+}
+"#,
+        );
+        check_assist(
+            replace_match_with_if_let,
+            r#"
+fn main() {
+    match$0 b {
+        false => code(),
+        true => (),
+    }
+}
+"#,
+            r#"
+fn main() {
+    if !b {
+        code()
+    }
+}
+"#,
+        );
+        check_assist(
+            replace_match_with_if_let,
+            r#"
+fn main() {
+    match$0 b {
+        false => (),
+        true => code(),
+    }
+}
+"#,
+            r#"
+fn main() {
+    if b {
+        code()
+    }
+}
+"#,
+        )
+    }
 }