diff options
Diffstat (limited to 'crates/ide_assists/src/handlers')
-rw-r--r-- | crates/ide_assists/src/handlers/apply_demorgan.rs | 78 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/early_return.rs | 2 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/invert_if.rs | 2 |
3 files changed, 74 insertions, 8 deletions
diff --git a/crates/ide_assists/src/handlers/apply_demorgan.rs b/crates/ide_assists/src/handlers/apply_demorgan.rs index ed4d11455..6997ea048 100644 --- a/crates/ide_assists/src/handlers/apply_demorgan.rs +++ b/crates/ide_assists/src/handlers/apply_demorgan.rs | |||
@@ -7,18 +7,17 @@ use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKin | |||
7 | // Apply https://en.wikipedia.org/wiki/De_Morgan%27s_laws[De Morgan's law]. | 7 | // Apply https://en.wikipedia.org/wiki/De_Morgan%27s_laws[De Morgan's law]. |
8 | // This transforms expressions of the form `!l || !r` into `!(l && r)`. | 8 | // This transforms expressions of the form `!l || !r` into `!(l && r)`. |
9 | // This also works with `&&`. This assist can only be applied with the cursor | 9 | // This also works with `&&`. This assist can only be applied with the cursor |
10 | // on either `||` or `&&`, with both operands being a negation of some kind. | 10 | // on either `||` or `&&`. |
11 | // This means something of the form `!x` or `x != y`. | ||
12 | // | 11 | // |
13 | // ``` | 12 | // ``` |
14 | // fn main() { | 13 | // fn main() { |
15 | // if x != 4 ||$0 !y {} | 14 | // if x != 4 ||$0 y < 3.14 {} |
16 | // } | 15 | // } |
17 | // ``` | 16 | // ``` |
18 | // -> | 17 | // -> |
19 | // ``` | 18 | // ``` |
20 | // fn main() { | 19 | // fn main() { |
21 | // if !(x == 4 && y) {} | 20 | // if !(x == 4 && !(y < 3.14)) {} |
22 | // } | 21 | // } |
23 | // ``` | 22 | // ``` |
24 | pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 23 | pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
@@ -33,11 +32,11 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
33 | 32 | ||
34 | let lhs = expr.lhs()?; | 33 | let lhs = expr.lhs()?; |
35 | let lhs_range = lhs.syntax().text_range(); | 34 | let lhs_range = lhs.syntax().text_range(); |
36 | let not_lhs = invert_boolean_expression(lhs); | 35 | let not_lhs = invert_boolean_expression(&ctx.sema, lhs); |
37 | 36 | ||
38 | let rhs = expr.rhs()?; | 37 | let rhs = expr.rhs()?; |
39 | let rhs_range = rhs.syntax().text_range(); | 38 | let rhs_range = rhs.syntax().text_range(); |
40 | let not_rhs = invert_boolean_expression(rhs); | 39 | let not_rhs = invert_boolean_expression(&ctx.sema, rhs); |
41 | 40 | ||
42 | acc.add( | 41 | acc.add( |
43 | AssistId("apply_demorgan", AssistKind::RefactorRewrite), | 42 | AssistId("apply_demorgan", AssistKind::RefactorRewrite), |
@@ -62,10 +61,77 @@ fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> { | |||
62 | 61 | ||
63 | #[cfg(test)] | 62 | #[cfg(test)] |
64 | mod tests { | 63 | mod tests { |
64 | use ide_db::helpers::FamousDefs; | ||
65 | |||
65 | use super::*; | 66 | use super::*; |
66 | 67 | ||
67 | use crate::tests::{check_assist, check_assist_not_applicable}; | 68 | use crate::tests::{check_assist, check_assist_not_applicable}; |
68 | 69 | ||
70 | const ORDABLE_FIXTURE: &'static str = r" | ||
71 | //- /lib.rs deps:core crate:ordable | ||
72 | struct NonOrderable; | ||
73 | struct Orderable; | ||
74 | impl core::cmp::Ord for Orderable {} | ||
75 | "; | ||
76 | |||
77 | fn check(ra_fixture_before: &str, ra_fixture_after: &str) { | ||
78 | let before = &format!( | ||
79 | "//- /main.rs crate:main deps:core,ordable\n{}\n{}{}", | ||
80 | ra_fixture_before, | ||
81 | FamousDefs::FIXTURE, | ||
82 | ORDABLE_FIXTURE | ||
83 | ); | ||
84 | check_assist(apply_demorgan, before, &format!("{}\n", ra_fixture_after)); | ||
85 | } | ||
86 | |||
87 | #[test] | ||
88 | fn demorgan_handles_leq() { | ||
89 | check( | ||
90 | r"use ordable::Orderable; | ||
91 | fn f() { | ||
92 | Orderable < Orderable &&$0 Orderable <= Orderable | ||
93 | }", | ||
94 | r"use ordable::Orderable; | ||
95 | fn f() { | ||
96 | !(Orderable >= Orderable || Orderable > Orderable) | ||
97 | }", | ||
98 | ); | ||
99 | check( | ||
100 | r"use ordable::NonOrderable; | ||
101 | fn f() { | ||
102 | NonOrderable < NonOrderable &&$0 NonOrderable <= NonOrderable | ||
103 | }", | ||
104 | r"use ordable::NonOrderable; | ||
105 | fn f() { | ||
106 | !(!(NonOrderable < NonOrderable) || !(NonOrderable <= NonOrderable)) | ||
107 | }", | ||
108 | ); | ||
109 | } | ||
110 | |||
111 | #[test] | ||
112 | fn demorgan_handles_geq() { | ||
113 | check( | ||
114 | r"use ordable::Orderable; | ||
115 | fn f() { | ||
116 | Orderable > Orderable &&$0 Orderable >= Orderable | ||
117 | }", | ||
118 | r"use ordable::Orderable; | ||
119 | fn f() { | ||
120 | !(Orderable <= Orderable || Orderable < Orderable) | ||
121 | }", | ||
122 | ); | ||
123 | check( | ||
124 | r"use ordable::NonOrderable; | ||
125 | fn f() { | ||
126 | Orderable > Orderable &&$0 Orderable >= Orderable | ||
127 | }", | ||
128 | r"use ordable::NonOrderable; | ||
129 | fn f() { | ||
130 | !(!(Orderable > Orderable) || !(Orderable >= Orderable)) | ||
131 | }", | ||
132 | ); | ||
133 | } | ||
134 | |||
69 | #[test] | 135 | #[test] |
70 | fn demorgan_turns_and_into_or() { | 136 | fn demorgan_turns_and_into_or() { |
71 | check_assist(apply_demorgan, "fn f() { !x &&$0 !x }", "fn f() { !(x || x) }") | 137 | check_assist(apply_demorgan, "fn f() { !x &&$0 !x }", "fn f() { !(x || x) }") |
diff --git a/crates/ide_assists/src/handlers/early_return.rs b/crates/ide_assists/src/handlers/early_return.rs index 6b87c3c05..9e0918477 100644 --- a/crates/ide_assists/src/handlers/early_return.rs +++ b/crates/ide_assists/src/handlers/early_return.rs | |||
@@ -111,7 +111,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) | |||
111 | let new_expr = { | 111 | let new_expr = { |
112 | let then_branch = | 112 | let then_branch = |
113 | make::block_expr(once(make::expr_stmt(early_expression).into()), None); | 113 | make::block_expr(once(make::expr_stmt(early_expression).into()), None); |
114 | let cond = invert_boolean_expression(cond_expr); | 114 | let cond = invert_boolean_expression(&ctx.sema, cond_expr); |
115 | make::expr_if(make::condition(cond, None), then_branch, None) | 115 | make::expr_if(make::condition(cond, None), then_branch, None) |
116 | .indent(if_indent_level) | 116 | .indent(if_indent_level) |
117 | }; | 117 | }; |
diff --git a/crates/ide_assists/src/handlers/invert_if.rs b/crates/ide_assists/src/handlers/invert_if.rs index 5b69dafd4..b131dc205 100644 --- a/crates/ide_assists/src/handlers/invert_if.rs +++ b/crates/ide_assists/src/handlers/invert_if.rs | |||
@@ -50,7 +50,7 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | acc.add(AssistId("invert_if", AssistKind::RefactorRewrite), "Invert if", if_range, |edit| { | 52 | acc.add(AssistId("invert_if", AssistKind::RefactorRewrite), "Invert if", if_range, |edit| { |
53 | let flip_cond = invert_boolean_expression(cond.clone()); | 53 | let flip_cond = invert_boolean_expression(&ctx.sema, cond.clone()); |
54 | edit.replace_ast(cond, flip_cond); | 54 | edit.replace_ast(cond, flip_cond); |
55 | 55 | ||
56 | let else_node = else_block.syntax(); | 56 | let else_node = else_block.syntax(); |