aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ide_assists/src/handlers/apply_demorgan.rs67
-rw-r--r--crates/ide_assists/src/utils.rs27
-rw-r--r--crates/syntax/src/ast/make.rs7
3 files changed, 83 insertions, 18 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)]
63mod tests { 63mod 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
72struct NonOrderable;
73struct Orderable;
74impl 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;
91fn f() {
92 Orderable < Orderable &&$0 Orderable <= Orderable
93}",
94 r"use ordable::Orderable;
95fn f() {
96 !(Orderable >= Orderable || Orderable > Orderable)
97}",
98 );
99 check(
100 r"use ordable::NonOrderable;
101fn f() {
102 NonOrderable < NonOrderable &&$0 NonOrderable <= NonOrderable
103}",
104 r"use ordable::NonOrderable;
105fn f() {
106 !(!(NonOrderable < NonOrderable) || !(NonOrderable <= NonOrderable))
107}",
108 );
109 }
110
111 #[test]
112 fn demorgan_handles_geq() {
113 check(
114 r"use ordable::Orderable;
115fn f() {
116 Orderable > Orderable &&$0 Orderable >= Orderable
117}",
118 r"use ordable::Orderable;
119fn f() {
120 !(Orderable <= Orderable || Orderable < Orderable)
121}",
122 );
123 check(
124 r"use ordable::NonOrderable;
125fn f() {
126 Orderable > Orderable &&$0 Orderable >= Orderable
127}",
128 r"use ordable::NonOrderable;
129fn 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
269fn bin_impls_ord(sema: &Semantics<RootDatabase>, bin: &ast::BinExpr) -> bool { 269fn 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| {
278fn 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
290pub(crate) fn next_prev() -> impl Iterator<Item = Direction> { 285pub(crate) fn next_prev() -> impl Iterator<Item = Direction> {
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 5eee33545..b6c5de658 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -527,8 +527,11 @@ pub mod tokens {
527 527
528 use crate::{ast, AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken}; 528 use crate::{ast, AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken};
529 529
530 pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = 530 pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| {
531 Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2, !true, *p)\n;\n\n")); 531 SourceFile::parse(
532 "const C: <()>::Item = (1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p)\n;\n\n",
533 )
534 });
532 535
533 pub fn single_space() -> SyntaxToken { 536 pub fn single_space() -> SyntaxToken {
534 SOURCE_FILE 537 SOURCE_FILE