From 9d6f8b4abb4275354f421f07f43ce1fbd648c7d7 Mon Sep 17 00:00:00 2001 From: Patrick Koenig Date: Tue, 19 Apr 2022 20:39:31 -0700 Subject: [PATCH] Add check for Immutables reference equality (#2210) --- README.md | 1 + .../ImmutablesReferenceEquality.java | 49 +++++++++++++++++++ .../ImmutablesReferenceEqualityTest.java | 42 ++++++++++++++++ changelog/@unreleased/pr-2210.v2.yml | 6 +++ 4 files changed, 98 insertions(+) create mode 100644 baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/ImmutablesReferenceEquality.java create mode 100644 baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/ImmutablesReferenceEqualityTest.java create mode 100644 changelog/@unreleased/pr-2210.v2.yml diff --git a/README.md b/README.md index 3025467f5..e1dd72637 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,7 @@ Safe Logging can be found at [github.com/palantir/safe-logging](https://github.c - `OptionalFlatMapOfNullable`: Optional.map functions may return null to safely produce an empty result. - `ExtendsErrorOrThrowable`: Avoid extending Error (or subclasses of it) or Throwable directly. - `ImmutablesStyle`: Disallow the use of inline immutables style annotations to avoid forcing compile dependencies on consumers. +- `ImmutablesReferenceEquality`: Comparison of Immutables value using reference equality instead of value equality. - `TooManyArguments`: Prefer Interface that take few arguments rather than many. - `ObjectsHashCodeUnnecessaryVarargs`: java.util.Objects.hash(non-varargs) should be replaced with java.util.Objects.hashCode(value) to avoid unnecessary varargs array allocations. - `PreferStaticLoggers`: Prefer static loggers over instance loggers. diff --git a/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/ImmutablesReferenceEquality.java b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/ImmutablesReferenceEquality.java new file mode 100644 index 000000000..f1aa52ad0 --- /dev/null +++ b/baseline-error-prone/src/main/java/com/palantir/baseline/errorprone/ImmutablesReferenceEquality.java @@ -0,0 +1,49 @@ +/* + * (c) Copyright 2022 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.palantir.baseline.errorprone; + +import com.google.auto.service.AutoService; +import com.google.errorprone.BugPattern; +import com.google.errorprone.BugPattern.LinkType; +import com.google.errorprone.BugPattern.SeverityLevel; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.AbstractReferenceEquality; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.util.ASTHelpers; +import com.sun.source.tree.ExpressionTree; +import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Type; + +@AutoService(BugChecker.class) +@BugPattern( + linkType = LinkType.CUSTOM, + link = "https://github.com/palantir/gradle-baseline#baseline-error-prone-checks", + severity = SeverityLevel.ERROR, + summary = "Comparison of Immutables value using reference equality instead of value equality.") +public final class ImmutablesReferenceEquality extends AbstractReferenceEquality { + + @Override + protected boolean matchArgument(ExpressionTree tree, VisitorState state) { + Type type = ASTHelpers.getType(tree); + if (!(type.tsym instanceof ClassSymbol)) { + return false; + } + + ClassSymbol symbol = (ClassSymbol) type.tsym; + + return ASTHelpers.hasAnnotation(symbol, "org.immutables.value.Value.Immutable", state); + } +} diff --git a/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/ImmutablesReferenceEqualityTest.java b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/ImmutablesReferenceEqualityTest.java new file mode 100644 index 000000000..ce3515750 --- /dev/null +++ b/baseline-error-prone/src/test/java/com/palantir/baseline/errorprone/ImmutablesReferenceEqualityTest.java @@ -0,0 +1,42 @@ +/* + * (c) Copyright 2022 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.palantir.baseline.errorprone; + +import com.google.errorprone.CompilationTestHelper; +import org.junit.jupiter.api.Test; + +public class ImmutablesReferenceEqualityTest { + + @Test + public void test() { + helper().addSourceLines( + "Test.java", + "import org.immutables.value.Value;", + "class Test {", + " static boolean f(Foo foo1, Foo foo2) {", + " // BUG: Diagnostic contains: foo1.equals(foo2)", + " return foo1 == foo2;", + " }", + " @Value.Immutable", + " interface Foo {}", + "}") + .doTest(); + } + + private CompilationTestHelper helper() { + return CompilationTestHelper.newInstance(ImmutablesReferenceEquality.class, getClass()); + } +} diff --git a/changelog/@unreleased/pr-2210.v2.yml b/changelog/@unreleased/pr-2210.v2.yml new file mode 100644 index 000000000..504a54263 --- /dev/null +++ b/changelog/@unreleased/pr-2210.v2.yml @@ -0,0 +1,6 @@ +type: improvement +improvement: + description: Add `ImmutablesReferenceEquality` check that checks for comparison + of Immutables values using reference equality. + links: + - https://github.com/palantir/gradle-baseline/pull/2210