Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring of boolean expressions, pushing negating in #53620

Open
Tracked by #55825
lukehutch opened this issue Sep 27, 2023 · 4 comments
Open
Tracked by #55825

Refactoring of boolean expressions, pushing negating in #53620

lukehutch opened this issue Sep 27, 2023 · 4 comments
Labels
analyzer-refactoring area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P3 A lower priority bug or feature request type-enhancement A request for a change that isn't a bug

Comments

@lukehutch
Copy link

Is your feature request related to a problem? Please describe.

Eclipse can push unary negation down into the following parenthetical expression, using De Morgan's laws. It would be great if the Dart language server could do this too. ("Invert if-expression" already exists, so the logic is already mostly written...)

Before:

if ((a || b || c) && !(a && b && c))

Insert the cursor right before or after '!' to initiate the "Push Down Negation" action.

After:

if ((a || b || c) && (!a || !b || !c))

In some cases, the parentheses will be needed after the transformation; in some cases, the parentheses won't be needed (it depends on precedence). (On a broader note, it would be nice if the Dart linter recognized unnecessary parentheses, but I digress...)

The reverse should also be possible: Any expression should be able to be selected, and an "Double-negate" action should be available, that parenthesizes and negates the selected expression, again using De Morgan's:

Before:

if (a || b || c) 

Select b || c and select the "Double-negate" action.

After:

if (a || !(!b && !c))

Although some thought will have to be given to this to respect precedence, for example if the expression was if (a && b || c) and b || c was selected for double-negation, this would violate precedence. So maybe this should only be able to be applied between boundaries with lower-precedence terms

(Also maybe a better name than "Double-negate" should be chosen -- "Pull up negation" to mirror "Push down negation"?)

  • Dart version and tooling diagnostic info (dart info): 3.1.2
  • Whether you are using Windows, macOS, or Linux (if applicable): Linux
@lrhn lrhn changed the title Create an issue Refactoring of boolean expressions, pushing negating in Sep 27, 2023
@lrhn lrhn added area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. analyzer-refactoring type-enhancement A request for a change that isn't a bug labels Sep 27, 2023
@lrhn
Copy link
Member

lrhn commented Sep 27, 2023

The "double-negate"/toggle on boolean operators should be applicable to any operator, respecting its precedence.
Applying it to || of (a && b || c) should just give (!(!(a && b) && !c)).

There's a number of changes and normalizations that can be applied to boolean expresions.
One could also put things into conjunctive or disjunctive normal forms.

@lukehutch
Copy link
Author

I mean, there's also Algebraic Normal Form, which I'm a big fan of, and it consists of only negation and XOR expressions, but there's a limit to how useful these forms are :)

But I agree that there should be a bigger range of transformations, normalizations, and simplifications available.

@bwilkerson
Copy link
Member

Thanks for the request! It's certainly something we could, and arguably should, add.

... it would be nice if the Dart linter recognized unnecessary parentheses ...

The lint unnecessary_parenthesis ought to do that. There are a few cases where the parentheses aren't required but that aren't reported because the general consensus is that they make the code more readable, but other than that ...

@pq pq added the P3 A lower priority bug or feature request label Sep 27, 2023
@lukehutch
Copy link
Author

Just wanted to point out that the code already exists to push negation down, because of the "Invert 'if' expression" refactoring capability. So the basic pushdown of negation should actually be a fairly simple change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer-refactoring area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P3 A lower priority bug or feature request type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

4 participants