aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Groppo <[email protected]>2019-03-26 22:12:46 +0000
committerMarco Groppo <[email protected]>2019-03-26 22:12:46 +0000
commit7b81c088f79a19289008f635d2e2e4105a750b96 (patch)
treea08d008c4faf2c1defe803f66e2d3fef8b1ea60e
parent6030d6f500e42bde012a391666b68363d8479d21 (diff)
Flip any binary expression except assignments.
-rw-r--r--crates/ra_assists/src/flip_binexpr.rs120
1 files changed, 56 insertions, 64 deletions
diff --git a/crates/ra_assists/src/flip_binexpr.rs b/crates/ra_assists/src/flip_binexpr.rs
index 8a0737b55..ec377642e 100644
--- a/crates/ra_assists/src/flip_binexpr.rs
+++ b/crates/ra_assists/src/flip_binexpr.rs
@@ -3,38 +3,26 @@ use ra_syntax::ast::{AstNode, BinExpr, BinOp};
3 3
4use crate::{AssistCtx, Assist, AssistId}; 4use crate::{AssistCtx, Assist, AssistId};
5 5
6/// Flip binary comparison expressions (==, !=, >, >=, <, <=). 6/// Flip binary expression assist.
7pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 7pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
8 let expr = ctx.node_at_offset::<BinExpr>()?; 8 let expr = ctx.node_at_offset::<BinExpr>()?;
9 let lhs = expr.lhs()?.syntax(); 9 let lhs = expr.lhs()?.syntax();
10 let rhs = expr.rhs()?.syntax(); 10 let rhs = expr.rhs()?.syntax();
11 let op_range = expr.op()?.range(); 11 let op_range = expr.op()?.range();
12 // The assist should be available only if the cursor is on the operator 12 // The assist should be applied only if the cursor is on the operator
13 let cursor_in_range = ctx.frange.range.is_subrange(&op_range); 13 let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
14 // The assist should be available only for these binary operators 14 if !cursor_in_range {
15 // (it should not change the meaning of the expression)
16 let allowed_ops = [
17 BinOp::EqualityTest,
18 BinOp::NegatedEqualityTest,
19 BinOp::GreaterTest,
20 BinOp::GreaterEqualTest,
21 BinOp::LesserTest,
22 BinOp::LesserEqualTest,
23 ];
24 let op_kind = expr.op_kind()?;
25 if !cursor_in_range || !allowed_ops.iter().any(|o| *o == op_kind) {
26 return None; 15 return None;
27 } 16 }
28 let new_op = match op_kind { 17 let action: FlipAction = expr.op_kind()?.into();
29 BinOp::GreaterTest => Some("<"), 18 // The assist should not be applied for certain operators
30 BinOp::GreaterEqualTest => Some("<="), 19 if let FlipAction::DontFlip = action {
31 BinOp::LesserTest => Some(">"), 20 return None;
32 BinOp::LesserEqualTest => Some(">="), 21 }
33 _ => None, 22
34 };
35 ctx.add_action(AssistId("flip_binexpr"), "flip binary expression", |edit| { 23 ctx.add_action(AssistId("flip_binexpr"), "flip binary expression", |edit| {
36 edit.target(op_range); 24 edit.target(op_range);
37 if let Some(new_op) = new_op { 25 if let FlipAction::FlipAndReplaceOp(new_op) = action {
38 edit.replace(op_range, new_op); 26 edit.replace(op_range, new_op);
39 } 27 }
40 edit.replace(lhs.range(), rhs.text()); 28 edit.replace(lhs.range(), rhs.text());
@@ -44,59 +32,74 @@ pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
44 ctx.build() 32 ctx.build()
45} 33}
46 34
35enum FlipAction {
36 // Flip the expression
37 Flip,
38 // Flip the expression and replace the operator with this string
39 FlipAndReplaceOp(&'static str),
40 // Do not flip the expression
41 DontFlip,
42}
43
44impl From<BinOp> for FlipAction {
45 fn from(op_kind: BinOp) -> Self {
46 match op_kind {
47 BinOp::Assignment => FlipAction::DontFlip,
48 BinOp::AddAssign => FlipAction::DontFlip,
49 BinOp::DivAssign => FlipAction::DontFlip,
50 BinOp::MulAssign => FlipAction::DontFlip,
51 BinOp::RemAssign => FlipAction::DontFlip,
52 BinOp::ShrAssign => FlipAction::DontFlip,
53 BinOp::ShlAssign => FlipAction::DontFlip,
54 BinOp::SubAssign => FlipAction::DontFlip,
55 BinOp::BitOrAssign => FlipAction::DontFlip,
56 BinOp::BitAndAssign => FlipAction::DontFlip,
57 BinOp::BitXorAssign => FlipAction::DontFlip,
58 BinOp::GreaterTest => FlipAction::FlipAndReplaceOp("<"),
59 BinOp::GreaterEqualTest => FlipAction::FlipAndReplaceOp("<="),
60 BinOp::LesserTest => FlipAction::FlipAndReplaceOp(">"),
61 BinOp::LesserEqualTest => FlipAction::FlipAndReplaceOp(">="),
62 _ => FlipAction::Flip,
63 }
64 }
65}
66
47#[cfg(test)] 67#[cfg(test)]
48mod tests { 68mod tests {
49 use super::*; 69 use super::*;
50 70
51 use crate::helpers::{check_assist, check_assist_target}; 71 use crate::helpers::{ check_assist, check_assist_target, check_assist_not_applicable };
52 72
53 #[test] 73 #[test]
54 fn flip_eq_operands_for_simple_stmt() { 74 fn flip_binexpr_target_is_the_op() {
55 check_assist( 75 check_assist_target(flip_binexpr, "fn f() { let res = 1 ==<|> 2; }", "==")
56 flip_binexpr,
57 "fn f() { let res = 1 ==<|> 2; }",
58 "fn f() { let res = 2 ==<|> 1; }",
59 )
60 }
61
62 #[test]
63 fn flip_neq_operands_for_simple_stmt() {
64 check_assist(
65 flip_binexpr,
66 "fn f() { let res = 1 !=<|> 2; }",
67 "fn f() { let res = 2 !=<|> 1; }",
68 )
69 } 76 }
70 77
71 #[test] 78 #[test]
72 fn flip_gt_operands_for_simple_stmt() { 79 fn flip_binexpr_not_applicable_for_assignment() {
73 check_assist( 80 check_assist_not_applicable(flip_binexpr, "fn f() { let mut _x = 1; _x +=<|> 2 }")
74 flip_binexpr,
75 "fn f() { let res = 1 ><|> 2; }",
76 "fn f() { let res = 2 <<|> 1; }",
77 )
78 } 81 }
79 82
80 #[test] 83 #[test]
81 fn flip_gteq_operands_for_simple_stmt() { 84 fn flip_binexpr_works_for_eq() {
82 check_assist( 85 check_assist(
83 flip_binexpr, 86 flip_binexpr,
84 "fn f() { let res = 1 >=<|> 2; }", 87 "fn f() { let res = 1 ==<|> 2; }",
85 "fn f() { let res = 2 <=<|> 1; }", 88 "fn f() { let res = 2 ==<|> 1; }",
86 ) 89 )
87 } 90 }
88 91
89 #[test] 92 #[test]
90 fn flip_lt_operands_for_simple_stmt() { 93 fn flip_binexpr_works_for_gt() {
91 check_assist( 94 check_assist(
92 flip_binexpr, 95 flip_binexpr,
93 "fn f() { let res = 1 <<|> 2; }", 96 "fn f() { let res = 1 ><|> 2; }",
94 "fn f() { let res = 2 ><|> 1; }", 97 "fn f() { let res = 2 <<|> 1; }",
95 ) 98 )
96 } 99 }
97 100
98 #[test] 101 #[test]
99 fn flip_lteq_operands_for_simple_stmt() { 102 fn flip_binexpr_works_for_lteq() {
100 check_assist( 103 check_assist(
101 flip_binexpr, 104 flip_binexpr,
102 "fn f() { let res = 1 <=<|> 2; }", 105 "fn f() { let res = 1 <=<|> 2; }",
@@ -105,7 +108,7 @@ mod tests {
105 } 108 }
106 109
107 #[test] 110 #[test]
108 fn flip_eq_operands_for_complex_stmt() { 111 fn flip_binexpr_works_for_complex_expr() {
109 check_assist( 112 check_assist(
110 flip_binexpr, 113 flip_binexpr,
111 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }", 114 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }",
@@ -114,7 +117,7 @@ mod tests {
114 } 117 }
115 118
116 #[test] 119 #[test]
117 fn flip_eq_operands_in_match_expr() { 120 fn flip_binexpr_works_inside_match() {
118 check_assist( 121 check_assist(
119 flip_binexpr, 122 flip_binexpr,
120 r#" 123 r#"
@@ -135,15 +138,4 @@ mod tests {
135 "#, 138 "#,
136 ) 139 )
137 } 140 }
138
139 #[test]
140 fn flip_eq_operands_target() {
141 check_assist_target(flip_binexpr, "fn f() { let res = 1 ==<|> 2; }", "==")
142 }
143
144 #[test]
145 fn flip_gt_operands_target() {
146 check_assist_target(flip_binexpr, "fn f() { let res = 1 ><|> 2; }", ">")
147 }
148
149} 141}