Skip to content

Commit 694f7a7

Browse files
committed
Add tests for apply_demorgan
1 parent 9db970e commit 694f7a7

File tree

3 files changed

+83
-18
lines changed

3 files changed

+83
-18
lines changed

crates/ide_assists/src/handlers/apply_demorgan.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,77 @@ fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> {
6161

6262
#[cfg(test)]
6363
mod tests {
64+
use ide_db::helpers::FamousDefs;
65+
6466
use super::*;
6567

6668
use crate::tests::{check_assist, check_assist_not_applicable};
6769

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+
68135
#[test]
69136
fn demorgan_turns_and_into_or() {
70137
check_assist(apply_demorgan, "fn f() { !x &&$0 !x }", "fn f() { !(x || x) }")

crates/ide_assists/src/utils.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -267,24 +267,19 @@ fn invert_special_case(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Opti
267267
}
268268

269269
fn bin_impls_ord(sema: &Semantics<RootDatabase>, bin: &ast::BinExpr) -> bool {
270-
if let (Some(lhs), Some(rhs)) = (bin.lhs(), bin.rhs()) {
271-
return sema.type_of_expr(&lhs) == sema.type_of_expr(&rhs)
272-
&& impls_ord(sema, &lhs)
273-
&& impls_ord(sema, &rhs);
274-
}
275-
false
276-
}
277-
278-
fn impls_ord(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> bool {
279-
let krate = sema.scope(expr.syntax()).module().map(|it| it.krate());
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, &[]));
270+
match (
271+
bin.lhs().and_then(|lhs| sema.type_of_expr(&lhs)),
272+
bin.rhs().and_then(|rhs| sema.type_of_expr(&rhs)),
273+
) {
274+
(Some(lhs_ty), Some(rhs_ty)) if lhs_ty == rhs_ty => {
275+
let krate = sema.scope(bin.syntax()).module().map(|it| it.krate());
276+
let ord_trait = FamousDefs(sema, krate).core_cmp_Ord();
277+
ord_trait.map_or(false, |ord_trait| {
278+
lhs_ty.autoderef(sema.db).any(|ty| ty.impls_trait(sema.db, ord_trait, &[]))
279+
})
285280
}
281+
_ => false,
286282
}
287-
false
288283
}
289284

290285
pub(crate) fn next_prev() -> impl Iterator<Item = Direction> {

crates/syntax/src/ast/make.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,11 @@ pub mod tokens {
527527

528528
use crate::{ast, AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken};
529529

530-
pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> =
531-
Lazy::new(|| SourceFile::parse("const C: <()>::Item = (1 != 1, 2 == 2, !true, *p)\n;\n\n"));
530+
pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| {
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+
});
532535

533536
pub fn single_space() -> SyntaxToken {
534537
SOURCE_FILE

0 commit comments

Comments
 (0)