aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists
diff options
context:
space:
mode:
authorMarco Groppo <[email protected]>2019-03-25 22:53:57 +0000
committerMarco Groppo <[email protected]>2019-03-25 22:53:57 +0000
commit12b5d4f795f69f7fa07051cdec7a1347d3aa7924 (patch)
tree6ecfb96b9d5920e96e38d90906f8841c8d09e636 /crates/ra_assists
parentd88a96bd05fdfdc6986e7807c93400af2cf6fa0f (diff)
Assist to flip (some) binary expressions.
This assist can flip the following operators: ==, !=, >, >=, <, <=.
Diffstat (limited to 'crates/ra_assists')
-rw-r--r--crates/ra_assists/src/flip_binexpr.rs149
-rw-r--r--crates/ra_assists/src/flip_eq_operands.rs86
-rw-r--r--crates/ra_assists/src/lib.rs4
3 files changed, 151 insertions, 88 deletions
diff --git a/crates/ra_assists/src/flip_binexpr.rs b/crates/ra_assists/src/flip_binexpr.rs
new file mode 100644
index 000000000..8a0737b55
--- /dev/null
+++ b/crates/ra_assists/src/flip_binexpr.rs
@@ -0,0 +1,149 @@
1use hir::db::HirDatabase;
2use ra_syntax::ast::{AstNode, BinExpr, BinOp};
3
4use crate::{AssistCtx, Assist, AssistId};
5
6/// Flip binary comparison expressions (==, !=, >, >=, <, <=).
7pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
8 let expr = ctx.node_at_offset::<BinExpr>()?;
9 let lhs = expr.lhs()?.syntax();
10 let rhs = expr.rhs()?.syntax();
11 let op_range = expr.op()?.range();
12 // The assist should be available only if the cursor is on the operator
13 let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
14 // The assist should be available only for these binary operators
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;
27 }
28 let new_op = match op_kind {
29 BinOp::GreaterTest => Some("<"),
30 BinOp::GreaterEqualTest => Some("<="),
31 BinOp::LesserTest => Some(">"),
32 BinOp::LesserEqualTest => Some(">="),
33 _ => None,
34 };
35 ctx.add_action(AssistId("flip_binexpr"), "flip binary expression", |edit| {
36 edit.target(op_range);
37 if let Some(new_op) = new_op {
38 edit.replace(op_range, new_op);
39 }
40 edit.replace(lhs.range(), rhs.text());
41 edit.replace(rhs.range(), lhs.text());
42 });
43
44 ctx.build()
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 use crate::helpers::{check_assist, check_assist_target};
52
53 #[test]
54 fn flip_eq_operands_for_simple_stmt() {
55 check_assist(
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 }
70
71 #[test]
72 fn flip_gt_operands_for_simple_stmt() {
73 check_assist(
74 flip_binexpr,
75 "fn f() { let res = 1 ><|> 2; }",
76 "fn f() { let res = 2 <<|> 1; }",
77 )
78 }
79
80 #[test]
81 fn flip_gteq_operands_for_simple_stmt() {
82 check_assist(
83 flip_binexpr,
84 "fn f() { let res = 1 >=<|> 2; }",
85 "fn f() { let res = 2 <=<|> 1; }",
86 )
87 }
88
89 #[test]
90 fn flip_lt_operands_for_simple_stmt() {
91 check_assist(
92 flip_binexpr,
93 "fn f() { let res = 1 <<|> 2; }",
94 "fn f() { let res = 2 ><|> 1; }",
95 )
96 }
97
98 #[test]
99 fn flip_lteq_operands_for_simple_stmt() {
100 check_assist(
101 flip_binexpr,
102 "fn f() { let res = 1 <=<|> 2; }",
103 "fn f() { let res = 2 >=<|> 1; }",
104 )
105 }
106
107 #[test]
108 fn flip_eq_operands_for_complex_stmt() {
109 check_assist(
110 flip_binexpr,
111 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }",
112 "fn f() { let res = (2 + 2) ==<|> (1 + 1); }",
113 )
114 }
115
116 #[test]
117 fn flip_eq_operands_in_match_expr() {
118 check_assist(
119 flip_binexpr,
120 r#"
121 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
122 match other.downcast_ref::<Self>() {
123 None => false,
124 Some(it) => it ==<|> self,
125 }
126 }
127 "#,
128 r#"
129 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
130 match other.downcast_ref::<Self>() {
131 None => false,
132 Some(it) => self ==<|> it,
133 }
134 }
135 "#,
136 )
137 }
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}
diff --git a/crates/ra_assists/src/flip_eq_operands.rs b/crates/ra_assists/src/flip_eq_operands.rs
deleted file mode 100644
index df0bb689d..000000000
--- a/crates/ra_assists/src/flip_eq_operands.rs
+++ /dev/null
@@ -1,86 +0,0 @@
1use hir::db::HirDatabase;
2use ra_syntax::ast::{AstNode, BinExpr, BinOp};
3
4use crate::{AssistCtx, Assist, AssistId};
5
6pub(crate) fn flip_eq_operands(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
7 let expr = ctx.node_at_offset::<BinExpr>()?;
8 let lhs = expr.lhs()?.syntax();
9 let rhs = expr.rhs()?.syntax();
10 let op_range = expr.op()?.range();
11 let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
12 let allowed_ops = [BinOp::EqualityTest, BinOp::NegatedEqualityTest];
13 let expr_op = expr.op_kind()?;
14 if !cursor_in_range || !allowed_ops.iter().any(|o| *o == expr_op) {
15 return None;
16 }
17 ctx.add_action(AssistId("flip_eq_operands"), "flip equality operands", |edit| {
18 edit.target(op_range);
19 edit.replace(lhs.range(), rhs.text());
20 edit.replace(rhs.range(), lhs.text());
21 });
22
23 ctx.build()
24}
25
26#[cfg(test)]
27mod tests {
28 use super::*;
29
30 use crate::helpers::{check_assist, check_assist_target};
31
32 #[test]
33 fn flip_eq_operands_for_simple_stmt() {
34 check_assist(
35 flip_eq_operands,
36 "fn f() { let res = 1 ==<|> 2; }",
37 "fn f() { let res = 2 ==<|> 1; }",
38 )
39 }
40
41 #[test]
42 fn flip_neq_operands_for_simple_stmt() {
43 check_assist(
44 flip_eq_operands,
45 "fn f() { let res = 1 !=<|> 2; }",
46 "fn f() { let res = 2 !=<|> 1; }",
47 )
48 }
49
50 #[test]
51 fn flip_eq_operands_for_complex_stmt() {
52 check_assist(
53 flip_eq_operands,
54 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }",
55 "fn f() { let res = (2 + 2) ==<|> (1 + 1); }",
56 )
57 }
58
59 #[test]
60 fn flip_eq_operands_in_match_expr() {
61 check_assist(
62 flip_eq_operands,
63 r#"
64 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
65 match other.downcast_ref::<Self>() {
66 None => false,
67 Some(it) => it ==<|> self,
68 }
69 }
70 "#,
71 r#"
72 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
73 match other.downcast_ref::<Self>() {
74 None => false,
75 Some(it) => self ==<|> it,
76 }
77 }
78 "#,
79 )
80 }
81
82 #[test]
83 fn flip_eq_operands_target() {
84 check_assist_target(flip_eq_operands, "fn f() { let res = 1 ==<|> 2; }", "==")
85 }
86}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 2e47b5215..c1514f8e5 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -88,7 +88,7 @@ where
88mod add_derive; 88mod add_derive;
89mod add_impl; 89mod add_impl;
90mod flip_comma; 90mod flip_comma;
91mod flip_eq_operands; 91mod flip_binexpr;
92mod change_visibility; 92mod change_visibility;
93mod fill_match_arms; 93mod fill_match_arms;
94mod fill_struct_fields; 94mod fill_struct_fields;
@@ -108,7 +108,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
108 fill_match_arms::fill_match_arms, 108 fill_match_arms::fill_match_arms,
109 fill_struct_fields::fill_struct_fields, 109 fill_struct_fields::fill_struct_fields,
110 flip_comma::flip_comma, 110 flip_comma::flip_comma,
111 flip_eq_operands::flip_eq_operands, 111 flip_binexpr::flip_binexpr,
112 introduce_variable::introduce_variable, 112 introduce_variable::introduce_variable,
113 replace_if_let_with_match::replace_if_let_with_match, 113 replace_if_let_with_match::replace_if_let_with_match,
114 split_import::split_import, 114 split_import::split_import,