Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/move_guard.rs')
-rw-r--r--crates/ide-assists/src/handlers/move_guard.rs100
1 files changed, 91 insertions, 9 deletions
diff --git a/crates/ide-assists/src/handlers/move_guard.rs b/crates/ide-assists/src/handlers/move_guard.rs
index 1c0c6e43d5..84f02bdfdb 100644
--- a/crates/ide-assists/src/handlers/move_guard.rs
+++ b/crates/ide-assists/src/handlers/move_guard.rs
@@ -3,7 +3,7 @@ use syntax::{
SyntaxKind::WHITESPACE,
ast::{
AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit, make,
- syntax_factory::SyntaxFactory,
+ prec::ExprPrecedence, syntax_factory::SyntaxFactory,
},
syntax_editor::Element,
};
@@ -49,7 +49,7 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>)
let guard_condition = guard.condition()?.reset_indent();
let arm_expr = match_arm.expr()?;
- let then_branch = make::block_expr(None, Some(arm_expr.reset_indent().indent(1.into())));
+ let then_branch = crate::utils::wrap_block(&arm_expr);
let if_expr = make::expr_if(guard_condition, then_branch, None).indent(arm_expr.indent_level());
let target = guard.syntax().text_range();
@@ -109,6 +109,7 @@ pub(crate) fn move_arm_cond_to_match_guard(
let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
let match_pat = match_arm.pat()?;
let arm_body = match_arm.expr()?;
+ let arm_guard = match_arm.guard().and_then(|it| it.condition());
let mut replace_node = None;
let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone()).or_else(|| {
@@ -149,6 +150,25 @@ pub(crate) fn move_arm_cond_to_match_guard(
0
};
let indent_level = match_arm.indent_level();
+ let make_guard = |cond: Option<Expr>| {
+ let condition = match (arm_guard.clone(), cond) {
+ (None, None) => return None,
+ (None, Some(it)) | (Some(it), None) => it,
+ (Some(lhs), Some(rhs)) => {
+ let op_expr = |expr: Expr| {
+ if expr.precedence().needs_parentheses_in(ExprPrecedence::LAnd) {
+ make.expr_paren(expr).into()
+ } else {
+ expr
+ }
+ };
+ let op = syntax::ast::BinaryOp::LogicOp(syntax::ast::LogicOp::And);
+ let expr_bin = make.expr_bin(op_expr(lhs), op, op_expr(rhs));
+ expr_bin.into()
+ }
+ };
+ Some(make.match_guard(condition))
+ };
for (cond, block) in conds_blocks {
let only_expr = block.statements().next().is_none();
@@ -156,8 +176,7 @@ pub(crate) fn move_arm_cond_to_match_guard(
Some(then_expr) if only_expr => then_expr,
_ => block.dedent(dedent.into()).into(),
};
- let guard = make.match_guard(cond);
- let new_arm = make.match_arm(match_pat.clone(), Some(guard), expr);
+ let new_arm = make.match_arm(match_pat.clone(), make_guard(Some(cond)), expr);
replace_arms.push(new_arm);
}
if let Some(block) = tail {
@@ -170,7 +189,7 @@ pub(crate) fn move_arm_cond_to_match_guard(
}
_ => block.dedent(dedent.into()).into(),
};
- let new_arm = make.match_arm(match_pat, None, expr);
+ let new_arm = make.match_arm(match_pat, make_guard(None), expr);
replace_arms.push(new_arm);
} else {
// There's no else branch. Add a pattern without guard, unless the following match
@@ -185,7 +204,7 @@ pub(crate) fn move_arm_cond_to_match_guard(
}
_ => {
let block_expr = make.expr_empty_block().into();
- replace_arms.push(make.match_arm(match_pat, None, block_expr));
+ replace_arms.push(make.match_arm(match_pat, make_guard(None), block_expr));
}
}
}
@@ -326,6 +345,35 @@ fn main() {
}
#[test]
+ fn move_guard_to_block_arm_body_works() {
+ check_assist(
+ move_guard_to_arm_body,
+ r#"
+fn main() {
+ match 92 {
+ x $0if x > 10 => {
+ let _ = true;
+ false
+ },
+ _ => true
+ }
+}
+"#,
+ r#"
+fn main() {
+ match 92 {
+ x => if x > 10 {
+ let _ = true;
+ false
+ },
+ _ => true
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
fn move_let_guard_to_arm_body_works() {
check_assist(
move_guard_to_arm_body,
@@ -376,9 +424,7 @@ fn main() {
&& true
&& true {
{
- {
- false
- }
+ false
}
},
_ => true
@@ -1084,4 +1130,40 @@ fn main() {
"#,
)
}
+
+ #[test]
+ fn move_arm_cond_to_match_guard_elseif_exist_guard() {
+ check_assist(
+ move_arm_cond_to_match_guard,
+ r#"
+fn main() {
+ let cond = true;
+ match 92 {
+ 3 => true,
+ x if cond => if x $0> 10 {
+ false
+ } else if x > 5 {
+ true
+ } else if x > 4 || x < -2 {
+ false
+ } else {
+ true
+ },
+ }
+}
+"#,
+ r#"
+fn main() {
+ let cond = true;
+ match 92 {
+ 3 => true,
+ x if cond && x > 10 => false,
+ x if cond && x > 5 => true,
+ x if cond && (x > 4 || x < -2) => false,
+ x if cond => true,
+ }
+}
+"#,
+ )
+ }
}