aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers/invert_if.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-02-07 16:28:33 +0000
committerGitHub <[email protected]>2020-02-07 16:28:33 +0000
commit5397f05bfe7f3b18229a65040c6685e762b2f9a3 (patch)
treea3c4aab400ffe1c84bd33e094a047798e7136d2d /crates/ra_assists/src/handlers/invert_if.rs
parent1996762b1f2b9cb196cc879f0ce26d28a3c450c8 (diff)
parentd00add1f1fec59494c3c1a99c27937ae3891458d (diff)
Merge #3049
3049: Introduce assists utils r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_assists/src/handlers/invert_if.rs')
-rw-r--r--crates/ra_assists/src/handlers/invert_if.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/crates/ra_assists/src/handlers/invert_if.rs b/crates/ra_assists/src/handlers/invert_if.rs
new file mode 100644
index 000000000..a594e7e0c
--- /dev/null
+++ b/crates/ra_assists/src/handlers/invert_if.rs
@@ -0,0 +1,91 @@
1use ra_syntax::ast::{self, AstNode};
2use ra_syntax::T;
3
4use crate::{utils::invert_boolean_expression, Assist, AssistCtx, AssistId};
5
6// Assist: invert_if
7//
8// Apply invert_if
9// This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
10// This also works with `!=`. This assist can only be applied with the cursor
11// on `if`.
12//
13// ```
14// fn main() {
15// if<|> !y { A } else { B }
16// }
17// ```
18// ->
19// ```
20// fn main() {
21// if y { B } else { A }
22// }
23// ```
24
25pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
26 let if_keyword = ctx.find_token_at_offset(T![if])?;
27 let expr = ast::IfExpr::cast(if_keyword.parent())?;
28 let if_range = if_keyword.text_range();
29 let cursor_in_range = ctx.frange.range.is_subrange(&if_range);
30 if !cursor_in_range {
31 return None;
32 }
33
34 let cond = expr.condition()?.expr()?;
35 let then_node = expr.then_branch()?.syntax().clone();
36
37 if let ast::ElseBranch::Block(else_block) = expr.else_branch()? {
38 let cond_range = cond.syntax().text_range();
39 let flip_cond = invert_boolean_expression(cond);
40 let else_node = else_block.syntax();
41 let else_range = else_node.text_range();
42 let then_range = then_node.text_range();
43 return ctx.add_assist(AssistId("invert_if"), "Invert if", |edit| {
44 edit.target(if_range);
45 edit.replace(cond_range, flip_cond.syntax().text());
46 edit.replace(else_range, then_node.text());
47 edit.replace(then_range, else_node.text());
48 });
49 }
50
51 None
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 use crate::helpers::{check_assist, check_assist_not_applicable};
59
60 #[test]
61 fn invert_if_remove_inequality() {
62 check_assist(
63 invert_if,
64 "fn f() { i<|>f x != 3 { 1 } else { 3 + 2 } }",
65 "fn f() { i<|>f x == 3 { 3 + 2 } else { 1 } }",
66 )
67 }
68
69 #[test]
70 fn invert_if_remove_not() {
71 check_assist(
72 invert_if,
73 "fn f() { <|>if !cond { 3 * 2 } else { 1 } }",
74 "fn f() { <|>if cond { 1 } else { 3 * 2 } }",
75 )
76 }
77
78 #[test]
79 fn invert_if_general_case() {
80 check_assist(
81 invert_if,
82 "fn f() { i<|>f cond { 3 * 2 } else { 1 } }",
83 "fn f() { i<|>f !cond { 1 } else { 3 * 2 } }",
84 )
85 }
86
87 #[test]
88 fn invert_if_doesnt_apply_with_cursor_not_on_if() {
89 check_assist_not_applicable(invert_if, "fn f() { if !<|>cond { 3 * 2 } else { 1 } }")
90 }
91}