diff options
author | Aleksey Kladov <[email protected]> | 2020-02-07 14:53:31 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-02-07 16:28:02 +0000 |
commit | 561b4b11ff1d87ea1ff2477dcba6ae1f396573a3 (patch) | |
tree | 0da58d08d5a2ff27f43c3eb6163ba9aced2f5782 /crates/ra_assists/src/handlers/flip_binexpr.rs | |
parent | aa64a84b493aa9c0b22f36b472a445d622cd2172 (diff) |
Name assist handlers
Diffstat (limited to 'crates/ra_assists/src/handlers/flip_binexpr.rs')
-rw-r--r-- | crates/ra_assists/src/handlers/flip_binexpr.rs | 142 |
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 @@ | |||
1 | use ra_syntax::ast::{AstNode, BinExpr, BinOp}; | ||
2 | |||
3 | use 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 | // ``` | ||
20 | pub(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 | |||
46 | enum 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 | |||
55 | impl 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)] | ||
69 | mod 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 | } | ||