From be9921779231a78f353e815e1edf41b4d9d8b6e0 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Fri, 20 Sep 2024 16:09:53 -0700 Subject: [PATCH] Extend MissingOverride to require @Override on "an explicitly declared accessor method for a record component" PiperOrigin-RevId: 677005515 --- .../bugpatterns/MissingOverride.java | 24 +++++++++++++++++ .../bugpatterns/MissingOverrideTest.java | 26 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/MissingOverride.java b/core/src/main/java/com/google/errorprone/bugpatterns/MissingOverride.java index 124573d266b..0977a47762d 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/MissingOverride.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/MissingOverride.java @@ -16,11 +16,14 @@ package com.google.errorprone.bugpatterns; +import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.errorprone.BugPattern.SeverityLevel.WARNING; import static com.google.errorprone.matchers.Description.NO_MATCH; +import static com.google.errorprone.util.ASTHelpers.getEnclosedElements; import static com.google.errorprone.util.ASTHelpers.hasAnnotation; import static com.google.errorprone.util.ASTHelpers.streamSuperMethods; +import com.google.common.collect.ImmutableSet; import com.google.errorprone.BugPattern; import com.google.errorprone.BugPattern.StandardTags; import com.google.errorprone.ErrorProneFlags; @@ -30,6 +33,8 @@ import com.google.errorprone.matchers.Description; import com.google.errorprone.util.ASTHelpers; import com.sun.source.tree.MethodTree; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.util.Name; import javax.inject.Inject; import javax.lang.model.element.Modifier; @@ -61,6 +66,25 @@ public Description matchMethod(MethodTree tree, VisitorState state) { if (ignoreInterfaceOverrides && sym.enclClass().isInterface()) { return NO_MATCH; } + if (ASTHelpers.isRecord(sym.owner) + && sym.getModifiers().contains(Modifier.PUBLIC) + && sym.getParameters().isEmpty()) { + ImmutableSet components = + getEnclosedElements(sym.owner).stream() + .filter(ASTHelpers::isRecord) + .map(Symbol::getSimpleName) + .collect(toImmutableSet()); + if (components.contains(sym.getSimpleName())) { + return buildDescription(tree) + .addFix(SuggestedFix.prefixWith(tree, "@Override ")) + .setMessage( + String.format( + "%s is an explicitly declared accessor method for a record component; expected" + + " @Override", + sym.getSimpleName())) + .build(); + } + } return streamSuperMethods(sym, state.getTypes()) .findFirst() .filter(unused -> ASTHelpers.getGeneratedBy(state).isEmpty()) diff --git a/core/src/test/java/com/google/errorprone/bugpatterns/MissingOverrideTest.java b/core/src/test/java/com/google/errorprone/bugpatterns/MissingOverrideTest.java index 52887c875f4..2618bddfcb7 100644 --- a/core/src/test/java/com/google/errorprone/bugpatterns/MissingOverrideTest.java +++ b/core/src/test/java/com/google/errorprone/bugpatterns/MissingOverrideTest.java @@ -16,6 +16,8 @@ package com.google.errorprone.bugpatterns; +import static com.google.common.truth.TruthJUnit.assume; + import com.google.common.collect.ImmutableList; import com.google.errorprone.CompilationTestHelper; import org.junit.Test; @@ -190,4 +192,28 @@ public interface Test extends Super { """) .doTest(); } + + @Test + public void explicitRecordAccessor() { + assume().that(Runtime.version().feature()).isAtLeast(16); + + compilationHelper + .addSourceLines( + "Baz.java", + """ + public record Baz(int x) { + // BUG: Diagnostic contains: x is an explicitly declared accessor method + public int x() { + return x; + } + public int x(int y) { + return y; + } + public int y() { + return x; + } + } + """) + .doTest(); + } }