Skip to content

Commit

Permalink
Support simplifying negated binary expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
knutwannheden committed Oct 18, 2023
1 parent a9e347e commit b0dd924
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,62 @@ public class A {
);
}

@Test
void doubleNegationWithParentheses() {
rewriteRun(
java(
"""
public class A {
{
boolean a = !!(!(!true));
boolean b = !(!a);
}
}
""",
"""
public class A {
{
boolean a = true;
boolean b = a;
}
}
"""
)
);
}

@Test
void doubleNegatedBinaryWithParentheses() {
rewriteRun(
java(
"""
public class A {
{
boolean a1 = !(1 == 1);
boolean a2 = !(1 != 1);
boolean a3 = !(1 < 1);
boolean a4 = !(1 <= 1);
boolean a5 = !(1 > 1);
boolean a6 = !(1 >= 1);
}
}
""",
"""
public class A {
{
boolean a1 = 1 != 1;
boolean a2 = 1 == 1;
boolean a3 = 1 >= 1;
boolean a4 = 1 > 1;
boolean a5 = 1 <= 1;
boolean a6 = 1 < 1;
}
}
"""
)
);
}

@Test
void simplifyEqualsLiteralTrue() {
rewriteRun(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public J visitBinary(J.Binary binary, ExecutionContext ctx) {

@Override
public J postVisit(J tree, ExecutionContext ctx) {
J j = super.postVisit(tree, ctx);
J j = tree;
if (j instanceof J.Parentheses) {
j = new UnwrapParentheses<>((J.Parentheses<?>) j).visit(j, ctx, getCursor().getParentOrThrow());
}
Expand All @@ -124,12 +124,19 @@ public J visitUnary(J.Unary unary, ExecutionContext ctx) {
J.Unary asUnary = (J.Unary) j;

if (asUnary.getOperator() == J.Unary.Type.Not) {
if (isLiteralTrue(asUnary.getExpression())) {
j = ((J.Literal) asUnary.getExpression()).withValue(false).withValueSource("false");
} else if (isLiteralFalse(asUnary.getExpression())) {
j = ((J.Literal) asUnary.getExpression()).withValue(true).withValueSource("true");
} else if (asUnary.getExpression() instanceof J.Unary && ((J.Unary) asUnary.getExpression()).getOperator() == J.Unary.Type.Not) {
j = ((J.Unary) asUnary.getExpression()).getExpression();
Expression expr = asUnary.getExpression();
if (isLiteralTrue(expr)) {
j = ((J.Literal) expr).withValue(false).withValueSource("false");
} else if (isLiteralFalse(expr)) {
j = ((J.Literal) expr).withValue(true).withValueSource("true");
} else if (expr instanceof J.Unary && ((J.Unary) expr).getOperator() == J.Unary.Type.Not) {
j = ((J.Unary) expr).getExpression();
} else if (expr instanceof J.Parentheses && ((J.Parentheses<?>) expr).getTree() instanceof J.Binary) {
J.Binary binary = (J.Binary) ((J.Parentheses<?>) expr).getTree();
J.Binary.Type negated = negate(binary.getOperator());
if (negated != binary.getOperator()) {
j = binary.withOperator(negated);
}
}
}
if (asUnary != j) {
Expand All @@ -138,6 +145,25 @@ public J visitUnary(J.Unary unary, ExecutionContext ctx) {
return j;
}

private J.Binary.Type negate(J.Binary.Type operator) {
switch (operator) {
case LessThan:
return J.Binary.Type.GreaterThanOrEqual;
case GreaterThan:
return J.Binary.Type.LessThanOrEqual;
case LessThanOrEqual:
return J.Binary.Type.GreaterThan;
case GreaterThanOrEqual:
return J.Binary.Type.LessThan;
case Equal:
return J.Binary.Type.NotEqual;
case NotEqual:
return J.Binary.Type.Equal;
default:
return operator;
}
}

private final MethodMatcher isEmpty = new MethodMatcher("java.lang.String isEmpty()");

@Override
Expand Down Expand Up @@ -210,10 +236,10 @@ public Space visitSpace(Space space, Space.Location loc, Integer integer) {
/**
* Override this method to disable simplification of equals expressions,
* specifically for Kotlin while that is not yet part of the OpenRewrite/rewrite.
*
* <p>
* Comparing Kotlin nullable type `?` with tree/false can not be simplified,
* e.g. `X?.fun() == true` is not equivalent to `X?.fun()`
*
* <p>
* Subclasses will want to check if the `org.openrewrite.kotlin.marker.IsNullSafe`
* marker is present.
*
Expand Down

0 comments on commit b0dd924

Please sign in to comment.