Skip to content

Commit

Permalink
Fix for detector UncallableMethodOfAnonymousClass to not report unu…
Browse files Browse the repository at this point in the history
…sed methods of method-local enumerations and records

During compilation, enumerations and records are turned into Java classes with some auto-generated methods. Some of these methods are called by the code but some of them not. However, this is not a programming error or bad practice, these methods must not be considered as dead code because their generation cannot be prevented. Therefore no bug report `UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS` must be issued to such classes even if they are defined inside a method. See issue ([spotbugs#2120](spotbugs#2120))
  • Loading branch information
Ádám Balogh committed Sep 9, 2022
1 parent b119457 commit aecf8b7
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Currently the versioning policy of this project follows [Semantic Versioning v2.
## Unreleased - 2022-??-??
### Fixed
- Fixed detector `DontUseFloatsAsLoopCounters` to prevent false positives. ([#2126](https://github.com/spotbugs/spotbugs/issues/2126))
- Fixed detector `UncallableMethodOfAnonymousClass` to not report unused methods of method-local enumerations and records ([#2120](https://github.com/spotbugs/spotbugs/issues/2120))

## 4.7.2 - 2022-09-02
### Fixed
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package edu.umd.cs.findbugs.detect;

import org.junit.Before;
import org.junit.Test;

import edu.umd.cs.findbugs.AbstractIntegrationTest;
import edu.umd.cs.findbugs.test.matcher.BugInstanceMatcher;
import edu.umd.cs.findbugs.test.matcher.BugInstanceMatcherBuilder;

import static edu.umd.cs.findbugs.test.CountMatcher.containsExactly;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeThat;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;

public class Issue2120Test extends AbstractIntegrationTest {
@Before
public void verifyJavaVersion() {
assumeFalse(System.getProperty("java.specification.version").startsWith("1."));
int javaVersion = Integer.parseInt(System.getProperty("java.specification.version"));
assumeThat(javaVersion, is(greaterThanOrEqualTo(11)));
}

@Test
public void test() {
performAnalysis("../java14/Issue2120.class");
BugInstanceMatcher matcher = new BugInstanceMatcherBuilder()
.bugType("UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS").build();
assertThat(getBugCollection(), containsExactly(0, matcher));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ public UncallableMethodOfAnonymousClass(BugReporter bugReporter) {

@Override
public void visitJavaClass(JavaClass obj) {
if (Values.DOTTED_JAVA_LANG_ENUM.equals(obj.getSuperclassName()) ||
Values.DOTTED_JAVA_LANG_RECORD.equals(obj.getSuperclassName())) {
return;
}

try {
obj.getSuperClass();
} catch (ClassNotFoundException e) {
Expand Down
4 changes: 4 additions & 0 deletions spotbugs/src/main/java/edu/umd/cs/findbugs/util/Values.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public final class Values {
@DottedClassName
public static final String DOTTED_JAVA_LANG_STRINGBUFFER = "java.lang.StringBuffer";
@DottedClassName
public static final String DOTTED_JAVA_LANG_ENUM = "java.lang.Enum";
@DottedClassName
public static final String DOTTED_JAVA_LANG_RECORD = "java.lang.Record";
@DottedClassName
public static final String DOTTED_JAVA_IO_FILE = "java.io.File";
@DottedClassName
public static final String DOTTED_JAVA_NIO_PATH = "java.nio.file.Path";
Expand Down
12 changes: 12 additions & 0 deletions spotbugsTestCases/src/java14/Issue2120.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
public class Issue2120 {
static void method() {
record MyRecord(int from, int to) { /**/ }

enum MyEnum {
RED, BLUE;
}

System.out.println(new MyRecord(1, 2));
System.out.println(MyEnum.RED);
}
}

0 comments on commit aecf8b7

Please sign in to comment.