1 use syntax::ast::{self, AstNode, BinExpr};
3 use crate::{AssistContext, AssistId, AssistKind, Assists};
5 // Assist: flip_binexpr
7 // Flips operands of a binary expression.
20 pub(crate) fn flip_binexpr(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
21 let expr = ctx.find_node_at_offset::<BinExpr>()?;
22 let lhs = expr.lhs()?.syntax().clone();
23 let rhs = expr.rhs()?.syntax().clone();
24 let op_range = expr.op_token()?.text_range();
25 // The assist should be applied only if the cursor is on the operator
26 let cursor_in_range = op_range.contains_range(ctx.frange.range);
30 let action: FlipAction = expr.op_kind()?.into();
31 // The assist should not be applied for certain operators
32 if let FlipAction::DontFlip = action {
37 AssistId("flip_binexpr", AssistKind::RefactorRewrite),
38 "Flip binary expression",
41 if let FlipAction::FlipAndReplaceOp(new_op) = action {
42 edit.replace(op_range, new_op);
44 edit.replace(lhs.text_range(), rhs.text());
45 edit.replace(rhs.text_range(), lhs.text());
51 // Flip the expression
53 // Flip the expression and replace the operator with this string
54 FlipAndReplaceOp(&'static str),
55 // Do not flip the expression
59 impl From<ast::BinaryOp> for FlipAction {
60 fn from(op_kind: ast::BinaryOp) -> Self {
62 ast::BinaryOp::Assignment { .. } => FlipAction::DontFlip,
63 ast::BinaryOp::CmpOp(ast::CmpOp::Ord { ordering, strict }) => {
64 let rev_op = match (ordering, strict) {
65 (ast::Ordering::Less, true) => ">",
66 (ast::Ordering::Less, false) => ">=",
67 (ast::Ordering::Greater, true) => "<",
68 (ast::Ordering::Greater, false) => "<=",
70 FlipAction::FlipAndReplaceOp(rev_op)
72 _ => FlipAction::Flip,
81 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
84 fn flip_binexpr_target_is_the_op() {
85 check_assist_target(flip_binexpr, "fn f() { let res = 1 ==$0 2; }", "==")
89 fn flip_binexpr_not_applicable_for_assignment() {
90 check_assist_not_applicable(flip_binexpr, "fn f() { let mut _x = 1; _x +=$0 2 }")
94 fn flip_binexpr_works_for_eq() {
95 check_assist(flip_binexpr, "fn f() { let res = 1 ==$0 2; }", "fn f() { let res = 2 == 1; }")
99 fn flip_binexpr_works_for_gt() {
100 check_assist(flip_binexpr, "fn f() { let res = 1 >$0 2; }", "fn f() { let res = 2 < 1; }")
104 fn flip_binexpr_works_for_lteq() {
105 check_assist(flip_binexpr, "fn f() { let res = 1 <=$0 2; }", "fn f() { let res = 2 >= 1; }")
109 fn flip_binexpr_works_for_complex_expr() {
112 "fn f() { let res = (1 + 1) ==$0 (2 + 2); }",
113 "fn f() { let res = (2 + 2) == (1 + 1); }",
118 fn flip_binexpr_works_inside_match() {
122 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
123 match other.downcast_ref::<Self>() {
125 Some(it) => it ==$0 self,
130 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
131 match other.downcast_ref::<Self>() {
133 Some(it) => self == it,