diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/EqualityRules.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/EqualityRules.java index 7d5f57c234..6f5da60794 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/EqualityRules.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/EqualityRules.java @@ -1,5 +1,6 @@ package tech.picnic.errorprone.refasterrules; +import static java.util.function.Predicate.isEqual; import static java.util.function.Predicate.not; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -19,9 +20,9 @@ final class EqualityRules { private EqualityRules() {} - /** Prefer reference-based quality for enums. */ - // Primitive value comparisons are not listed, because Error Prone flags those out of the box. - static final class PrimitiveOrReferenceEquality> { + /** Prefer reference-based equality for enums. */ + // Primitive value comparisons are not matched, because Error Prone flags those out of the box. + static final class EnumReferenceEquality> { /** * Enums can be compared by reference. It is safe to do so even in the face of refactorings, * because if the type is ever converted to a non-enum, then Error-Prone will complain about any @@ -43,6 +44,19 @@ boolean after(T a, T b) { } } + /** Prefer reference-based equality for enums. */ + static final class EnumReferenceEqualityLambda> { + @BeforeTemplate + Predicate before(T e) { + return Refaster.anyOf(isEqual(e), e::equals); + } + + @AfterTemplate + Predicate after(T e) { + return v -> v == e; + } + } + /** Prefer {@link Object#equals(Object)} over the equivalent lambda function. */ // XXX: As it stands, this rule is a special case of what `MethodReferenceUsage` tries to achieve. // If/when `MethodReferenceUsage` becomes production ready, we should simply drop this check. diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/EqualityRulesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/EqualityRulesTestInput.java index 7cd4e3bfb4..986dabad17 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/EqualityRulesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/EqualityRulesTestInput.java @@ -1,5 +1,6 @@ package tech.picnic.errorprone.refasterrules; +import static java.util.function.Predicate.isEqual; import static java.util.function.Predicate.not; import com.google.common.collect.BoundType; @@ -14,10 +15,10 @@ final class EqualityRulesTest implements RefasterRuleCollectionTestCase { @Override public ImmutableSet elidedTypesAndStaticImports() { - return ImmutableSet.of(Objects.class, Optional.class, not(null)); + return ImmutableSet.of(Objects.class, Optional.class, isEqual(null), not(null)); } - ImmutableSet testPrimitiveOrReferenceEquality() { + ImmutableSet testEnumReferenceEquality() { return ImmutableSet.of( RoundingMode.UP.equals(RoundingMode.DOWN), Objects.equals(RoundingMode.UP, RoundingMode.DOWN), @@ -27,6 +28,10 @@ ImmutableSet testPrimitiveOrReferenceEquality() { RoundingMode.UP.ordinal() != RoundingMode.DOWN.ordinal()); } + ImmutableSet> testEnumReferenceEqualityLambda() { + return ImmutableSet.of(isEqual(RoundingMode.DOWN), RoundingMode.UP::equals); + } + boolean testEqualsPredicate() { // XXX: When boxing is involved this rule seems to break. Example: // Stream.of(1).anyMatch(e -> Integer.MIN_VALUE.equals(e)); diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/EqualityRulesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/EqualityRulesTestOutput.java index 0b8af555a7..b89decfb0d 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/EqualityRulesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/EqualityRulesTestOutput.java @@ -1,5 +1,6 @@ package tech.picnic.errorprone.refasterrules; +import static java.util.function.Predicate.isEqual; import static java.util.function.Predicate.not; import com.google.common.collect.BoundType; @@ -14,10 +15,10 @@ final class EqualityRulesTest implements RefasterRuleCollectionTestCase { @Override public ImmutableSet elidedTypesAndStaticImports() { - return ImmutableSet.of(Objects.class, Optional.class, not(null)); + return ImmutableSet.of(Objects.class, Optional.class, isEqual(null), not(null)); } - ImmutableSet testPrimitiveOrReferenceEquality() { + ImmutableSet testEnumReferenceEquality() { return ImmutableSet.of( RoundingMode.UP == RoundingMode.DOWN, RoundingMode.UP == RoundingMode.DOWN, @@ -27,6 +28,10 @@ ImmutableSet testPrimitiveOrReferenceEquality() { RoundingMode.UP != RoundingMode.DOWN); } + ImmutableSet> testEnumReferenceEqualityLambda() { + return ImmutableSet.of(v -> v == RoundingMode.DOWN, v -> v == RoundingMode.UP); + } + boolean testEqualsPredicate() { // XXX: When boxing is involved this rule seems to break. Example: // Stream.of(1).anyMatch(e -> Integer.MIN_VALUE.equals(e));