Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21412 from A4-Tacks/move-guard-exist
Fix loses exists guard for move_guard
Shoyu Vanilla (Flint) 3 months ago
parent ec64ea0 · parent 978aa81 · commit ac646ee
-rw-r--r--crates/ide-assists/src/handlers/move_guard.rs65
1 files changed, 60 insertions, 5 deletions
diff --git a/crates/ide-assists/src/handlers/move_guard.rs b/crates/ide-assists/src/handlers/move_guard.rs
index 1c0c6e43d5..31baa63372 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,
};
@@ -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));
}
}
}
@@ -1084,4 +1103,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,
+ }
+}
+"#,
+ )
+ }
}