diff options
Diffstat (limited to 'crates/ide_assists')
-rw-r--r-- | crates/ide_assists/src/handlers/apply_demorgan.rs | 67 | ||||
-rw-r--r-- | crates/ide_assists/src/utils.rs | 27 |
2 files changed, 78 insertions, 16 deletions
diff --git a/crates/ide_assists/src/handlers/apply_demorgan.rs b/crates/ide_assists/src/handlers/apply_demorgan.rs index 3cd6699c3..6997ea048 100644 --- a/crates/ide_assists/src/handlers/apply_demorgan.rs +++ b/crates/ide_assists/src/handlers/apply_demorgan.rs | |||
@@ -61,10 +61,77 @@ fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> { | |||
61 | 61 | ||
62 | #[cfg(test)] | 62 | #[cfg(test)] |
63 | mod tests { | 63 | mod tests { |
64 | use ide_db::helpers::FamousDefs; | ||
65 | |||
64 | use super::*; | 66 | use super::*; |
65 | 67 | ||
66 | use crate::tests::{check_assist, check_assist_not_applicable}; | 68 | use crate::tests::{check_assist, check_assist_not_applicable}; |
67 | 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 | |||
68 | #[test] | 135 | #[test] |
69 | fn demorgan_turns_and_into_or() { | 136 | fn demorgan_turns_and_into_or() { |
70 | 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/utils.rs b/crates/ide_assists/src/utils.rs index 38ed74673..276792bc1 100644 --- a/crates/ide_assists/src/utils.rs +++ b/crates/ide_assists/src/utils.rs | |||
@@ -267,24 +267,19 @@ fn invert_special_case(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Opti | |||
267 | } | 267 | } |
268 | 268 | ||
269 | fn bin_impls_ord(sema: &Semantics<RootDatabase>, bin: &ast::BinExpr) -> bool { | 269 | fn bin_impls_ord(sema: &Semantics<RootDatabase>, bin: &ast::BinExpr) -> bool { |
270 | if let (Some(lhs), Some(rhs)) = (bin.lhs(), bin.rhs()) { | 270 | match ( |
271 | return sema.type_of_expr(&lhs) == sema.type_of_expr(&rhs) | 271 | bin.lhs().and_then(|lhs| sema.type_of_expr(&lhs)), |
272 | && impls_ord(sema, &lhs) | 272 | bin.rhs().and_then(|rhs| sema.type_of_expr(&rhs)), |
273 | && impls_ord(sema, &rhs); | 273 | ) { |
274 | } | 274 | (Some(lhs_ty), Some(rhs_ty)) if lhs_ty == rhs_ty => { |
275 | false | 275 | let krate = sema.scope(bin.syntax()).module().map(|it| it.krate()); |
276 | } | 276 | let ord_trait = FamousDefs(sema, krate).core_cmp_Ord(); |
277 | 277 | ord_trait.map_or(false, |ord_trait| { | |
278 | fn impls_ord(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> bool { | 278 | lhs_ty.autoderef(sema.db).any(|ty| ty.impls_trait(sema.db, ord_trait, &[])) |
279 | let krate = sema.scope(expr.syntax()).module().map(|it| it.krate()); | 279 | }) |
280 | let famous_defs = FamousDefs(&sema, krate); | ||
281 | |||
282 | if let Some(ty) = sema.type_of_expr(expr) { | ||
283 | if let Some(ord_trait) = famous_defs.core_cmp_Ord() { | ||
284 | return ty.autoderef(sema.db).any(|ty| ty.impls_trait(sema.db, ord_trait, &[])); | ||
285 | } | 280 | } |
281 | _ => false, | ||
286 | } | 282 | } |
287 | false | ||
288 | } | 283 | } |
289 | 284 | ||
290 | pub(crate) fn next_prev() -> impl Iterator<Item = Direction> { | 285 | pub(crate) fn next_prev() -> impl Iterator<Item = Direction> { |