From f7a4a87de2840789e12722afc7df9f4db2db013c Mon Sep 17 00:00:00 2001 From: lbrande Date: Fri, 19 Feb 2021 14:48:07 +0100 Subject: De Morgan's Law assist now correctly parenthesizes binary expressions. --- crates/ide_assists/src/handlers/apply_demorgan.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'crates/ide_assists/src/handlers') diff --git a/crates/ide_assists/src/handlers/apply_demorgan.rs b/crates/ide_assists/src/handlers/apply_demorgan.rs index ed4d11455..e478ff2ce 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 // Apply https://en.wikipedia.org/wiki/De_Morgan%27s_laws[De Morgan's law]. // This transforms expressions of the form `!l || !r` into `!(l && r)`. // This also works with `&&`. This assist can only be applied with the cursor -// on either `||` or `&&`, with both operands being a negation of some kind. -// This means something of the form `!x` or `x != y`. +// on either `||` or `&&`. // // ``` // fn main() { -// if x != 4 ||$0 !y {} +// if x != 4 ||$0 y < 3 {} // } // ``` // -> // ``` // fn main() { -// if !(x == 4 && y) {} +// if !(x == 4 && !(y < 3)) {} // } // ``` pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { -- cgit v1.2.3 From 9db970ee082e315cfa04db163fe2e0268b618531 Mon Sep 17 00:00:00 2001 From: lbrande Date: Mon, 22 Feb 2021 16:23:42 +0100 Subject: De Morgan's Law assist now correctly inverts <, <=, >, >=. --- crates/ide_assists/src/handlers/apply_demorgan.rs | 8 ++++---- crates/ide_assists/src/handlers/early_return.rs | 2 +- crates/ide_assists/src/handlers/invert_if.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'crates/ide_assists/src/handlers') diff --git a/crates/ide_assists/src/handlers/apply_demorgan.rs b/crates/ide_assists/src/handlers/apply_demorgan.rs index e478ff2ce..3cd6699c3 100644 --- a/crates/ide_assists/src/handlers/apply_demorgan.rs +++ b/crates/ide_assists/src/handlers/apply_demorgan.rs @@ -11,13 +11,13 @@ use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKin // // ``` // fn main() { -// if x != 4 ||$0 y < 3 {} +// if x != 4 ||$0 y < 3.14 {} // } // ``` // -> // ``` // fn main() { -// if !(x == 4 && !(y < 3)) {} +// if !(x == 4 && !(y < 3.14)) {} // } // ``` pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { @@ -32,11 +32,11 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<( let lhs = expr.lhs()?; let lhs_range = lhs.syntax().text_range(); - let not_lhs = invert_boolean_expression(lhs); + let not_lhs = invert_boolean_expression(&ctx.sema, lhs); let rhs = expr.rhs()?; let rhs_range = rhs.syntax().text_range(); - let not_rhs = invert_boolean_expression(rhs); + let not_rhs = invert_boolean_expression(&ctx.sema, rhs); acc.add( AssistId("apply_demorgan", AssistKind::RefactorRewrite), 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) let new_expr = { let then_branch = make::block_expr(once(make::expr_stmt(early_expression).into()), None); - let cond = invert_boolean_expression(cond_expr); + let cond = invert_boolean_expression(&ctx.sema, cond_expr); make::expr_if(make::condition(cond, None), then_branch, None) .indent(if_indent_level) }; 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<()> { }; acc.add(AssistId("invert_if", AssistKind::RefactorRewrite), "Invert if", if_range, |edit| { - let flip_cond = invert_boolean_expression(cond.clone()); + let flip_cond = invert_boolean_expression(&ctx.sema, cond.clone()); edit.replace_ast(cond, flip_cond); let else_node = else_block.syntax(); -- cgit v1.2.3 From 694f7a7e9f90cc435afcaade23b5908728d17ed2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 24 Feb 2021 11:42:32 +0100 Subject: Add tests for apply_demorgan --- crates/ide_assists/src/handlers/apply_demorgan.rs | 67 +++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'crates/ide_assists/src/handlers') 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> { #[cfg(test)] mod tests { + use ide_db::helpers::FamousDefs; + use super::*; use crate::tests::{check_assist, check_assist_not_applicable}; + const ORDABLE_FIXTURE: &'static str = r" +//- /lib.rs deps:core crate:ordable +struct NonOrderable; +struct Orderable; +impl core::cmp::Ord for Orderable {} +"; + + fn check(ra_fixture_before: &str, ra_fixture_after: &str) { + let before = &format!( + "//- /main.rs crate:main deps:core,ordable\n{}\n{}{}", + ra_fixture_before, + FamousDefs::FIXTURE, + ORDABLE_FIXTURE + ); + check_assist(apply_demorgan, before, &format!("{}\n", ra_fixture_after)); + } + + #[test] + fn demorgan_handles_leq() { + check( + r"use ordable::Orderable; +fn f() { + Orderable < Orderable &&$0 Orderable <= Orderable +}", + r"use ordable::Orderable; +fn f() { + !(Orderable >= Orderable || Orderable > Orderable) +}", + ); + check( + r"use ordable::NonOrderable; +fn f() { + NonOrderable < NonOrderable &&$0 NonOrderable <= NonOrderable +}", + r"use ordable::NonOrderable; +fn f() { + !(!(NonOrderable < NonOrderable) || !(NonOrderable <= NonOrderable)) +}", + ); + } + + #[test] + fn demorgan_handles_geq() { + check( + r"use ordable::Orderable; +fn f() { + Orderable > Orderable &&$0 Orderable >= Orderable +}", + r"use ordable::Orderable; +fn f() { + !(Orderable <= Orderable || Orderable < Orderable) +}", + ); + check( + r"use ordable::NonOrderable; +fn f() { + Orderable > Orderable &&$0 Orderable >= Orderable +}", + r"use ordable::NonOrderable; +fn f() { + !(!(Orderable > Orderable) || !(Orderable >= Orderable)) +}", + ); + } + #[test] fn demorgan_turns_and_into_or() { check_assist(apply_demorgan, "fn f() { !x &&$0 !x }", "fn f() { !(x || x) }") -- cgit v1.2.3