summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs')
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs183
1 files changed, 159 insertions, 24 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
index 484c27387..457559656 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
+++ b/src/tools/rust-analyzer/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()
+ }
+}
+"#,
+ )
+ }
}