aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers/flip_binexpr.rs
diff options
context:
space:
mode:
authorKevin DeLorey <[email protected]>2020-02-09 16:25:47 +0000
committerKevin DeLorey <[email protected]>2020-02-09 16:37:43 +0000
commita957c473fdb79880c39b73dc9e0c923093cf16ac (patch)
treef998b548f530ce604651e0e6af314ed2ec74b3b5 /crates/ra_assists/src/handlers/flip_binexpr.rs
parent22caf982b99c54058e2e9200aeea0e61cada284a (diff)
parent1b9b13b4b4a75b5531c3f046ce6bf72d681f2732 (diff)
Merge branch 'master' into kdelorey/complete-trait-impl
Diffstat (limited to 'crates/ra_assists/src/handlers/flip_binexpr.rs')
-rw-r--r--crates/ra_assists/src/handlers/flip_binexpr.rs142
1 files changed, 142 insertions, 0 deletions
diff --git a/crates/ra_assists/src/handlers/flip_binexpr.rs b/crates/ra_assists/src/handlers/flip_binexpr.rs
new file mode 100644
index 000000000..bfcc09e90
--- /dev/null
+++ b/crates/ra_assists/src/handlers/flip_binexpr.rs
@@ -0,0 +1,142 @@
1use ra_syntax::ast::{AstNode, BinExpr, BinOp};
2
3use crate::{Assist, AssistCtx, AssistId};
4
5// Assist: flip_binexpr
6//
7// Flips operands of a binary expression.
8//
9// ```
10// fn main() {
11// let _ = 90 +<|> 2;
12// }
13// ```
14// ->
15// ```
16// fn main() {
17// let _ = 2 + 90;
18// }
19// ```
20pub(crate) fn flip_binexpr(ctx: AssistCtx) -> Option<Assist> {
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 = ctx.frange.range.is_subrange(&op_range);
27 if !cursor_in_range {
28 return None;
29 }
30 let action: FlipAction = expr.op_kind()?.into();
31 // The assist should not be applied for certain operators
32 if let FlipAction::DontFlip = action {
33 return None;
34 }
35
36 ctx.add_assist(AssistId("flip_binexpr"), "Flip binary expression", |edit| {
37 edit.target(op_range);
38 if let FlipAction::FlipAndReplaceOp(new_op) = action {
39 edit.replace(op_range, new_op);
40 }
41 edit.replace(lhs.text_range(), rhs.text());
42 edit.replace(rhs.text_range(), lhs.text());
43 })
44}
45
46enum FlipAction {
47 // Flip the expression
48 Flip,
49 // Flip the expression and replace the operator with this string
50 FlipAndReplaceOp(&'static str),
51 // Do not flip the expression
52 DontFlip,
53}
54
55impl From<BinOp> for FlipAction {
56 fn from(op_kind: BinOp) -> Self {
57 match op_kind {
58 kind if kind.is_assignment() => FlipAction::DontFlip,
59 BinOp::GreaterTest => FlipAction::FlipAndReplaceOp("<"),
60 BinOp::GreaterEqualTest => FlipAction::FlipAndReplaceOp("<="),
61 BinOp::LesserTest => FlipAction::FlipAndReplaceOp(">"),
62 BinOp::LesserEqualTest => FlipAction::FlipAndReplaceOp(">="),
63 _ => FlipAction::Flip,
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
73
74 #[test]
75 fn flip_binexpr_target_is_the_op() {
76 check_assist_target(flip_binexpr, "fn f() { let res = 1 ==<|> 2; }", "==")
77 }
78
79 #[test]
80 fn flip_binexpr_not_applicable_for_assignment() {
81 check_assist_not_applicable(flip_binexpr, "fn f() { let mut _x = 1; _x +=<|> 2 }")
82 }
83
84 #[test]
85 fn flip_binexpr_works_for_eq() {
86 check_assist(
87 flip_binexpr,
88 "fn f() { let res = 1 ==<|> 2; }",
89 "fn f() { let res = 2 ==<|> 1; }",
90 )
91 }
92
93 #[test]
94 fn flip_binexpr_works_for_gt() {
95 check_assist(
96 flip_binexpr,
97 "fn f() { let res = 1 ><|> 2; }",
98 "fn f() { let res = 2 <<|> 1; }",
99 )
100 }
101
102 #[test]
103 fn flip_binexpr_works_for_lteq() {
104 check_assist(
105 flip_binexpr,
106 "fn f() { let res = 1 <=<|> 2; }",
107 "fn f() { let res = 2 >=<|> 1; }",
108 )
109 }
110
111 #[test]
112 fn flip_binexpr_works_for_complex_expr() {
113 check_assist(
114 flip_binexpr,
115 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }",
116 "fn f() { let res = (2 + 2) ==<|> (1 + 1); }",
117 )
118 }
119
120 #[test]
121 fn flip_binexpr_works_inside_match() {
122 check_assist(
123 flip_binexpr,
124 r#"
125 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
126 match other.downcast_ref::<Self>() {
127 None => false,
128 Some(it) => it ==<|> self,
129 }
130 }
131 "#,
132 r#"
133 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
134 match other.downcast_ref::<Self>() {
135 None => false,
136 Some(it) => self ==<|> it,
137 }
138 }
139 "#,
140 )
141 }
142}