mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 08:11:25 +00:00
Compare commits
51 Commits
junie-init
...
sschroever
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
817bd685b0 | ||
|
|
f27dd279e5 | ||
|
|
ce4bcd00f2 | ||
|
|
3d45b4f1c6 | ||
|
|
49d06f47f0 | ||
|
|
b0549244fd | ||
|
|
a6f72ece0d | ||
|
|
288ef7af94 | ||
|
|
b6e17b5d54 | ||
|
|
ed4679ab09 | ||
|
|
87eec476ef | ||
|
|
95594c00a7 | ||
|
|
7adc5ab557 | ||
|
|
c71407af01 | ||
|
|
4453f66005 | ||
|
|
ceeccd3f55 | ||
|
|
89e49b118e | ||
|
|
943a409ec1 | ||
|
|
15622acfc2 | ||
|
|
9f39ac7942 | ||
|
|
9221f7f212 | ||
|
|
34024296a6 | ||
|
|
c3f952f12d | ||
|
|
19e4e17c88 | ||
|
|
73bea4aa90 | ||
|
|
2e2ce473b5 | ||
|
|
23450cb942 | ||
|
|
dbe72b4561 | ||
|
|
e220f0e65c | ||
|
|
68f6c328b3 | ||
|
|
ac88295c96 | ||
|
|
0ff590ef96 | ||
|
|
098e07dc3b | ||
|
|
327ab1e629 | ||
|
|
ccd6ae67a6 | ||
|
|
15e61b85a2 | ||
|
|
61dd2e72f2 | ||
|
|
41e59944c3 | ||
|
|
7ccf3e6b42 | ||
|
|
13a1cd2f4b | ||
|
|
24636372c8 | ||
|
|
6d3180df85 | ||
|
|
1d625f9f76 | ||
|
|
b9f2f8dd0d | ||
|
|
3f659cac50 | ||
|
|
890c8b23f3 | ||
|
|
c24e6cc25d | ||
|
|
1292f7121f | ||
|
|
cb4b973f7c | ||
|
|
f8251a7b7e | ||
|
|
cebb66479f |
35
.github/workflows/build-jdk11.yaml
vendored
Normal file
35
.github/workflows/build-jdk11.yaml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Build with JDK 17 and test against JDK 11
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [ master ]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
# We run the build twice: once against the original Error Prone
|
||||
# release, and once against the Picnic Error Prone fork. In both cases
|
||||
# the code is compiled using JDK 17, while the tests are executed
|
||||
# using JDK 11.
|
||||
- name: Check out code
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0
|
||||
with:
|
||||
java-version: |
|
||||
11.0.20
|
||||
17.0.8
|
||||
distribution: temurin
|
||||
cache: maven
|
||||
- name: Display build environment details
|
||||
run: mvn --version
|
||||
- name: Build project against vanilla Error Prone
|
||||
run: mvn -T1C install -Dsurefire.jdk-toolchain-version=11.0.20
|
||||
- name: Build project with self-check against Error Prone fork
|
||||
run: mvn -T1C clean verify -Perror-prone-fork -Dsurefire.jdk-toolchain-version=11.0.20 -s settings.xml
|
||||
- name: Remove installed project artifacts
|
||||
run: mvn build-helper:remove-project-artifact
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-22.04 ]
|
||||
jdk: [ 11.0.20, 17.0.8, 21.0.0 ]
|
||||
jdk: [ 17.0.8, 21.0.0 ]
|
||||
distribution: [ temurin ]
|
||||
experimental: [ false ]
|
||||
include:
|
||||
|
||||
18
README.md
18
README.md
@@ -233,17 +233,11 @@ Other highly relevant commands:
|
||||
against _all_ code in the current working directory. For more information
|
||||
check the [PIT Maven plugin][pitest-maven].
|
||||
|
||||
When running the project's tests in IntelliJ IDEA, you might see the following
|
||||
error:
|
||||
|
||||
```
|
||||
java: exporting a package from system module jdk.compiler is not allowed with --release
|
||||
```
|
||||
|
||||
If this happens, go to _Settings -> Build, Execution, Deployment -> Compiler ->
|
||||
Java Compiler_ and deselect the option _Use '--release' option for
|
||||
cross-compilation (Java 9 and later)_. See [IDEA-288052][idea-288052] for
|
||||
details.
|
||||
The `BugChecker` implementations provided by this project are tested using
|
||||
Error Prone's `CompilationTestHelper` and `BugCheckerRefactoringTestHelper`
|
||||
classes. These utilities accept text blocks containing inline Java source code.
|
||||
To ease modification of this inline source code, consider using IntelliJ IDEA's
|
||||
[language injection][idea-language-injection] feature.
|
||||
|
||||
## 💡 How it works
|
||||
|
||||
@@ -280,7 +274,7 @@ channel; please see our [security policy][security] for details.
|
||||
[github-actions-build-badge]: https://github.com/PicnicSupermarket/error-prone-support/actions/workflows/build.yml/badge.svg
|
||||
[github-actions-build-master]: https://github.com/PicnicSupermarket/error-prone-support/actions/workflows/build.yml?query=branch:master&event=push
|
||||
[google-java-format]: https://github.com/google/google-java-format
|
||||
[idea-288052]: https://youtrack.jetbrains.com/issue/IDEA-288052
|
||||
[idea-language-injection]: https://www.jetbrains.com/help/idea/using-language-injections.html
|
||||
[license-badge]: https://img.shields.io/github/license/PicnicSupermarket/error-prone-support
|
||||
[license]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/LICENSE.md
|
||||
[maven-central-badge]: https://img.shields.io/maven-central/v/tech.picnic.error-prone-support/error-prone-support?color=blue
|
||||
|
||||
@@ -125,8 +125,8 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
|
||||
}
|
||||
|
||||
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
|
||||
return receiver instanceof MethodInvocationTree
|
||||
? getClassUnderTest((MethodInvocationTree) receiver, state)
|
||||
return receiver instanceof MethodInvocationTree methodInvocation
|
||||
? getClassUnderTest(methodInvocation, state)
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
@@ -144,8 +144,8 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
|
||||
}
|
||||
|
||||
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
|
||||
if (receiver instanceof MethodInvocationTree) {
|
||||
extractIdentificationTestCases((MethodInvocationTree) receiver, sink, state);
|
||||
if (receiver instanceof MethodInvocationTree methodInvocation) {
|
||||
extractIdentificationTestCases(methodInvocation, sink, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,8 +174,8 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
|
||||
}
|
||||
|
||||
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
|
||||
if (receiver instanceof MethodInvocationTree) {
|
||||
extractReplacementTestCases((MethodInvocationTree) receiver, sink, state);
|
||||
if (receiver instanceof MethodInvocationTree methodInvocation) {
|
||||
extractReplacementTestCases(methodInvocation, sink, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ package tech.picnic.errorprone.documentation;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
@@ -15,92 +13,148 @@ final class BugPatternExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerWithoutAnnotation.java",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"public final class TestCheckerWithoutAnnotation extends BugChecker {}");
|
||||
"""
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
public final class TestCheckerWithoutAnnotation extends BugChecker {}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
|
||||
@Test
|
||||
void minimalBugPattern(@TempDir Path outputDirectory) throws IOException {
|
||||
void minimalBugPattern(@TempDir Path outputDirectory) {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"MinimalBugChecker.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import com.google.errorprone.BugPattern;",
|
||||
"import com.google.errorprone.BugPattern.SeverityLevel;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"@BugPattern(summary = \"MinimalBugChecker summary\", severity = SeverityLevel.ERROR)",
|
||||
"public final class MinimalBugChecker extends BugChecker {}");
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
verifyGeneratedFileContent(outputDirectory, "MinimalBugChecker");
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
@BugPattern(summary = "MinimalBugChecker summary", severity = SeverityLevel.ERROR)
|
||||
public final class MinimalBugChecker extends BugChecker {}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(
|
||||
outputDirectory,
|
||||
"MinimalBugChecker",
|
||||
"""
|
||||
{
|
||||
"fullyQualifiedName": "pkg.MinimalBugChecker",
|
||||
"name": "MinimalBugChecker",
|
||||
"altNames": [],
|
||||
"link": "",
|
||||
"tags": [],
|
||||
"summary": "MinimalBugChecker summary",
|
||||
"explanation": "",
|
||||
"severityLevel": "ERROR",
|
||||
"canDisable": true,
|
||||
"suppressionAnnotations": [
|
||||
"java.lang.SuppressWarnings"
|
||||
]
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
void completeBugPattern(@TempDir Path outputDirectory) throws IOException {
|
||||
void completeBugPattern(@TempDir Path outputDirectory) {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"CompleteBugChecker.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import com.google.errorprone.BugPattern;",
|
||||
"import com.google.errorprone.BugPattern.SeverityLevel;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"",
|
||||
"@BugPattern(",
|
||||
" name = \"OtherName\",",
|
||||
" summary = \"CompleteBugChecker summary\",",
|
||||
" linkType = BugPattern.LinkType.CUSTOM,",
|
||||
" link = \"https://error-prone.picnic.tech\",",
|
||||
" explanation = \"Example explanation\",",
|
||||
" severity = SeverityLevel.SUGGESTION,",
|
||||
" altNames = \"Check\",",
|
||||
" tags = BugPattern.StandardTags.SIMPLIFICATION,",
|
||||
" disableable = false,",
|
||||
" suppressionAnnotations = {BugPattern.class, Test.class})",
|
||||
"public final class CompleteBugChecker extends BugChecker {}");
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
verifyGeneratedFileContent(outputDirectory, "CompleteBugChecker");
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@BugPattern(
|
||||
name = "OtherName",
|
||||
summary = "CompleteBugChecker summary",
|
||||
linkType = BugPattern.LinkType.CUSTOM,
|
||||
link = "https://error-prone.picnic.tech",
|
||||
explanation = "Example explanation",
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
altNames = "Check",
|
||||
tags = BugPattern.StandardTags.SIMPLIFICATION,
|
||||
disableable = false,
|
||||
suppressionAnnotations = {BugPattern.class, Test.class})
|
||||
public final class CompleteBugChecker extends BugChecker {}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(
|
||||
outputDirectory,
|
||||
"CompleteBugChecker",
|
||||
"""
|
||||
{
|
||||
"fullyQualifiedName": "pkg.CompleteBugChecker",
|
||||
"name": "OtherName",
|
||||
"altNames": [
|
||||
"Check"
|
||||
],
|
||||
"link": "https://error-prone.picnic.tech",
|
||||
"tags": [
|
||||
"Simplification"
|
||||
],
|
||||
"summary": "CompleteBugChecker summary",
|
||||
"explanation": "Example explanation",
|
||||
"severityLevel": "SUGGESTION",
|
||||
"canDisable": false,
|
||||
"suppressionAnnotations": [
|
||||
"com.google.errorprone.BugPattern",
|
||||
"org.junit.jupiter.api.Test"
|
||||
]
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
void undocumentedSuppressionBugPattern(@TempDir Path outputDirectory) throws IOException {
|
||||
void undocumentedSuppressionBugPattern(@TempDir Path outputDirectory) {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"UndocumentedSuppressionBugPattern.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import com.google.errorprone.BugPattern;",
|
||||
"import com.google.errorprone.BugPattern.SeverityLevel;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"@BugPattern(",
|
||||
" summary = \"UndocumentedSuppressionBugPattern summary\",",
|
||||
" severity = SeverityLevel.WARNING,",
|
||||
" documentSuppression = false)",
|
||||
"public final class UndocumentedSuppressionBugPattern extends BugChecker {}");
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
verifyGeneratedFileContent(outputDirectory, "UndocumentedSuppressionBugPattern");
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
@BugPattern(
|
||||
summary = "UndocumentedSuppressionBugPattern summary",
|
||||
severity = SeverityLevel.WARNING,
|
||||
documentSuppression = false)
|
||||
public final class UndocumentedSuppressionBugPattern extends BugChecker {}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(
|
||||
outputDirectory,
|
||||
"UndocumentedSuppressionBugPattern",
|
||||
"""
|
||||
{
|
||||
"fullyQualifiedName": "pkg.UndocumentedSuppressionBugPattern",
|
||||
"name": "UndocumentedSuppressionBugPattern",
|
||||
"altNames": [],
|
||||
"link": "",
|
||||
"tags": [],
|
||||
"summary": "UndocumentedSuppressionBugPattern summary",
|
||||
"explanation": "",
|
||||
"severityLevel": "WARNING",
|
||||
"canDisable": true,
|
||||
"suppressionAnnotations": []
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
private static void verifyGeneratedFileContent(Path outputDirectory, String testClass)
|
||||
throws IOException {
|
||||
private static void verifyGeneratedFileContent(
|
||||
Path outputDirectory, String testClass, String expectedContent) {
|
||||
String resourceName = String.format("bugpattern-%s.json", testClass);
|
||||
assertThat(outputDirectory.resolve(resourceName))
|
||||
.content(UTF_8)
|
||||
.isEqualToIgnoringWhitespace(
|
||||
getResource(
|
||||
String.join("-", BugPatternExtractorTest.class.getSimpleName(), resourceName)));
|
||||
}
|
||||
|
||||
// XXX: Once we support only JDK 15+, drop this method in favour of including the resources as
|
||||
// text blocks in this class.
|
||||
private static String getResource(String resourceName) throws IOException {
|
||||
return Resources.toString(
|
||||
Resources.getResource(BugPatternExtractorTest.class, resourceName), UTF_8);
|
||||
.isEqualToIgnoringWhitespace(expectedContent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,11 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerWithoutAnnotation.java",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"public final class TestCheckerWithoutAnnotation extends BugChecker {}");
|
||||
"""
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
public final class TestCheckerWithoutAnnotation extends BugChecker {}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -27,22 +29,24 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class TestCheckerTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\");",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\");",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class TestCheckerTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}");
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }");
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -52,22 +56,24 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class TestCheckerTest {",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance((Class<BugChecker>) null, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance((Class<BugChecker>) null, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class TestCheckerTest {
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance((Class<BugChecker>) null, getClass())
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance((Class<BugChecker>) null, getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -77,28 +83,30 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class TestCheckerTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" @SuppressWarnings(\"unchecked\")",
|
||||
" void m() {",
|
||||
" @SuppressWarnings(\"rawtypes\")",
|
||||
" Class bugChecker = TestChecker.class;",
|
||||
"",
|
||||
" CompilationTestHelper.newInstance(bugChecker, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(bugChecker, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class TestCheckerTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void m() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
Class bugChecker = TestChecker.class;
|
||||
|
||||
CompilationTestHelper.newInstance(bugChecker, getClass())
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(bugChecker, getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -108,27 +116,29 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"import com.google.errorprone.scanner.ScannerSupplier;",
|
||||
"",
|
||||
"final class TestCheckerTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(",
|
||||
" ScannerSupplier.fromBugCheckerClasses(TestChecker.class), getClass())",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(",
|
||||
" ScannerSupplier.fromBugCheckerClasses(TestChecker.class), getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.scanner.ScannerSupplier;
|
||||
|
||||
final class TestCheckerTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(
|
||||
ScannerSupplier.fromBugCheckerClasses(TestChecker.class), getClass())
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
ScannerSupplier.fromBugCheckerClasses(TestChecker.class), getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -138,29 +148,31 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class TestCheckerTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addSourceLines(toString() + \"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .addSourceLines(\"B.java\", \"// BUG: Diagnostic contains:\", \"class B {}\", toString())",
|
||||
" .doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addInputLines(toString() + \"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .addInputLines(\"B.java\", \"class B {}\", toString())",
|
||||
" .addOutputLines(\"B.java\", \"class B { /* This is a change. */ }\")",
|
||||
" .addInputLines(\"C.java\", \"class C {}\")",
|
||||
" .addOutputLines(\"C.java\", \"class C { /* This is a change. */ }\", toString())",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class TestCheckerTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines(toString() + "A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.addSourceLines("B.java", "// BUG: Diagnostic contains:", "class B {}", toString())
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addInputLines(toString() + "A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.addInputLines("B.java", "class B {}", toString())
|
||||
.addOutputLines("B.java", "class B { /* This is a change. */ }")
|
||||
.addInputLines("C.java", "class C {}")
|
||||
.addOutputLines("C.java", "class C { /* This is a change. */ }", toString())
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -170,26 +182,28 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class TestCheckerTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper testHelper =",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"class A {}\");",
|
||||
" testHelper.doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.ExpectOutput expectedOutput =",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\");",
|
||||
" expectedOutput.addOutputLines(\"A.java\", \"class A {}\").doTest();",
|
||||
" expectedOutput.expectUnchanged().doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class TestCheckerTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper testHelper =
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines("A.java", "class A {}");
|
||||
testHelper.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.ExpectOutput expectedOutput =
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addInputLines("A.java", "class A {}");
|
||||
expectedOutput.addOutputLines("A.java", "class A {}").doTest();
|
||||
expectedOutput.expectUnchanged().doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -199,19 +213,21 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class TestCheckerTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass()).doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass()).doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class TestCheckerTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass()).doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass()).doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -221,26 +237,28 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"TestCheckerTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class TestCheckerTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"class A {}\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A {}\")",
|
||||
" .addInputLines(\"B.java\", \"class B {}\")",
|
||||
" .expectUnchanged()",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class TestCheckerTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines("A.java", "class A {}")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A {}")
|
||||
.addInputLines("B.java", "class B {}")
|
||||
.expectUnchanged()
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
|
||||
}
|
||||
@@ -250,18 +268,20 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"SingleFileCompilationTestHelperTest.java",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class SingleFileCompilationTestHelperTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class SingleFileCompilationTestHelperTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(outputDirectory, "SingleFileCompilationTestHelperTest");
|
||||
}
|
||||
@@ -272,19 +292,21 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"SingleFileCompilationTestHelperWithSetArgsTest.java",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class SingleFileCompilationTestHelperWithSetArgsTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .setArgs(\"-XepAllSuggestionsAsWarnings\")",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class SingleFileCompilationTestHelperWithSetArgsTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.setArgs("-XepAllSuggestionsAsWarnings")
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(outputDirectory, "SingleFileCompilationTestHelperWithSetArgsTest");
|
||||
}
|
||||
@@ -294,19 +316,21 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"MultiFileCompilationTestHelperTest.java",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class MultiFileCompilationTestHelperTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .addSourceLines(\"B.java\", \"// BUG: Diagnostic contains:\", \"class B {}\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class MultiFileCompilationTestHelperTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.addSourceLines("B.java", "// BUG: Diagnostic contains:", "class B {}")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(outputDirectory, "MultiFileCompilationTestHelperTest");
|
||||
}
|
||||
@@ -316,19 +340,21 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"SingleFileBugCheckerRefactoringTestHelperTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class SingleFileBugCheckerRefactoringTestHelperTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class SingleFileBugCheckerRefactoringTestHelperTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(outputDirectory, "SingleFileBugCheckerRefactoringTestHelperTest");
|
||||
}
|
||||
@@ -339,23 +365,25 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"SingleFileBugCheckerRefactoringTestHelperWithSetArgsFixChooserAndCustomTestModeTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class SingleFileBugCheckerRefactoringTestHelperWithSetArgsFixChooserAndCustomTestModeTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .setArgs(\"-XepAllSuggestionsAsWarnings\")",
|
||||
" .setFixChooser(FixChoosers.SECOND)",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .doTest(TestMode.TEXT_MATCH);",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class SingleFileBugCheckerRefactoringTestHelperWithSetArgsFixChooserAndCustomTestModeTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.setArgs("-XepAllSuggestionsAsWarnings")
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(
|
||||
outputDirectory,
|
||||
@@ -367,21 +395,23 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"MultiFileBugCheckerRefactoringTestHelperTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class MultiFileBugCheckerRefactoringTestHelperTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .addInputLines(\"B.java\", \"class B {}\")",
|
||||
" .addOutputLines(\"B.java\", \"class B { /* This is a change. */ }\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class MultiFileBugCheckerRefactoringTestHelperTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.addInputLines("B.java", "class B {}")
|
||||
.addOutputLines("B.java", "class B { /* This is a change. */ }")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(outputDirectory, "MultiFileBugCheckerRefactoringTestHelperTest");
|
||||
}
|
||||
@@ -392,24 +422,26 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"CompilationAndBugCheckerRefactoringTestHelpersTest.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class CompilationAndBugCheckerRefactoringTestHelpersTest {",
|
||||
" private static class TestChecker extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class CompilationAndBugCheckerRefactoringTestHelpersTest {
|
||||
private static class TestChecker extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(
|
||||
outputDirectory, "CompilationAndBugCheckerRefactoringTestHelpersTest");
|
||||
@@ -421,28 +453,30 @@ final class BugPatternTestExtractorTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"CompilationAndBugCheckerRefactoringTestHelpersWithCustomCheckerPackageAndNamesTest.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"",
|
||||
"final class CompilationAndBugCheckerRefactoringTestHelpersWithCustomCheckerPackageAndNamesTest {",
|
||||
" private static class CustomTestChecker extends BugChecker {}",
|
||||
"",
|
||||
" private static class CustomTestChecker2 extends BugChecker {}",
|
||||
"",
|
||||
" void m() {",
|
||||
" CompilationTestHelper.newInstance(CustomTestChecker.class, getClass())",
|
||||
" .addSourceLines(\"A.java\", \"// BUG: Diagnostic contains:\", \"class A {}\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(CustomTestChecker2.class, getClass())",
|
||||
" .addInputLines(\"A.java\", \"class A {}\")",
|
||||
" .addOutputLines(\"A.java\", \"class A { /* This is a change. */ }\")",
|
||||
" .doTest();",
|
||||
" }",
|
||||
"}");
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
|
||||
final class CompilationAndBugCheckerRefactoringTestHelpersWithCustomCheckerPackageAndNamesTest {
|
||||
private static class CustomTestChecker extends BugChecker {}
|
||||
|
||||
private static class CustomTestChecker2 extends BugChecker {}
|
||||
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(CustomTestChecker.class, getClass())
|
||||
.addSourceLines("A.java", "// BUG: Diagnostic contains:", "class A {}")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(CustomTestChecker2.class, getClass())
|
||||
.addInputLines("A.java", "class A {}")
|
||||
.addOutputLines("A.java", "class A { /* This is a change. */ }")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
verifyGeneratedFileContent(
|
||||
outputDirectory,
|
||||
|
||||
@@ -62,7 +62,11 @@ final class DocumentationGeneratorTaskListenerTest {
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory, "A.java", "class A {}"))
|
||||
outputDirectory,
|
||||
"A.java",
|
||||
"""
|
||||
class A {}
|
||||
"""))
|
||||
.hasRootCauseInstanceOf(FileSystemException.class)
|
||||
.hasCauseInstanceOf(IllegalStateException.class)
|
||||
.hasMessageEndingWith("Error while creating directory with path '%s'", outputDirectory);
|
||||
@@ -70,7 +74,10 @@ final class DocumentationGeneratorTaskListenerTest {
|
||||
|
||||
@Test
|
||||
void noClassNoOutput(@TempDir Path outputDirectory) {
|
||||
Compilation.compileWithDocumentationGenerator(outputDirectory, "A.java", "package pkg;");
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory, "A.java", """
|
||||
package pkg;
|
||||
""");
|
||||
|
||||
assertThat(outputDirectory).isEmptyDirectory();
|
||||
}
|
||||
@@ -81,7 +88,11 @@ final class DocumentationGeneratorTaskListenerTest {
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
actualOutputDirectory, "A.java", "package pkg;"))
|
||||
actualOutputDirectory,
|
||||
"A.java",
|
||||
"""
|
||||
package pkg;
|
||||
"""))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Precisely one path must be provided");
|
||||
}
|
||||
@@ -91,7 +102,9 @@ final class DocumentationGeneratorTaskListenerTest {
|
||||
Compilation.compileWithDocumentationGenerator(
|
||||
outputDirectory,
|
||||
"DocumentationGeneratorTaskListenerTestClass.java",
|
||||
"class DocumentationGeneratorTaskListenerTestClass {}");
|
||||
"""
|
||||
class DocumentationGeneratorTaskListenerTestClass {}
|
||||
""");
|
||||
|
||||
// XXX: Once we support only JDK 15+, use a text block for the `expected` string.
|
||||
assertThat(
|
||||
@@ -125,8 +138,8 @@ final class DocumentationGeneratorTaskListenerTest {
|
||||
}
|
||||
|
||||
private static String describeTree(Tree tree) {
|
||||
return (tree instanceof ClassTree)
|
||||
? String.join(": ", String.valueOf(tree.getKind()), ((ClassTree) tree).getSimpleName())
|
||||
return (tree instanceof ClassTree clazz)
|
||||
? String.join(": ", String.valueOf(tree.getKind()), clazz.getSimpleName())
|
||||
: tree.getKind().toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"fullyQualifiedName": "pkg.CompleteBugChecker",
|
||||
"name": "OtherName",
|
||||
"altNames": [
|
||||
"Check"
|
||||
],
|
||||
"link": "https://error-prone.picnic.tech",
|
||||
"tags": [
|
||||
"Simplification"
|
||||
],
|
||||
"summary": "CompleteBugChecker summary",
|
||||
"explanation": "Example explanation",
|
||||
"severityLevel": "SUGGESTION",
|
||||
"canDisable": false,
|
||||
"suppressionAnnotations": [
|
||||
"com.google.errorprone.BugPattern",
|
||||
"org.junit.jupiter.api.Test"
|
||||
]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"fullyQualifiedName": "pkg.MinimalBugChecker",
|
||||
"name": "MinimalBugChecker",
|
||||
"altNames": [],
|
||||
"link": "",
|
||||
"tags": [],
|
||||
"summary": "MinimalBugChecker summary",
|
||||
"explanation": "",
|
||||
"severityLevel": "ERROR",
|
||||
"canDisable": true,
|
||||
"suppressionAnnotations": [
|
||||
"java.lang.SuppressWarnings"
|
||||
]
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"fullyQualifiedName": "pkg.UndocumentedSuppressionBugPattern",
|
||||
"name": "UndocumentedSuppressionBugPattern",
|
||||
"altNames": [],
|
||||
"link": "",
|
||||
"tags": [],
|
||||
"summary": "UndocumentedSuppressionBugPattern summary",
|
||||
"explanation": "",
|
||||
"severityLevel": "WARNING",
|
||||
"canDisable": true,
|
||||
"suppressionAnnotations": []
|
||||
}
|
||||
@@ -248,7 +248,6 @@
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs combine.children="append">
|
||||
<arg>-Xplugin:RefasterRuleCompiler</arg>
|
||||
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import java.util.Map;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
@@ -46,7 +46,7 @@ public final class AmbiguousJsonCreator extends BugChecker implements Annotation
|
||||
}
|
||||
|
||||
ClassTree clazz = state.findEnclosing(ClassTree.class);
|
||||
if (clazz == null || clazz.getKind() != Tree.Kind.ENUM) {
|
||||
if (clazz == null || clazz.getKind() != Kind.ENUM) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.AssignmentTree;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.NewArrayTree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -119,7 +118,7 @@ public final class CanonicalAnnotationSyntax extends BugChecker implements Annot
|
||||
* the expression as a whole.
|
||||
*/
|
||||
ExpressionTree value =
|
||||
(arg.getKind() == Kind.ASSIGNMENT) ? ((AssignmentTree) arg).getExpression() : arg;
|
||||
(arg instanceof AssignmentTree assignment) ? assignment.getExpression() : arg;
|
||||
|
||||
/* Store a fix for each expression that was successfully simplified. */
|
||||
simplifyAttributeValue(value, state)
|
||||
@@ -130,13 +129,10 @@ public final class CanonicalAnnotationSyntax extends BugChecker implements Annot
|
||||
}
|
||||
|
||||
private static Optional<String> simplifyAttributeValue(ExpressionTree expr, VisitorState state) {
|
||||
if (expr.getKind() != Kind.NEW_ARRAY) {
|
||||
/* There are no curly braces or commas to be dropped here. */
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
NewArrayTree array = (NewArrayTree) expr;
|
||||
return simplifySingletonArray(array, state).or(() -> dropTrailingComma(array, state));
|
||||
/* Drop curly braces or commas if possible. */
|
||||
return expr instanceof NewArrayTree newArray
|
||||
? simplifySingletonArray(newArray, state).or(() -> dropTrailingComma(newArray, state))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
/** Returns the expression describing the array's sole element, if any. */
|
||||
|
||||
@@ -98,19 +98,17 @@ public final class DirectReturn extends BugChecker implements BlockTreeMatcher {
|
||||
}
|
||||
|
||||
private static Optional<ExpressionTree> tryMatchAssignment(Symbol targetSymbol, Tree tree) {
|
||||
if (tree instanceof ExpressionStatementTree) {
|
||||
return tryMatchAssignment(targetSymbol, ((ExpressionStatementTree) tree).getExpression());
|
||||
if (tree instanceof ExpressionStatementTree expressionStatement) {
|
||||
return tryMatchAssignment(targetSymbol, expressionStatement.getExpression());
|
||||
}
|
||||
|
||||
if (tree instanceof AssignmentTree) {
|
||||
AssignmentTree assignment = (AssignmentTree) tree;
|
||||
if (tree instanceof AssignmentTree assignment) {
|
||||
return targetSymbol.equals(ASTHelpers.getSymbol(assignment.getVariable()))
|
||||
? Optional.of(assignment.getExpression())
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
if (tree instanceof VariableTree) {
|
||||
VariableTree declaration = (VariableTree) tree;
|
||||
if (tree instanceof VariableTree declaration) {
|
||||
return declaration.getModifiers().getAnnotations().isEmpty()
|
||||
&& targetSymbol.equals(ASTHelpers.getSymbol(declaration))
|
||||
? Optional.ofNullable(declaration.getInitializer())
|
||||
@@ -148,11 +146,11 @@ public final class DirectReturn extends BugChecker implements BlockTreeMatcher {
|
||||
Streams.stream(state.getPath()).skip(1),
|
||||
Streams.stream(state.getPath()),
|
||||
(tree, child) -> {
|
||||
if (!(tree instanceof TryTree)) {
|
||||
if (!(tree instanceof TryTree tryTree)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BlockTree finallyBlock = ((TryTree) tree).getFinallyBlock();
|
||||
BlockTree finallyBlock = tryTree.getFinallyBlock();
|
||||
return !child.equals(finallyBlock) ? finallyBlock : null;
|
||||
})
|
||||
.anyMatch(finallyBlock -> referencesIdentifierSymbol(symbol, finallyBlock));
|
||||
|
||||
@@ -6,19 +6,24 @@ import static com.google.errorprone.BugPattern.StandardTags.STYLE;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static com.sun.tools.javac.util.Position.NOPOS;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static tech.picnic.errorprone.bugpatterns.util.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.ErrorProneFlags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.suppliers.Supplier;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.google.errorprone.util.SourceVersion;
|
||||
import com.google.googlejavaformat.java.Formatter;
|
||||
import com.google.googlejavaformat.java.FormatterException;
|
||||
import com.google.googlejavaformat.java.ImportOrderer;
|
||||
@@ -27,9 +32,12 @@ import com.google.googlejavaformat.java.RemoveUnusedImports;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.tools.javac.util.Position;
|
||||
import com.sun.tools.javac.api.MultiTaskListener;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.inject.Inject;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags improperly formatted Error Prone test code.
|
||||
@@ -45,20 +53,33 @@ import java.util.Optional;
|
||||
* are not able to) remove imports that become obsolete as a result of applying their suggested
|
||||
* fix(es).
|
||||
*/
|
||||
// XXX: Once we target JDK 17 (optionally?) suggest text block fixes.
|
||||
// XXX: The check does not flag well-formatted text blocks with insufficient indentation. Cover this
|
||||
// using an generic check or wait for Google Java Format support (see
|
||||
// https://github.com/google/google-java-format/issues/883#issuecomment-1404336418).
|
||||
// XXX: The check does not flag well-formatted text blocks with excess indentation.
|
||||
// XXX: ^ Validate this claim.
|
||||
// XXX: GJF guesses the line separator to be used by inspecting the source. When using text blocks
|
||||
// this may cause the current unconditional use of `\n` not to be sufficient when building on
|
||||
// Windows; TBD.
|
||||
// XXX: Forward compatibility: ignore "malformed" code in tests that, based on an
|
||||
// `@DisabledForJreRange` or `@EnableForJreRange` annotation, target a Java runtime greater than the
|
||||
// current runtime.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Test code should follow the Google Java style",
|
||||
summary =
|
||||
"Test code should follow the Google Java style (and when targeting JDK 15+ be "
|
||||
+ "specified using a single text block)",
|
||||
link = BUG_PATTERNS_BASE_URL + "ErrorProneTestHelperSourceFormat",
|
||||
linkType = CUSTOM,
|
||||
severity = SUGGESTION,
|
||||
tags = STYLE)
|
||||
// XXX: Drop suppression if/when the `avoidTextBlocks` field is dropped.
|
||||
@SuppressWarnings("java:S2160" /* Super class equality definition suffices. */)
|
||||
public final class ErrorProneTestHelperSourceFormat extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String FLAG_AVOID_TEXT_BLOCKS =
|
||||
"ErrorProneTestHelperSourceFormat:AvoidTextBlocks";
|
||||
private static final Formatter FORMATTER = new Formatter();
|
||||
private static final Matcher<ExpressionTree> INPUT_SOURCE_ACCEPTING_METHOD =
|
||||
anyOf(
|
||||
@@ -77,9 +98,31 @@ public final class ErrorProneTestHelperSourceFormat extends BugChecker
|
||||
instanceMethod()
|
||||
.onDescendantOf("com.google.errorprone.BugCheckerRefactoringTestHelper.ExpectOutput")
|
||||
.named("addOutputLines");
|
||||
private static final Supplier<Boolean> IS_JABEL_ENABLED =
|
||||
VisitorState.memoize(ErrorProneTestHelperSourceFormat::isJabelEnabled);
|
||||
// XXX: Proper name for this?
|
||||
// XXX: Something about tabs.
|
||||
private static final String TEXT_BLOCK_MARKER = "\"\"\"";
|
||||
private static final String TEXT_BLOCK_LINE_SEPARATOR = "\n";
|
||||
private static final String DEFAULT_TEXT_BLOCK_INDENTATION = " ".repeat(12);
|
||||
private static final String METHOD_SELECT_ARGUMENT_RELATIVE_INDENTATION = " ".repeat(8);
|
||||
|
||||
/** Instantiates a new {@link ErrorProneTestHelperSourceFormat} instance. */
|
||||
public ErrorProneTestHelperSourceFormat() {}
|
||||
private final boolean avoidTextBlocks;
|
||||
|
||||
/** Instantiates a default {@link ErrorProneTestHelperSourceFormat} instance. */
|
||||
public ErrorProneTestHelperSourceFormat() {
|
||||
this(ErrorProneFlags.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a customized {@link ErrorProneTestHelperSourceFormat}.
|
||||
*
|
||||
* @param flags Any provided command line flags.
|
||||
*/
|
||||
@Inject
|
||||
ErrorProneTestHelperSourceFormat(ErrorProneFlags flags) {
|
||||
avoidTextBlocks = flags.getBoolean(FLAG_AVOID_TEXT_BLOCKS).orElse(Boolean.FALSE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
@@ -95,22 +138,23 @@ public final class ErrorProneTestHelperSourceFormat extends BugChecker
|
||||
return buildDescription(tree).setMessage("No source code provided").build();
|
||||
}
|
||||
|
||||
int startPos = ASTHelpers.getStartPosition(sourceLines.get(0));
|
||||
int endPos = state.getEndPosition(sourceLines.get(sourceLines.size() - 1));
|
||||
|
||||
/* Attempt to format the source code only if it fully consists of constant expressions. */
|
||||
return getConstantSourceCode(sourceLines)
|
||||
.map(source -> flagFormattingIssues(startPos, endPos, source, isOutputSource, state))
|
||||
.map(source -> flagFormattingIssues(sourceLines, source, isOutputSource, state))
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
|
||||
private Description flagFormattingIssues(
|
||||
int startPos, int endPos, String source, boolean retainUnusedImports, VisitorState state) {
|
||||
Tree methodInvocation = state.getPath().getLeaf();
|
||||
List<? extends ExpressionTree> sourceLines,
|
||||
String source,
|
||||
boolean retainUnusedImports,
|
||||
VisitorState state) {
|
||||
MethodInvocationTree methodInvocation = (MethodInvocationTree) state.getPath().getLeaf();
|
||||
|
||||
String formatted;
|
||||
try {
|
||||
formatted = formatSourceCode(source, retainUnusedImports).trim();
|
||||
String gjfResult = formatSourceCode(source, retainUnusedImports);
|
||||
formatted = canUseTextBlocks(sourceLines, state) ? gjfResult : gjfResult.stripTrailing();
|
||||
} catch (
|
||||
@SuppressWarnings("java:S1166" /* Stack trace not relevant. */)
|
||||
FormatterException e) {
|
||||
@@ -119,31 +163,113 @@ public final class ErrorProneTestHelperSourceFormat extends BugChecker
|
||||
.build();
|
||||
}
|
||||
|
||||
if (source.trim().equals(formatted)) {
|
||||
boolean isFormatted = source.equals(formatted);
|
||||
boolean hasStringLiteralMismatch = shouldUpdateStringLiteralFormat(sourceLines, state);
|
||||
|
||||
if (isFormatted && !hasStringLiteralMismatch) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
if (startPos == Position.NOPOS || endPos == Position.NOPOS) {
|
||||
/*
|
||||
* We have insufficient source information to emit a fix, so we only flag the fact that the
|
||||
* code isn't properly formatted.
|
||||
*/
|
||||
return describeMatch(methodInvocation);
|
||||
}
|
||||
int startPos = ASTHelpers.getStartPosition(sourceLines.get(0));
|
||||
int endPos = state.getEndPosition(sourceLines.get(sourceLines.size() - 1));
|
||||
boolean hasNewlineMismatch =
|
||||
!isFormatted && source.stripTrailing().equals(formatted.stripTrailing());
|
||||
|
||||
/*
|
||||
* The code isn't properly formatted; replace all lines with the properly formatted
|
||||
* alternatives.
|
||||
* The source code is not properly formatted and/or not specified using a single text block.
|
||||
* Report the more salient of the violations, and suggest a fix if sufficient source information
|
||||
* is available.
|
||||
*/
|
||||
return describeMatch(
|
||||
methodInvocation,
|
||||
SuggestedFix.replace(
|
||||
startPos,
|
||||
endPos,
|
||||
Splitter.on(System.lineSeparator())
|
||||
.splitToStream(formatted)
|
||||
.map(state::getConstantExpression)
|
||||
.collect(joining(", "))));
|
||||
boolean isTextBlockUsageIssue = isFormatted || (hasNewlineMismatch && hasStringLiteralMismatch);
|
||||
boolean canSuggestFix = startPos != NOPOS && endPos != NOPOS;
|
||||
return buildDescription(methodInvocation)
|
||||
.setMessage(
|
||||
isTextBlockUsageIssue
|
||||
? String.format(
|
||||
"Test code should %sbe specified using a single text block",
|
||||
avoidTextBlocks ? "not " : "")
|
||||
: String.format(
|
||||
"Test code should follow the Google Java style%s",
|
||||
hasNewlineMismatch ? " (pay attention to trailing newlines)" : ""))
|
||||
.addFix(
|
||||
canSuggestFix
|
||||
? SuggestedFix.replace(
|
||||
startPos,
|
||||
endPos,
|
||||
canUseTextBlocks(sourceLines, state)
|
||||
? toTextBlockExpression(methodInvocation, formatted, state)
|
||||
: toLineEnumeration(formatted, state))
|
||||
: SuggestedFix.emptyFix())
|
||||
.build();
|
||||
}
|
||||
|
||||
private boolean shouldUpdateStringLiteralFormat(
|
||||
List<? extends ExpressionTree> sourceLines, VisitorState state) {
|
||||
return canUseTextBlocks(sourceLines, state)
|
||||
? (sourceLines.size() > 1 || !SourceCode.isTextBlock(sourceLines.get(0), state))
|
||||
: sourceLines.stream().anyMatch(tree -> SourceCode.isTextBlock(tree, state));
|
||||
}
|
||||
|
||||
private boolean canUseTextBlocks(List<? extends ExpressionTree> sourceLines, VisitorState state) {
|
||||
return !avoidTextBlocks
|
||||
&& (SourceVersion.supportsTextBlocks(state.context)
|
||||
|| IS_JABEL_ENABLED.get(state)
|
||||
|| sourceLines.stream().anyMatch(line -> SourceCode.isTextBlock(line, state)));
|
||||
}
|
||||
|
||||
private static String toTextBlockExpression(
|
||||
MethodInvocationTree tree, String source, VisitorState state) {
|
||||
String indentation = suggestTextBlockIndentation(tree, state);
|
||||
|
||||
// XXX: Verify trailing """ on new line.
|
||||
return TEXT_BLOCK_MARKER
|
||||
+ System.lineSeparator()
|
||||
+ indentation
|
||||
+ source
|
||||
.replace(TEXT_BLOCK_LINE_SEPARATOR, System.lineSeparator() + indentation)
|
||||
.replace("\\", "\\\\")
|
||||
.replace(TEXT_BLOCK_MARKER, "\"\"\\\"")
|
||||
+ TEXT_BLOCK_MARKER;
|
||||
}
|
||||
|
||||
private static String toLineEnumeration(String source, VisitorState state) {
|
||||
return Splitter.on(TEXT_BLOCK_LINE_SEPARATOR)
|
||||
.splitToStream(source)
|
||||
.map(state::getConstantExpression)
|
||||
.collect(joining(", "));
|
||||
}
|
||||
|
||||
// XXX: This makes certain assumptions; document these.
|
||||
private static String suggestTextBlockIndentation(
|
||||
MethodInvocationTree target, VisitorState state) {
|
||||
CharSequence sourceCode = state.getSourceCode();
|
||||
if (sourceCode == null) {
|
||||
return DEFAULT_TEXT_BLOCK_INDENTATION;
|
||||
}
|
||||
|
||||
String source = sourceCode.toString();
|
||||
return getIndentation(target.getArguments().get(1), source)
|
||||
.or(() -> getIndentation(target.getArguments().get(0), source))
|
||||
.or(
|
||||
() ->
|
||||
getIndentation(target.getMethodSelect(), source)
|
||||
.map(METHOD_SELECT_ARGUMENT_RELATIVE_INDENTATION::concat))
|
||||
.orElse(DEFAULT_TEXT_BLOCK_INDENTATION);
|
||||
}
|
||||
|
||||
private static Optional<String> getIndentation(Tree tree, String source) {
|
||||
int startPos = ASTHelpers.getStartPosition(tree);
|
||||
if (startPos == NOPOS) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
int finalNewLine = source.lastIndexOf(System.lineSeparator(), startPos);
|
||||
if (finalNewLine < 0) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(source.substring(finalNewLine + 1, startPos))
|
||||
.filter(CharMatcher.whitespace()::matchesAllOf);
|
||||
}
|
||||
|
||||
private static String formatSourceCode(String source, boolean retainUnusedImports)
|
||||
@@ -162,14 +288,29 @@ public final class ErrorProneTestHelperSourceFormat extends BugChecker
|
||||
StringBuilder source = new StringBuilder();
|
||||
|
||||
for (ExpressionTree sourceLine : sourceLines) {
|
||||
if (source.length() > 0) {
|
||||
source.append(TEXT_BLOCK_LINE_SEPARATOR);
|
||||
}
|
||||
|
||||
String value = ASTHelpers.constValue(sourceLine, String.class);
|
||||
if (value == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
source.append(value).append(System.lineSeparator());
|
||||
source.append(value);
|
||||
}
|
||||
|
||||
return Optional.of(source.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether Jabel appears to be enabled, indicating that text blocks are supported, even if
|
||||
* may <em>appear</em> that they {@link SourceVersion#supportsTextBlocks(Context) aren't}.
|
||||
*
|
||||
* @see <a href="https://github.com/bsideup/jabel">Jabel</a>
|
||||
*/
|
||||
private static boolean isJabelEnabled(VisitorState state) {
|
||||
return MultiTaskListener.instance(state.context).getTaskListeners().stream()
|
||||
.anyMatch(listener -> listener.toString().contains("com.github.bsideup.jabel"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,9 @@ import reactor.core.publisher.Flux;
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary =
|
||||
"`Flux#flatMap` and `Flux#flatMapSequential` have subtle semantics; "
|
||||
+ "please use `Flux#concatMap` or explicitly specify the desired amount of concurrency",
|
||||
"""
|
||||
`Flux#flatMap` and `Flux#flatMapSequential` have subtle semantics; please use \
|
||||
`Flux#concatMap` or explicitly specify the desired amount of concurrency""",
|
||||
link = BUG_PATTERNS_BASE_URL + "FluxFlatMapUsage",
|
||||
linkType = CUSTOM,
|
||||
severity = ERROR,
|
||||
|
||||
@@ -242,8 +242,8 @@ public final class FormatStringConcatenation extends BugChecker
|
||||
}
|
||||
|
||||
private void appendExpression(Tree tree) {
|
||||
if (tree instanceof LiteralTree) {
|
||||
formatString.append(((LiteralTree) tree).getValue());
|
||||
if (tree instanceof LiteralTree literal) {
|
||||
formatString.append(literal.getValue());
|
||||
} else {
|
||||
formatString.append(formatSpecifier);
|
||||
formatArguments.add(tree);
|
||||
|
||||
@@ -114,8 +114,9 @@ public final class IdentityConversion extends BugChecker implements MethodInvoca
|
||||
|
||||
return buildDescription(tree)
|
||||
.setMessage(
|
||||
"This method invocation appears redundant; remove it or suppress this warning and "
|
||||
+ "add a comment explaining its purpose")
|
||||
"""
|
||||
This method invocation appears redundant; remove it or suppress this warning and add a \
|
||||
comment explaining its purpose""")
|
||||
.addFix(SuggestedFix.replace(tree, SourceCode.treeToString(sourceTree, state)))
|
||||
.addFix(SuggestedFixes.addSuppressWarnings(state, canonicalName()))
|
||||
.build();
|
||||
|
||||
@@ -43,8 +43,9 @@ import javax.lang.model.element.Modifier;
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary =
|
||||
"`SortedSet` properties of a `@Value.Immutable` or `@Value.Modifiable` type must be "
|
||||
+ "annotated with `@Value.NaturalOrder` or `@Value.ReverseOrder`",
|
||||
"""
|
||||
`SortedSet` properties of a `@Value.Immutable` or `@Value.Modifiable` type must be \
|
||||
annotated with `@Value.NaturalOrder` or `@Value.ReverseOrder`""",
|
||||
link = BUG_PATTERNS_BASE_URL + "ImmutablesSortedSetComparator",
|
||||
linkType = CUSTOM,
|
||||
severity = ERROR,
|
||||
|
||||
@@ -16,7 +16,6 @@ import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.InstanceOfTree;
|
||||
import com.sun.source.tree.LambdaExpressionTree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
@@ -42,12 +41,12 @@ public final class IsInstanceLambdaUsage extends BugChecker implements LambdaExp
|
||||
|
||||
@Override
|
||||
public Description matchLambdaExpression(LambdaExpressionTree tree, VisitorState state) {
|
||||
if (tree.getParameters().size() != 1 || tree.getBody().getKind() != Kind.INSTANCE_OF) {
|
||||
if (tree.getParameters().size() != 1
|
||||
|| !(tree.getBody() instanceof InstanceOfTree instanceOf)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
VariableTree param = Iterables.getOnlyElement(tree.getParameters());
|
||||
InstanceOfTree instanceOf = (InstanceOfTree) tree.getBody();
|
||||
if (!ASTHelpers.getSymbol(param).equals(ASTHelpers.getSymbol(instanceOf.getExpression()))) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
@@ -257,8 +257,8 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
|
||||
arguments.stream()
|
||||
.map(
|
||||
arg ->
|
||||
arg instanceof MethodInvocationTree
|
||||
? Iterables.getOnlyElement(((MethodInvocationTree) arg).getArguments())
|
||||
arg instanceof MethodInvocationTree methodInvocation
|
||||
? Iterables.getOnlyElement(methodInvocation.getArguments())
|
||||
: arg)
|
||||
.map(argument -> SourceCode.treeToString(argument, state))
|
||||
.collect(joining(", ")))
|
||||
@@ -268,16 +268,12 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
|
||||
private static String toValueSourceAttributeName(Type type) {
|
||||
String typeString = type.tsym.name.toString();
|
||||
|
||||
switch (typeString) {
|
||||
case "Class":
|
||||
return "classes";
|
||||
case "Character":
|
||||
return "chars";
|
||||
case "Integer":
|
||||
return "ints";
|
||||
default:
|
||||
return typeString.toLowerCase(Locale.ROOT) + 's';
|
||||
}
|
||||
return switch (typeString) {
|
||||
case "Class" -> "classes";
|
||||
case "Character" -> "chars";
|
||||
case "Integer" -> "ints";
|
||||
default -> typeString.toLowerCase(Locale.ROOT) + 's';
|
||||
};
|
||||
}
|
||||
|
||||
private static <T> Optional<T> getElementIfSingleton(Collection<T> collection) {
|
||||
@@ -289,11 +285,10 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
|
||||
private static Matcher<ExpressionTree> isSingleDimensionArrayCreationWithAllElementsMatching(
|
||||
Matcher<? super ExpressionTree> elementMatcher) {
|
||||
return (tree, state) -> {
|
||||
if (!(tree instanceof NewArrayTree)) {
|
||||
if (!(tree instanceof NewArrayTree newArray)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NewArrayTree newArray = (NewArrayTree) tree;
|
||||
return newArray.getDimensions().isEmpty()
|
||||
&& !newArray.getInitializers().isEmpty()
|
||||
&& newArray.getInitializers().stream()
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.sun.source.tree.LiteralTree;
|
||||
import com.sun.source.tree.NewArrayTree;
|
||||
import com.sun.source.tree.PrimitiveTypeTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import com.sun.tools.javac.code.Symtab;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
@@ -122,13 +121,9 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
|
||||
}
|
||||
|
||||
private static Optional<NewArrayTree> extractArray(ExpressionTree expr) {
|
||||
if (expr.getKind() == Kind.ASSIGNMENT) {
|
||||
return extractArray(((AssignmentTree) expr).getExpression());
|
||||
}
|
||||
|
||||
return Optional.of(expr)
|
||||
.filter(e -> e.getKind() == Kind.NEW_ARRAY)
|
||||
.map(NewArrayTree.class::cast);
|
||||
return expr instanceof AssignmentTree assignment
|
||||
? extractArray(assignment.getExpression())
|
||||
: Optional.of(expr).filter(NewArrayTree.class::isInstance).map(NewArrayTree.class::cast);
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix.Builder> suggestSorting(
|
||||
@@ -200,8 +195,8 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
|
||||
public @Nullable Void visitLiteral(LiteralTree node, @Nullable Void unused) {
|
||||
Object value = ASTHelpers.constValue(node);
|
||||
nodes.add(
|
||||
value instanceof String
|
||||
? STRING_ARGUMENT_SPLITTER.splitToStream((String) value).collect(toImmutableList())
|
||||
value instanceof String str
|
||||
? STRING_ARGUMENT_SPLITTER.splitToStream(str).collect(toImmutableList())
|
||||
: ImmutableList.of(String.valueOf(value)));
|
||||
|
||||
return super.visitLiteral(node, unused);
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.ParenthesizedTree;
|
||||
import com.sun.source.tree.ReturnTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
@@ -85,22 +84,19 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
|
||||
// XXX: Use switch pattern matching once the targeted JDK supports this.
|
||||
private static Optional<SuggestedFix.Builder> constructMethodRef(
|
||||
LambdaExpressionTree lambdaExpr, Tree subTree) {
|
||||
switch (subTree.getKind()) {
|
||||
case BLOCK:
|
||||
return constructMethodRef(lambdaExpr, (BlockTree) subTree);
|
||||
case EXPRESSION_STATEMENT:
|
||||
return constructMethodRef(lambdaExpr, ((ExpressionStatementTree) subTree).getExpression());
|
||||
case METHOD_INVOCATION:
|
||||
return constructMethodRef(lambdaExpr, (MethodInvocationTree) subTree);
|
||||
case PARENTHESIZED:
|
||||
return constructMethodRef(lambdaExpr, ((ParenthesizedTree) subTree).getExpression());
|
||||
case RETURN:
|
||||
return constructMethodRef(lambdaExpr, ((ReturnTree) subTree).getExpression());
|
||||
default:
|
||||
return Optional.empty();
|
||||
}
|
||||
return switch (subTree.getKind()) {
|
||||
case BLOCK -> constructMethodRef(lambdaExpr, (BlockTree) subTree);
|
||||
case EXPRESSION_STATEMENT -> constructMethodRef(
|
||||
lambdaExpr, ((ExpressionStatementTree) subTree).getExpression());
|
||||
case METHOD_INVOCATION -> constructMethodRef(lambdaExpr, (MethodInvocationTree) subTree);
|
||||
case PARENTHESIZED -> constructMethodRef(
|
||||
lambdaExpr, ((ParenthesizedTree) subTree).getExpression());
|
||||
case RETURN -> constructMethodRef(lambdaExpr, ((ReturnTree) subTree).getExpression());
|
||||
default -> Optional.empty();
|
||||
};
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix.Builder> constructMethodRef(
|
||||
@@ -118,33 +114,35 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
.flatMap(expectedInstance -> constructMethodRef(lambdaExpr, subTree, expectedInstance));
|
||||
}
|
||||
|
||||
@SuppressWarnings(
|
||||
"java:S1151" /* Extracting `IDENTIFIER` case block to separate method does not improve readability. */)
|
||||
// XXX: Review whether to use switch pattern matching once the targeted JDK supports this.
|
||||
private static Optional<SuggestedFix.Builder> constructMethodRef(
|
||||
LambdaExpressionTree lambdaExpr,
|
||||
MethodInvocationTree subTree,
|
||||
Optional<Name> expectedInstance) {
|
||||
ExpressionTree methodSelect = subTree.getMethodSelect();
|
||||
switch (methodSelect.getKind()) {
|
||||
case IDENTIFIER:
|
||||
if (expectedInstance.isPresent()) {
|
||||
/* Direct method call; there is no matching "implicit parameter". */
|
||||
return Optional.empty();
|
||||
}
|
||||
Symbol sym = ASTHelpers.getSymbol(methodSelect);
|
||||
return ASTHelpers.isStatic(sym)
|
||||
? constructFix(lambdaExpr, sym.owner, methodSelect)
|
||||
: constructFix(lambdaExpr, "this", methodSelect);
|
||||
case MEMBER_SELECT:
|
||||
return constructMethodRef(lambdaExpr, (MemberSelectTree) methodSelect, expectedInstance);
|
||||
default:
|
||||
throw new VerifyException("Unexpected type of expression: " + methodSelect.getKind());
|
||||
|
||||
if (methodSelect instanceof IdentifierTree) {
|
||||
if (expectedInstance.isPresent()) {
|
||||
/* Direct method call; there is no matching "implicit parameter". */
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Symbol sym = ASTHelpers.getSymbol(methodSelect);
|
||||
return ASTHelpers.isStatic(sym)
|
||||
? constructFix(lambdaExpr, sym.owner, methodSelect)
|
||||
: constructFix(lambdaExpr, "this", methodSelect);
|
||||
}
|
||||
|
||||
if (methodSelect instanceof MemberSelectTree memberSelect) {
|
||||
return constructMethodRef(lambdaExpr, memberSelect, expectedInstance);
|
||||
}
|
||||
|
||||
throw new VerifyException("Unexpected type of expression: " + methodSelect.getKind());
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix.Builder> constructMethodRef(
|
||||
LambdaExpressionTree lambdaExpr, MemberSelectTree subTree, Optional<Name> expectedInstance) {
|
||||
if (subTree.getExpression().getKind() != Kind.IDENTIFIER) {
|
||||
if (!(subTree.getExpression() instanceof IdentifierTree identifier)) {
|
||||
// XXX: Could be parenthesized. Handle. Also in other classes.
|
||||
/*
|
||||
* Only suggest a replacement if the method select's expression provably doesn't have
|
||||
@@ -153,12 +151,12 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Name lhs = ((IdentifierTree) subTree.getExpression()).getName();
|
||||
Name lhs = identifier.getName();
|
||||
if (expectedInstance.isEmpty()) {
|
||||
return constructFix(lambdaExpr, lhs, subTree.getIdentifier());
|
||||
}
|
||||
|
||||
Type lhsType = ASTHelpers.getType(subTree.getExpression());
|
||||
Type lhsType = ASTHelpers.getType(identifier);
|
||||
if (lhsType == null || !expectedInstance.orElseThrow().equals(lhs)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
@@ -183,8 +181,8 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
ExpressionTree arg = args.get(i);
|
||||
if (arg.getKind() != Kind.IDENTIFIER
|
||||
|| !((IdentifierTree) arg).getName().equals(expectedArguments.get(i + diff))) {
|
||||
if (!(arg instanceof IdentifierTree identifier)
|
||||
|| !identifier.getName().equals(expectedArguments.get(i + diff))) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,20 +67,17 @@ public final class MockitoMockClassReference extends BugChecker
|
||||
return describeMatch(tree, SuggestedFixes.removeElement(arguments.get(0), arguments, state));
|
||||
}
|
||||
|
||||
// XXX: Use switch pattern matching once the targeted JDK supports this.
|
||||
private static boolean isTypeDerivableFromContext(MethodInvocationTree tree, VisitorState state) {
|
||||
Tree parent = state.getPath().getParentPath().getLeaf();
|
||||
switch (parent.getKind()) {
|
||||
case VARIABLE:
|
||||
return !ASTHelpers.hasImplicitType((VariableTree) parent, state)
|
||||
&& MoreASTHelpers.areSameType(tree, parent, state);
|
||||
case ASSIGNMENT:
|
||||
return MoreASTHelpers.areSameType(tree, parent, state);
|
||||
case RETURN:
|
||||
return MoreASTHelpers.findMethodExitedOnReturn(state)
|
||||
.filter(m -> MoreASTHelpers.areSameType(tree, m.getReturnType(), state))
|
||||
.isPresent();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return switch (parent.getKind()) {
|
||||
case VARIABLE -> !ASTHelpers.hasImplicitType((VariableTree) parent, state)
|
||||
&& MoreASTHelpers.areSameType(tree, parent, state);
|
||||
case ASSIGNMENT -> MoreASTHelpers.areSameType(tree, parent, state);
|
||||
case RETURN -> MoreASTHelpers.findMethodExitedOnReturn(state)
|
||||
.filter(m -> MoreASTHelpers.areSameType(tree, m.getReturnType(), state))
|
||||
.isPresent();
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,9 @@ import com.sun.tools.javac.code.Type;
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary =
|
||||
"Avoid `Publisher`s that emit other `Publishers`s; "
|
||||
+ "the resultant code is hard to reason about",
|
||||
"""
|
||||
Avoid `Publisher`s that emit other `Publishers`s; the resultant code is hard to reason \
|
||||
about""",
|
||||
link = BUG_PATTERNS_BASE_URL + "NestedPublishers",
|
||||
linkType = CUSTOM,
|
||||
severity = WARNING,
|
||||
|
||||
@@ -159,10 +159,9 @@ public final class NonStaticImport extends BugChecker implements CompilationUnit
|
||||
ImmutableTable.builder();
|
||||
for (ImportTree importTree : tree.getImports()) {
|
||||
Tree qualifiedIdentifier = importTree.getQualifiedIdentifier();
|
||||
if (importTree.isStatic() && qualifiedIdentifier instanceof MemberSelectTree) {
|
||||
MemberSelectTree memberSelectTree = (MemberSelectTree) qualifiedIdentifier;
|
||||
String type = SourceCode.treeToString(memberSelectTree.getExpression(), state);
|
||||
String member = memberSelectTree.getIdentifier().toString();
|
||||
if (importTree.isStatic() && qualifiedIdentifier instanceof MemberSelectTree memberSelect) {
|
||||
String type = SourceCode.treeToString(memberSelect.getExpression(), state);
|
||||
String member = memberSelect.getIdentifier().toString();
|
||||
if (shouldNotBeStaticallyImported(type, member)) {
|
||||
imports.put(
|
||||
type,
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.IdentifierTree;
|
||||
import com.sun.source.tree.LambdaExpressionTree;
|
||||
import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
@@ -43,8 +44,9 @@ import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary =
|
||||
"Ensure invocations of `Comparator#comparing{,Double,Int,Long}` match the return type"
|
||||
+ " of the provided function",
|
||||
"""
|
||||
Ensure invocations of `Comparator#comparing{,Double,Int,Long}` match the return type of \
|
||||
the provided function""",
|
||||
link = BUG_PATTERNS_BASE_URL + "PrimitiveComparison",
|
||||
linkType = CUSTOM,
|
||||
severity = WARNING,
|
||||
@@ -146,37 +148,42 @@ public final class PrimitiveComparison extends BugChecker implements MethodInvoc
|
||||
return isStatic ? "comparing" : "thenComparing";
|
||||
}
|
||||
|
||||
// XXX: Use switch pattern matching once the targeted JDK supports this.
|
||||
private static Optional<Type> getPotentiallyBoxedReturnType(ExpressionTree tree) {
|
||||
switch (tree.getKind()) {
|
||||
case LAMBDA_EXPRESSION:
|
||||
/* Return the lambda expression's actual return type. */
|
||||
return Optional.ofNullable(ASTHelpers.getType(((LambdaExpressionTree) tree).getBody()));
|
||||
case MEMBER_REFERENCE:
|
||||
/* Return the method's declared return type. */
|
||||
// XXX: Very fragile. Do better.
|
||||
Type subType2 = ((JCMemberReference) tree).referentType;
|
||||
return Optional.of(subType2.getReturnType());
|
||||
default:
|
||||
/* This appears to be a genuine `{,ToInt,ToLong,ToDouble}Function`. */
|
||||
return Optional.empty();
|
||||
if (tree instanceof LambdaExpressionTree lambdaExpression) {
|
||||
/* Return the lambda expression's actual return type. */
|
||||
return Optional.ofNullable(ASTHelpers.getType(lambdaExpression.getBody()));
|
||||
}
|
||||
|
||||
// XXX: The match against a concrete type and reference to one of its fields is fragile. Do
|
||||
// better.
|
||||
if (tree instanceof JCMemberReference memberReference) {
|
||||
/* Return the method's declared return type. */
|
||||
Type subType = memberReference.referentType;
|
||||
return Optional.of(subType.getReturnType());
|
||||
}
|
||||
|
||||
/* This appears to be a genuine `{,ToInt,ToLong,ToDouble}Function`. */
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static Fix suggestFix(
|
||||
MethodInvocationTree tree, String preferredMethodName, VisitorState state) {
|
||||
ExpressionTree expr = tree.getMethodSelect();
|
||||
switch (expr.getKind()) {
|
||||
case IDENTIFIER:
|
||||
return SuggestedFix.builder()
|
||||
.addStaticImport(Comparator.class.getName() + '.' + preferredMethodName)
|
||||
.replace(expr, preferredMethodName)
|
||||
.build();
|
||||
case MEMBER_SELECT:
|
||||
MemberSelectTree ms = (MemberSelectTree) tree.getMethodSelect();
|
||||
return SuggestedFix.replace(
|
||||
ms, SourceCode.treeToString(ms.getExpression(), state) + '.' + preferredMethodName);
|
||||
default:
|
||||
throw new VerifyException("Unexpected type of expression: " + expr.getKind());
|
||||
|
||||
if (expr instanceof IdentifierTree) {
|
||||
return SuggestedFix.builder()
|
||||
.addStaticImport(Comparator.class.getName() + '.' + preferredMethodName)
|
||||
.replace(expr, preferredMethodName)
|
||||
.build();
|
||||
}
|
||||
|
||||
if (expr instanceof MemberSelectTree memberSelect) {
|
||||
return SuggestedFix.replace(
|
||||
memberSelect,
|
||||
SourceCode.treeToString(memberSelect.getExpression(), state) + '.' + preferredMethodName);
|
||||
}
|
||||
|
||||
throw new VerifyException("Unexpected type of expression: " + expr.getKind());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,36 +327,31 @@ public final class RedundantStringConversion extends BugChecker
|
||||
}
|
||||
|
||||
private Optional<ExpressionTree> trySimplify(ExpressionTree tree, VisitorState state) {
|
||||
if (tree.getKind() != Kind.METHOD_INVOCATION) {
|
||||
if (!(tree instanceof MethodInvocationTree methodInvocation)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
MethodInvocationTree methodInvocation = (MethodInvocationTree) tree;
|
||||
if (!conversionMethodMatcher.matches(methodInvocation, state)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
switch (methodInvocation.getArguments().size()) {
|
||||
case 0:
|
||||
return trySimplifyNullaryMethod(methodInvocation, state);
|
||||
case 1:
|
||||
return trySimplifyUnaryMethod(methodInvocation, state);
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"Cannot simplify method call with two or more arguments: "
|
||||
+ SourceCode.treeToString(tree, state));
|
||||
}
|
||||
return switch (methodInvocation.getArguments().size()) {
|
||||
case 0 -> trySimplifyNullaryMethod(methodInvocation, state);
|
||||
case 1 -> trySimplifyUnaryMethod(methodInvocation, state);
|
||||
default -> throw new IllegalStateException(
|
||||
"Cannot simplify method call with two or more arguments: "
|
||||
+ SourceCode.treeToString(tree, state));
|
||||
};
|
||||
}
|
||||
|
||||
private static Optional<ExpressionTree> trySimplifyNullaryMethod(
|
||||
MethodInvocationTree methodInvocation, VisitorState state) {
|
||||
if (!instanceMethod().matches(methodInvocation, state)) {
|
||||
if (!instanceMethod().matches(methodInvocation, state)
|
||||
|| !(methodInvocation.getMethodSelect() instanceof MemberSelectTree memberSelect)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(methodInvocation.getMethodSelect())
|
||||
.filter(methodSelect -> methodSelect.getKind() == Kind.MEMBER_SELECT)
|
||||
.map(methodSelect -> ((MemberSelectTree) methodSelect).getExpression())
|
||||
return Optional.of(memberSelect.getExpression())
|
||||
.filter(expr -> !"super".equals(SourceCode.treeToString(expr, state)));
|
||||
}
|
||||
|
||||
|
||||
@@ -42,21 +42,18 @@ public final class RefasterAnyOfUsage extends BugChecker implements MethodInvoca
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
if (REFASTER_ANY_OF.matches(tree, state)) {
|
||||
switch (tree.getArguments().size()) {
|
||||
case 0:
|
||||
// We can't safely fix this case; dropping the expression may produce non-compilable code.
|
||||
return describeMatch(tree);
|
||||
case 1:
|
||||
return describeMatch(
|
||||
tree,
|
||||
SuggestedFix.replace(
|
||||
tree, SourceCode.treeToString(tree.getArguments().get(0), state)));
|
||||
default:
|
||||
/* Handled below. */
|
||||
}
|
||||
int argumentCount = tree.getArguments().size();
|
||||
if (argumentCount > 1 || !REFASTER_ANY_OF.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return Description.NO_MATCH;
|
||||
if (argumentCount == 0) {
|
||||
/* We can't safely fix this case; dropping the expression may produce non-compilable code. */
|
||||
return describeMatch(tree);
|
||||
}
|
||||
|
||||
return describeMatch(
|
||||
tree,
|
||||
SuggestedFix.replace(tree, SourceCode.treeToString(tree.getArguments().get(0), state)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,9 +99,10 @@ public final class RequestMappingAnnotation extends BugChecker implements Method
|
||||
&& LACKS_PARAMETER_ANNOTATION.matches(tree, state)
|
||||
? buildDescription(tree)
|
||||
.setMessage(
|
||||
"Not all parameters of this request mapping method are annotated; this may be a "
|
||||
+ "mistake. If the unannotated parameters represent query string parameters, "
|
||||
+ "annotate them with `@RequestParam`.")
|
||||
"""
|
||||
Not all parameters of this request mapping method are annotated; this may be a \
|
||||
mistake. If the unannotated parameters represent query string parameters, annotate \
|
||||
them with `@RequestParam`.""")
|
||||
.build()
|
||||
: Description.NO_MATCH;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
@@ -24,7 +23,6 @@ import com.sun.source.tree.AssignmentTree;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.NewArrayTree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import java.util.Optional;
|
||||
import tech.picnic.errorprone.bugpatterns.util.AnnotationAttributeMatcher;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
@@ -79,31 +77,25 @@ public final class SpringMvcAnnotation extends BugChecker implements AnnotationT
|
||||
}
|
||||
|
||||
private static Optional<String> extractUniqueMethod(ExpressionTree arg, VisitorState state) {
|
||||
verify(
|
||||
arg.getKind() == Kind.ASSIGNMENT,
|
||||
"Annotation attribute is not an assignment: %s",
|
||||
arg.getKind());
|
||||
|
||||
ExpressionTree expr = ((AssignmentTree) arg).getExpression();
|
||||
if (expr.getKind() != Kind.NEW_ARRAY) {
|
||||
return Optional.of(extractMethod(expr, state));
|
||||
if (!(arg instanceof AssignmentTree assignment)) {
|
||||
throw new VerifyException("Annotation attribute is not an assignment:" + arg.getKind());
|
||||
}
|
||||
|
||||
NewArrayTree newArray = (NewArrayTree) expr;
|
||||
return Optional.of(newArray.getInitializers())
|
||||
.filter(args -> args.size() == 1)
|
||||
.map(args -> extractMethod(args.get(0), state));
|
||||
ExpressionTree expr = assignment.getExpression();
|
||||
return expr instanceof NewArrayTree newArray
|
||||
? Optional.of(newArray.getInitializers())
|
||||
.filter(args -> args.size() == 1)
|
||||
.map(args -> extractMethod(args.get(0), state))
|
||||
: Optional.of(extractMethod(expr, state));
|
||||
}
|
||||
|
||||
// XXX: Use switch pattern matching once the targeted JDK supports this.
|
||||
private static String extractMethod(ExpressionTree expr, VisitorState state) {
|
||||
switch (expr.getKind()) {
|
||||
case IDENTIFIER:
|
||||
return SourceCode.treeToString(expr, state);
|
||||
case MEMBER_SELECT:
|
||||
return ((MemberSelectTree) expr).getIdentifier().toString();
|
||||
default:
|
||||
throw new VerifyException("Unexpected type of expression: " + expr.getKind());
|
||||
}
|
||||
return switch (expr.getKind()) {
|
||||
case IDENTIFIER -> SourceCode.treeToString(expr, state);
|
||||
case MEMBER_SELECT -> ((MemberSelectTree) expr).getIdentifier().toString();
|
||||
default -> throw new VerifyException("Unexpected type of expression: " + expr.getKind());
|
||||
};
|
||||
}
|
||||
|
||||
private static Fix replaceAnnotation(
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -176,15 +177,10 @@ public final class StaticImport extends BugChecker implements MemberSelectTreeMa
|
||||
Tree parentTree =
|
||||
requireNonNull(state.getPath().getParentPath(), "MemberSelectTree lacks enclosing node")
|
||||
.getLeaf();
|
||||
switch (parentTree.getKind()) {
|
||||
case IMPORT:
|
||||
case MEMBER_SELECT:
|
||||
return false;
|
||||
case METHOD_INVOCATION:
|
||||
return ((MethodInvocationTree) parentTree).getTypeArguments().isEmpty();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return parentTree instanceof MethodInvocationTree methodInvocation
|
||||
? methodInvocation.getTypeArguments().isEmpty()
|
||||
: (parentTree.getKind() != Kind.IMPORT && parentTree.getKind() != Kind.MEMBER_SELECT);
|
||||
}
|
||||
|
||||
private static boolean isCandidate(MemberSelectTree tree) {
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.AssignmentTree;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
@@ -116,8 +115,8 @@ public final class AnnotationAttributeMatcher implements Serializable {
|
||||
}
|
||||
|
||||
private static String extractAttributeName(ExpressionTree expr) {
|
||||
return (expr.getKind() == Kind.ASSIGNMENT)
|
||||
? ASTHelpers.getSymbol(((AssignmentTree) expr).getVariable()).getSimpleName().toString()
|
||||
return (expr instanceof AssignmentTree assignment)
|
||||
? ASTHelpers.getSymbol(assignment.getVariable()).getSimpleName().toString()
|
||||
: "value";
|
||||
}
|
||||
|
||||
|
||||
@@ -99,14 +99,13 @@ public final class MoreJUnitMatchers {
|
||||
String methodName = method.getName().toString();
|
||||
ExpressionTree value = AnnotationMatcherUtils.getArgument(methodSourceAnnotation, "value");
|
||||
|
||||
if (!(value instanceof NewArrayTree)) {
|
||||
if (!(value instanceof NewArrayTree newArray)) {
|
||||
return ImmutableList.of(toMethodSourceFactoryDescriptor(value, methodName));
|
||||
}
|
||||
|
||||
return ((NewArrayTree) value)
|
||||
.getInitializers().stream()
|
||||
.map(name -> toMethodSourceFactoryDescriptor(name, methodName))
|
||||
.collect(toImmutableList());
|
||||
return newArray.getInitializers().stream()
|
||||
.map(name -> toMethodSourceFactoryDescriptor(name, methodName))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
private static String toMethodSourceFactoryDescriptor(
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.util.ErrorProneToken;
|
||||
import com.google.errorprone.util.ErrorProneTokens;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
@@ -26,8 +27,30 @@ public final class SourceCode {
|
||||
/** The complement of {@link CharMatcher#whitespace()}. */
|
||||
private static final CharMatcher NON_WHITESPACE_MATCHER = CharMatcher.whitespace().negate();
|
||||
|
||||
// XXX: Proper name for this?
|
||||
private static final String TEXT_BLOCK_MARKER = "\"\"\"";
|
||||
|
||||
private SourceCode() {}
|
||||
|
||||
/**
|
||||
* Tells whether the given expression is a text block.
|
||||
*
|
||||
* @param tree The AST node of interest.
|
||||
* @param state A {@link VisitorState} describing the context in which the given {@link
|
||||
* ExpressionTree} is found.
|
||||
* @return {@code true} iff the given expression is a text block.
|
||||
*/
|
||||
// XXX: Add tests!
|
||||
public static boolean isTextBlock(ExpressionTree tree, VisitorState state) {
|
||||
if (tree.getKind() != Tree.Kind.STRING_LITERAL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the source code is unavailable then we assume that this literal is _not_ a text block. */
|
||||
String src = state.getSourceForNode(tree);
|
||||
return src != null && src.startsWith(TEXT_BLOCK_MARKER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the given {@link Tree}, preferring the original source code
|
||||
* (if available) over its prettified representation.
|
||||
|
||||
@@ -75,8 +75,12 @@ public enum ThirdPartyLibrary {
|
||||
*
|
||||
* <p>The {@link VisitorState}'s symbol table is consulted first. If the type has not yet been
|
||||
* loaded, then an attempt is made to do so.
|
||||
*
|
||||
* @param className The type of interest.
|
||||
* @param state The context under consideration.
|
||||
* @return {@code true} iff the indicated type is on the classpath.
|
||||
*/
|
||||
private static boolean isKnownClass(String className, VisitorState state) {
|
||||
public static boolean isKnownClass(String className, VisitorState state) {
|
||||
return state.getTypeFromString(className) != null || canLoadClass(className, state);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ final class StringRules {
|
||||
private StringRules() {}
|
||||
|
||||
/** Prefer {@link String#isEmpty()} over alternatives that consult the string's length. */
|
||||
// XXX: Once we target JDK 15+, generalize this rule to cover all `CharSequence` subtypes.
|
||||
// XXX: Now that we build with JDK 15+, this rule can be generalized to cover all `CharSequence`
|
||||
// subtypes. This does require a mechanism (perhaps an annotation, or a separate Maven module) to
|
||||
// make sure that non-String expressions are rewritten only if client code also targets JDK 15+.
|
||||
static final class StringIsEmpty {
|
||||
@BeforeTemplate
|
||||
boolean before(String str) {
|
||||
@@ -44,7 +46,9 @@ final class StringRules {
|
||||
}
|
||||
|
||||
/** Prefer a method reference to {@link String#isEmpty()} over the equivalent lambda function. */
|
||||
// XXX: Once we target JDK 15+, generalize this rule to cover all `CharSequence` subtypes.
|
||||
// XXX: Now that we build with JDK 15+, this rule can be generalized to cover all `CharSequence`
|
||||
// subtypes. However, `CharSequence::isEmpty` isn't as nice as `String::isEmpty`, so we might want
|
||||
// to introduce a rule that suggests `String::isEmpty` where possible.
|
||||
// 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.
|
||||
static final class StringIsEmptyPredicate {
|
||||
@@ -60,7 +64,9 @@ final class StringRules {
|
||||
}
|
||||
|
||||
/** Prefer a method reference to {@link String#isEmpty()} over the equivalent lambda function. */
|
||||
// XXX: Once we target JDK 15+, generalize this rule to cover all `CharSequence` subtypes.
|
||||
// XXX: Now that we build with JDK 15+, this rule can be generalized to cover all `CharSequence`
|
||||
// subtypes. However, `CharSequence::isEmpty` isn't as nice as `String::isEmpty`, so we might want
|
||||
// to introduce a rule that suggests `String::isEmpty` where possible.
|
||||
static final class StringIsNotEmptyPredicate {
|
||||
@BeforeTemplate
|
||||
Predicate<String> before() {
|
||||
|
||||
@@ -13,99 +13,101 @@ final class AmbiguousJsonCreatorTest {
|
||||
"X", m -> m.contains("`JsonCreator.Mode` should be set for single-argument creators"))
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import com.fasterxml.jackson.annotation.JsonCreator;",
|
||||
"import com.fasterxml.jackson.annotation.JsonValue;",
|
||||
"",
|
||||
"interface Container {",
|
||||
" enum A {",
|
||||
" FOO(1);",
|
||||
"",
|
||||
" private final int i;",
|
||||
"",
|
||||
" A(int i) {",
|
||||
" this.i = i;",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic matches: X",
|
||||
" @JsonCreator",
|
||||
" public static A of(int i) {",
|
||||
" return FOO;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" enum B {",
|
||||
" FOO(1);",
|
||||
"",
|
||||
" private final int i;",
|
||||
"",
|
||||
" B(int i) {",
|
||||
" this.i = i;",
|
||||
" }",
|
||||
"",
|
||||
" @JsonCreator(mode = JsonCreator.Mode.DELEGATING)",
|
||||
" public static B of(int i) {",
|
||||
" return FOO;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" enum C {",
|
||||
" FOO(1, \"s\");",
|
||||
"",
|
||||
" @JsonValue private final int i;",
|
||||
" private final String s;",
|
||||
"",
|
||||
" C(int i, String s) {",
|
||||
" this.i = i;",
|
||||
" this.s = s;",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic matches: X",
|
||||
" @JsonCreator",
|
||||
" public static C of(int i) {",
|
||||
" return FOO;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" enum D {",
|
||||
" FOO(1, \"s\");",
|
||||
"",
|
||||
" private final int i;",
|
||||
" private final String s;",
|
||||
"",
|
||||
" D(int i, String s) {",
|
||||
" this.i = i;",
|
||||
" this.s = s;",
|
||||
" }",
|
||||
"",
|
||||
" @JsonCreator",
|
||||
" public static D of(int i, String s) {",
|
||||
" return FOO;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" enum E {",
|
||||
" FOO;",
|
||||
"",
|
||||
" // BUG: Diagnostic matches: X",
|
||||
" @JsonCreator",
|
||||
" public static E of(String s) {",
|
||||
" return FOO;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" class F {",
|
||||
" private final String s;",
|
||||
"",
|
||||
" F(String s) {",
|
||||
" this.s = s;",
|
||||
" }",
|
||||
"",
|
||||
" @JsonCreator",
|
||||
" public static F of(String s) {",
|
||||
" return new F(s);",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
interface Container {
|
||||
enum A {
|
||||
FOO(1);
|
||||
|
||||
private final int i;
|
||||
|
||||
A(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
// BUG: Diagnostic matches: X
|
||||
@JsonCreator
|
||||
public static A of(int i) {
|
||||
return FOO;
|
||||
}
|
||||
}
|
||||
|
||||
enum B {
|
||||
FOO(1);
|
||||
|
||||
private final int i;
|
||||
|
||||
B(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||
public static B of(int i) {
|
||||
return FOO;
|
||||
}
|
||||
}
|
||||
|
||||
enum C {
|
||||
FOO(1, "s");
|
||||
|
||||
@JsonValue private final int i;
|
||||
private final String s;
|
||||
|
||||
C(int i, String s) {
|
||||
this.i = i;
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
// BUG: Diagnostic matches: X
|
||||
@JsonCreator
|
||||
public static C of(int i) {
|
||||
return FOO;
|
||||
}
|
||||
}
|
||||
|
||||
enum D {
|
||||
FOO(1, "s");
|
||||
|
||||
private final int i;
|
||||
private final String s;
|
||||
|
||||
D(int i, String s) {
|
||||
this.i = i;
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static D of(int i, String s) {
|
||||
return FOO;
|
||||
}
|
||||
}
|
||||
|
||||
enum E {
|
||||
FOO;
|
||||
|
||||
// BUG: Diagnostic matches: X
|
||||
@JsonCreator
|
||||
public static E of(String s) {
|
||||
return FOO;
|
||||
}
|
||||
}
|
||||
|
||||
class F {
|
||||
private final String s;
|
||||
|
||||
F(String s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static F of(String s) {
|
||||
return new F(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -114,28 +116,32 @@ final class AmbiguousJsonCreatorTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(AmbiguousJsonCreator.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.fasterxml.jackson.annotation.JsonCreator;",
|
||||
"",
|
||||
"enum A {",
|
||||
" FOO;",
|
||||
"",
|
||||
" @JsonCreator",
|
||||
" public static A of(String s) {",
|
||||
" return FOO;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
enum A {
|
||||
FOO;
|
||||
|
||||
@JsonCreator
|
||||
public static A of(String s) {
|
||||
return FOO;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.fasterxml.jackson.annotation.JsonCreator;",
|
||||
"",
|
||||
"enum A {",
|
||||
" FOO;",
|
||||
"",
|
||||
" @JsonCreator(mode = JsonCreator.Mode.DELEGATING)",
|
||||
" public static A of(String s) {",
|
||||
" return FOO;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
enum A {
|
||||
FOO;
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||
public static A of(String s) {
|
||||
return FOO;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,22 +11,24 @@ final class AssertJIsNullTest {
|
||||
CompilationTestHelper.newInstance(AssertJIsNull.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" assertThat(1).isEqualTo(1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(1).isEqualTo(null);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(\"foo\").isEqualTo(null);",
|
||||
" isEqualTo(null);",
|
||||
" }",
|
||||
"",
|
||||
" private boolean isEqualTo(Object value) {",
|
||||
" return value.equals(\"bar\");",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
assertThat(1).isEqualTo(1);
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(1).isEqualTo(null);
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat("foo").isEqualTo(null);
|
||||
isEqualTo(null);
|
||||
}
|
||||
|
||||
private boolean isEqualTo(Object value) {
|
||||
return value.equals("bar");
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -35,24 +37,28 @@ final class AssertJIsNullTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(AssertJIsNull.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" assertThat(1).isEqualTo(null);",
|
||||
" assertThat(\"foo\").isEqualTo(null);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
assertThat(1).isEqualTo(null);
|
||||
assertThat("foo").isEqualTo(null);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" assertThat(1).isNull();",
|
||||
" assertThat(\"foo\").isNull();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
assertThat(1).isNull();
|
||||
assertThat("foo").isNull();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,44 +11,46 @@ final class AssociativeMethodInvocationTest {
|
||||
CompilationTestHelper.newInstance(AssociativeMethodInvocation.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.errorprone.matchers.Matchers;",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Matchers.allOf();",
|
||||
" Matchers.anyOf();",
|
||||
" Refaster.anyOf();",
|
||||
"",
|
||||
" Matchers.allOf((t, s) -> true);",
|
||||
" Matchers.anyOf((t, s) -> true);",
|
||||
" Refaster.anyOf(0);",
|
||||
"",
|
||||
" Matchers.allOf(Matchers.anyOf((t, s) -> true));",
|
||||
" Matchers.anyOf(Matchers.allOf((t, s) -> true));",
|
||||
" Refaster.anyOf(Matchers.allOf((t, s) -> true));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Matchers.allOf(Matchers.allOf((t, s) -> true));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Matchers.anyOf(Matchers.anyOf((t, s) -> true));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Refaster.anyOf(Refaster.anyOf(0));",
|
||||
"",
|
||||
" Matchers.allOf(Matchers.allOf(ImmutableList.of((t, s) -> true)));",
|
||||
" Matchers.anyOf(Matchers.anyOf(ImmutableList.of((t, s) -> true)));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Matchers.allOf(",
|
||||
" (t, s) -> true, Matchers.allOf((t, s) -> false, (t, s) -> true), (t, s) -> false);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Matchers.anyOf(",
|
||||
" (t, s) -> true, Matchers.anyOf((t, s) -> false, (t, s) -> true), (t, s) -> false);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Refaster.anyOf(0, Refaster.anyOf(1, 2), 3);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.matchers.Matchers;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Matchers.allOf();
|
||||
Matchers.anyOf();
|
||||
Refaster.anyOf();
|
||||
|
||||
Matchers.allOf((t, s) -> true);
|
||||
Matchers.anyOf((t, s) -> true);
|
||||
Refaster.anyOf(0);
|
||||
|
||||
Matchers.allOf(Matchers.anyOf((t, s) -> true));
|
||||
Matchers.anyOf(Matchers.allOf((t, s) -> true));
|
||||
Refaster.anyOf(Matchers.allOf((t, s) -> true));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Matchers.allOf(Matchers.allOf((t, s) -> true));
|
||||
// BUG: Diagnostic contains:
|
||||
Matchers.anyOf(Matchers.anyOf((t, s) -> true));
|
||||
// BUG: Diagnostic contains:
|
||||
Refaster.anyOf(Refaster.anyOf(0));
|
||||
|
||||
Matchers.allOf(Matchers.allOf(ImmutableList.of((t, s) -> true)));
|
||||
Matchers.anyOf(Matchers.anyOf(ImmutableList.of((t, s) -> true)));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Matchers.allOf(
|
||||
(t, s) -> true, Matchers.allOf((t, s) -> false, (t, s) -> true), (t, s) -> false);
|
||||
// BUG: Diagnostic contains:
|
||||
Matchers.anyOf(
|
||||
(t, s) -> true, Matchers.anyOf((t, s) -> false, (t, s) -> true), (t, s) -> false);
|
||||
// BUG: Diagnostic contains:
|
||||
Refaster.anyOf(0, Refaster.anyOf(1, 2), 3);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -57,54 +59,58 @@ final class AssociativeMethodInvocationTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(AssociativeMethodInvocation.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.matchers.Matchers;",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Matchers.allOf(Matchers.allOf());",
|
||||
" Matchers.anyOf(Matchers.anyOf());",
|
||||
" Refaster.anyOf(Refaster.anyOf());",
|
||||
"",
|
||||
" Matchers.allOf(Matchers.allOf((t, s) -> true));",
|
||||
" Matchers.anyOf(Matchers.anyOf((t, s) -> true));",
|
||||
" Refaster.anyOf(Refaster.anyOf(0));",
|
||||
"",
|
||||
" Matchers.allOf(",
|
||||
" Matchers.anyOf(),",
|
||||
" Matchers.allOf((t, s) -> false, (t, s) -> true),",
|
||||
" Matchers.allOf(),",
|
||||
" Matchers.anyOf((t, s) -> false));",
|
||||
" Matchers.anyOf(",
|
||||
" Matchers.allOf(),",
|
||||
" Matchers.anyOf((t, s) -> false, (t, s) -> true),",
|
||||
" Matchers.anyOf(),",
|
||||
" Matchers.allOf((t, s) -> false));",
|
||||
" Refaster.anyOf(Matchers.allOf(), Refaster.anyOf(1, 2), Matchers.anyOf());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.matchers.Matchers;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Matchers.allOf(Matchers.allOf());
|
||||
Matchers.anyOf(Matchers.anyOf());
|
||||
Refaster.anyOf(Refaster.anyOf());
|
||||
|
||||
Matchers.allOf(Matchers.allOf((t, s) -> true));
|
||||
Matchers.anyOf(Matchers.anyOf((t, s) -> true));
|
||||
Refaster.anyOf(Refaster.anyOf(0));
|
||||
|
||||
Matchers.allOf(
|
||||
Matchers.anyOf(),
|
||||
Matchers.allOf((t, s) -> false, (t, s) -> true),
|
||||
Matchers.allOf(),
|
||||
Matchers.anyOf((t, s) -> false));
|
||||
Matchers.anyOf(
|
||||
Matchers.allOf(),
|
||||
Matchers.anyOf((t, s) -> false, (t, s) -> true),
|
||||
Matchers.anyOf(),
|
||||
Matchers.allOf((t, s) -> false));
|
||||
Refaster.anyOf(Matchers.allOf(), Refaster.anyOf(1, 2), Matchers.anyOf());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.matchers.Matchers;",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Matchers.allOf();",
|
||||
" Matchers.anyOf();",
|
||||
" Refaster.anyOf();",
|
||||
"",
|
||||
" Matchers.allOf((t, s) -> true);",
|
||||
" Matchers.anyOf((t, s) -> true);",
|
||||
" Refaster.anyOf(0);",
|
||||
"",
|
||||
" Matchers.allOf(",
|
||||
" Matchers.anyOf(), (t, s) -> false, (t, s) -> true, Matchers.anyOf((t, s) -> false));",
|
||||
" Matchers.anyOf(",
|
||||
" Matchers.allOf(), (t, s) -> false, (t, s) -> true, Matchers.allOf((t, s) -> false));",
|
||||
" Refaster.anyOf(Matchers.allOf(), 1, 2, Matchers.anyOf());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.matchers.Matchers;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Matchers.allOf();
|
||||
Matchers.anyOf();
|
||||
Refaster.anyOf();
|
||||
|
||||
Matchers.allOf((t, s) -> true);
|
||||
Matchers.anyOf((t, s) -> true);
|
||||
Refaster.anyOf(0);
|
||||
|
||||
Matchers.allOf(
|
||||
Matchers.anyOf(), (t, s) -> false, (t, s) -> true, Matchers.anyOf((t, s) -> false));
|
||||
Matchers.anyOf(
|
||||
Matchers.allOf(), (t, s) -> false, (t, s) -> true, Matchers.allOf((t, s) -> false));
|
||||
Refaster.anyOf(Matchers.allOf(), 1, 2, Matchers.anyOf());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,56 +11,58 @@ final class AutowiredConstructorTest {
|
||||
CompilationTestHelper.newInstance(AutowiredConstructor.class, getClass())
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import com.google.errorprone.annotations.Immutable;",
|
||||
"import java.util.List;",
|
||||
"import org.springframework.beans.factory.annotation.Autowired;",
|
||||
"",
|
||||
"interface Container {",
|
||||
" @Immutable",
|
||||
" class A {",
|
||||
" A() {}",
|
||||
" }",
|
||||
"",
|
||||
" class B {",
|
||||
" @Autowired",
|
||||
" void setProperty(Object o) {}",
|
||||
" }",
|
||||
"",
|
||||
" class C {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Autowired",
|
||||
" C() {}",
|
||||
" }",
|
||||
"",
|
||||
" class D {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Autowired",
|
||||
" D(String x) {}",
|
||||
" }",
|
||||
"",
|
||||
" class E {",
|
||||
" @Autowired",
|
||||
" E() {}",
|
||||
"",
|
||||
" E(String x) {}",
|
||||
" }",
|
||||
"",
|
||||
" class F {",
|
||||
" F() {}",
|
||||
"",
|
||||
" @Autowired",
|
||||
" F(String x) {}",
|
||||
" }",
|
||||
"",
|
||||
" class G {",
|
||||
" @Autowired private Object o;",
|
||||
" }",
|
||||
"",
|
||||
" class H {",
|
||||
" @SafeVarargs",
|
||||
" H(List<String>... lists) {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.annotations.Immutable;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
interface Container {
|
||||
@Immutable
|
||||
class A {
|
||||
A() {}
|
||||
}
|
||||
|
||||
class B {
|
||||
@Autowired
|
||||
void setProperty(Object o) {}
|
||||
}
|
||||
|
||||
class C {
|
||||
// BUG: Diagnostic contains:
|
||||
@Autowired
|
||||
C() {}
|
||||
}
|
||||
|
||||
class D {
|
||||
// BUG: Diagnostic contains:
|
||||
@Autowired
|
||||
D(String x) {}
|
||||
}
|
||||
|
||||
class E {
|
||||
@Autowired
|
||||
E() {}
|
||||
|
||||
E(String x) {}
|
||||
}
|
||||
|
||||
class F {
|
||||
F() {}
|
||||
|
||||
@Autowired
|
||||
F(String x) {}
|
||||
}
|
||||
|
||||
class G {
|
||||
@Autowired private Object o;
|
||||
}
|
||||
|
||||
class H {
|
||||
@SafeVarargs
|
||||
H(List<String>... lists) {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -69,34 +71,38 @@ final class AutowiredConstructorTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(AutowiredConstructor.class, getClass())
|
||||
.addInputLines(
|
||||
"Container.java",
|
||||
"import org.springframework.beans.factory.annotation.Autowired;",
|
||||
"",
|
||||
"interface Container {",
|
||||
" class A {",
|
||||
" @Autowired",
|
||||
" @Deprecated",
|
||||
" A() {}",
|
||||
" }",
|
||||
"",
|
||||
" class B {",
|
||||
" @Autowired",
|
||||
" B(String x) {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
interface Container {
|
||||
class A {
|
||||
@Autowired
|
||||
@Deprecated
|
||||
A() {}
|
||||
}
|
||||
|
||||
class B {
|
||||
@Autowired
|
||||
B(String x) {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"Container.java",
|
||||
"import org.springframework.beans.factory.annotation.Autowired;",
|
||||
"",
|
||||
"interface Container {",
|
||||
" class A {",
|
||||
" @Deprecated",
|
||||
" A() {}",
|
||||
" }",
|
||||
"",
|
||||
" class B {",
|
||||
" B(String x) {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
interface Container {
|
||||
class A {
|
||||
@Deprecated
|
||||
A() {}
|
||||
}
|
||||
|
||||
class B {
|
||||
B(String x) {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,128 +11,130 @@ final class CanonicalAnnotationSyntaxTest {
|
||||
CompilationTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass())
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" int[] value() default {};",
|
||||
"",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo",
|
||||
" A minimal1();",
|
||||
"",
|
||||
" @A.Foo",
|
||||
" A minimal2();",
|
||||
"",
|
||||
" @Foo",
|
||||
" A minimal3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo()",
|
||||
" A functional1();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo()",
|
||||
" A functional2();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo()",
|
||||
" A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(1)",
|
||||
" A simple1();",
|
||||
"",
|
||||
" @A.Foo(1)",
|
||||
" A simple2();",
|
||||
"",
|
||||
" @Foo(1)",
|
||||
" A simple3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo({1})",
|
||||
" A singleton1();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo({1})",
|
||||
" A singleton2();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({1})",
|
||||
" A singleton3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo(value = 1)",
|
||||
" A verbose1();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo(value = 1)",
|
||||
" A verbose2();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(value = 1)",
|
||||
" A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value2 = 2)",
|
||||
" A custom1();",
|
||||
"",
|
||||
" @A.Foo(value2 = 2)",
|
||||
" A custom2();",
|
||||
"",
|
||||
" @Foo(value2 = 2)",
|
||||
" A custom3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo(value2 = {2})",
|
||||
" A customSingleton1();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo(value2 = {2})",
|
||||
" A customSingleton2();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(value2 = {2})",
|
||||
" A customSingleton3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value2 = {2, 2})",
|
||||
" A customPair1();",
|
||||
"",
|
||||
" @A.Foo(value2 = {2, 2})",
|
||||
" A customPair2();",
|
||||
"",
|
||||
" @Foo(value2 = {2, 2})",
|
||||
" A customPair3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = 1, value2 = 2)",
|
||||
" A extended1();",
|
||||
"",
|
||||
" @A.Foo(value = 1, value2 = 2)",
|
||||
" A extended2();",
|
||||
"",
|
||||
" @Foo(value = 1, value2 = 2)",
|
||||
" A extended3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo({",
|
||||
" 1, 1,",
|
||||
" })",
|
||||
" A trailingComma1();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo({",
|
||||
" 1, 1,",
|
||||
" })",
|
||||
" A trailingComma2();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({",
|
||||
" 1, 1,",
|
||||
" })",
|
||||
" A trailingComma3();",
|
||||
"}")
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
import pkg.A.Foo;
|
||||
|
||||
interface A {
|
||||
@interface Foo {
|
||||
int[] value() default {};
|
||||
|
||||
int[] value2() default {};
|
||||
}
|
||||
|
||||
@pkg.A.Foo
|
||||
A minimal1();
|
||||
|
||||
@A.Foo
|
||||
A minimal2();
|
||||
|
||||
@Foo
|
||||
A minimal3();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@pkg.A.Foo()
|
||||
A functional1();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@A.Foo()
|
||||
A functional2();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo()
|
||||
A functional3();
|
||||
|
||||
@pkg.A.Foo(1)
|
||||
A simple1();
|
||||
|
||||
@A.Foo(1)
|
||||
A simple2();
|
||||
|
||||
@Foo(1)
|
||||
A simple3();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@pkg.A.Foo({1})
|
||||
A singleton1();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@A.Foo({1})
|
||||
A singleton2();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo({1})
|
||||
A singleton3();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@pkg.A.Foo(value = 1)
|
||||
A verbose1();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@A.Foo(value = 1)
|
||||
A verbose2();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo(value = 1)
|
||||
A verbose3();
|
||||
|
||||
@pkg.A.Foo(value2 = 2)
|
||||
A custom1();
|
||||
|
||||
@A.Foo(value2 = 2)
|
||||
A custom2();
|
||||
|
||||
@Foo(value2 = 2)
|
||||
A custom3();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@pkg.A.Foo(value2 = {2})
|
||||
A customSingleton1();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@A.Foo(value2 = {2})
|
||||
A customSingleton2();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo(value2 = {2})
|
||||
A customSingleton3();
|
||||
|
||||
@pkg.A.Foo(value2 = {2, 2})
|
||||
A customPair1();
|
||||
|
||||
@A.Foo(value2 = {2, 2})
|
||||
A customPair2();
|
||||
|
||||
@Foo(value2 = {2, 2})
|
||||
A customPair3();
|
||||
|
||||
@pkg.A.Foo(value = 1, value2 = 2)
|
||||
A extended1();
|
||||
|
||||
@A.Foo(value = 1, value2 = 2)
|
||||
A extended2();
|
||||
|
||||
@Foo(value = 1, value2 = 2)
|
||||
A extended3();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@pkg.A.Foo({
|
||||
1, 1,
|
||||
})
|
||||
A trailingComma1();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@A.Foo({
|
||||
1, 1,
|
||||
})
|
||||
A trailingComma2();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo({
|
||||
1, 1,
|
||||
})
|
||||
A trailingComma3();
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -141,139 +143,143 @@ final class CanonicalAnnotationSyntaxTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass())
|
||||
.addInputLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo()",
|
||||
" A functional1();",
|
||||
"",
|
||||
" @A.Foo()",
|
||||
" A functional2();",
|
||||
"",
|
||||
" @Foo()",
|
||||
" A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = \"foo\")",
|
||||
" A verbose1();",
|
||||
"",
|
||||
" @A.Foo(value = \"a'b\")",
|
||||
" A verbose2();",
|
||||
"",
|
||||
" @Foo(value = \"a\" + \"\\nb\")",
|
||||
" A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = {\"foo\"})",
|
||||
" A moreVerbose1();",
|
||||
"",
|
||||
" @A.Foo(value = {\"a'b\"})",
|
||||
" A moreVerbose2();",
|
||||
"",
|
||||
" @Foo(value = {\"a\" + \"\\nb\"})",
|
||||
" A moreVerbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(",
|
||||
" value = {\"foo\", \"bar\"},",
|
||||
" value2 = {2})",
|
||||
" A extended1();",
|
||||
"",
|
||||
" @A.Foo(",
|
||||
" value = {\"a'b\", \"c'd\"},",
|
||||
" value2 = {2})",
|
||||
" A extended2();",
|
||||
"",
|
||||
" @Foo(",
|
||||
" value = {\"a\" + \"\\nb\", \"c\" + \"\\nd\"},",
|
||||
" value2 = {2})",
|
||||
" A extended3();",
|
||||
"",
|
||||
" @pkg.A.Foo({",
|
||||
" \"foo\", \"bar\",",
|
||||
" })",
|
||||
" A trailingComma1();",
|
||||
"",
|
||||
" @A.Foo({",
|
||||
" \"a'b\", \"c'd\",",
|
||||
" })",
|
||||
" A trailingComma2();",
|
||||
"",
|
||||
" @Foo({",
|
||||
" \"a\" + \"\\nb\",",
|
||||
" \"c\" + \"\\nd\",",
|
||||
" })",
|
||||
" A trailingComma3();",
|
||||
"}")
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
import pkg.A.Foo;
|
||||
|
||||
interface A {
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
int[] value2() default {};
|
||||
}
|
||||
|
||||
@pkg.A.Foo()
|
||||
A functional1();
|
||||
|
||||
@A.Foo()
|
||||
A functional2();
|
||||
|
||||
@Foo()
|
||||
A functional3();
|
||||
|
||||
@pkg.A.Foo(value = "foo")
|
||||
A verbose1();
|
||||
|
||||
@A.Foo(value = "a'b")
|
||||
A verbose2();
|
||||
|
||||
@Foo(value = "a" + "\\nb")
|
||||
A verbose3();
|
||||
|
||||
@pkg.A.Foo(value = {"foo"})
|
||||
A moreVerbose1();
|
||||
|
||||
@A.Foo(value = {"a'b"})
|
||||
A moreVerbose2();
|
||||
|
||||
@Foo(value = {"a" + "\\nb"})
|
||||
A moreVerbose3();
|
||||
|
||||
@pkg.A.Foo(
|
||||
value = {"foo", "bar"},
|
||||
value2 = {2})
|
||||
A extended1();
|
||||
|
||||
@A.Foo(
|
||||
value = {"a'b", "c'd"},
|
||||
value2 = {2})
|
||||
A extended2();
|
||||
|
||||
@Foo(
|
||||
value = {"a" + "\\nb", "c" + "\\nd"},
|
||||
value2 = {2})
|
||||
A extended3();
|
||||
|
||||
@pkg.A.Foo({
|
||||
"foo", "bar",
|
||||
})
|
||||
A trailingComma1();
|
||||
|
||||
@A.Foo({
|
||||
"a'b", "c'd",
|
||||
})
|
||||
A trailingComma2();
|
||||
|
||||
@Foo({
|
||||
"a" + "\\nb",
|
||||
"c" + "\\nd",
|
||||
})
|
||||
A trailingComma3();
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo",
|
||||
" A functional1();",
|
||||
"",
|
||||
" @A.Foo",
|
||||
" A functional2();",
|
||||
"",
|
||||
" @Foo",
|
||||
" A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(\"foo\")",
|
||||
" A verbose1();",
|
||||
"",
|
||||
" @A.Foo(\"a'b\")",
|
||||
" A verbose2();",
|
||||
"",
|
||||
" @Foo(\"a\" + \"\\nb\")",
|
||||
" A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(\"foo\")",
|
||||
" A moreVerbose1();",
|
||||
"",
|
||||
" @A.Foo(\"a'b\")",
|
||||
" A moreVerbose2();",
|
||||
"",
|
||||
" @Foo(\"a\" + \"\\nb\")",
|
||||
" A moreVerbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(",
|
||||
" value = {\"foo\", \"bar\"},",
|
||||
" value2 = 2)",
|
||||
" A extended1();",
|
||||
"",
|
||||
" @A.Foo(",
|
||||
" value = {\"a'b\", \"c'd\"},",
|
||||
" value2 = 2)",
|
||||
" A extended2();",
|
||||
"",
|
||||
" @Foo(",
|
||||
" value = {\"a\" + \"\\nb\", \"c\" + \"\\nd\"},",
|
||||
" value2 = 2)",
|
||||
" A extended3();",
|
||||
"",
|
||||
" @pkg.A.Foo({\"foo\", \"bar\"})",
|
||||
" A trailingComma1();",
|
||||
"",
|
||||
" @A.Foo({\"a'b\", \"c'd\"})",
|
||||
" A trailingComma2();",
|
||||
"",
|
||||
" @Foo({\"a\" + \"\\nb\", \"c\" + \"\\nd\"})",
|
||||
" A trailingComma3();",
|
||||
"}")
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
import pkg.A.Foo;
|
||||
|
||||
interface A {
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
int[] value2() default {};
|
||||
}
|
||||
|
||||
@pkg.A.Foo
|
||||
A functional1();
|
||||
|
||||
@A.Foo
|
||||
A functional2();
|
||||
|
||||
@Foo
|
||||
A functional3();
|
||||
|
||||
@pkg.A.Foo("foo")
|
||||
A verbose1();
|
||||
|
||||
@A.Foo("a'b")
|
||||
A verbose2();
|
||||
|
||||
@Foo("a" + "\\nb")
|
||||
A verbose3();
|
||||
|
||||
@pkg.A.Foo("foo")
|
||||
A moreVerbose1();
|
||||
|
||||
@A.Foo("a'b")
|
||||
A moreVerbose2();
|
||||
|
||||
@Foo("a" + "\\nb")
|
||||
A moreVerbose3();
|
||||
|
||||
@pkg.A.Foo(
|
||||
value = {"foo", "bar"},
|
||||
value2 = 2)
|
||||
A extended1();
|
||||
|
||||
@A.Foo(
|
||||
value = {"a'b", "c'd"},
|
||||
value2 = 2)
|
||||
A extended2();
|
||||
|
||||
@Foo(
|
||||
value = {"a" + "\\nb", "c" + "\\nd"},
|
||||
value2 = 2)
|
||||
A extended3();
|
||||
|
||||
@pkg.A.Foo({"foo", "bar"})
|
||||
A trailingComma1();
|
||||
|
||||
@A.Foo({"a'b", "c'd"})
|
||||
A trailingComma2();
|
||||
|
||||
@Foo({"a" + "\\nb", "c" + "\\nd"})
|
||||
A trailingComma3();
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,50 +13,52 @@ final class CollectorMutabilityTest {
|
||||
CompilationTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
"import static com.google.common.collect.ImmutableMap.toImmutableMap;",
|
||||
"import static com.google.common.collect.ImmutableSet.toImmutableSet;",
|
||||
"import static java.util.stream.Collectors.toCollection;",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.HashMap;",
|
||||
"import java.util.HashSet;",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collect(Collectors.toList());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(2).collect(toList());",
|
||||
" Flux.just(3).collect(toImmutableList());",
|
||||
" Flux.just(4).collect(toCollection(ArrayList::new));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(\"foo\").collect(Collectors.toMap(String::getBytes, String::length));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(\"bar\").collect(toMap(String::getBytes, String::length));",
|
||||
" Flux.just(\"baz\").collect(toImmutableMap(String::getBytes, String::length));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(\"qux\").collect(toMap(String::getBytes, String::length, (a, b) -> a));",
|
||||
" Flux.just(\"quux\").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> a));",
|
||||
" Flux.just(\"quuz\").collect(toMap(String::getBytes, String::length, (a, b) -> a, HashMap::new));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of(1).collect(Collectors.toSet());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of(2).collect(toSet());",
|
||||
" Stream.of(3).collect(toImmutableSet());",
|
||||
" Stream.of(4).collect(toCollection(HashSet::new));",
|
||||
"",
|
||||
" Flux.just(\"foo\").collect(Collectors.joining());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collect(Collectors.toList());
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(2).collect(toList());
|
||||
Flux.just(3).collect(toImmutableList());
|
||||
Flux.just(4).collect(toCollection(ArrayList::new));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just("foo").collect(Collectors.toMap(String::getBytes, String::length));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just("bar").collect(toMap(String::getBytes, String::length));
|
||||
Flux.just("baz").collect(toImmutableMap(String::getBytes, String::length));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just("qux").collect(toMap(String::getBytes, String::length, (a, b) -> a));
|
||||
Flux.just("quux").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> a));
|
||||
Flux.just("quuz").collect(toMap(String::getBytes, String::length, (a, b) -> a, HashMap::new));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Stream.of(1).collect(Collectors.toSet());
|
||||
// BUG: Diagnostic contains:
|
||||
Stream.of(2).collect(toSet());
|
||||
Stream.of(3).collect(toImmutableSet());
|
||||
Stream.of(4).collect(toCollection(HashSet::new));
|
||||
|
||||
Flux.just("foo").collect(Collectors.joining());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -66,14 +68,16 @@ final class CollectorMutabilityTest {
|
||||
.withClasspath()
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Stream.empty().collect(Collectors.toList());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Stream.empty().collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -82,55 +86,59 @@ final class CollectorMutabilityTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(CollectorMutability.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(Collectors.toList());",
|
||||
" Flux.just(2).collect(toList());",
|
||||
"",
|
||||
" Stream.of(\"foo\").collect(Collectors.toMap(String::getBytes, String::length));",
|
||||
" Stream.of(\"bar\").collect(toMap(String::getBytes, String::length));",
|
||||
" Flux.just(\"baz\").collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
" Flux.just(\"qux\").collect(toMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
"",
|
||||
" Stream.of(1).collect(Collectors.toSet());",
|
||||
" Stream.of(2).collect(toSet());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).collect(Collectors.toList());
|
||||
Flux.just(2).collect(toList());
|
||||
|
||||
Stream.of("foo").collect(Collectors.toMap(String::getBytes, String::length));
|
||||
Stream.of("bar").collect(toMap(String::getBytes, String::length));
|
||||
Flux.just("baz").collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b));
|
||||
Flux.just("qux").collect(toMap(String::getBytes, String::length, (a, b) -> b));
|
||||
|
||||
Stream.of(1).collect(Collectors.toSet());
|
||||
Stream.of(2).collect(toSet());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
"import static com.google.common.collect.ImmutableMap.toImmutableMap;",
|
||||
"import static com.google.common.collect.ImmutableSet.toImmutableSet;",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(toImmutableList());",
|
||||
" Flux.just(2).collect(toImmutableList());",
|
||||
"",
|
||||
" Stream.of(\"foo\").collect(toImmutableMap(String::getBytes, String::length));",
|
||||
" Stream.of(\"bar\").collect(toImmutableMap(String::getBytes, String::length));",
|
||||
" Flux.just(\"baz\").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
" Flux.just(\"qux\").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
"",
|
||||
" Stream.of(1).collect(toImmutableSet());",
|
||||
" Stream.of(2).collect(toImmutableSet());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).collect(toImmutableList());
|
||||
Flux.just(2).collect(toImmutableList());
|
||||
|
||||
Stream.of("foo").collect(toImmutableMap(String::getBytes, String::length));
|
||||
Stream.of("bar").collect(toImmutableMap(String::getBytes, String::length));
|
||||
Flux.just("baz").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> b));
|
||||
Flux.just("qux").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> b));
|
||||
|
||||
Stream.of(1).collect(toImmutableSet());
|
||||
Stream.of(2).collect(toImmutableSet());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -140,73 +148,77 @@ final class CollectorMutabilityTest {
|
||||
.setFixChooser(SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(Collectors.toList());",
|
||||
" Flux.just(2).collect(toList());",
|
||||
"",
|
||||
" Stream.of(\"foo\").collect(Collectors.toMap(String::getBytes, String::length));",
|
||||
" Stream.of(\"bar\").collect(toMap(String::getBytes, String::length));",
|
||||
" Flux.just(\"baz\").collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
" Flux.just(\"qux\").collect(toMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
"",
|
||||
" Stream.of(1).collect(Collectors.toSet());",
|
||||
" Stream.of(2).collect(toSet());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).collect(Collectors.toList());
|
||||
Flux.just(2).collect(toList());
|
||||
|
||||
Stream.of("foo").collect(Collectors.toMap(String::getBytes, String::length));
|
||||
Stream.of("bar").collect(toMap(String::getBytes, String::length));
|
||||
Flux.just("baz").collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b));
|
||||
Flux.just("qux").collect(toMap(String::getBytes, String::length, (a, b) -> b));
|
||||
|
||||
Stream.of(1).collect(Collectors.toSet());
|
||||
Stream.of(2).collect(toSet());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toCollection;",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.HashMap;",
|
||||
"import java.util.HashSet;",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(toCollection(ArrayList::new));",
|
||||
" Flux.just(2).collect(toCollection(ArrayList::new));",
|
||||
"",
|
||||
" Stream.of(\"foo\")",
|
||||
" .collect(",
|
||||
" Collectors.toMap(",
|
||||
" String::getBytes,",
|
||||
" String::length,",
|
||||
" (a, b) -> {",
|
||||
" throw new IllegalStateException();",
|
||||
" },",
|
||||
" HashMap::new));",
|
||||
" Stream.of(\"bar\")",
|
||||
" .collect(",
|
||||
" toMap(",
|
||||
" String::getBytes,",
|
||||
" String::length,",
|
||||
" (a, b) -> {",
|
||||
" throw new IllegalStateException();",
|
||||
" },",
|
||||
" HashMap::new));",
|
||||
" Flux.just(\"baz\")",
|
||||
" .collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b, HashMap::new));",
|
||||
" Flux.just(\"qux\").collect(toMap(String::getBytes, String::length, (a, b) -> b, HashMap::new));",
|
||||
"",
|
||||
" Stream.of(1).collect(toCollection(HashSet::new));",
|
||||
" Stream.of(2).collect(toCollection(HashSet::new));",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).collect(toCollection(ArrayList::new));
|
||||
Flux.just(2).collect(toCollection(ArrayList::new));
|
||||
|
||||
Stream.of("foo")
|
||||
.collect(
|
||||
Collectors.toMap(
|
||||
String::getBytes,
|
||||
String::length,
|
||||
(a, b) -> {
|
||||
throw new IllegalStateException();
|
||||
},
|
||||
HashMap::new));
|
||||
Stream.of("bar")
|
||||
.collect(
|
||||
toMap(
|
||||
String::getBytes,
|
||||
String::length,
|
||||
(a, b) -> {
|
||||
throw new IllegalStateException();
|
||||
},
|
||||
HashMap::new));
|
||||
Flux.just("baz")
|
||||
.collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b, HashMap::new));
|
||||
Flux.just("qux").collect(toMap(String::getBytes, String::length, (a, b) -> b, HashMap::new));
|
||||
|
||||
Stream.of(1).collect(toCollection(HashSet::new));
|
||||
Stream.of(2).collect(toCollection(HashSet::new));
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,184 +11,186 @@ final class DirectReturnTest {
|
||||
CompilationTestHelper.newInstance(DirectReturn.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.mockito.Mockito.mock;",
|
||||
"import static org.mockito.Mockito.spy;",
|
||||
"",
|
||||
"import java.util.function.Supplier;",
|
||||
"",
|
||||
"class A {",
|
||||
" private String field;",
|
||||
"",
|
||||
" void emptyMethod() {}",
|
||||
"",
|
||||
" void voidMethod() {",
|
||||
" toString();",
|
||||
" return;",
|
||||
" }",
|
||||
"",
|
||||
" String directReturnOfParam(String param) {",
|
||||
" return param;",
|
||||
" }",
|
||||
"",
|
||||
" String assignmentToField() {",
|
||||
" field = toString();",
|
||||
" return field;",
|
||||
" }",
|
||||
"",
|
||||
" Object redundantAssignmentToParam(String param) {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" param = toString();",
|
||||
" return param;",
|
||||
" }",
|
||||
"",
|
||||
" String redundantMockAssignmentToParam(String param) {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" param = mock();",
|
||||
" return param;",
|
||||
" }",
|
||||
"",
|
||||
" Object redundantMockWithExplicitTypeAssignmentToParam(String param) {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" param = mock(String.class);",
|
||||
" return param;",
|
||||
" }",
|
||||
"",
|
||||
" Object salientMockAssignmentToParam(String param) {",
|
||||
" param = mock();",
|
||||
" return param;",
|
||||
" }",
|
||||
"",
|
||||
" String redundantAssignmentToLocalVariable() {",
|
||||
" String variable = null;",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variable = toString();",
|
||||
" return variable;",
|
||||
" }",
|
||||
"",
|
||||
" String unusedAssignmentToLocalVariable(String param) {",
|
||||
" String variable = null;",
|
||||
" variable = toString();",
|
||||
" return param;",
|
||||
" }",
|
||||
"",
|
||||
" String redundantVariableDeclaration() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String variable = toString();",
|
||||
" return variable;",
|
||||
" }",
|
||||
"",
|
||||
" String redundantSpyVariableDeclaration() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String variable = spy();",
|
||||
" return variable;",
|
||||
" }",
|
||||
"",
|
||||
" Object redundantSpyWithExplicitTypeVariableDeclaration() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String variable = spy(String.class);",
|
||||
" return variable;",
|
||||
" }",
|
||||
"",
|
||||
" Object salientSpyTypeVariableDeclaration() {",
|
||||
" String variable = spy(\"name\");",
|
||||
" return variable;",
|
||||
" }",
|
||||
"",
|
||||
" String unusedVariableDeclaration(String param) {",
|
||||
" String variable = toString();",
|
||||
" return param;",
|
||||
" }",
|
||||
"",
|
||||
" String assignmentToAnnotatedVariable() {",
|
||||
" @SuppressWarnings(\"HereBeDragons\")",
|
||||
" String variable = toString();",
|
||||
" return variable;",
|
||||
" }",
|
||||
"",
|
||||
" String complexReturnStatement() {",
|
||||
" String variable = toString();",
|
||||
" return variable + toString();",
|
||||
" }",
|
||||
"",
|
||||
" String assignmentInsideIfClause() {",
|
||||
" String variable = null;",
|
||||
" if (true) {",
|
||||
" variable = toString();",
|
||||
" }",
|
||||
" return variable;",
|
||||
" }",
|
||||
"",
|
||||
" String redundantAssignmentInsideElseClause() {",
|
||||
" String variable = toString();",
|
||||
" if (true) {",
|
||||
" return variable;",
|
||||
" } else {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variable = \"foo\";",
|
||||
" return variable;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" Supplier<String> redundantAssignmentInsideLambda() {",
|
||||
" return () -> {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String variable = toString();",
|
||||
" return variable;",
|
||||
" };",
|
||||
" }",
|
||||
"",
|
||||
" String redundantAssignmentInsideTryBlock(AutoCloseable closeable) throws Exception {",
|
||||
" try (closeable) {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String variable = toString();",
|
||||
" return variable;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" String redundantAssignmentsInsideTryAndFinallyBlocks() {",
|
||||
" String variable = toString();",
|
||||
" try {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variable = \"foo\";",
|
||||
" return variable;",
|
||||
" } finally {",
|
||||
" String variable2 = toString();",
|
||||
" if (true) {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String variable3 = toString();",
|
||||
" return variable3;",
|
||||
" }",
|
||||
" return variable2;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" String assignmentUsedInsideFinallyBlock() {",
|
||||
" String variable = toString();",
|
||||
" try {",
|
||||
" variable = \"foo\";",
|
||||
" return variable;",
|
||||
" } finally {",
|
||||
" String variable2 = toString();",
|
||||
" return variable + variable2;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" String redundantAssignmentToVariableUsedInsideUnexecutedFinallyBlock(AutoCloseable closeable)",
|
||||
" throws Exception {",
|
||||
" String variable = toString();",
|
||||
" try (closeable) {",
|
||||
" if (true) {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variable = \"foo\";",
|
||||
" return variable;",
|
||||
" }",
|
||||
" }",
|
||||
" try {",
|
||||
" } finally {",
|
||||
" return variable;",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class A {
|
||||
private String field;
|
||||
|
||||
void emptyMethod() {}
|
||||
|
||||
void voidMethod() {
|
||||
toString();
|
||||
return;
|
||||
}
|
||||
|
||||
String directReturnOfParam(String param) {
|
||||
return param;
|
||||
}
|
||||
|
||||
String assignmentToField() {
|
||||
field = toString();
|
||||
return field;
|
||||
}
|
||||
|
||||
Object redundantAssignmentToParam(String param) {
|
||||
// BUG: Diagnostic contains:
|
||||
param = toString();
|
||||
return param;
|
||||
}
|
||||
|
||||
String redundantMockAssignmentToParam(String param) {
|
||||
// BUG: Diagnostic contains:
|
||||
param = mock();
|
||||
return param;
|
||||
}
|
||||
|
||||
Object redundantMockWithExplicitTypeAssignmentToParam(String param) {
|
||||
// BUG: Diagnostic contains:
|
||||
param = mock(String.class);
|
||||
return param;
|
||||
}
|
||||
|
||||
Object salientMockAssignmentToParam(String param) {
|
||||
param = mock();
|
||||
return param;
|
||||
}
|
||||
|
||||
String redundantAssignmentToLocalVariable() {
|
||||
String variable = null;
|
||||
// BUG: Diagnostic contains:
|
||||
variable = toString();
|
||||
return variable;
|
||||
}
|
||||
|
||||
String unusedAssignmentToLocalVariable(String param) {
|
||||
String variable = null;
|
||||
variable = toString();
|
||||
return param;
|
||||
}
|
||||
|
||||
String redundantVariableDeclaration() {
|
||||
// BUG: Diagnostic contains:
|
||||
String variable = toString();
|
||||
return variable;
|
||||
}
|
||||
|
||||
String redundantSpyVariableDeclaration() {
|
||||
// BUG: Diagnostic contains:
|
||||
String variable = spy();
|
||||
return variable;
|
||||
}
|
||||
|
||||
Object redundantSpyWithExplicitTypeVariableDeclaration() {
|
||||
// BUG: Diagnostic contains:
|
||||
String variable = spy(String.class);
|
||||
return variable;
|
||||
}
|
||||
|
||||
Object salientSpyTypeVariableDeclaration() {
|
||||
String variable = spy("name");
|
||||
return variable;
|
||||
}
|
||||
|
||||
String unusedVariableDeclaration(String param) {
|
||||
String variable = toString();
|
||||
return param;
|
||||
}
|
||||
|
||||
String assignmentToAnnotatedVariable() {
|
||||
@SuppressWarnings("HereBeDragons")
|
||||
String variable = toString();
|
||||
return variable;
|
||||
}
|
||||
|
||||
String complexReturnStatement() {
|
||||
String variable = toString();
|
||||
return variable + toString();
|
||||
}
|
||||
|
||||
String assignmentInsideIfClause() {
|
||||
String variable = null;
|
||||
if (true) {
|
||||
variable = toString();
|
||||
}
|
||||
return variable;
|
||||
}
|
||||
|
||||
String redundantAssignmentInsideElseClause() {
|
||||
String variable = toString();
|
||||
if (true) {
|
||||
return variable;
|
||||
} else {
|
||||
// BUG: Diagnostic contains:
|
||||
variable = "foo";
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
Supplier<String> redundantAssignmentInsideLambda() {
|
||||
return () -> {
|
||||
// BUG: Diagnostic contains:
|
||||
String variable = toString();
|
||||
return variable;
|
||||
};
|
||||
}
|
||||
|
||||
String redundantAssignmentInsideTryBlock(AutoCloseable closeable) throws Exception {
|
||||
try (closeable) {
|
||||
// BUG: Diagnostic contains:
|
||||
String variable = toString();
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
String redundantAssignmentsInsideTryAndFinallyBlocks() {
|
||||
String variable = toString();
|
||||
try {
|
||||
// BUG: Diagnostic contains:
|
||||
variable = "foo";
|
||||
return variable;
|
||||
} finally {
|
||||
String variable2 = toString();
|
||||
if (true) {
|
||||
// BUG: Diagnostic contains:
|
||||
String variable3 = toString();
|
||||
return variable3;
|
||||
}
|
||||
return variable2;
|
||||
}
|
||||
}
|
||||
|
||||
String assignmentUsedInsideFinallyBlock() {
|
||||
String variable = toString();
|
||||
try {
|
||||
variable = "foo";
|
||||
return variable;
|
||||
} finally {
|
||||
String variable2 = toString();
|
||||
return variable + variable2;
|
||||
}
|
||||
}
|
||||
|
||||
String redundantAssignmentToVariableUsedInsideUnexecutedFinallyBlock(AutoCloseable closeable)
|
||||
throws Exception {
|
||||
String variable = toString();
|
||||
try (closeable) {
|
||||
if (true) {
|
||||
// BUG: Diagnostic contains:
|
||||
variable = "foo";
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
try {
|
||||
} finally {
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -197,30 +199,34 @@ final class DirectReturnTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(DirectReturn.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" String m1() {",
|
||||
" String variable = null;",
|
||||
" variable = toString();",
|
||||
" return variable;",
|
||||
" }",
|
||||
"",
|
||||
" String m2() {",
|
||||
" String variable = toString();",
|
||||
" return variable;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
String m1() {
|
||||
String variable = null;
|
||||
variable = toString();
|
||||
return variable;
|
||||
}
|
||||
|
||||
String m2() {
|
||||
String variable = toString();
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" String m1() {",
|
||||
" String variable = null;",
|
||||
" return toString();",
|
||||
" }",
|
||||
"",
|
||||
" String m2() {",
|
||||
" return toString();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
String m1() {
|
||||
String variable = null;
|
||||
return toString();
|
||||
}
|
||||
|
||||
String m2() {
|
||||
return toString();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,54 +11,58 @@ final class EmptyMethodTest {
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" Object m1() {",
|
||||
" return null;",
|
||||
" }",
|
||||
"",
|
||||
" void m2() {",
|
||||
" System.out.println(42);",
|
||||
" }",
|
||||
"",
|
||||
" void m3() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" static void m4() {}",
|
||||
"",
|
||||
" interface F {",
|
||||
" void fun();",
|
||||
" }",
|
||||
"",
|
||||
" final class MyTestClass {",
|
||||
" void helperMethod() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
Object m1() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void m2() {
|
||||
System.out.println(42);
|
||||
}
|
||||
|
||||
void m3() {}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
static void m4() {}
|
||||
|
||||
interface F {
|
||||
void fun();
|
||||
}
|
||||
|
||||
final class MyTestClass {
|
||||
void helperMethod() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"B.java",
|
||||
"import org.aspectj.lang.annotation.Pointcut;",
|
||||
"",
|
||||
"final class B implements A.F {",
|
||||
" @Override",
|
||||
" public void fun() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void m3() {}",
|
||||
"",
|
||||
" /** Javadoc. */",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void m4() {}",
|
||||
"",
|
||||
" void m5() {",
|
||||
" // Single-line comment.",
|
||||
" }",
|
||||
"",
|
||||
" void m6() {",
|
||||
" /* Multi-line comment. */",
|
||||
" }",
|
||||
"",
|
||||
" @Pointcut",
|
||||
" void m7() {}",
|
||||
"}")
|
||||
"""
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
|
||||
final class B implements A.F {
|
||||
@Override
|
||||
public void fun() {}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
void m3() {}
|
||||
|
||||
/** Javadoc. */
|
||||
// BUG: Diagnostic contains:
|
||||
void m4() {}
|
||||
|
||||
void m5() {
|
||||
// Single-line comment.
|
||||
}
|
||||
|
||||
void m6() {
|
||||
/* Multi-line comment. */
|
||||
}
|
||||
|
||||
@Pointcut
|
||||
void m7() {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -67,22 +71,26 @@ final class EmptyMethodTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"final class A {",
|
||||
" void instanceMethod() {}",
|
||||
"",
|
||||
" static void staticMethod() {}",
|
||||
"",
|
||||
" static void staticMethodWithComment() {",
|
||||
" /* Foo. */",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
final class A {
|
||||
void instanceMethod() {}
|
||||
|
||||
static void staticMethod() {}
|
||||
|
||||
static void staticMethodWithComment() {
|
||||
/* Foo. */
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"final class A {",
|
||||
" static void staticMethodWithComment() {",
|
||||
" /* Foo. */",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
final class A {
|
||||
static void staticMethodWithComment() {
|
||||
/* Foo. */
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,142 +4,314 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledForJreRange;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
final class ErrorProneTestHelperSourceFormatTest {
|
||||
// XXX: Add tests cases for `ErrorProneTestHelperSourceFormat:IgnoreMalformedCode`.
|
||||
// XXX: Consider reducing the `@DisabledForJreRange(max = JRE.JAVA_14)` test scope by moving the
|
||||
// text blocks to smaller test methods.
|
||||
|
||||
@DisabledForJreRange(max = JRE.JAVA_14)
|
||||
@Test
|
||||
void identification() {
|
||||
CompilationTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import tech.picnic.errorprone.bugpatterns.EmptyMethod;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final CompilationTestHelper compilationTestHelper =",
|
||||
" CompilationTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
"",
|
||||
" void m() {",
|
||||
" compilationTestHelper",
|
||||
" // BUG: Diagnostic contains: No source code provided",
|
||||
" .addSourceLines(\"A.java\")",
|
||||
" // BUG: Diagnostic contains: Source code is malformed:",
|
||||
" .addSourceLines(\"B.java\", \"class B {\")",
|
||||
" // Well-formed code, so not flagged.",
|
||||
" .addSourceLines(\"C.java\", \"class C {}\")",
|
||||
" // Malformed code, but not compile-time constant, so not flagged.",
|
||||
" .addSourceLines(\"D.java\", \"class D {\" + getClass())",
|
||||
" // BUG: Diagnostic contains: Test code should follow the Google Java style",
|
||||
" .addSourceLines(\"E.java\", \"class E { }\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" refactoringTestHelper",
|
||||
" // BUG: Diagnostic contains: Test code should follow the Google Java style",
|
||||
" .addInputLines(\"A.java\", \"class A { }\")",
|
||||
" // BUG: Diagnostic contains: Test code should follow the Google Java style",
|
||||
" .addOutputLines(\"A.java\", \"class A { }\")",
|
||||
" // BUG: Diagnostic contains: Test code should follow the Google Java style",
|
||||
" .addInputLines(\"B.java\", \"import java.util.Map;\", \"\", \"class B {}\")",
|
||||
" // Unused import, but in an output file, so not flagged.",
|
||||
" .addOutputLines(\"B.java\", \"import java.util.Map;\", \"\", \"class B {}\")",
|
||||
" .doTest(TestMode.TEXT_MATCH);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import tech.picnic.errorprone.bugpatterns.EmptyMethod;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
// BUG: Diagnostic contains: No source code provided
|
||||
.addSourceLines("A.java")
|
||||
// BUG: Diagnostic contains: Source code is malformed:
|
||||
.addSourceLines("B.java", "class B {")
|
||||
// BUG: Diagnostic contains: Test code should be specified using a single text block
|
||||
.addSourceLines("C.java", "class C {}")
|
||||
// Malformed code, but not compile-time constant, so not flagged.
|
||||
.addSourceLines("D.java", "class D {" + getClass())
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style
|
||||
.addSourceLines("E.java", "class E { }")
|
||||
// Well-formed code, so not flagged.
|
||||
.addSourceLines("F.java", ""\"
|
||||
class F {}
|
||||
""\")
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style (pay attention to
|
||||
// trailing newlines)
|
||||
.addSourceLines("G.java", ""\"
|
||||
class G {}""\")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style
|
||||
.addInputLines("in/A.java", "class A { }")
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style
|
||||
.addOutputLines("out/A.java", "class A { }")
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style
|
||||
.addInputLines(
|
||||
"in/B.java",
|
||||
""\"
|
||||
import java.util.Map;
|
||||
|
||||
class B {}
|
||||
""\")
|
||||
// Unused import, but in an output file, so not flagged.
|
||||
.addOutputLines(
|
||||
"out/B.java",
|
||||
""\"
|
||||
import java.util.Map;
|
||||
|
||||
class B {}
|
||||
""\")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@DisabledForJreRange(max = JRE.JAVA_14)
|
||||
@Test
|
||||
void identificationAvoidTextBlocks() {
|
||||
CompilationTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass())
|
||||
.setArgs("-XepOpt:ErrorProneTestHelperSourceFormat:AvoidTextBlocks=true")
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import tech.picnic.errorprone.bugpatterns.EmptyMethod;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
// BUG: Diagnostic contains: No source code provided
|
||||
.addSourceLines("A.java")
|
||||
// BUG: Diagnostic contains: Source code is malformed:
|
||||
.addSourceLines("B.java", "class B {")
|
||||
// Well-formed code, so not flagged.
|
||||
.addSourceLines("C.java", "class C {}")
|
||||
// Malformed code, but not compile-time constant, so not flagged.
|
||||
.addSourceLines("D.java", "class D {" + getClass())
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style
|
||||
.addSourceLines("E.java", "class E { }")
|
||||
// BUG: Diagnostic contains: Test code should not be specified using a single text block
|
||||
.addSourceLines("F.java", ""\"
|
||||
class F {}
|
||||
""\")
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style (pay attention to
|
||||
// trailing newlines)
|
||||
.addSourceLines("G.java", "class G {}", "")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style
|
||||
.addInputLines("A.java", "class A { }")
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style
|
||||
.addOutputLines("A.java", "class A { }")
|
||||
// BUG: Diagnostic contains: Test code should follow the Google Java style
|
||||
.addInputLines("B.java", "import java.util.Map;", "", "class B {}")
|
||||
// Unused import, but in an output file, so not flagged.
|
||||
.addOutputLines("B.java", "import java.util.Map;", "", "class B {}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
// XXX: Add `replacement` test.
|
||||
@DisabledForJreRange(max = JRE.JAVA_14)
|
||||
@Test
|
||||
void replacement() {
|
||||
/*
|
||||
* Verifies that import sorting and code formatting is performed unconditionally, while unused
|
||||
* imports are removed unless part of a `BugCheckerRefactoringTestHelper` expected output file.
|
||||
* Also verifies that text blocks are properly indented.
|
||||
*/
|
||||
BugCheckerRefactoringTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import tech.picnic.errorprone.bugpatterns.EmptyMethod;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final CompilationTestHelper compilationTestHelper =",
|
||||
" CompilationTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
"",
|
||||
" void m() {",
|
||||
" compilationTestHelper",
|
||||
" .addSourceLines(",
|
||||
" \"A.java\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"import java.util.Collection;\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A,A> { }\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" refactoringTestHelper",
|
||||
" .addInputLines(",
|
||||
" \"A.java\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"import java.util.Collection;\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A,A> { }\")",
|
||||
" .addOutputLines(",
|
||||
" \"A.java\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"import java.util.Collection;\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A,A> { }\")",
|
||||
" .doTest(TestMode.TEXT_MATCH);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import tech.picnic.errorprone.bugpatterns.EmptyMethod;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
""\"
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
interface A extends List<A>, Map<A,A> { }""\")
|
||||
.addSourceLines("B.java", "class B {}")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addInputLines(
|
||||
"in/A.java",
|
||||
""\"
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
interface A extends List<A>, Map<A,A> { }""\")
|
||||
.addOutputLines(
|
||||
"out/A.java",
|
||||
""\"
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
interface A extends List<A>, Map<A,A> { }""\")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"out/A.java",
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import tech.picnic.errorprone.bugpatterns.EmptyMethod;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
""\"
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
interface A extends List<A>, Map<A, A> {}
|
||||
""\")
|
||||
.addSourceLines("B.java", ""\"
|
||||
class B {}
|
||||
""\")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addInputLines(
|
||||
"in/A.java",
|
||||
""\"
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
interface A extends List<A>, Map<A, A> {}
|
||||
""\")
|
||||
.addOutputLines(
|
||||
"out/A.java",
|
||||
""\"
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
interface A extends List<A>, Map<A, A> {}
|
||||
""\")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacementAvoidTextBlocks() {
|
||||
/*
|
||||
* Verifies that import sorting and code formatting is performed unconditionally, while unused
|
||||
* imports are removed unless part of a `BugCheckerRefactoringTestHelper` expected output file.
|
||||
*/
|
||||
BugCheckerRefactoringTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass())
|
||||
.setArgs("-XepOpt:ErrorProneTestHelperSourceFormat:AvoidTextBlocks=true")
|
||||
.addInputLines(
|
||||
"in/A.java",
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import tech.picnic.errorprone.bugpatterns.EmptyMethod;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Map;",
|
||||
"import java.util.Collection;",
|
||||
"import java.util.List;",
|
||||
"",
|
||||
"interface A extends List<A>, Map<A,A> { }")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Map;",
|
||||
"import java.util.Collection;",
|
||||
"import java.util.List;",
|
||||
"",
|
||||
"interface A extends List<A>, Map<A,A> { }")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import java.util.Map;",
|
||||
"import java.util.Collection;",
|
||||
"import java.util.List;",
|
||||
"",
|
||||
"interface A extends List<A>, Map<A,A> { }")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import tech.picnic.errorprone.bugpatterns.EmptyMethod;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final CompilationTestHelper compilationTestHelper =",
|
||||
" CompilationTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
"",
|
||||
" void m() {",
|
||||
" compilationTestHelper",
|
||||
" .addSourceLines(",
|
||||
" \"A.java\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A, A> {}\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" refactoringTestHelper",
|
||||
" .addInputLines(",
|
||||
" \"A.java\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A, A> {}\")",
|
||||
" .addOutputLines(",
|
||||
" \"A.java\",",
|
||||
" \"import java.util.Collection;\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A, A> {}\")",
|
||||
" .doTest(TestMode.TEXT_MATCH);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import tech.picnic.errorprone.bugpatterns.EmptyMethod;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.List;",
|
||||
"import java.util.Map;",
|
||||
"",
|
||||
"interface A extends List<A>, Map<A, A> {}")
|
||||
.doTest();
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.List;",
|
||||
"import java.util.Map;",
|
||||
"",
|
||||
"interface A extends List<A>, Map<A, A> {}")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import java.util.Collection;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Map;",
|
||||
"",
|
||||
"interface A extends List<A>, Map<A, A> {}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,74 +9,76 @@ final class ExplicitEnumOrderingTest {
|
||||
CompilationTestHelper.newInstance(ExplicitEnumOrdering.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.lang.annotation.RetentionPolicy.CLASS;",
|
||||
"import static java.lang.annotation.RetentionPolicy.RUNTIME;",
|
||||
"import static java.lang.annotation.RetentionPolicy.SOURCE;",
|
||||
"import static java.time.chrono.IsoEra.BCE;",
|
||||
"import static java.time.chrono.IsoEra.CE;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.Ordering;",
|
||||
"import java.lang.annotation.RetentionPolicy;",
|
||||
"import java.time.chrono.IsoEra;",
|
||||
"",
|
||||
"class A {",
|
||||
" {",
|
||||
" // The `List`-accepting overload is currently ignored.",
|
||||
" Ordering.explicit(ImmutableList.of(RetentionPolicy.SOURCE, RetentionPolicy.CLASS));",
|
||||
"",
|
||||
" Ordering.explicit(IsoEra.BCE, IsoEra.CE);",
|
||||
" // BUG: Diagnostic contains: IsoEra.CE",
|
||||
" Ordering.explicit(IsoEra.BCE);",
|
||||
" // BUG: Diagnostic contains: IsoEra.BCE",
|
||||
" Ordering.explicit(IsoEra.CE);",
|
||||
"",
|
||||
" Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.CLASS, RetentionPolicy.RUNTIME);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.CLASS, RetentionPolicy.RUNTIME",
|
||||
" Ordering.explicit(RetentionPolicy.SOURCE);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME",
|
||||
" Ordering.explicit(RetentionPolicy.CLASS);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.CLASS",
|
||||
" Ordering.explicit(RetentionPolicy.RUNTIME);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.RUNTIME",
|
||||
" Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.CLASS);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.CLASS",
|
||||
" Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE",
|
||||
" Ordering.explicit(RetentionPolicy.CLASS, RetentionPolicy.RUNTIME);",
|
||||
"",
|
||||
" Ordering.explicit(BCE, CE);",
|
||||
" // BUG: Diagnostic contains: IsoEra.CE",
|
||||
" Ordering.explicit(BCE);",
|
||||
" // BUG: Diagnostic contains: IsoEra.BCE",
|
||||
" Ordering.explicit(CE);",
|
||||
"",
|
||||
" Ordering.explicit(SOURCE, CLASS, RUNTIME);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.CLASS, RetentionPolicy.RUNTIME",
|
||||
" Ordering.explicit(SOURCE);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME",
|
||||
" Ordering.explicit(CLASS);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.CLASS",
|
||||
" Ordering.explicit(RUNTIME);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.RUNTIME",
|
||||
" Ordering.explicit(SOURCE, CLASS);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.CLASS",
|
||||
" Ordering.explicit(SOURCE, RUNTIME);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE",
|
||||
" Ordering.explicit(CLASS, RUNTIME);",
|
||||
"",
|
||||
" Ordering.explicit(RetentionPolicy.SOURCE, BCE, RetentionPolicy.CLASS, CE, RUNTIME);",
|
||||
" Ordering.explicit(SOURCE, IsoEra.BCE, CLASS, IsoEra.CE, RetentionPolicy.RUNTIME);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.CLASS",
|
||||
" Ordering.explicit(RetentionPolicy.SOURCE, BCE, CE, RUNTIME);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.CLASS",
|
||||
" Ordering.explicit(IsoEra.BCE, SOURCE, IsoEra.CE, RetentionPolicy.RUNTIME);",
|
||||
" // BUG: Diagnostic contains: IsoEra.CE, RetentionPolicy.RUNTIME",
|
||||
" Ordering.explicit(IsoEra.BCE, SOURCE, RetentionPolicy.CLASS);",
|
||||
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, IsoEra.BCE",
|
||||
" Ordering.explicit(CLASS, RUNTIME, CE);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
import static java.time.chrono.IsoEra.BCE;
|
||||
import static java.time.chrono.IsoEra.CE;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Ordering;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.time.chrono.IsoEra;
|
||||
|
||||
class A {
|
||||
{
|
||||
// The `List`-accepting overload is currently ignored.
|
||||
Ordering.explicit(ImmutableList.of(RetentionPolicy.SOURCE, RetentionPolicy.CLASS));
|
||||
|
||||
Ordering.explicit(IsoEra.BCE, IsoEra.CE);
|
||||
// BUG: Diagnostic contains: IsoEra.CE
|
||||
Ordering.explicit(IsoEra.BCE);
|
||||
// BUG: Diagnostic contains: IsoEra.BCE
|
||||
Ordering.explicit(IsoEra.CE);
|
||||
|
||||
Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.CLASS, RetentionPolicy.RUNTIME);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.CLASS, RetentionPolicy.RUNTIME
|
||||
Ordering.explicit(RetentionPolicy.SOURCE);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME
|
||||
Ordering.explicit(RetentionPolicy.CLASS);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.CLASS
|
||||
Ordering.explicit(RetentionPolicy.RUNTIME);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.RUNTIME
|
||||
Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.CLASS);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.CLASS
|
||||
Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.SOURCE
|
||||
Ordering.explicit(RetentionPolicy.CLASS, RetentionPolicy.RUNTIME);
|
||||
|
||||
Ordering.explicit(BCE, CE);
|
||||
// BUG: Diagnostic contains: IsoEra.CE
|
||||
Ordering.explicit(BCE);
|
||||
// BUG: Diagnostic contains: IsoEra.BCE
|
||||
Ordering.explicit(CE);
|
||||
|
||||
Ordering.explicit(SOURCE, CLASS, RUNTIME);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.CLASS, RetentionPolicy.RUNTIME
|
||||
Ordering.explicit(SOURCE);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME
|
||||
Ordering.explicit(CLASS);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.CLASS
|
||||
Ordering.explicit(RUNTIME);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.RUNTIME
|
||||
Ordering.explicit(SOURCE, CLASS);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.CLASS
|
||||
Ordering.explicit(SOURCE, RUNTIME);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.SOURCE
|
||||
Ordering.explicit(CLASS, RUNTIME);
|
||||
|
||||
Ordering.explicit(RetentionPolicy.SOURCE, BCE, RetentionPolicy.CLASS, CE, RUNTIME);
|
||||
Ordering.explicit(SOURCE, IsoEra.BCE, CLASS, IsoEra.CE, RetentionPolicy.RUNTIME);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.CLASS
|
||||
Ordering.explicit(RetentionPolicy.SOURCE, BCE, CE, RUNTIME);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.CLASS
|
||||
Ordering.explicit(IsoEra.BCE, SOURCE, IsoEra.CE, RetentionPolicy.RUNTIME);
|
||||
// BUG: Diagnostic contains: IsoEra.CE, RetentionPolicy.RUNTIME
|
||||
Ordering.explicit(IsoEra.BCE, SOURCE, RetentionPolicy.CLASS);
|
||||
// BUG: Diagnostic contains: RetentionPolicy.SOURCE, IsoEra.BCE
|
||||
Ordering.explicit(CLASS, RUNTIME, CE);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,55 +12,57 @@ final class FluxFlatMapUsageTest {
|
||||
CompilationTestHelper.newInstance(FluxFlatMapUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.function.BiFunction;",
|
||||
"import java.util.function.Function;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).flatMap(Flux::just);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).<String>flatMap(i -> Flux.just(String.valueOf(i)));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).flatMapSequential(Flux::just);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).<String>flatMapSequential(i -> Flux.just(String.valueOf(i)));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1, 2).groupBy(i -> i).flatMap(Flux::just);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1, 2).groupBy(i -> i).<String>flatMap(i -> Flux.just(String.valueOf(i)));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1, 2).groupBy(i -> i).flatMapSequential(Flux::just);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1, 2).groupBy(i -> i).<String>flatMapSequential(i -> Flux.just(String.valueOf(i)));",
|
||||
"",
|
||||
" Mono.just(1).flatMap(Mono::just);",
|
||||
" Flux.just(1).concatMap(Flux::just);",
|
||||
"",
|
||||
" Flux.just(1).flatMap(Flux::just, 1);",
|
||||
" Flux.just(1).flatMap(Flux::just, 1, 1);",
|
||||
" Flux.just(1).flatMap(Flux::just, throwable -> Flux.empty(), Flux::empty);",
|
||||
"",
|
||||
" Flux.just(1).flatMapSequential(Flux::just, 1);",
|
||||
" Flux.just(1).flatMapSequential(Flux::just, 1, 1);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.<String, Flux<String>>sink(Flux::flatMap);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.<Integer, Flux<Integer>>sink(Flux::<Integer>flatMap);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.<String, Flux<String>>sink(Flux::flatMapSequential);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.<Integer, Flux<Integer>>sink(Flux::<Integer>flatMapSequential);",
|
||||
"",
|
||||
" this.<String, Mono<String>>sink(Mono::flatMap);",
|
||||
" }",
|
||||
"",
|
||||
" private <T, P> void sink(BiFunction<P, Function<T, P>, P> fun) {}",
|
||||
"}")
|
||||
"""
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).flatMap(Flux::just);
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).<String>flatMap(i -> Flux.just(String.valueOf(i)));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).flatMapSequential(Flux::just);
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).<String>flatMapSequential(i -> Flux.just(String.valueOf(i)));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1, 2).groupBy(i -> i).flatMap(Flux::just);
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1, 2).groupBy(i -> i).<String>flatMap(i -> Flux.just(String.valueOf(i)));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1, 2).groupBy(i -> i).flatMapSequential(Flux::just);
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1, 2).groupBy(i -> i).<String>flatMapSequential(i -> Flux.just(String.valueOf(i)));
|
||||
|
||||
Mono.just(1).flatMap(Mono::just);
|
||||
Flux.just(1).concatMap(Flux::just);
|
||||
|
||||
Flux.just(1).flatMap(Flux::just, 1);
|
||||
Flux.just(1).flatMap(Flux::just, 1, 1);
|
||||
Flux.just(1).flatMap(Flux::just, throwable -> Flux.empty(), Flux::empty);
|
||||
|
||||
Flux.just(1).flatMapSequential(Flux::just, 1);
|
||||
Flux.just(1).flatMapSequential(Flux::just, 1, 1);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
this.<String, Flux<String>>sink(Flux::flatMap);
|
||||
// BUG: Diagnostic contains:
|
||||
this.<Integer, Flux<Integer>>sink(Flux::<Integer>flatMap);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
this.<String, Flux<String>>sink(Flux::flatMapSequential);
|
||||
// BUG: Diagnostic contains:
|
||||
this.<Integer, Flux<Integer>>sink(Flux::<Integer>flatMapSequential);
|
||||
|
||||
this.<String, Mono<String>>sink(Mono::flatMap);
|
||||
}
|
||||
|
||||
private <T, P> void sink(BiFunction<P, Function<T, P>, P> fun) {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -69,32 +71,36 @@ final class FluxFlatMapUsageTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(FluxFlatMapUsage.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final int MAX_CONCURRENCY = 8;",
|
||||
"",
|
||||
" void m() {",
|
||||
" Flux.just(1).flatMap(Flux::just);",
|
||||
" Flux.just(1).flatMapSequential(Flux::just);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).flatMap(Flux::just);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).flatMapSequential(Flux::just);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
private static final int MAX_CONCURRENCY = 8;
|
||||
|
||||
void m() {
|
||||
Flux.just(1).flatMap(Flux::just);
|
||||
Flux.just(1).flatMapSequential(Flux::just);
|
||||
Flux.just(1, 2).groupBy(i -> i).flatMap(Flux::just);
|
||||
Flux.just(1, 2).groupBy(i -> i).flatMapSequential(Flux::just);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final int MAX_CONCURRENCY = 8;",
|
||||
"",
|
||||
" void m() {",
|
||||
" Flux.just(1).concatMap(Flux::just);",
|
||||
" Flux.just(1).concatMap(Flux::just);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).flatMap(Flux::just, MAX_CONCURRENCY);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).flatMapSequential(Flux::just, MAX_CONCURRENCY);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
private static final int MAX_CONCURRENCY = 8;
|
||||
|
||||
void m() {
|
||||
Flux.just(1).concatMap(Flux::just);
|
||||
Flux.just(1).concatMap(Flux::just);
|
||||
Flux.just(1, 2).groupBy(i -> i).flatMap(Flux::just, MAX_CONCURRENCY);
|
||||
Flux.just(1, 2).groupBy(i -> i).flatMapSequential(Flux::just, MAX_CONCURRENCY);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -104,32 +110,36 @@ final class FluxFlatMapUsageTest {
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final int MAX_CONCURRENCY = 8;",
|
||||
"",
|
||||
" void m() {",
|
||||
" Flux.just(1).flatMap(Flux::just);",
|
||||
" Flux.just(1).flatMapSequential(Flux::just);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).flatMap(Flux::just);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).flatMapSequential(Flux::just);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
private static final int MAX_CONCURRENCY = 8;
|
||||
|
||||
void m() {
|
||||
Flux.just(1).flatMap(Flux::just);
|
||||
Flux.just(1).flatMapSequential(Flux::just);
|
||||
Flux.just(1, 2).groupBy(i -> i).flatMap(Flux::just);
|
||||
Flux.just(1, 2).groupBy(i -> i).flatMapSequential(Flux::just);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final int MAX_CONCURRENCY = 8;",
|
||||
"",
|
||||
" void m() {",
|
||||
" Flux.just(1).flatMap(Flux::just, MAX_CONCURRENCY);",
|
||||
" Flux.just(1).flatMapSequential(Flux::just, MAX_CONCURRENCY);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).concatMap(Flux::just);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).concatMap(Flux::just);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
private static final int MAX_CONCURRENCY = 8;
|
||||
|
||||
void m() {
|
||||
Flux.just(1).flatMap(Flux::just, MAX_CONCURRENCY);
|
||||
Flux.just(1).flatMapSequential(Flux::just, MAX_CONCURRENCY);
|
||||
Flux.just(1, 2).groupBy(i -> i).concatMap(Flux::just);
|
||||
Flux.just(1, 2).groupBy(i -> i).concatMap(Flux::just);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,36 +21,38 @@ final class FluxImplicitBlockTest {
|
||||
m -> Stream.of("SuppressWarnings", "toImmutableList", "toList").allMatch(m::contains))
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" // BUG: Diagnostic matches: X",
|
||||
" Flux.just(1).toIterable();",
|
||||
" // BUG: Diagnostic matches: X",
|
||||
" Flux.just(2).toStream();",
|
||||
" // BUG: Diagnostic matches: X",
|
||||
" long count = Flux.just(3).toStream().count();",
|
||||
"",
|
||||
" Flux.just(4).toIterable(1);",
|
||||
" Flux.just(5).toIterable(2, null);",
|
||||
" Flux.just(6).toStream(3);",
|
||||
" new Foo().toIterable();",
|
||||
" new Foo().toStream();",
|
||||
" }",
|
||||
"",
|
||||
" class Foo<T> {",
|
||||
" Iterable<T> toIterable() {",
|
||||
" return ImmutableList.of();",
|
||||
" }",
|
||||
"",
|
||||
" Stream<T> toStream() {",
|
||||
" return Stream.empty();",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.stream.Stream;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
// BUG: Diagnostic matches: X
|
||||
Flux.just(1).toIterable();
|
||||
// BUG: Diagnostic matches: X
|
||||
Flux.just(2).toStream();
|
||||
// BUG: Diagnostic matches: X
|
||||
long count = Flux.just(3).toStream().count();
|
||||
|
||||
Flux.just(4).toIterable(1);
|
||||
Flux.just(5).toIterable(2, null);
|
||||
Flux.just(6).toStream(3);
|
||||
new Foo().toIterable();
|
||||
new Foo().toStream();
|
||||
}
|
||||
|
||||
class Foo<T> {
|
||||
Iterable<T> toIterable() {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
Stream<T> toStream() {
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -61,16 +63,18 @@ final class FluxImplicitBlockTest {
|
||||
.expectErrorMessage("X", m -> !m.contains("toImmutableList"))
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" // BUG: Diagnostic matches: X",
|
||||
" Flux.just(1).toIterable();",
|
||||
" // BUG: Diagnostic matches: X",
|
||||
" Flux.just(2).toStream();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
// BUG: Diagnostic matches: X
|
||||
Flux.just(1).toIterable();
|
||||
// BUG: Diagnostic matches: X
|
||||
Flux.just(2).toStream();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -79,25 +83,29 @@ final class FluxImplicitBlockTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(FluxImplicitBlock.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).toIterable();",
|
||||
" Flux.just(2).toStream();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).toIterable();
|
||||
Flux.just(2).toStream();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" @SuppressWarnings(\"FluxImplicitBlock\")",
|
||||
" void m() {",
|
||||
" Flux.just(1).toIterable();",
|
||||
" Flux.just(2).toStream();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
@SuppressWarnings("FluxImplicitBlock")
|
||||
void m() {
|
||||
Flux.just(1).toIterable();
|
||||
Flux.just(2).toStream();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -107,34 +115,38 @@ final class FluxImplicitBlockTest {
|
||||
.setFixChooser(SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).toIterable();",
|
||||
" Flux.just(2).toStream();",
|
||||
" Flux.just(3).toIterable().iterator();",
|
||||
" Flux.just(4).toStream().count();",
|
||||
" Flux.just(5) /* a */./* b */ toIterable /* c */(/* d */ ) /* e */;",
|
||||
" Flux.just(6) /* a */./* b */ toStream /* c */(/* d */ ) /* e */;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).toIterable();
|
||||
Flux.just(2).toStream();
|
||||
Flux.just(3).toIterable().iterator();
|
||||
Flux.just(4).toStream().count();
|
||||
Flux.just(5) /* a */./* b */ toIterable /* c */(/* d */ ) /* e */;
|
||||
Flux.just(6) /* a */./* b */ toStream /* c */(/* d */ ) /* e */;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
"",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(toImmutableList()).block();",
|
||||
" Flux.just(2).collect(toImmutableList()).block().stream();",
|
||||
" Flux.just(3).collect(toImmutableList()).block().iterator();",
|
||||
" Flux.just(4).collect(toImmutableList()).block().stream().count();",
|
||||
" Flux.just(5).collect(toImmutableList()).block() /* e */;",
|
||||
" Flux.just(6).collect(toImmutableList()).block().stream() /* e */;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).collect(toImmutableList()).block();
|
||||
Flux.just(2).collect(toImmutableList()).block().stream();
|
||||
Flux.just(3).collect(toImmutableList()).block().iterator();
|
||||
Flux.just(4).collect(toImmutableList()).block().stream().count();
|
||||
Flux.just(5).collect(toImmutableList()).block() /* e */;
|
||||
Flux.just(6).collect(toImmutableList()).block().stream() /* e */;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -144,34 +156,38 @@ final class FluxImplicitBlockTest {
|
||||
.setFixChooser(THIRD)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).toIterable();",
|
||||
" Flux.just(2).toStream();",
|
||||
" Flux.just(3).toIterable().iterator();",
|
||||
" Flux.just(4).toStream().count();",
|
||||
" Flux.just(5) /* a */./* b */ toIterable /* c */(/* d */ ) /* e */;",
|
||||
" Flux.just(6) /* a */./* b */ toStream /* c */(/* d */ ) /* e */;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).toIterable();
|
||||
Flux.just(2).toStream();
|
||||
Flux.just(3).toIterable().iterator();
|
||||
Flux.just(4).toStream().count();
|
||||
Flux.just(5) /* a */./* b */ toIterable /* c */(/* d */ ) /* e */;
|
||||
Flux.just(6) /* a */./* b */ toStream /* c */(/* d */ ) /* e */;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(toList()).block();",
|
||||
" Flux.just(2).collect(toList()).block().stream();",
|
||||
" Flux.just(3).collect(toList()).block().iterator();",
|
||||
" Flux.just(4).collect(toList()).block().stream().count();",
|
||||
" Flux.just(5).collect(toList()).block() /* e */;",
|
||||
" Flux.just(6).collect(toList()).block().stream() /* e */;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).collect(toList()).block();
|
||||
Flux.just(2).collect(toList()).block().stream();
|
||||
Flux.just(3).collect(toList()).block().iterator();
|
||||
Flux.just(4).collect(toList()).block().stream().count();
|
||||
Flux.just(5).collect(toList()).block() /* e */;
|
||||
Flux.just(6).collect(toList()).block().stream() /* e */;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,294 +11,296 @@ final class FormatStringConcatenationTest {
|
||||
CompilationTestHelper.newInstance(FormatStringConcatenation.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
"import static com.google.common.base.Preconditions.checkNotNull;",
|
||||
"import static com.google.common.base.Preconditions.checkState;",
|
||||
"import static com.google.common.base.Verify.verify;",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"import static org.assertj.core.api.SoftAssertions.assertSoftly;",
|
||||
"",
|
||||
"import java.util.Formatter;",
|
||||
"import java.util.Locale;",
|
||||
"import org.assertj.core.api.Assertions;",
|
||||
"import org.assertj.core.api.BDDAssertions;",
|
||||
"import org.assertj.core.api.Fail;",
|
||||
"import org.assertj.core.api.ThrowableAssertAlternative;",
|
||||
"import org.assertj.core.api.WithAssertions;",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
"",
|
||||
" void negative() {",
|
||||
" hashCode();",
|
||||
" equals(new A());",
|
||||
" equals(toString());",
|
||||
" equals(0);",
|
||||
" equals(\"str\");",
|
||||
" equals(\"str\" + 0);",
|
||||
" equals(0 + 0);",
|
||||
" equals(0 - 0);",
|
||||
" equals(\"str \" + toString());",
|
||||
" }",
|
||||
"",
|
||||
" void assertj() {",
|
||||
" assertThat(0).overridingErrorMessage(toString());",
|
||||
" assertThat(0).overridingErrorMessage(\"str\");",
|
||||
" assertThat(0).overridingErrorMessage(\"str \" + 0);",
|
||||
" assertThat(0).overridingErrorMessage(\"str %s\", 2 * 3);",
|
||||
" assertThat(0).overridingErrorMessage(\"str %s\", toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).overridingErrorMessage(\"str \" + hashCode() / 2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).overridingErrorMessage((\"str \" + toString()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).overridingErrorMessage(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).overridingErrorMessage(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).withFailMessage(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).withFailMessage(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertSoftly(softly -> softly.fail(\"str \" + toString()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertSoftly(softly -> softly.fail(\"%s \" + toString(), \"arg\"));",
|
||||
" assertSoftly(softly -> softly.fail(\"str \" + toString(), new Throwable()));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(\"\").isEqualTo(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(\"\").isEqualTo(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasMessage(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasMessage(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasMessageContaining(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasMessageContaining(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasMessageEndingWith(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasMessageEndingWith(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasMessageStartingWith(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasMessageStartingWith(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasRootCauseMessage(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasRootCauseMessage(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasStackTraceContaining(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(new Error()).hasStackTraceContaining(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).as(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).as(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).describedAs(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(0).describedAs(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withMessage(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withMessage(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withMessageContaining(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withMessageContaining(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withMessageEndingWith(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withMessageEndingWith(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withMessageStartingWith(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withMessageStartingWith(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withStackTraceContaining(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((ThrowableAssertAlternative) null).withStackTraceContaining(\"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((WithAssertions) null).fail(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ((WithAssertions) null).fail(\"%s \" + toString(), \"arg\");",
|
||||
" ((WithAssertions) null).fail(\"str \" + toString(), new Throwable());",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Assertions.fail(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Assertions.fail(\"%s \" + toString(), \"arg\");",
|
||||
" Assertions.fail(\"str \" + toString(), new Throwable());",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" BDDAssertions.fail(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" BDDAssertions.fail(\"%s \" + toString(), \"arg\");",
|
||||
" BDDAssertions.fail(\"str \" + toString(), new Throwable());",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Fail.fail(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Fail.fail(\"%s \" + toString(), \"arg\");",
|
||||
" Fail.fail(\"str \" + toString(), new Throwable());",
|
||||
" }",
|
||||
"",
|
||||
" void guava() {",
|
||||
" checkArgument(true);",
|
||||
" checkArgument(true, toString());",
|
||||
" checkArgument(true, \"str\");",
|
||||
" checkArgument(true, \"str \" + 0);",
|
||||
" checkArgument(true, \"str %s\", 2 * 3);",
|
||||
" checkArgument(true, \"str %s\", toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkArgument(true, \"str \" + hashCode() / 2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkArgument(true, (\"str \" + toString()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkArgument(true, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkArgument(true, \"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkNotNull(true, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkNotNull(true, \"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkState(true, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkState(true, \"%s \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" verify(true, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" verify(true, \"%s \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"",
|
||||
" void jdk() {",
|
||||
" String.format(\"str\");",
|
||||
" String.format(\"str \" + 0);",
|
||||
" String.format(\"str {}\", 2 * 3);",
|
||||
" String.format(\"str {}\", toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(\"str \" + hashCode() / 2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format((\"str \" + toString()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(\"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" String.format(Locale.ROOT, \"str\");",
|
||||
" String.format(Locale.ROOT, \"str \" + 0);",
|
||||
" String.format(Locale.ROOT, \"str {}\", 2 * 3);",
|
||||
" String.format(Locale.ROOT, \"str {}\", toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(Locale.ROOT, (\"str \" + toString()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(Locale.ROOT, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" new Formatter().format(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" new Formatter().format(\"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" new Formatter().format(Locale.ROOT, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" new Formatter().format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"",
|
||||
" void slf4j() {",
|
||||
" LOG.debug(\"str\");",
|
||||
" LOG.debug(\"str \" + 0);",
|
||||
" LOG.debug(\"str {}\", 2 * 3);",
|
||||
" LOG.debug(\"str {}\", toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(\"str \" + hashCode() / 2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug((\"str \" + toString()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(\"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" LOG.debug((Marker) null, \"str\");",
|
||||
" LOG.debug((Marker) null, \"str \" + 0);",
|
||||
" LOG.debug((Marker) null, \"str {}\", 2 * 3);",
|
||||
" LOG.debug((Marker) null, \"str {}\", toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug((Marker) null, (\"str \" + toString()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug((Marker) null, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug((Marker) null, \"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.error(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.error(\"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.error((Marker) null, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.error((Marker) null, \"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.info(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.info(\"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.info((Marker) null, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.info((Marker) null, \"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace(\"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace((Marker) null, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace((Marker) null, \"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.warn(\"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.warn(\"{} \" + toString(), \"arg\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.warn((Marker) null, \"str \" + toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.warn((Marker) null, \"{} \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.SoftAssertions.assertSoftly;
|
||||
|
||||
import java.util.Formatter;
|
||||
import java.util.Locale;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.assertj.core.api.BDDAssertions;
|
||||
import org.assertj.core.api.Fail;
|
||||
import org.assertj.core.api.ThrowableAssertAlternative;
|
||||
import org.assertj.core.api.WithAssertions;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
|
||||
class A {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(A.class);
|
||||
|
||||
void negative() {
|
||||
hashCode();
|
||||
equals(new A());
|
||||
equals(toString());
|
||||
equals(0);
|
||||
equals("str");
|
||||
equals("str" + 0);
|
||||
equals(0 + 0);
|
||||
equals(0 - 0);
|
||||
equals("str " + toString());
|
||||
}
|
||||
|
||||
void assertj() {
|
||||
assertThat(0).overridingErrorMessage(toString());
|
||||
assertThat(0).overridingErrorMessage("str");
|
||||
assertThat(0).overridingErrorMessage("str " + 0);
|
||||
assertThat(0).overridingErrorMessage("str %s", 2 * 3);
|
||||
assertThat(0).overridingErrorMessage("str %s", toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).overridingErrorMessage("str " + hashCode() / 2);
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).overridingErrorMessage(("str " + toString()));
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).overridingErrorMessage("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).overridingErrorMessage("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).withFailMessage("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).withFailMessage("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertSoftly(softly -> softly.fail("str " + toString()));
|
||||
// BUG: Diagnostic contains:
|
||||
assertSoftly(softly -> softly.fail("%s " + toString(), "arg"));
|
||||
assertSoftly(softly -> softly.fail("str " + toString(), new Throwable()));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat("").isEqualTo("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat("").isEqualTo("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasMessage("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasMessage("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasMessageContaining("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasMessageContaining("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasMessageEndingWith("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasMessageEndingWith("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasMessageStartingWith("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasMessageStartingWith("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasRootCauseMessage("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasRootCauseMessage("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasStackTraceContaining("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(new Error()).hasStackTraceContaining("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).as("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).as("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).describedAs("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
assertThat(0).describedAs("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withMessage("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withMessage("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withMessageContaining("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withMessageContaining("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withMessageEndingWith("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withMessageEndingWith("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withMessageStartingWith("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withMessageStartingWith("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withStackTraceContaining("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
((ThrowableAssertAlternative) null).withStackTraceContaining("%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
((WithAssertions) null).fail("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
((WithAssertions) null).fail("%s " + toString(), "arg");
|
||||
((WithAssertions) null).fail("str " + toString(), new Throwable());
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Assertions.fail("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
Assertions.fail("%s " + toString(), "arg");
|
||||
Assertions.fail("str " + toString(), new Throwable());
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
BDDAssertions.fail("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
BDDAssertions.fail("%s " + toString(), "arg");
|
||||
BDDAssertions.fail("str " + toString(), new Throwable());
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Fail.fail("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
Fail.fail("%s " + toString(), "arg");
|
||||
Fail.fail("str " + toString(), new Throwable());
|
||||
}
|
||||
|
||||
void guava() {
|
||||
checkArgument(true);
|
||||
checkArgument(true, toString());
|
||||
checkArgument(true, "str");
|
||||
checkArgument(true, "str " + 0);
|
||||
checkArgument(true, "str %s", 2 * 3);
|
||||
checkArgument(true, "str %s", toString());
|
||||
// BUG: Diagnostic contains:
|
||||
checkArgument(true, "str " + hashCode() / 2);
|
||||
// BUG: Diagnostic contains:
|
||||
checkArgument(true, ("str " + toString()));
|
||||
// BUG: Diagnostic contains:
|
||||
checkArgument(true, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
checkArgument(true, "%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
checkNotNull(true, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
checkNotNull(true, "%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
checkState(true, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
checkState(true, "%s " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
verify(true, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
verify(true, "%s " + toString(), "arg");
|
||||
}
|
||||
|
||||
void jdk() {
|
||||
String.format("str");
|
||||
String.format("str " + 0);
|
||||
String.format("str {}", 2 * 3);
|
||||
String.format("str {}", toString());
|
||||
// BUG: Diagnostic contains:
|
||||
String.format("str " + hashCode() / 2);
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(("str " + toString()));
|
||||
// BUG: Diagnostic contains:
|
||||
String.format("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
String.format("{} " + toString(), "arg");
|
||||
|
||||
String.format(Locale.ROOT, "str");
|
||||
String.format(Locale.ROOT, "str " + 0);
|
||||
String.format(Locale.ROOT, "str {}", 2 * 3);
|
||||
String.format(Locale.ROOT, "str {}", toString());
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(Locale.ROOT, ("str " + toString()));
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(Locale.ROOT, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(Locale.ROOT, "{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
new Formatter().format("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
new Formatter().format("{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
new Formatter().format(Locale.ROOT, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
new Formatter().format(Locale.ROOT, "{} " + toString(), "arg");
|
||||
}
|
||||
|
||||
void slf4j() {
|
||||
LOG.debug("str");
|
||||
LOG.debug("str " + 0);
|
||||
LOG.debug("str {}", 2 * 3);
|
||||
LOG.debug("str {}", toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug("str " + hashCode() / 2);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug(("str " + toString()));
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug("{} " + toString(), "arg");
|
||||
|
||||
LOG.debug((Marker) null, "str");
|
||||
LOG.debug((Marker) null, "str " + 0);
|
||||
LOG.debug((Marker) null, "str {}", 2 * 3);
|
||||
LOG.debug((Marker) null, "str {}", toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug((Marker) null, ("str " + toString()));
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug((Marker) null, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug((Marker) null, "{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.error("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.error("{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.error((Marker) null, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.error((Marker) null, "{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.info("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.info("{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.info((Marker) null, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.info((Marker) null, "{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace("{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace((Marker) null, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace((Marker) null, "{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.warn("str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.warn("{} " + toString(), "arg");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.warn((Marker) null, "str " + toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.warn((Marker) null, "{} " + toString(), "arg");
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -307,102 +309,106 @@ final class FormatStringConcatenationTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(FormatStringConcatenation.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"import java.util.Locale;",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
"",
|
||||
" void assertj() {",
|
||||
" assertThat(0).overridingErrorMessage(toString() + \" str\");",
|
||||
" assertThat(0).overridingErrorMessage(\"str \" + toString());",
|
||||
" assertThat(0).overridingErrorMessage(toString() + toString());",
|
||||
" assertThat(0).overridingErrorMessage(\"str \" + toString() + \" word \" + new A().hashCode());",
|
||||
" assertThat(0).overridingErrorMessage(\"str \" + (toString() + \" word \") + (hashCode() / 2));",
|
||||
"",
|
||||
" // Flagged but not auto-fixed.",
|
||||
" assertThat(0).overridingErrorMessage(\"%s \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"",
|
||||
" void guava() {",
|
||||
" checkArgument(true, \"str \" + toString());",
|
||||
"",
|
||||
" // Flagged but not auto-fixed.",
|
||||
" checkArgument(true, \"%s \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"",
|
||||
" void jdk() {",
|
||||
" String.format(\"str \" + toString());",
|
||||
" String.format(Locale.ROOT, \"str \" + toString());",
|
||||
"",
|
||||
" // Flagged but not auto-fixed.",
|
||||
" String.format(\"{} \" + toString(), \"arg\");",
|
||||
" String.format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"",
|
||||
" void slf4j() {",
|
||||
" LOG.debug(\"str \" + toString());",
|
||||
" LOG.debug((Marker) null, \"str \" + toString());",
|
||||
"",
|
||||
" // Flagged but not auto-fixed.",
|
||||
" LOG.debug(\"{} \" + toString(), \"arg\");",
|
||||
" LOG.debug((Marker) null, \"{} \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Locale;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
|
||||
class A {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(A.class);
|
||||
|
||||
void assertj() {
|
||||
assertThat(0).overridingErrorMessage(toString() + " str");
|
||||
assertThat(0).overridingErrorMessage("str " + toString());
|
||||
assertThat(0).overridingErrorMessage(toString() + toString());
|
||||
assertThat(0).overridingErrorMessage("str " + toString() + " word " + new A().hashCode());
|
||||
assertThat(0).overridingErrorMessage("str " + (toString() + " word ") + (hashCode() / 2));
|
||||
|
||||
// Flagged but not auto-fixed.
|
||||
assertThat(0).overridingErrorMessage("%s " + toString(), "arg");
|
||||
}
|
||||
|
||||
void guava() {
|
||||
checkArgument(true, "str " + toString());
|
||||
|
||||
// Flagged but not auto-fixed.
|
||||
checkArgument(true, "%s " + toString(), "arg");
|
||||
}
|
||||
|
||||
void jdk() {
|
||||
String.format("str " + toString());
|
||||
String.format(Locale.ROOT, "str " + toString());
|
||||
|
||||
// Flagged but not auto-fixed.
|
||||
String.format("{} " + toString(), "arg");
|
||||
String.format(Locale.ROOT, "{} " + toString(), "arg");
|
||||
}
|
||||
|
||||
void slf4j() {
|
||||
LOG.debug("str " + toString());
|
||||
LOG.debug((Marker) null, "str " + toString());
|
||||
|
||||
// Flagged but not auto-fixed.
|
||||
LOG.debug("{} " + toString(), "arg");
|
||||
LOG.debug((Marker) null, "{} " + toString(), "arg");
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"import java.util.Locale;",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
"",
|
||||
" void assertj() {",
|
||||
" assertThat(0).overridingErrorMessage(\"%s str\", toString());",
|
||||
" assertThat(0).overridingErrorMessage(\"str %s\", toString());",
|
||||
" assertThat(0).overridingErrorMessage(\"%s%s\", toString(), toString());",
|
||||
" assertThat(0).overridingErrorMessage(\"str %s word %s\", toString(), new A().hashCode());",
|
||||
" assertThat(0).overridingErrorMessage(\"str %s word %s\", toString(), hashCode() / 2);",
|
||||
"",
|
||||
" // Flagged but not auto-fixed.",
|
||||
" assertThat(0).overridingErrorMessage(\"%s \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"",
|
||||
" void guava() {",
|
||||
" checkArgument(true, \"str %s\", toString());",
|
||||
"",
|
||||
" // Flagged but not auto-fixed.",
|
||||
" checkArgument(true, \"%s \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"",
|
||||
" void jdk() {",
|
||||
" String.format(\"str %s\", toString());",
|
||||
" String.format(Locale.ROOT, \"str %s\", toString());",
|
||||
"",
|
||||
" // Flagged but not auto-fixed.",
|
||||
" String.format(\"{} \" + toString(), \"arg\");",
|
||||
" String.format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"",
|
||||
" void slf4j() {",
|
||||
" LOG.debug(\"str {}\", toString());",
|
||||
" LOG.debug((Marker) null, \"str {}\", toString());",
|
||||
"",
|
||||
" // Flagged but not auto-fixed.",
|
||||
" LOG.debug(\"{} \" + toString(), \"arg\");",
|
||||
" LOG.debug((Marker) null, \"{} \" + toString(), \"arg\");",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Locale;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
|
||||
class A {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(A.class);
|
||||
|
||||
void assertj() {
|
||||
assertThat(0).overridingErrorMessage("%s str", toString());
|
||||
assertThat(0).overridingErrorMessage("str %s", toString());
|
||||
assertThat(0).overridingErrorMessage("%s%s", toString(), toString());
|
||||
assertThat(0).overridingErrorMessage("str %s word %s", toString(), new A().hashCode());
|
||||
assertThat(0).overridingErrorMessage("str %s word %s", toString(), hashCode() / 2);
|
||||
|
||||
// Flagged but not auto-fixed.
|
||||
assertThat(0).overridingErrorMessage("%s " + toString(), "arg");
|
||||
}
|
||||
|
||||
void guava() {
|
||||
checkArgument(true, "str %s", toString());
|
||||
|
||||
// Flagged but not auto-fixed.
|
||||
checkArgument(true, "%s " + toString(), "arg");
|
||||
}
|
||||
|
||||
void jdk() {
|
||||
String.format("str %s", toString());
|
||||
String.format(Locale.ROOT, "str %s", toString());
|
||||
|
||||
// Flagged but not auto-fixed.
|
||||
String.format("{} " + toString(), "arg");
|
||||
String.format(Locale.ROOT, "{} " + toString(), "arg");
|
||||
}
|
||||
|
||||
void slf4j() {
|
||||
LOG.debug("str {}", toString());
|
||||
LOG.debug((Marker) null, "str {}", toString());
|
||||
|
||||
// Flagged but not auto-fixed.
|
||||
LOG.debug("{} " + toString(), "arg");
|
||||
LOG.debug((Marker) null, "{} " + toString(), "arg");
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,168 +12,170 @@ final class IdentityConversionTest {
|
||||
CompilationTestHelper.newInstance(IdentityConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.errorprone.matchers.Matchers.instanceMethod;",
|
||||
"import static com.google.errorprone.matchers.Matchers.staticMethod;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableBiMap;",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableListMultimap;",
|
||||
"import com.google.common.collect.ImmutableMap;",
|
||||
"import com.google.common.collect.ImmutableMultimap;",
|
||||
"import com.google.common.collect.ImmutableMultiset;",
|
||||
"import com.google.common.collect.ImmutableRangeMap;",
|
||||
"import com.google.common.collect.ImmutableRangeSet;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.common.collect.ImmutableSetMultimap;",
|
||||
"import com.google.common.collect.ImmutableTable;",
|
||||
"import com.google.errorprone.matchers.Matcher;",
|
||||
"import com.google.errorprone.matchers.Matchers;",
|
||||
"import reactor.adapter.rxjava.RxJava2Adapter;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"public final class A {",
|
||||
" public void m() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Boolean b1 = Boolean.valueOf(Boolean.FALSE);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Boolean b2 = Boolean.valueOf(false);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" boolean b3 = Boolean.valueOf(Boolean.FALSE);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" boolean b4 = Boolean.valueOf(false);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Byte byte1 = Byte.valueOf((Byte) Byte.MIN_VALUE);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Byte byte2 = Byte.valueOf(Byte.MIN_VALUE);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" byte byte3 = Byte.valueOf((Byte) Byte.MIN_VALUE);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" byte byte4 = Byte.valueOf(Byte.MIN_VALUE);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Character c1 = Character.valueOf((Character) 'a');",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Character c2 = Character.valueOf('a');",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" char c3 = Character.valueOf((Character) 'a');",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" char c4 = Character.valueOf('a');",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Double d1 = Double.valueOf((Double) 0.0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Double d2 = Double.valueOf(0.0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" double d3 = Double.valueOf((Double) 0.0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" double d4 = Double.valueOf(0.0);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Float f1 = Float.valueOf((Float) 0.0F);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Float f2 = Float.valueOf(0.0F);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" float f3 = Float.valueOf((Float) 0.0F);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" float f4 = Float.valueOf(0.0F);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Integer i1 = Integer.valueOf((Integer) 1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Integer i2 = Integer.valueOf(1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" int i3 = Integer.valueOf((Integer) 1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" int i4 = Integer.valueOf(1);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Long l1 = Long.valueOf((Long) 1L);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Long l2 = Long.valueOf(1L);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" long l3 = Long.valueOf((Long) 1L);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" long l4 = Long.valueOf(1L);",
|
||||
"",
|
||||
" Long l5 = Long.valueOf((Integer) 1);",
|
||||
" Long l6 = Long.valueOf(1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" long l7 = Long.valueOf((Integer) 1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" long l8 = Long.valueOf(1);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Short s1 = Short.valueOf((Short) Short.MIN_VALUE);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Short s2 = Short.valueOf(Short.MIN_VALUE);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" short s3 = Short.valueOf((Short) Short.MIN_VALUE);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" short s4 = Short.valueOf(Short.MIN_VALUE);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String boolStr = Boolean.valueOf(Boolean.FALSE).toString();",
|
||||
" int boolHash = Boolean.valueOf(false).hashCode();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" int byteHash = Byte.valueOf((Byte) Byte.MIN_VALUE).hashCode();",
|
||||
" String byteStr = Byte.valueOf(Byte.MIN_VALUE).toString();",
|
||||
"",
|
||||
" String str1 = String.valueOf(0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String str2 = String.valueOf(\"1\");",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableBiMap<Object, Object> o1 = ImmutableBiMap.copyOf(ImmutableBiMap.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableList<Object> o2 = ImmutableList.copyOf(ImmutableList.of());",
|
||||
" ImmutableListMultimap<Object, Object> o3 =",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableListMultimap.copyOf(ImmutableListMultimap.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableMap<Object, Object> o4 = ImmutableMap.copyOf(ImmutableMap.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableMultimap<Object, Object> o5 = ImmutableMultimap.copyOf(ImmutableMultimap.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableMultiset<Object> o6 = ImmutableMultiset.copyOf(ImmutableMultiset.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableRangeMap<String, Object> o7 = ImmutableRangeMap.copyOf(ImmutableRangeMap.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableRangeSet<String> o8 = ImmutableRangeSet.copyOf(ImmutableRangeSet.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSet<Object> o9 = ImmutableSet.copyOf(ImmutableSet.of());",
|
||||
" ImmutableSetMultimap<Object, Object> o10 =",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSetMultimap.copyOf(ImmutableSetMultimap.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableTable<Object, Object, Object> o11 = ImmutableTable.copyOf(ImmutableTable.of());",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Matcher allOf1 = Matchers.allOf(instanceMethod());",
|
||||
" Matcher allOf2 = Matchers.allOf(instanceMethod(), staticMethod());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Matcher anyOf1 = Matchers.anyOf(staticMethod());",
|
||||
" Matcher anyOf2 = Matchers.anyOf(instanceMethod(), staticMethod());",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux<Integer> flux1 = Flux.just(1).flatMap(e -> RxJava2Adapter.fluxToFlowable(Flux.just(2)));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux<Integer> flux2 = Flux.concat(Flux.just(1));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux<Integer> flux3 = Flux.firstWithSignal(Flux.just(1));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux<Integer> flux4 = Flux.from(Flux.just(1));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux<Integer> flux5 = Flux.merge(Flux.just(1));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono<Integer> mono1 = Mono.from(Mono.just(1));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono<Integer> mono2 = Mono.fromDirect(Mono.just(1));",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableRangeMap;
|
||||
import com.google.common.collect.ImmutableRangeSet;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.matchers.Matchers;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public final class A {
|
||||
public void m() {
|
||||
// BUG: Diagnostic contains:
|
||||
Boolean b1 = Boolean.valueOf(Boolean.FALSE);
|
||||
// BUG: Diagnostic contains:
|
||||
Boolean b2 = Boolean.valueOf(false);
|
||||
// BUG: Diagnostic contains:
|
||||
boolean b3 = Boolean.valueOf(Boolean.FALSE);
|
||||
// BUG: Diagnostic contains:
|
||||
boolean b4 = Boolean.valueOf(false);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Byte byte1 = Byte.valueOf((Byte) Byte.MIN_VALUE);
|
||||
// BUG: Diagnostic contains:
|
||||
Byte byte2 = Byte.valueOf(Byte.MIN_VALUE);
|
||||
// BUG: Diagnostic contains:
|
||||
byte byte3 = Byte.valueOf((Byte) Byte.MIN_VALUE);
|
||||
// BUG: Diagnostic contains:
|
||||
byte byte4 = Byte.valueOf(Byte.MIN_VALUE);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Character c1 = Character.valueOf((Character) 'a');
|
||||
// BUG: Diagnostic contains:
|
||||
Character c2 = Character.valueOf('a');
|
||||
// BUG: Diagnostic contains:
|
||||
char c3 = Character.valueOf((Character) 'a');
|
||||
// BUG: Diagnostic contains:
|
||||
char c4 = Character.valueOf('a');
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Double d1 = Double.valueOf((Double) 0.0);
|
||||
// BUG: Diagnostic contains:
|
||||
Double d2 = Double.valueOf(0.0);
|
||||
// BUG: Diagnostic contains:
|
||||
double d3 = Double.valueOf((Double) 0.0);
|
||||
// BUG: Diagnostic contains:
|
||||
double d4 = Double.valueOf(0.0);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Float f1 = Float.valueOf((Float) 0.0F);
|
||||
// BUG: Diagnostic contains:
|
||||
Float f2 = Float.valueOf(0.0F);
|
||||
// BUG: Diagnostic contains:
|
||||
float f3 = Float.valueOf((Float) 0.0F);
|
||||
// BUG: Diagnostic contains:
|
||||
float f4 = Float.valueOf(0.0F);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Integer i1 = Integer.valueOf((Integer) 1);
|
||||
// BUG: Diagnostic contains:
|
||||
Integer i2 = Integer.valueOf(1);
|
||||
// BUG: Diagnostic contains:
|
||||
int i3 = Integer.valueOf((Integer) 1);
|
||||
// BUG: Diagnostic contains:
|
||||
int i4 = Integer.valueOf(1);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Long l1 = Long.valueOf((Long) 1L);
|
||||
// BUG: Diagnostic contains:
|
||||
Long l2 = Long.valueOf(1L);
|
||||
// BUG: Diagnostic contains:
|
||||
long l3 = Long.valueOf((Long) 1L);
|
||||
// BUG: Diagnostic contains:
|
||||
long l4 = Long.valueOf(1L);
|
||||
|
||||
Long l5 = Long.valueOf((Integer) 1);
|
||||
Long l6 = Long.valueOf(1);
|
||||
// BUG: Diagnostic contains:
|
||||
long l7 = Long.valueOf((Integer) 1);
|
||||
// BUG: Diagnostic contains:
|
||||
long l8 = Long.valueOf(1);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Short s1 = Short.valueOf((Short) Short.MIN_VALUE);
|
||||
// BUG: Diagnostic contains:
|
||||
Short s2 = Short.valueOf(Short.MIN_VALUE);
|
||||
// BUG: Diagnostic contains:
|
||||
short s3 = Short.valueOf((Short) Short.MIN_VALUE);
|
||||
// BUG: Diagnostic contains:
|
||||
short s4 = Short.valueOf(Short.MIN_VALUE);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
String boolStr = Boolean.valueOf(Boolean.FALSE).toString();
|
||||
int boolHash = Boolean.valueOf(false).hashCode();
|
||||
// BUG: Diagnostic contains:
|
||||
int byteHash = Byte.valueOf((Byte) Byte.MIN_VALUE).hashCode();
|
||||
String byteStr = Byte.valueOf(Byte.MIN_VALUE).toString();
|
||||
|
||||
String str1 = String.valueOf(0);
|
||||
// BUG: Diagnostic contains:
|
||||
String str2 = String.valueOf("1");
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableBiMap<Object, Object> o1 = ImmutableBiMap.copyOf(ImmutableBiMap.of());
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableList<Object> o2 = ImmutableList.copyOf(ImmutableList.of());
|
||||
ImmutableListMultimap<Object, Object> o3 =
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableListMultimap.copyOf(ImmutableListMultimap.of());
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableMap<Object, Object> o4 = ImmutableMap.copyOf(ImmutableMap.of());
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableMultimap<Object, Object> o5 = ImmutableMultimap.copyOf(ImmutableMultimap.of());
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableMultiset<Object> o6 = ImmutableMultiset.copyOf(ImmutableMultiset.of());
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableRangeMap<String, Object> o7 = ImmutableRangeMap.copyOf(ImmutableRangeMap.of());
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableRangeSet<String> o8 = ImmutableRangeSet.copyOf(ImmutableRangeSet.of());
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSet<Object> o9 = ImmutableSet.copyOf(ImmutableSet.of());
|
||||
ImmutableSetMultimap<Object, Object> o10 =
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSetMultimap.copyOf(ImmutableSetMultimap.of());
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableTable<Object, Object, Object> o11 = ImmutableTable.copyOf(ImmutableTable.of());
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Matcher allOf1 = Matchers.allOf(instanceMethod());
|
||||
Matcher allOf2 = Matchers.allOf(instanceMethod(), staticMethod());
|
||||
// BUG: Diagnostic contains:
|
||||
Matcher anyOf1 = Matchers.anyOf(staticMethod());
|
||||
Matcher anyOf2 = Matchers.anyOf(instanceMethod(), staticMethod());
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux<Integer> flux1 = Flux.just(1).flatMap(e -> RxJava2Adapter.fluxToFlowable(Flux.just(2)));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux<Integer> flux2 = Flux.concat(Flux.just(1));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux<Integer> flux3 = Flux.firstWithSignal(Flux.just(1));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux<Integer> flux4 = Flux.from(Flux.just(1));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux<Integer> flux5 = Flux.merge(Flux.just(1));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Mono<Integer> mono1 = Mono.from(Mono.just(1));
|
||||
// BUG: Diagnostic contains:
|
||||
Mono<Integer> mono2 = Mono.fromDirect(Mono.just(1));
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -182,104 +184,108 @@ final class IdentityConversionTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(IdentityConversion.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.errorprone.matchers.Matchers.staticMethod;",
|
||||
"import static org.mockito.Mockito.when;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableCollection;",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.errorprone.matchers.Matcher;",
|
||||
"import com.google.errorprone.matchers.Matchers;",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.Collection;",
|
||||
"import org.reactivestreams.Publisher;",
|
||||
"import reactor.adapter.rxjava.RxJava2Adapter;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"public final class A {",
|
||||
" public void m() {",
|
||||
" ImmutableSet<Object> set1 = ImmutableSet.copyOf(ImmutableSet.of());",
|
||||
" ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||
"",
|
||||
" ImmutableCollection<Integer> list1 = ImmutableList.copyOf(ImmutableList.of(1));",
|
||||
" ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||
"",
|
||||
" Collection<Integer> c1 = ImmutableSet.copyOf(ImmutableSet.of(1));",
|
||||
" Collection<Integer> c2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||
"",
|
||||
" Flux<Integer> f1 = Flux.just(1).flatMap(e -> RxJava2Adapter.fluxToFlowable(Flux.just(2)));",
|
||||
" Flux<Integer> f2 = Flux.concat(Flux.just(3));",
|
||||
" Publisher<Integer> f3 = Flux.firstWithSignal(Flux.just(4));",
|
||||
" Publisher<Integer> f4 = Flux.from(Flux.just(5));",
|
||||
" Publisher<Integer> f5 = Flux.merge(Flux.just(6));",
|
||||
"",
|
||||
" Mono<Integer> m1 = Mono.from(Mono.just(7));",
|
||||
" Publisher<Integer> m2 = Mono.fromDirect(Mono.just(8));",
|
||||
"",
|
||||
" bar(Flux.concat(Flux.just(9)));",
|
||||
" bar(Mono.from(Mono.just(10)));",
|
||||
"",
|
||||
" Object o1 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||
" Object o2 = ImmutableSet.copyOf(ImmutableSet.of());",
|
||||
"",
|
||||
" Matcher matcher = Matchers.allOf(staticMethod());",
|
||||
"",
|
||||
" when(\"foo\".contains(\"f\")).thenAnswer(inv -> ImmutableSet.copyOf(ImmutableList.of(1)));",
|
||||
" }",
|
||||
"",
|
||||
" void bar(Publisher<Integer> publisher) {}",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.matchers.Matchers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public final class A {
|
||||
public void m() {
|
||||
ImmutableSet<Object> set1 = ImmutableSet.copyOf(ImmutableSet.of());
|
||||
ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());
|
||||
|
||||
ImmutableCollection<Integer> list1 = ImmutableList.copyOf(ImmutableList.of(1));
|
||||
ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));
|
||||
|
||||
Collection<Integer> c1 = ImmutableSet.copyOf(ImmutableSet.of(1));
|
||||
Collection<Integer> c2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));
|
||||
|
||||
Flux<Integer> f1 = Flux.just(1).flatMap(e -> RxJava2Adapter.fluxToFlowable(Flux.just(2)));
|
||||
Flux<Integer> f2 = Flux.concat(Flux.just(3));
|
||||
Publisher<Integer> f3 = Flux.firstWithSignal(Flux.just(4));
|
||||
Publisher<Integer> f4 = Flux.from(Flux.just(5));
|
||||
Publisher<Integer> f5 = Flux.merge(Flux.just(6));
|
||||
|
||||
Mono<Integer> m1 = Mono.from(Mono.just(7));
|
||||
Publisher<Integer> m2 = Mono.fromDirect(Mono.just(8));
|
||||
|
||||
bar(Flux.concat(Flux.just(9)));
|
||||
bar(Mono.from(Mono.just(10)));
|
||||
|
||||
Object o1 = ImmutableSet.copyOf(ImmutableList.of());
|
||||
Object o2 = ImmutableSet.copyOf(ImmutableSet.of());
|
||||
|
||||
Matcher matcher = Matchers.allOf(staticMethod());
|
||||
|
||||
when("foo".contains("f")).thenAnswer(inv -> ImmutableSet.copyOf(ImmutableList.of(1)));
|
||||
}
|
||||
|
||||
void bar(Publisher<Integer> publisher) {}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static com.google.errorprone.matchers.Matchers.staticMethod;",
|
||||
"import static org.mockito.Mockito.when;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableCollection;",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.errorprone.matchers.Matcher;",
|
||||
"import com.google.errorprone.matchers.Matchers;",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.Collection;",
|
||||
"import org.reactivestreams.Publisher;",
|
||||
"import reactor.adapter.rxjava.RxJava2Adapter;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"public final class A {",
|
||||
" public void m() {",
|
||||
" ImmutableSet<Object> set1 = ImmutableSet.of();",
|
||||
" ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||
"",
|
||||
" ImmutableCollection<Integer> list1 = ImmutableList.of(1);",
|
||||
" ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||
"",
|
||||
" Collection<Integer> c1 = ImmutableSet.of(1);",
|
||||
" Collection<Integer> c2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||
"",
|
||||
" Flux<Integer> f1 = Flux.just(1).flatMap(e -> Flux.just(2));",
|
||||
" Flux<Integer> f2 = Flux.just(3);",
|
||||
" Publisher<Integer> f3 = Flux.just(4);",
|
||||
" Publisher<Integer> f4 = Flux.just(5);",
|
||||
" Publisher<Integer> f5 = Flux.just(6);",
|
||||
"",
|
||||
" Mono<Integer> m1 = Mono.just(7);",
|
||||
" Publisher<Integer> m2 = Mono.just(8);",
|
||||
"",
|
||||
" bar(Flux.just(9));",
|
||||
" bar(Mono.just(10));",
|
||||
"",
|
||||
" Object o1 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||
" Object o2 = ImmutableSet.of();",
|
||||
"",
|
||||
" Matcher matcher = staticMethod();",
|
||||
"",
|
||||
" when(\"foo\".contains(\"f\")).thenAnswer(inv -> ImmutableSet.copyOf(ImmutableList.of(1)));",
|
||||
" }",
|
||||
"",
|
||||
" void bar(Publisher<Integer> publisher) {}",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.matchers.Matchers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public final class A {
|
||||
public void m() {
|
||||
ImmutableSet<Object> set1 = ImmutableSet.of();
|
||||
ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());
|
||||
|
||||
ImmutableCollection<Integer> list1 = ImmutableList.of(1);
|
||||
ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));
|
||||
|
||||
Collection<Integer> c1 = ImmutableSet.of(1);
|
||||
Collection<Integer> c2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));
|
||||
|
||||
Flux<Integer> f1 = Flux.just(1).flatMap(e -> Flux.just(2));
|
||||
Flux<Integer> f2 = Flux.just(3);
|
||||
Publisher<Integer> f3 = Flux.just(4);
|
||||
Publisher<Integer> f4 = Flux.just(5);
|
||||
Publisher<Integer> f5 = Flux.just(6);
|
||||
|
||||
Mono<Integer> m1 = Mono.just(7);
|
||||
Publisher<Integer> m2 = Mono.just(8);
|
||||
|
||||
bar(Flux.just(9));
|
||||
bar(Mono.just(10));
|
||||
|
||||
Object o1 = ImmutableSet.copyOf(ImmutableList.of());
|
||||
Object o2 = ImmutableSet.of();
|
||||
|
||||
Matcher matcher = staticMethod();
|
||||
|
||||
when("foo".contains("f")).thenAnswer(inv -> ImmutableSet.copyOf(ImmutableList.of(1)));
|
||||
}
|
||||
|
||||
void bar(Publisher<Integer> publisher) {}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -289,38 +295,42 @@ final class IdentityConversionTest {
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableCollection;",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.util.ArrayList;",
|
||||
"",
|
||||
"public final class A {",
|
||||
" public void m() {",
|
||||
" ImmutableSet<Object> set1 = ImmutableSet.copyOf(ImmutableSet.of());",
|
||||
" ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||
"",
|
||||
" ImmutableCollection<Integer> list1 = ImmutableList.copyOf(ImmutableList.of(1));",
|
||||
" ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public final class A {
|
||||
public void m() {
|
||||
ImmutableSet<Object> set1 = ImmutableSet.copyOf(ImmutableSet.of());
|
||||
ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());
|
||||
|
||||
ImmutableCollection<Integer> list1 = ImmutableList.copyOf(ImmutableList.of(1));
|
||||
ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableCollection;",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.util.ArrayList;",
|
||||
"",
|
||||
"public final class A {",
|
||||
" public void m() {",
|
||||
" @SuppressWarnings(\"IdentityConversion\")",
|
||||
" ImmutableSet<Object> set1 = ImmutableSet.copyOf(ImmutableSet.of());",
|
||||
" ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||
"",
|
||||
" @SuppressWarnings(\"IdentityConversion\")",
|
||||
" ImmutableCollection<Integer> list1 = ImmutableList.copyOf(ImmutableList.of(1));",
|
||||
" ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public final class A {
|
||||
public void m() {
|
||||
@SuppressWarnings("IdentityConversion")
|
||||
ImmutableSet<Object> set1 = ImmutableSet.copyOf(ImmutableSet.of());
|
||||
ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());
|
||||
|
||||
@SuppressWarnings("IdentityConversion")
|
||||
ImmutableCollection<Integer> list1 = ImmutableList.copyOf(ImmutableList.of(1));
|
||||
ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,94 +11,96 @@ final class ImmutablesSortedSetComparatorTest {
|
||||
CompilationTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ContiguousSet;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
"import java.util.NavigableSet;",
|
||||
"import java.util.Set;",
|
||||
"import java.util.SortedSet;",
|
||||
"import java.util.TreeSet;",
|
||||
"import org.immutables.value.Value;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @Value.Immutable",
|
||||
" interface ImmutableInterface {",
|
||||
" Set<String> set();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" SortedSet<String> sortedSet();",
|
||||
"",
|
||||
" @Value.NaturalOrder",
|
||||
" SortedSet<String> sortedSet2();",
|
||||
" }",
|
||||
"",
|
||||
" @Value.Modifiable",
|
||||
" interface ModifiableInterfaceWithDefaults {",
|
||||
" @Value.Default",
|
||||
" default Set<Integer> set() {",
|
||||
" return new TreeSet<>();",
|
||||
" }",
|
||||
"",
|
||||
" @Value.Default",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" default NavigableSet<Integer> navigableSet() {",
|
||||
" return new TreeSet<>();",
|
||||
" }",
|
||||
"",
|
||||
" @Value.Default",
|
||||
" @Value.ReverseOrder",
|
||||
" default NavigableSet<Integer> navigableSet2() {",
|
||||
" return new TreeSet<>();",
|
||||
" }",
|
||||
"",
|
||||
" default NavigableSet<Integer> nonPropertyNavigableSet() {",
|
||||
" return new TreeSet<>();",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" interface NonImmutablesInterface {",
|
||||
" SortedSet<String> sortedSet();",
|
||||
" }",
|
||||
"",
|
||||
" @Value.Immutable",
|
||||
" abstract class AbstractImmutableWithDefaults {",
|
||||
" @Value.Default",
|
||||
" ImmutableSet<Integer> immutableSet() {",
|
||||
" return ImmutableSet.of();",
|
||||
" }",
|
||||
"",
|
||||
" @Value.Default",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSortedSet<String> immutableSortedSet() {",
|
||||
" return ImmutableSortedSet.of();",
|
||||
" }",
|
||||
"",
|
||||
" @Value.Default",
|
||||
" @Value.NaturalOrder",
|
||||
" ImmutableSortedSet<String> immutableSortedSet2() {",
|
||||
" return ImmutableSortedSet.of();",
|
||||
" }",
|
||||
"",
|
||||
" ImmutableSortedSet<String> nonPropertyImmutableSortedSet() {",
|
||||
" return ImmutableSortedSet.of();",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" @Value.Modifiable",
|
||||
" abstract class AbstractModifiable {",
|
||||
" abstract ImmutableSet<Integer> immutableSet();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" abstract ContiguousSet<Integer> contiguousSet();",
|
||||
"",
|
||||
" @Value.ReverseOrder",
|
||||
" abstract ContiguousSet<Integer> contiguousSet2();",
|
||||
" }",
|
||||
"",
|
||||
" abstract class AbstractNonImmutables {",
|
||||
" abstract SortedSet<Integer> sortedSet();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ContiguousSet;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import org.immutables.value.Value;
|
||||
|
||||
interface A {
|
||||
@Value.Immutable
|
||||
interface ImmutableInterface {
|
||||
Set<String> set();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
SortedSet<String> sortedSet();
|
||||
|
||||
@Value.NaturalOrder
|
||||
SortedSet<String> sortedSet2();
|
||||
}
|
||||
|
||||
@Value.Modifiable
|
||||
interface ModifiableInterfaceWithDefaults {
|
||||
@Value.Default
|
||||
default Set<Integer> set() {
|
||||
return new TreeSet<>();
|
||||
}
|
||||
|
||||
@Value.Default
|
||||
// BUG: Diagnostic contains:
|
||||
default NavigableSet<Integer> navigableSet() {
|
||||
return new TreeSet<>();
|
||||
}
|
||||
|
||||
@Value.Default
|
||||
@Value.ReverseOrder
|
||||
default NavigableSet<Integer> navigableSet2() {
|
||||
return new TreeSet<>();
|
||||
}
|
||||
|
||||
default NavigableSet<Integer> nonPropertyNavigableSet() {
|
||||
return new TreeSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
interface NonImmutablesInterface {
|
||||
SortedSet<String> sortedSet();
|
||||
}
|
||||
|
||||
@Value.Immutable
|
||||
abstract class AbstractImmutableWithDefaults {
|
||||
@Value.Default
|
||||
ImmutableSet<Integer> immutableSet() {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
@Value.Default
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSortedSet<String> immutableSortedSet() {
|
||||
return ImmutableSortedSet.of();
|
||||
}
|
||||
|
||||
@Value.Default
|
||||
@Value.NaturalOrder
|
||||
ImmutableSortedSet<String> immutableSortedSet2() {
|
||||
return ImmutableSortedSet.of();
|
||||
}
|
||||
|
||||
ImmutableSortedSet<String> nonPropertyImmutableSortedSet() {
|
||||
return ImmutableSortedSet.of();
|
||||
}
|
||||
}
|
||||
|
||||
@Value.Modifiable
|
||||
abstract class AbstractModifiable {
|
||||
abstract ImmutableSet<Integer> immutableSet();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
abstract ContiguousSet<Integer> contiguousSet();
|
||||
|
||||
@Value.ReverseOrder
|
||||
abstract ContiguousSet<Integer> contiguousSet2();
|
||||
}
|
||||
|
||||
abstract class AbstractNonImmutables {
|
||||
abstract SortedSet<Integer> sortedSet();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -107,36 +109,40 @@ final class ImmutablesSortedSetComparatorTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
"import java.util.SortedSet;",
|
||||
"import org.immutables.value.Value;",
|
||||
"",
|
||||
"@Value.Immutable",
|
||||
"abstract class A {",
|
||||
" abstract ImmutableSortedSet<String> sortedSet();",
|
||||
"",
|
||||
" @Value.Modifiable",
|
||||
" interface B {",
|
||||
" SortedSet<String> sortedSet();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import java.util.SortedSet;
|
||||
import org.immutables.value.Value;
|
||||
|
||||
@Value.Immutable
|
||||
abstract class A {
|
||||
abstract ImmutableSortedSet<String> sortedSet();
|
||||
|
||||
@Value.Modifiable
|
||||
interface B {
|
||||
SortedSet<String> sortedSet();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
"import java.util.SortedSet;",
|
||||
"import org.immutables.value.Value;",
|
||||
"",
|
||||
"@Value.Immutable",
|
||||
"abstract class A {",
|
||||
" @Value.NaturalOrder",
|
||||
" abstract ImmutableSortedSet<String> sortedSet();",
|
||||
"",
|
||||
" @Value.Modifiable",
|
||||
" interface B {",
|
||||
" @Value.NaturalOrder",
|
||||
" SortedSet<String> sortedSet();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import java.util.SortedSet;
|
||||
import org.immutables.value.Value;
|
||||
|
||||
@Value.Immutable
|
||||
abstract class A {
|
||||
@Value.NaturalOrder
|
||||
abstract ImmutableSortedSet<String> sortedSet();
|
||||
|
||||
@Value.Modifiable
|
||||
interface B {
|
||||
@Value.NaturalOrder
|
||||
SortedSet<String> sortedSet();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -145,33 +151,37 @@ final class ImmutablesSortedSetComparatorTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(ImmutablesSortedSetComparator.class, getClass())
|
||||
.addInputLines(
|
||||
"MySpringService.java",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
"import org.springframework.beans.factory.annotation.Value;",
|
||||
"",
|
||||
"class MySpringService {",
|
||||
" MySpringService(@Value(\"${someProperty}\") String prop) {}",
|
||||
" ;",
|
||||
"",
|
||||
" @org.immutables.value.Value.Immutable",
|
||||
" interface A {",
|
||||
" ImmutableSortedSet<String> sortedSet();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
class MySpringService {
|
||||
MySpringService(@Value("${someProperty}") String prop) {}
|
||||
;
|
||||
|
||||
@org.immutables.value.Value.Immutable
|
||||
interface A {
|
||||
ImmutableSortedSet<String> sortedSet();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"MySpringService.java",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
"import org.springframework.beans.factory.annotation.Value;",
|
||||
"",
|
||||
"class MySpringService {",
|
||||
" MySpringService(@Value(\"${someProperty}\") String prop) {}",
|
||||
" ;",
|
||||
"",
|
||||
" @org.immutables.value.Value.Immutable",
|
||||
" interface A {",
|
||||
" @org.immutables.value.Value.NaturalOrder",
|
||||
" ImmutableSortedSet<String> sortedSet();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
class MySpringService {
|
||||
MySpringService(@Value("${someProperty}") String prop) {}
|
||||
;
|
||||
|
||||
@org.immutables.value.Value.Immutable
|
||||
interface A {
|
||||
@org.immutables.value.Value.NaturalOrder
|
||||
ImmutableSortedSet<String> sortedSet();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,31 +11,33 @@ final class IsInstanceLambdaUsageTest {
|
||||
CompilationTestHelper.newInstance(IsInstanceLambdaUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Integer localVariable = 0;",
|
||||
"",
|
||||
" Stream.of(0).map(i -> i + 1);",
|
||||
" Stream.of(1).filter(Integer.class::isInstance);",
|
||||
" Stream.of(2).filter(i -> i.getClass() instanceof Class);",
|
||||
" Stream.of(3).filter(i -> localVariable instanceof Integer);",
|
||||
" // XXX: Ideally this case is also flagged. Pick this up in the context of merging the",
|
||||
" // `IsInstanceLambdaUsage` and `MethodReferenceUsage` checks, or introduce a separate check that",
|
||||
" // simplifies unnecessary block lambda expressions.",
|
||||
" Stream.of(4)",
|
||||
" .filter(",
|
||||
" i -> {",
|
||||
" return localVariable instanceof Integer;",
|
||||
" });",
|
||||
" Flux.just(5, \"foo\").distinctUntilChanged(v -> v, (a, b) -> a instanceof Integer);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of(6).filter(i -> i instanceof Integer);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.stream.Stream;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Integer localVariable = 0;
|
||||
|
||||
Stream.of(0).map(i -> i + 1);
|
||||
Stream.of(1).filter(Integer.class::isInstance);
|
||||
Stream.of(2).filter(i -> i.getClass() instanceof Class);
|
||||
Stream.of(3).filter(i -> localVariable instanceof Integer);
|
||||
// XXX: Ideally this case is also flagged. Pick this up in the context of merging the
|
||||
// `IsInstanceLambdaUsage` and `MethodReferenceUsage` checks, or introduce a separate check that
|
||||
// simplifies unnecessary block lambda expressions.
|
||||
Stream.of(4)
|
||||
.filter(
|
||||
i -> {
|
||||
return localVariable instanceof Integer;
|
||||
});
|
||||
Flux.just(5, "foo").distinctUntilChanged(v -> v, (a, b) -> a instanceof Integer);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Stream.of(6).filter(i -> i instanceof Integer);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -44,22 +46,26 @@ final class IsInstanceLambdaUsageTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(IsInstanceLambdaUsage.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Stream.of(1).filter(i -> i instanceof Integer);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Stream.of(1).filter(i -> i instanceof Integer);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Stream.of(1).filter(Integer.class::isInstance);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Stream.of(1).filter(Integer.class::isInstance);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,83 +11,85 @@ final class JUnitClassModifiersTest {
|
||||
CompilationTestHelper.newInstance(JUnitClassModifiers.class, getClass())
|
||||
.addSourceLines(
|
||||
"Container.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"import org.springframework.boot.test.context.TestConfiguration;",
|
||||
"import org.springframework.context.annotation.Configuration;",
|
||||
"",
|
||||
"class Container {",
|
||||
" final class FinalAndPackagePrivate {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" final class FinalAndPackagePrivateWithCustomTestMethod {",
|
||||
" @ParameterizedTest",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" public abstract class Abstract {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" @Configuration",
|
||||
" class WithConfigurationAnnotation {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" @TestConfiguration",
|
||||
" class WithConfigurationMetaAnnotation {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private final class Private {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected final class Protected {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public final class Public {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" class NonFinal {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" class NonFinalWithCustomTestMethod {",
|
||||
" @ParameterizedTest",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" @Configuration",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public class PublicWithConfigurationAnnotation {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"",
|
||||
" @TestConfiguration",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected class ProtectedWithConfigurationMetaAnnotation {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
class Container {
|
||||
final class FinalAndPackagePrivate {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
final class FinalAndPackagePrivateWithCustomTestMethod {
|
||||
@ParameterizedTest
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
public abstract class Abstract {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
class WithConfigurationAnnotation {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
@TestConfiguration
|
||||
class WithConfigurationMetaAnnotation {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
private final class Private {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
protected final class Protected {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
public final class Public {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
class NonFinal {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
class NonFinalWithCustomTestMethod {
|
||||
@ParameterizedTest
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
// BUG: Diagnostic contains:
|
||||
public class PublicWithConfigurationAnnotation {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
@TestConfiguration
|
||||
// BUG: Diagnostic contains:
|
||||
protected class ProtectedWithConfigurationMetaAnnotation {
|
||||
@Test
|
||||
void foo() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -96,34 +98,38 @@ final class JUnitClassModifiersTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitClassModifiers.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.springframework.context.annotation.Configuration;",
|
||||
"",
|
||||
"public class A {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
"",
|
||||
" @Configuration",
|
||||
" private static class B {",
|
||||
" @Test",
|
||||
" void bar() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
public class A {
|
||||
@Test
|
||||
void foo() {}
|
||||
|
||||
@Configuration
|
||||
private static class B {
|
||||
@Test
|
||||
void bar() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.springframework.context.annotation.Configuration;",
|
||||
"",
|
||||
"final class A {",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
"",
|
||||
" @Configuration",
|
||||
" static class B {",
|
||||
" @Test",
|
||||
" void bar() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
final class A {
|
||||
@Test
|
||||
void foo() {}
|
||||
|
||||
@Configuration
|
||||
static class B {
|
||||
@Test
|
||||
void bar() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,330 +11,336 @@ final class JUnitMethodDeclarationTest {
|
||||
CompilationTestHelper.newInstance(JUnitMethodDeclaration.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"",
|
||||
"import org.junit.jupiter.api.AfterAll;",
|
||||
"import org.junit.jupiter.api.AfterEach;",
|
||||
"import org.junit.jupiter.api.BeforeAll;",
|
||||
"import org.junit.jupiter.api.BeforeEach;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"",
|
||||
"class A {",
|
||||
" {",
|
||||
" arguments();",
|
||||
" }",
|
||||
"",
|
||||
" @BeforeAll",
|
||||
" void setUp1() {}",
|
||||
"",
|
||||
" @BeforeAll",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public void setUp2() {}",
|
||||
"",
|
||||
" @BeforeAll",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected void setUp3() {}",
|
||||
"",
|
||||
" @BeforeAll",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private void setUp4() {}",
|
||||
"",
|
||||
" @BeforeEach",
|
||||
" void setup5() {}",
|
||||
"",
|
||||
" @BeforeEach",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public void setUp6() {}",
|
||||
"",
|
||||
" @BeforeEach",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected void setUp7() {}",
|
||||
"",
|
||||
" @BeforeEach",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private void setUp8() {}",
|
||||
"",
|
||||
" @AfterEach",
|
||||
" void tearDown1() {}",
|
||||
"",
|
||||
" @AfterEach",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public void tearDown2() {}",
|
||||
"",
|
||||
" @AfterEach",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected void tearDown3() {}",
|
||||
"",
|
||||
" @AfterEach",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private void tearDown4() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" void tearDown5() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public void tearDown6() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected void tearDown7() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private void tearDown8() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void test() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void method1() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void testMethod2() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public void method3() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected void method4() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private void method5() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" void method6() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void testMethod7() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public void method8() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected void method9() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private void method10() {}",
|
||||
"",
|
||||
" @BeforeEach",
|
||||
" @BeforeAll",
|
||||
" @AfterEach",
|
||||
" @AfterAll",
|
||||
" void testNonTestMethod1() {}",
|
||||
"",
|
||||
" public void testNonTestMethod2() {}",
|
||||
"",
|
||||
" protected void testNonTestMethod3() {}",
|
||||
"",
|
||||
" private void testNonTestMethod4() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void test5() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: (but note that a method named `toString` is already defined in this",
|
||||
" // class or a supertype)",
|
||||
" void testToString() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: (but note that a method named `overload` is already defined in this",
|
||||
" // class or a supertype)",
|
||||
" void testOverload() {}",
|
||||
"",
|
||||
" void overload() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: (but note that `arguments` is already statically imported)",
|
||||
" void testArguments() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: (but note that `public` is not a valid identifier)",
|
||||
" void testPublic() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: (but note that `null` is not a valid identifier)",
|
||||
" void testNull() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void testRecord() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void testMethodThatIsOverriddenWithoutOverrideAnnotation() {}",
|
||||
"}")
|
||||
"""
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
||||
class A {
|
||||
{
|
||||
arguments();
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
void setUp1() {}
|
||||
|
||||
@BeforeAll
|
||||
// BUG: Diagnostic contains:
|
||||
public void setUp2() {}
|
||||
|
||||
@BeforeAll
|
||||
// BUG: Diagnostic contains:
|
||||
protected void setUp3() {}
|
||||
|
||||
@BeforeAll
|
||||
// BUG: Diagnostic contains:
|
||||
private void setUp4() {}
|
||||
|
||||
@BeforeEach
|
||||
void setup5() {}
|
||||
|
||||
@BeforeEach
|
||||
// BUG: Diagnostic contains:
|
||||
public void setUp6() {}
|
||||
|
||||
@BeforeEach
|
||||
// BUG: Diagnostic contains:
|
||||
protected void setUp7() {}
|
||||
|
||||
@BeforeEach
|
||||
// BUG: Diagnostic contains:
|
||||
private void setUp8() {}
|
||||
|
||||
@AfterEach
|
||||
void tearDown1() {}
|
||||
|
||||
@AfterEach
|
||||
// BUG: Diagnostic contains:
|
||||
public void tearDown2() {}
|
||||
|
||||
@AfterEach
|
||||
// BUG: Diagnostic contains:
|
||||
protected void tearDown3() {}
|
||||
|
||||
@AfterEach
|
||||
// BUG: Diagnostic contains:
|
||||
private void tearDown4() {}
|
||||
|
||||
@AfterAll
|
||||
void tearDown5() {}
|
||||
|
||||
@AfterAll
|
||||
// BUG: Diagnostic contains:
|
||||
public void tearDown6() {}
|
||||
|
||||
@AfterAll
|
||||
// BUG: Diagnostic contains:
|
||||
protected void tearDown7() {}
|
||||
|
||||
@AfterAll
|
||||
// BUG: Diagnostic contains:
|
||||
private void tearDown8() {}
|
||||
|
||||
@Test
|
||||
void test() {}
|
||||
|
||||
@Test
|
||||
void method1() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains:
|
||||
void testMethod2() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains:
|
||||
public void method3() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains:
|
||||
protected void method4() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains:
|
||||
private void method5() {}
|
||||
|
||||
@ParameterizedTest
|
||||
void method6() {}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
void testMethod7() {}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
public void method8() {}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
protected void method9() {}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
private void method10() {}
|
||||
|
||||
@BeforeEach
|
||||
@BeforeAll
|
||||
@AfterEach
|
||||
@AfterAll
|
||||
void testNonTestMethod1() {}
|
||||
|
||||
public void testNonTestMethod2() {}
|
||||
|
||||
protected void testNonTestMethod3() {}
|
||||
|
||||
private void testNonTestMethod4() {}
|
||||
|
||||
@Test
|
||||
void test5() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains: (but note that a method named `toString` is already defined in this
|
||||
// class or a supertype)
|
||||
void testToString() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains: (but note that a method named `overload` is already defined in this
|
||||
// class or a supertype)
|
||||
void testOverload() {}
|
||||
|
||||
void overload() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains: (but note that `arguments` is already statically imported)
|
||||
void testArguments() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains: (but note that `public` is not a valid identifier)
|
||||
void testPublic() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains: (but note that `null` is not a valid identifier)
|
||||
void testNull() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains:
|
||||
void testRecord() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains:
|
||||
void testMethodThatIsOverriddenWithoutOverrideAnnotation() {}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"B.java",
|
||||
"import org.junit.jupiter.api.AfterAll;",
|
||||
"import org.junit.jupiter.api.AfterEach;",
|
||||
"import org.junit.jupiter.api.BeforeAll;",
|
||||
"import org.junit.jupiter.api.BeforeEach;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"",
|
||||
"class B extends A {",
|
||||
" @Override",
|
||||
" @BeforeAll",
|
||||
" void setUp1() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @BeforeAll",
|
||||
" public void setUp2() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @BeforeAll",
|
||||
" protected void setUp3() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @BeforeEach",
|
||||
" void setup5() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @BeforeEach",
|
||||
" public void setUp6() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @BeforeEach",
|
||||
" protected void setUp7() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @AfterEach",
|
||||
" void tearDown1() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @AfterEach",
|
||||
" public void tearDown2() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @AfterEach",
|
||||
" protected void tearDown3() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @AfterAll",
|
||||
" void tearDown5() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @AfterAll",
|
||||
" public void tearDown6() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @AfterAll",
|
||||
" protected void tearDown7() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void test() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void method1() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void testMethod2() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" public void method3() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" protected void method4() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @ParameterizedTest",
|
||||
" void method6() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @ParameterizedTest",
|
||||
" void testMethod7() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @ParameterizedTest",
|
||||
" public void method8() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @ParameterizedTest",
|
||||
" protected void method9() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @BeforeEach",
|
||||
" @BeforeAll",
|
||||
" @AfterEach",
|
||||
" @AfterAll",
|
||||
" void testNonTestMethod1() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" public void testNonTestMethod2() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" protected void testNonTestMethod3() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void test5() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void testToString() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void testOverload() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" void overload() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void testArguments() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void testPublic() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void testNull() {}",
|
||||
"",
|
||||
" @Override",
|
||||
" @Test",
|
||||
" void testRecord() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void testMethodThatIsOverriddenWithoutOverrideAnnotation() {}",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
||||
class B extends A {
|
||||
@Override
|
||||
@BeforeAll
|
||||
void setUp1() {}
|
||||
|
||||
@Override
|
||||
@BeforeAll
|
||||
public void setUp2() {}
|
||||
|
||||
@Override
|
||||
@BeforeAll
|
||||
protected void setUp3() {}
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
void setup5() {}
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
public void setUp6() {}
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
protected void setUp7() {}
|
||||
|
||||
@Override
|
||||
@AfterEach
|
||||
void tearDown1() {}
|
||||
|
||||
@Override
|
||||
@AfterEach
|
||||
public void tearDown2() {}
|
||||
|
||||
@Override
|
||||
@AfterEach
|
||||
protected void tearDown3() {}
|
||||
|
||||
@Override
|
||||
@AfterAll
|
||||
void tearDown5() {}
|
||||
|
||||
@Override
|
||||
@AfterAll
|
||||
public void tearDown6() {}
|
||||
|
||||
@Override
|
||||
@AfterAll
|
||||
protected void tearDown7() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void test() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void method1() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void testMethod2() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void method3() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
protected void method4() {}
|
||||
|
||||
@Override
|
||||
@ParameterizedTest
|
||||
void method6() {}
|
||||
|
||||
@Override
|
||||
@ParameterizedTest
|
||||
void testMethod7() {}
|
||||
|
||||
@Override
|
||||
@ParameterizedTest
|
||||
public void method8() {}
|
||||
|
||||
@Override
|
||||
@ParameterizedTest
|
||||
protected void method9() {}
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
@BeforeAll
|
||||
@AfterEach
|
||||
@AfterAll
|
||||
void testNonTestMethod1() {}
|
||||
|
||||
@Override
|
||||
public void testNonTestMethod2() {}
|
||||
|
||||
@Override
|
||||
protected void testNonTestMethod3() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void test5() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void testToString() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void testOverload() {}
|
||||
|
||||
@Override
|
||||
void overload() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void testArguments() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void testPublic() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void testNull() {}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
void testRecord() {}
|
||||
|
||||
@Test
|
||||
void testMethodThatIsOverriddenWithoutOverrideAnnotation() {}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"C.java",
|
||||
"import org.junit.jupiter.api.AfterAll;",
|
||||
"import org.junit.jupiter.api.BeforeAll;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"",
|
||||
"abstract class C {",
|
||||
" @BeforeAll",
|
||||
" public void setUp() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void testMethod1() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private void tearDown() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" final void testMethod2() {}",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
abstract class C {
|
||||
@BeforeAll
|
||||
public void setUp() {}
|
||||
|
||||
@Test
|
||||
void testMethod1() {}
|
||||
|
||||
@AfterAll
|
||||
// BUG: Diagnostic contains:
|
||||
private void tearDown() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains:
|
||||
final void testMethod2() {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -343,126 +349,130 @@ final class JUnitMethodDeclarationTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitMethodDeclaration.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"",
|
||||
"import org.junit.jupiter.api.AfterAll;",
|
||||
"import org.junit.jupiter.api.AfterEach;",
|
||||
"import org.junit.jupiter.api.BeforeAll;",
|
||||
"import org.junit.jupiter.api.BeforeEach;",
|
||||
"import org.junit.jupiter.api.RepeatedTest;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"",
|
||||
"class A {",
|
||||
" {",
|
||||
" arguments();",
|
||||
" }",
|
||||
"",
|
||||
" @BeforeAll",
|
||||
" public void setUp1() {}",
|
||||
"",
|
||||
" @BeforeEach",
|
||||
" protected void setUp2() {}",
|
||||
"",
|
||||
" @AfterEach",
|
||||
" private void setUp3() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" private void setUp4() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void testFoo() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" void testBar() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" public void baz() {}",
|
||||
"",
|
||||
" @RepeatedTest(2)",
|
||||
" private void qux() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" protected void quux() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" public void testToString() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" public void testOverload() {}",
|
||||
"",
|
||||
" void overload() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" protected void testArguments() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" private void testClass() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" private void testTrue() {}",
|
||||
"}")
|
||||
"""
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.RepeatedTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
||||
class A {
|
||||
{
|
||||
arguments();
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public void setUp1() {}
|
||||
|
||||
@BeforeEach
|
||||
protected void setUp2() {}
|
||||
|
||||
@AfterEach
|
||||
private void setUp3() {}
|
||||
|
||||
@AfterAll
|
||||
private void setUp4() {}
|
||||
|
||||
@Test
|
||||
void testFoo() {}
|
||||
|
||||
@ParameterizedTest
|
||||
void testBar() {}
|
||||
|
||||
@Test
|
||||
public void baz() {}
|
||||
|
||||
@RepeatedTest(2)
|
||||
private void qux() {}
|
||||
|
||||
@ParameterizedTest
|
||||
protected void quux() {}
|
||||
|
||||
@Test
|
||||
public void testToString() {}
|
||||
|
||||
@Test
|
||||
public void testOverload() {}
|
||||
|
||||
void overload() {}
|
||||
|
||||
@Test
|
||||
protected void testArguments() {}
|
||||
|
||||
@Test
|
||||
private void testClass() {}
|
||||
|
||||
@Test
|
||||
private void testTrue() {}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"",
|
||||
"import org.junit.jupiter.api.AfterAll;",
|
||||
"import org.junit.jupiter.api.AfterEach;",
|
||||
"import org.junit.jupiter.api.BeforeAll;",
|
||||
"import org.junit.jupiter.api.BeforeEach;",
|
||||
"import org.junit.jupiter.api.RepeatedTest;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"",
|
||||
"class A {",
|
||||
" {",
|
||||
" arguments();",
|
||||
" }",
|
||||
"",
|
||||
" @BeforeAll",
|
||||
" void setUp1() {}",
|
||||
"",
|
||||
" @BeforeEach",
|
||||
" void setUp2() {}",
|
||||
"",
|
||||
" @AfterEach",
|
||||
" void setUp3() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" void setUp4() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void foo() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" void bar() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void baz() {}",
|
||||
"",
|
||||
" @RepeatedTest(2)",
|
||||
" void qux() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" void quux() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void testToString() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void testOverload() {}",
|
||||
"",
|
||||
" void overload() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void testArguments() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void testClass() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void testTrue() {}",
|
||||
"}")
|
||||
"""
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.RepeatedTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
||||
class A {
|
||||
{
|
||||
arguments();
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
void setUp1() {}
|
||||
|
||||
@BeforeEach
|
||||
void setUp2() {}
|
||||
|
||||
@AfterEach
|
||||
void setUp3() {}
|
||||
|
||||
@AfterAll
|
||||
void setUp4() {}
|
||||
|
||||
@Test
|
||||
void foo() {}
|
||||
|
||||
@ParameterizedTest
|
||||
void bar() {}
|
||||
|
||||
@Test
|
||||
void baz() {}
|
||||
|
||||
@RepeatedTest(2)
|
||||
void qux() {}
|
||||
|
||||
@ParameterizedTest
|
||||
void quux() {}
|
||||
|
||||
@Test
|
||||
void testToString() {}
|
||||
|
||||
@Test
|
||||
void testOverload() {}
|
||||
|
||||
void overload() {}
|
||||
|
||||
@Test
|
||||
void testArguments() {}
|
||||
|
||||
@Test
|
||||
void testClass() {}
|
||||
|
||||
@Test
|
||||
void testTrue() {}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,25 +11,27 @@ final class JUnitNullaryParameterizedTestDeclarationTest {
|
||||
CompilationTestHelper.newInstance(JUnitNullaryParameterizedTestDeclaration.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"import org.junit.jupiter.params.provider.ValueSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" void nonTest() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void nonParameterizedTest() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(ints = {0, 1})",
|
||||
" void goodParameterizedTest(int someInt) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(ints = {0, 1})",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void nullaryParameterizedTest() {}",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
class A {
|
||||
void nonTest() {}
|
||||
|
||||
@Test
|
||||
void nonParameterizedTest() {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {0, 1})
|
||||
void goodParameterizedTest(int someInt) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {0, 1})
|
||||
// BUG: Diagnostic contains:
|
||||
void nullaryParameterizedTest() {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -39,117 +41,125 @@ final class JUnitNullaryParameterizedTestDeclarationTest {
|
||||
JUnitNullaryParameterizedTestDeclaration.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"import org.junit.jupiter.params.provider.ArgumentsProvider;",
|
||||
"import org.junit.jupiter.params.provider.ArgumentsSource;",
|
||||
"import org.junit.jupiter.params.provider.ArgumentsSources;",
|
||||
"import org.junit.jupiter.params.provider.MethodSource;",
|
||||
"import org.junit.jupiter.params.provider.ValueSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" @ParameterizedTest",
|
||||
" void withoutArgumentSource() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ArgumentsSource(ArgumentsProvider.class)",
|
||||
" void withCustomArgumentSource() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ArgumentsSources({",
|
||||
" @ArgumentsSource(ArgumentsProvider.class),",
|
||||
" @ArgumentsSource(ArgumentsProvider.class)",
|
||||
" })",
|
||||
" void withCustomerArgumentSources() {}",
|
||||
"",
|
||||
" /** Foo. */",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(ints = {0, 1})",
|
||||
" void withValueSourceAndJavadoc() {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"nonexistentMethod\")",
|
||||
" @SuppressWarnings(\"foo\")",
|
||||
" void withMethodSourceAndUnrelatedAnnotation() {}",
|
||||
"",
|
||||
" @org.junit.jupiter.params.ParameterizedTest",
|
||||
" @ArgumentsSource(ArgumentsProvider.class)",
|
||||
" @ValueSource(ints = {0, 1})",
|
||||
" @MethodSource(\"nonexistentMethod\")",
|
||||
" void withMultipleArgumentSourcesAndFullyQualifiedImport() {}",
|
||||
"",
|
||||
" class NestedWithTestAnnotationFirst {",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(ints = {0, 1})",
|
||||
" void withValueSource() {}",
|
||||
" }",
|
||||
"",
|
||||
" class NestedWithTestAnnotationSecond {",
|
||||
" @ValueSource(ints = {0, 1})",
|
||||
" @ParameterizedTest",
|
||||
" void withValueSource() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsProvider;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSources;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
class A {
|
||||
@ParameterizedTest
|
||||
void withoutArgumentSource() {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(ArgumentsProvider.class)
|
||||
void withCustomArgumentSource() {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSources({
|
||||
@ArgumentsSource(ArgumentsProvider.class),
|
||||
@ArgumentsSource(ArgumentsProvider.class)
|
||||
})
|
||||
void withCustomerArgumentSources() {}
|
||||
|
||||
/** Foo. */
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {0, 1})
|
||||
void withValueSourceAndJavadoc() {}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("nonexistentMethod")
|
||||
@SuppressWarnings("foo")
|
||||
void withMethodSourceAndUnrelatedAnnotation() {}
|
||||
|
||||
@org.junit.jupiter.params.ParameterizedTest
|
||||
@ArgumentsSource(ArgumentsProvider.class)
|
||||
@ValueSource(ints = {0, 1})
|
||||
@MethodSource("nonexistentMethod")
|
||||
void withMultipleArgumentSourcesAndFullyQualifiedImport() {}
|
||||
|
||||
class NestedWithTestAnnotationFirst {
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {0, 1})
|
||||
void withValueSource() {}
|
||||
}
|
||||
|
||||
class NestedWithTestAnnotationSecond {
|
||||
@ValueSource(ints = {0, 1})
|
||||
@ParameterizedTest
|
||||
void withValueSource() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"import org.junit.jupiter.params.provider.ArgumentsProvider;",
|
||||
"import org.junit.jupiter.params.provider.ArgumentsSource;",
|
||||
"import org.junit.jupiter.params.provider.ArgumentsSources;",
|
||||
"import org.junit.jupiter.params.provider.MethodSource;",
|
||||
"import org.junit.jupiter.params.provider.ValueSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" @Test",
|
||||
" void withoutArgumentSource() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void withCustomArgumentSource() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void withCustomerArgumentSources() {}",
|
||||
"",
|
||||
" /** Foo. */",
|
||||
" @Test",
|
||||
" void withValueSourceAndJavadoc() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" @SuppressWarnings(\"foo\")",
|
||||
" void withMethodSourceAndUnrelatedAnnotation() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void withMultipleArgumentSourcesAndFullyQualifiedImport() {}",
|
||||
"",
|
||||
" class NestedWithTestAnnotationFirst {",
|
||||
" @Test",
|
||||
" void withValueSource() {}",
|
||||
" }",
|
||||
"",
|
||||
" class NestedWithTestAnnotationSecond {",
|
||||
" @Test",
|
||||
" void withValueSource() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsProvider;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSources;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
class A {
|
||||
@Test
|
||||
void withoutArgumentSource() {}
|
||||
|
||||
@Test
|
||||
void withCustomArgumentSource() {}
|
||||
|
||||
@Test
|
||||
void withCustomerArgumentSources() {}
|
||||
|
||||
/** Foo. */
|
||||
@Test
|
||||
void withValueSourceAndJavadoc() {}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("foo")
|
||||
void withMethodSourceAndUnrelatedAnnotation() {}
|
||||
|
||||
@Test
|
||||
void withMultipleArgumentSourcesAndFullyQualifiedImport() {}
|
||||
|
||||
class NestedWithTestAnnotationFirst {
|
||||
@Test
|
||||
void withValueSource() {}
|
||||
}
|
||||
|
||||
class NestedWithTestAnnotationSecond {
|
||||
@Test
|
||||
void withValueSource() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addInputLines(
|
||||
"B.java",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"",
|
||||
"class B {",
|
||||
" @ParameterizedTest",
|
||||
" void scopeInWhichIdentifierTestIsAlreadyDeclared() {}",
|
||||
"",
|
||||
" class Test {}",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
||||
class B {
|
||||
@ParameterizedTest
|
||||
void scopeInWhichIdentifierTestIsAlreadyDeclared() {}
|
||||
|
||||
class Test {}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"B.java",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"",
|
||||
"class B {",
|
||||
" @org.junit.jupiter.api.Test",
|
||||
" void scopeInWhichIdentifierTestIsAlreadyDeclared() {}",
|
||||
"",
|
||||
" class Test {}",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
||||
class B {
|
||||
@org.junit.jupiter.api.Test
|
||||
void scopeInWhichIdentifierTestIsAlreadyDeclared() {}
|
||||
|
||||
class Test {}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,189 +11,191 @@ final class JUnitValueSourceTest {
|
||||
CompilationTestHelper.newInstance(JUnitValueSource.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"",
|
||||
"import java.util.Optional;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"import org.junit.jupiter.params.provider.Arguments;",
|
||||
"import org.junit.jupiter.params.provider.MethodSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static Stream<Arguments> identificationTestCases() {",
|
||||
" return Stream.of(arguments(1), Arguments.of(2));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @MethodSource(\"identificationTestCases\")",
|
||||
" void identification(int foo) {}",
|
||||
"",
|
||||
" private static int[] identificationWithParensTestCases() {",
|
||||
" return new int[] {1, 2};",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @MethodSource(\"identificationWithParensTestCases()\")",
|
||||
" void identificationWithParens(int foo) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"valueFactoryMissingTestCases\")",
|
||||
" void valueFactoryMissing(int foo) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> multipleUsagesTestCases() {",
|
||||
" return Stream.of(arguments(1), Arguments.of(2));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"multipleUsagesTestCases\")",
|
||||
" void multipleUsages1(int foo) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"multipleUsagesTestCases()\")",
|
||||
" void multipleUsages2(int bar) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> valueFactoryRepeatedTestCases() {",
|
||||
" return Stream.of(arguments(1), arguments(2));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource({\"valueFactoryRepeatedTestCases\", \"valueFactoryRepeatedTestCases\"})",
|
||||
" void valueFactoryRepeated(int foo) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> multipleParametersTestCases() {",
|
||||
" return Stream.of(arguments(1, 2), arguments(3, 4));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"multipleParametersTestCases\")",
|
||||
" void multipleParameters(int first, int second) {}",
|
||||
"",
|
||||
" private static int[] arrayWithoutInitializersTestCases() {",
|
||||
" return new int[1];",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"arrayWithoutInitializersTestCases\")",
|
||||
" void arrayWithoutInitializers(int foo) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> runtimeValueTestCases() {",
|
||||
" int second = 2;",
|
||||
" return Stream.of(arguments(1), arguments(second));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"runtimeValueTestCases\")",
|
||||
" void runtimeValue(int foo) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> streamChainTestCases() {",
|
||||
" return Stream.of(1, 2).map(Arguments::arguments);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"streamChainTestCases\")",
|
||||
" void streamChain(int number) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> multipleReturnsTestCases() {",
|
||||
" if (true) {",
|
||||
" return Stream.of(arguments(1), arguments(2));",
|
||||
" } else {",
|
||||
" return Stream.of(arguments(3), arguments(4));",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"multipleReturnsTestCases\")",
|
||||
" void multipleReturns(int number) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> multipleFactoriesFooTestCases() {",
|
||||
" return Stream.of(arguments(1));",
|
||||
" }",
|
||||
"",
|
||||
" private static Stream<Arguments> multipleFactoriesBarTestCases() {",
|
||||
" return Stream.of(arguments(1));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource({\"multipleFactoriesFooTestCases\", \"multipleFactoriesBarTestCases\"})",
|
||||
" void multipleFactories(int i) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> extraArgsTestCases() {",
|
||||
" return Stream.of(arguments(1), arguments(1, 2));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"extraArgsTestCases\")",
|
||||
" void extraArgs(int... i) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> localClassTestCases() {",
|
||||
" class Foo {",
|
||||
" Stream<Arguments> foo() {",
|
||||
" return Stream.of(arguments(1), arguments(2));",
|
||||
" }",
|
||||
" }",
|
||||
" return Stream.of(arguments(1), arguments(2));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @MethodSource(\"localClassTestCases\")",
|
||||
" void localClass(int i) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> lambdaReturnTestCases() {",
|
||||
" int foo =",
|
||||
" Optional.of(10)",
|
||||
" .map(",
|
||||
" i -> {",
|
||||
" return i / 2;",
|
||||
" })",
|
||||
" .orElse(0);",
|
||||
" return Stream.of(arguments(1), arguments(1));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @MethodSource(\"lambdaReturnTestCases\")",
|
||||
" void lambdaReturn(int i) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"tech.picnic.errorprone.Foo#fooTestCases\")",
|
||||
" void staticMethodReference(int foo) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> valueFactoryWithArgumentTestCases(int amount) {",
|
||||
" return Stream.of(arguments(1), arguments(2));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @MethodSource(\"valueFactoryWithArgumentTestCases\")",
|
||||
" void valueFactoryWithArgument(int foo) {}",
|
||||
"",
|
||||
" private static Arguments[] emptyArrayValueFactoryTestCases() {",
|
||||
" return new Arguments[] {};",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"emptyArrayValueFactoryTestCases\")",
|
||||
" void emptyArrayValueFactory(int foo) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> emptyStreamValueFactoryTestCases() {",
|
||||
" return Stream.of();",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"emptyStreamValueFactoryTestCases\")",
|
||||
" void emptyStreamValueFactory(int foo) {}",
|
||||
"",
|
||||
" private static Arguments[] invalidValueFactoryArgumentsTestCases() {",
|
||||
" return new Arguments[] {arguments(1), arguments(new Object() {})};",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"invalidValueFactoryArgumentsTestCases\")",
|
||||
" void invalidValueFactoryArguments(int foo) {}",
|
||||
"}")
|
||||
"""
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class A {
|
||||
private static Stream<Arguments> identificationTestCases() {
|
||||
return Stream.of(arguments(1), Arguments.of(2));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
@MethodSource("identificationTestCases")
|
||||
void identification(int foo) {}
|
||||
|
||||
private static int[] identificationWithParensTestCases() {
|
||||
return new int[] {1, 2};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
@MethodSource("identificationWithParensTestCases()")
|
||||
void identificationWithParens(int foo) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("valueFactoryMissingTestCases")
|
||||
void valueFactoryMissing(int foo) {}
|
||||
|
||||
private static Stream<Arguments> multipleUsagesTestCases() {
|
||||
return Stream.of(arguments(1), Arguments.of(2));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("multipleUsagesTestCases")
|
||||
void multipleUsages1(int foo) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("multipleUsagesTestCases()")
|
||||
void multipleUsages2(int bar) {}
|
||||
|
||||
private static Stream<Arguments> valueFactoryRepeatedTestCases() {
|
||||
return Stream.of(arguments(1), arguments(2));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource({"valueFactoryRepeatedTestCases", "valueFactoryRepeatedTestCases"})
|
||||
void valueFactoryRepeated(int foo) {}
|
||||
|
||||
private static Stream<Arguments> multipleParametersTestCases() {
|
||||
return Stream.of(arguments(1, 2), arguments(3, 4));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("multipleParametersTestCases")
|
||||
void multipleParameters(int first, int second) {}
|
||||
|
||||
private static int[] arrayWithoutInitializersTestCases() {
|
||||
return new int[1];
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("arrayWithoutInitializersTestCases")
|
||||
void arrayWithoutInitializers(int foo) {}
|
||||
|
||||
private static Stream<Arguments> runtimeValueTestCases() {
|
||||
int second = 2;
|
||||
return Stream.of(arguments(1), arguments(second));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("runtimeValueTestCases")
|
||||
void runtimeValue(int foo) {}
|
||||
|
||||
private static Stream<Arguments> streamChainTestCases() {
|
||||
return Stream.of(1, 2).map(Arguments::arguments);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("streamChainTestCases")
|
||||
void streamChain(int number) {}
|
||||
|
||||
private static Stream<Arguments> multipleReturnsTestCases() {
|
||||
if (true) {
|
||||
return Stream.of(arguments(1), arguments(2));
|
||||
} else {
|
||||
return Stream.of(arguments(3), arguments(4));
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("multipleReturnsTestCases")
|
||||
void multipleReturns(int number) {}
|
||||
|
||||
private static Stream<Arguments> multipleFactoriesFooTestCases() {
|
||||
return Stream.of(arguments(1));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> multipleFactoriesBarTestCases() {
|
||||
return Stream.of(arguments(1));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource({"multipleFactoriesFooTestCases", "multipleFactoriesBarTestCases"})
|
||||
void multipleFactories(int i) {}
|
||||
|
||||
private static Stream<Arguments> extraArgsTestCases() {
|
||||
return Stream.of(arguments(1), arguments(1, 2));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("extraArgsTestCases")
|
||||
void extraArgs(int... i) {}
|
||||
|
||||
private static Stream<Arguments> localClassTestCases() {
|
||||
class Foo {
|
||||
Stream<Arguments> foo() {
|
||||
return Stream.of(arguments(1), arguments(2));
|
||||
}
|
||||
}
|
||||
return Stream.of(arguments(1), arguments(2));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
@MethodSource("localClassTestCases")
|
||||
void localClass(int i) {}
|
||||
|
||||
private static Stream<Arguments> lambdaReturnTestCases() {
|
||||
int foo =
|
||||
Optional.of(10)
|
||||
.map(
|
||||
i -> {
|
||||
return i / 2;
|
||||
})
|
||||
.orElse(0);
|
||||
return Stream.of(arguments(1), arguments(1));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
@MethodSource("lambdaReturnTestCases")
|
||||
void lambdaReturn(int i) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("tech.picnic.errorprone.Foo#fooTestCases")
|
||||
void staticMethodReference(int foo) {}
|
||||
|
||||
private static Stream<Arguments> valueFactoryWithArgumentTestCases(int amount) {
|
||||
return Stream.of(arguments(1), arguments(2));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
// BUG: Diagnostic contains:
|
||||
@MethodSource("valueFactoryWithArgumentTestCases")
|
||||
void valueFactoryWithArgument(int foo) {}
|
||||
|
||||
private static Arguments[] emptyArrayValueFactoryTestCases() {
|
||||
return new Arguments[] {};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("emptyArrayValueFactoryTestCases")
|
||||
void emptyArrayValueFactory(int foo) {}
|
||||
|
||||
private static Stream<Arguments> emptyStreamValueFactoryTestCases() {
|
||||
return Stream.of();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("emptyStreamValueFactoryTestCases")
|
||||
void emptyStreamValueFactory(int foo) {}
|
||||
|
||||
private static Arguments[] invalidValueFactoryArgumentsTestCases() {
|
||||
return new Arguments[] {arguments(1), arguments(new Object() {})};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("invalidValueFactoryArgumentsTestCases")
|
||||
void invalidValueFactoryArguments(int foo) {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -202,295 +204,299 @@ final class JUnitValueSourceTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(JUnitValueSource.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Set;",
|
||||
"import java.util.stream.DoubleStream;",
|
||||
"import java.util.stream.IntStream;",
|
||||
"import java.util.stream.LongStream;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"import org.junit.jupiter.params.provider.Arguments;",
|
||||
"import org.junit.jupiter.params.provider.MethodSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final boolean CONST_BOOLEAN = false;",
|
||||
" private static final byte CONST_BYTE = 42;",
|
||||
" private static final char CONST_CHARACTER = 'a';",
|
||||
" private static final short CONST_SHORT = 42;",
|
||||
" private static final int CONST_INTEGER = 42;",
|
||||
" private static final long CONST_LONG = 42;",
|
||||
" private static final float CONST_FLOAT = 42;",
|
||||
" private static final double CONST_DOUBLE = 42;",
|
||||
" private static final String CONST_STRING = \"foo\";",
|
||||
"",
|
||||
" private static Stream<Arguments> streamOfBooleanArguments() {",
|
||||
" return Stream.of(arguments(false), arguments(true), arguments(CONST_BOOLEAN));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"streamOfBooleanArguments\")",
|
||||
" void primitiveBoolean(boolean b) {}",
|
||||
"",
|
||||
" private static Stream<Object> streamOfBooleansAndBooleanArguments() {",
|
||||
" return Stream.of(false, arguments(true), CONST_BOOLEAN);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"streamOfBooleansAndBooleanArguments\")",
|
||||
" void boxedBoolean(Boolean b) {}",
|
||||
"",
|
||||
" private static List<Arguments> listOfByteArguments() {",
|
||||
" return List.of(arguments((byte) 0), arguments((byte) 1), arguments(CONST_BYTE));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"listOfByteArguments\")",
|
||||
" void primitiveByte(byte b) {}",
|
||||
"",
|
||||
" private static List<Object> listOfBytesAndByteArguments() {",
|
||||
" return List.of((byte) 0, arguments((byte) 1), CONST_BYTE);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"listOfBytesAndByteArguments\")",
|
||||
" void boxedByte(Byte b) {}",
|
||||
"",
|
||||
" private static Set<Arguments> setOfCharacterArguments() {",
|
||||
" return Set.of(arguments((char) 0), arguments((char) 1), arguments(CONST_CHARACTER));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"setOfCharacterArguments\")",
|
||||
" void primitiveCharacter(char c) {}",
|
||||
"",
|
||||
" private static Set<Object> setOfCharactersAndCharacterArguments() {",
|
||||
" return Set.of((char) 0, arguments((char) 1), CONST_CHARACTER);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"setOfCharactersAndCharacterArguments\")",
|
||||
" void boxedCharacter(Character c) {}",
|
||||
"",
|
||||
" private static Arguments[] arrayOfShortArguments() {",
|
||||
" return new Arguments[] {arguments((short) 0), arguments((short) 1), arguments(CONST_SHORT)};",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"arrayOfShortArguments\")",
|
||||
" void primitiveShort(short s) {}",
|
||||
"",
|
||||
" private static Object[] arrayOfShortsAndShortArguments() {",
|
||||
" return new Object[] {(short) 0, arguments((short) 1), CONST_SHORT};",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"arrayOfShortsAndShortArguments\")",
|
||||
" void boxedShort(Short s) {}",
|
||||
"",
|
||||
" private static IntStream intStream() {",
|
||||
" return IntStream.of(0, 1, CONST_INTEGER);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"intStream\")",
|
||||
" void primitiveInteger(int i) {}",
|
||||
"",
|
||||
" private static int[] intArray() {",
|
||||
" return new int[] {0, 1, CONST_INTEGER};",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"intArray\")",
|
||||
" void boxedInteger(Integer i) {}",
|
||||
"",
|
||||
" private static LongStream longStream() {",
|
||||
" return LongStream.of(0, 1, CONST_LONG);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"longStream\")",
|
||||
" void primitiveLong(long l) {}",
|
||||
"",
|
||||
" private static long[] longArray() {",
|
||||
" return new long[] {0, 1, CONST_LONG};",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"longArray\")",
|
||||
" void boxedLong(Long l) {}",
|
||||
"",
|
||||
" private static ImmutableList<Arguments> immutableListOfFloatArguments() {",
|
||||
" return ImmutableList.of(arguments(0.0F), arguments(1.0F), arguments(CONST_FLOAT));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"immutableListOfFloatArguments\")",
|
||||
" void primitiveFloat(float f) {}",
|
||||
"",
|
||||
" private static Stream<Object> streamOfFloatsAndFloatArguments() {",
|
||||
" return Stream.of(0.0F, arguments(1.0F), CONST_FLOAT);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"streamOfFloatsAndFloatArguments\")",
|
||||
" void boxedFloat(Float f) {}",
|
||||
"",
|
||||
" private static DoubleStream doubleStream() {",
|
||||
" return DoubleStream.of(0, 1, CONST_DOUBLE);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"doubleStream\")",
|
||||
" void primitiveDouble(double d) {}",
|
||||
"",
|
||||
" private static double[] doubleArray() {",
|
||||
" return new double[] {0, 1, CONST_DOUBLE};",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"doubleArray\")",
|
||||
" void boxedDouble(Double d) {}",
|
||||
"",
|
||||
" private static ImmutableSet<Arguments> immutableSetOfStringArguments() {",
|
||||
" return ImmutableSet.of(arguments(\"foo\"), arguments(\"bar\"), arguments(CONST_STRING));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"immutableSetOfStringArguments\")",
|
||||
" void string(String s) {}",
|
||||
"",
|
||||
" private static Stream<Class<?>> streamOfClasses() {",
|
||||
" return Stream.of(Stream.class, java.util.Map.class);",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"streamOfClasses\")",
|
||||
" void clazz(Class<?> c) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> sameNameFactoryTestCases() {",
|
||||
" return Stream.of(arguments(1));",
|
||||
" }",
|
||||
"",
|
||||
" private static Stream<Arguments> sameNameFactoryTestCases(int overload) {",
|
||||
" return Stream.of(arguments(overload));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"sameNameFactoryTestCases\")",
|
||||
" void sameNameFactory(int i) {}",
|
||||
"}")
|
||||
"""
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.DoubleStream;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class A {
|
||||
private static final boolean CONST_BOOLEAN = false;
|
||||
private static final byte CONST_BYTE = 42;
|
||||
private static final char CONST_CHARACTER = 'a';
|
||||
private static final short CONST_SHORT = 42;
|
||||
private static final int CONST_INTEGER = 42;
|
||||
private static final long CONST_LONG = 42;
|
||||
private static final float CONST_FLOAT = 42;
|
||||
private static final double CONST_DOUBLE = 42;
|
||||
private static final String CONST_STRING = "foo";
|
||||
|
||||
private static Stream<Arguments> streamOfBooleanArguments() {
|
||||
return Stream.of(arguments(false), arguments(true), arguments(CONST_BOOLEAN));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("streamOfBooleanArguments")
|
||||
void primitiveBoolean(boolean b) {}
|
||||
|
||||
private static Stream<Object> streamOfBooleansAndBooleanArguments() {
|
||||
return Stream.of(false, arguments(true), CONST_BOOLEAN);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("streamOfBooleansAndBooleanArguments")
|
||||
void boxedBoolean(Boolean b) {}
|
||||
|
||||
private static List<Arguments> listOfByteArguments() {
|
||||
return List.of(arguments((byte) 0), arguments((byte) 1), arguments(CONST_BYTE));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("listOfByteArguments")
|
||||
void primitiveByte(byte b) {}
|
||||
|
||||
private static List<Object> listOfBytesAndByteArguments() {
|
||||
return List.of((byte) 0, arguments((byte) 1), CONST_BYTE);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("listOfBytesAndByteArguments")
|
||||
void boxedByte(Byte b) {}
|
||||
|
||||
private static Set<Arguments> setOfCharacterArguments() {
|
||||
return Set.of(arguments((char) 0), arguments((char) 1), arguments(CONST_CHARACTER));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("setOfCharacterArguments")
|
||||
void primitiveCharacter(char c) {}
|
||||
|
||||
private static Set<Object> setOfCharactersAndCharacterArguments() {
|
||||
return Set.of((char) 0, arguments((char) 1), CONST_CHARACTER);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("setOfCharactersAndCharacterArguments")
|
||||
void boxedCharacter(Character c) {}
|
||||
|
||||
private static Arguments[] arrayOfShortArguments() {
|
||||
return new Arguments[] {arguments((short) 0), arguments((short) 1), arguments(CONST_SHORT)};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("arrayOfShortArguments")
|
||||
void primitiveShort(short s) {}
|
||||
|
||||
private static Object[] arrayOfShortsAndShortArguments() {
|
||||
return new Object[] {(short) 0, arguments((short) 1), CONST_SHORT};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("arrayOfShortsAndShortArguments")
|
||||
void boxedShort(Short s) {}
|
||||
|
||||
private static IntStream intStream() {
|
||||
return IntStream.of(0, 1, CONST_INTEGER);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("intStream")
|
||||
void primitiveInteger(int i) {}
|
||||
|
||||
private static int[] intArray() {
|
||||
return new int[] {0, 1, CONST_INTEGER};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("intArray")
|
||||
void boxedInteger(Integer i) {}
|
||||
|
||||
private static LongStream longStream() {
|
||||
return LongStream.of(0, 1, CONST_LONG);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("longStream")
|
||||
void primitiveLong(long l) {}
|
||||
|
||||
private static long[] longArray() {
|
||||
return new long[] {0, 1, CONST_LONG};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("longArray")
|
||||
void boxedLong(Long l) {}
|
||||
|
||||
private static ImmutableList<Arguments> immutableListOfFloatArguments() {
|
||||
return ImmutableList.of(arguments(0.0F), arguments(1.0F), arguments(CONST_FLOAT));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("immutableListOfFloatArguments")
|
||||
void primitiveFloat(float f) {}
|
||||
|
||||
private static Stream<Object> streamOfFloatsAndFloatArguments() {
|
||||
return Stream.of(0.0F, arguments(1.0F), CONST_FLOAT);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("streamOfFloatsAndFloatArguments")
|
||||
void boxedFloat(Float f) {}
|
||||
|
||||
private static DoubleStream doubleStream() {
|
||||
return DoubleStream.of(0, 1, CONST_DOUBLE);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("doubleStream")
|
||||
void primitiveDouble(double d) {}
|
||||
|
||||
private static double[] doubleArray() {
|
||||
return new double[] {0, 1, CONST_DOUBLE};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("doubleArray")
|
||||
void boxedDouble(Double d) {}
|
||||
|
||||
private static ImmutableSet<Arguments> immutableSetOfStringArguments() {
|
||||
return ImmutableSet.of(arguments("foo"), arguments("bar"), arguments(CONST_STRING));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("immutableSetOfStringArguments")
|
||||
void string(String s) {}
|
||||
|
||||
private static Stream<Class<?>> streamOfClasses() {
|
||||
return Stream.of(Stream.class, java.util.Map.class);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("streamOfClasses")
|
||||
void clazz(Class<?> c) {}
|
||||
|
||||
private static Stream<Arguments> sameNameFactoryTestCases() {
|
||||
return Stream.of(arguments(1));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> sameNameFactoryTestCases(int overload) {
|
||||
return Stream.of(arguments(overload));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("sameNameFactoryTestCases")
|
||||
void sameNameFactory(int i) {}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Set;",
|
||||
"import java.util.stream.DoubleStream;",
|
||||
"import java.util.stream.IntStream;",
|
||||
"import java.util.stream.LongStream;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"import org.junit.jupiter.params.provider.Arguments;",
|
||||
"import org.junit.jupiter.params.provider.MethodSource;",
|
||||
"import org.junit.jupiter.params.provider.ValueSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final boolean CONST_BOOLEAN = false;",
|
||||
" private static final byte CONST_BYTE = 42;",
|
||||
" private static final char CONST_CHARACTER = 'a';",
|
||||
" private static final short CONST_SHORT = 42;",
|
||||
" private static final int CONST_INTEGER = 42;",
|
||||
" private static final long CONST_LONG = 42;",
|
||||
" private static final float CONST_FLOAT = 42;",
|
||||
" private static final double CONST_DOUBLE = 42;",
|
||||
" private static final String CONST_STRING = \"foo\";",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(booleans = {false, true, CONST_BOOLEAN})",
|
||||
" void primitiveBoolean(boolean b) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(booleans = {false, true, CONST_BOOLEAN})",
|
||||
" void boxedBoolean(Boolean b) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(bytes = {(byte) 0, (byte) 1, CONST_BYTE})",
|
||||
" void primitiveByte(byte b) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(bytes = {(byte) 0, (byte) 1, CONST_BYTE})",
|
||||
" void boxedByte(Byte b) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(chars = {(char) 0, (char) 1, CONST_CHARACTER})",
|
||||
" void primitiveCharacter(char c) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(chars = {(char) 0, (char) 1, CONST_CHARACTER})",
|
||||
" void boxedCharacter(Character c) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(shorts = {(short) 0, (short) 1, CONST_SHORT})",
|
||||
" void primitiveShort(short s) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(shorts = {(short) 0, (short) 1, CONST_SHORT})",
|
||||
" void boxedShort(Short s) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(ints = {0, 1, CONST_INTEGER})",
|
||||
" void primitiveInteger(int i) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(ints = {0, 1, CONST_INTEGER})",
|
||||
" void boxedInteger(Integer i) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(longs = {0, 1, CONST_LONG})",
|
||||
" void primitiveLong(long l) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(longs = {0, 1, CONST_LONG})",
|
||||
" void boxedLong(Long l) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(floats = {0.0F, 1.0F, CONST_FLOAT})",
|
||||
" void primitiveFloat(float f) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(floats = {0.0F, 1.0F, CONST_FLOAT})",
|
||||
" void boxedFloat(Float f) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(doubles = {0, 1, CONST_DOUBLE})",
|
||||
" void primitiveDouble(double d) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(doubles = {0, 1, CONST_DOUBLE})",
|
||||
" void boxedDouble(Double d) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(strings = {\"foo\", \"bar\", CONST_STRING})",
|
||||
" void string(String s) {}",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(classes = {Stream.class, java.util.Map.class})",
|
||||
" void clazz(Class<?> c) {}",
|
||||
"",
|
||||
" private static Stream<Arguments> sameNameFactoryTestCases(int overload) {",
|
||||
" return Stream.of(arguments(overload));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @ValueSource(ints = 1)",
|
||||
" void sameNameFactory(int i) {}",
|
||||
"}")
|
||||
"""
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.DoubleStream;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
class A {
|
||||
private static final boolean CONST_BOOLEAN = false;
|
||||
private static final byte CONST_BYTE = 42;
|
||||
private static final char CONST_CHARACTER = 'a';
|
||||
private static final short CONST_SHORT = 42;
|
||||
private static final int CONST_INTEGER = 42;
|
||||
private static final long CONST_LONG = 42;
|
||||
private static final float CONST_FLOAT = 42;
|
||||
private static final double CONST_DOUBLE = 42;
|
||||
private static final String CONST_STRING = "foo";
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {false, true, CONST_BOOLEAN})
|
||||
void primitiveBoolean(boolean b) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {false, true, CONST_BOOLEAN})
|
||||
void boxedBoolean(Boolean b) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(bytes = {(byte) 0, (byte) 1, CONST_BYTE})
|
||||
void primitiveByte(byte b) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(bytes = {(byte) 0, (byte) 1, CONST_BYTE})
|
||||
void boxedByte(Byte b) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(chars = {(char) 0, (char) 1, CONST_CHARACTER})
|
||||
void primitiveCharacter(char c) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(chars = {(char) 0, (char) 1, CONST_CHARACTER})
|
||||
void boxedCharacter(Character c) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(shorts = {(short) 0, (short) 1, CONST_SHORT})
|
||||
void primitiveShort(short s) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(shorts = {(short) 0, (short) 1, CONST_SHORT})
|
||||
void boxedShort(Short s) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {0, 1, CONST_INTEGER})
|
||||
void primitiveInteger(int i) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {0, 1, CONST_INTEGER})
|
||||
void boxedInteger(Integer i) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = {0, 1, CONST_LONG})
|
||||
void primitiveLong(long l) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(longs = {0, 1, CONST_LONG})
|
||||
void boxedLong(Long l) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(floats = {0.0F, 1.0F, CONST_FLOAT})
|
||||
void primitiveFloat(float f) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(floats = {0.0F, 1.0F, CONST_FLOAT})
|
||||
void boxedFloat(Float f) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = {0, 1, CONST_DOUBLE})
|
||||
void primitiveDouble(double d) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = {0, 1, CONST_DOUBLE})
|
||||
void boxedDouble(Double d) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"foo", "bar", CONST_STRING})
|
||||
void string(String s) {}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(classes = {Stream.class, java.util.Map.class})
|
||||
void clazz(Class<?> c) {}
|
||||
|
||||
private static Stream<Arguments> sameNameFactoryTestCases(int overload) {
|
||||
return Stream.of(arguments(overload));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = 1)
|
||||
void sameNameFactory(int i) {}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,146 +12,148 @@ final class LexicographicalAnnotationAttributeListingTest {
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.math.RoundingMode.DOWN;",
|
||||
"import static java.math.RoundingMode.UP;",
|
||||
"",
|
||||
"import com.fasterxml.jackson.annotation.JsonPropertyOrder;",
|
||||
"import io.swagger.annotations.ApiImplicitParam;",
|
||||
"import io.swagger.annotations.ApiImplicitParams;",
|
||||
"import io.swagger.v3.oas.annotations.Parameter;",
|
||||
"import io.swagger.v3.oas.annotations.Parameters;",
|
||||
"import java.math.RoundingMode;",
|
||||
"import javax.xml.bind.annotation.XmlType;",
|
||||
"import org.springframework.context.annotation.PropertySource;",
|
||||
"import org.springframework.test.context.TestPropertySource;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" int[] ints() default {};",
|
||||
"",
|
||||
" Class<?>[] cls() default {};",
|
||||
"",
|
||||
" RoundingMode[] enums() default {};",
|
||||
"",
|
||||
" Bar[] anns() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Bar {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Foo({})",
|
||||
" A noString();",
|
||||
"",
|
||||
" @Foo({\"a\"})",
|
||||
" A oneString();",
|
||||
"",
|
||||
" @Foo({\"a\", \"b\"})",
|
||||
" A sortedStrings();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({\"b\", \"a\"})",
|
||||
" A unsortedString();",
|
||||
"",
|
||||
" @Foo({\"ab\", \"Ac\"})",
|
||||
" A sortedStringCaseInsensitive();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({\"ac\", \"Ab\"})",
|
||||
" A unsortedStringCaseInsensitive();",
|
||||
"",
|
||||
" @Foo({\"A\", \"a\"})",
|
||||
" A sortedStringCaseInsensitiveWithTotalOrderFallback();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({\"a\", \"A\"})",
|
||||
" A unsortedStringCaseInsensitiveWithTotalOrderFallback();",
|
||||
"",
|
||||
" @Foo(ints = {})",
|
||||
" A noInts();",
|
||||
"",
|
||||
" @Foo(ints = {0})",
|
||||
" A oneInt();",
|
||||
"",
|
||||
" @Foo(ints = {0, 1})",
|
||||
" A sortedInts();",
|
||||
"",
|
||||
" @Foo(ints = {1, 0})",
|
||||
" A unsortedInts();",
|
||||
"",
|
||||
" @Foo(cls = {})",
|
||||
" A noClasses();",
|
||||
"",
|
||||
" @Foo(cls = {int.class})",
|
||||
" A oneClass();",
|
||||
"",
|
||||
" @Foo(cls = {int.class, long.class})",
|
||||
" A sortedClasses();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(cls = {long.class, int.class})",
|
||||
" A unsortedClasses();",
|
||||
"",
|
||||
" @Foo(enums = {})",
|
||||
" A noEnums();",
|
||||
"",
|
||||
" @Foo(enums = {DOWN})",
|
||||
" A oneEnum();",
|
||||
"",
|
||||
" @Foo(enums = {DOWN, UP})",
|
||||
" A sortedEnums();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(enums = {UP, DOWN})",
|
||||
" A unsortedEnums();",
|
||||
"",
|
||||
" @Foo(anns = {})",
|
||||
" A noAnns();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"a\")})",
|
||||
" A oneAnn();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"a\"), @Bar(\"b\")})",
|
||||
" A sortedAnns();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" A unsortedAnns();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(anns = {@Bar(\"a\"), @Bar({\"b\", \"a\"})})",
|
||||
" A unsortedInnderAnns();",
|
||||
"",
|
||||
" @Foo({\"a=foo\", \"a.b=bar\", \"a.c=baz\"})",
|
||||
" A hierarchicallySorted();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({\"a.b=bar\", \"a.c=baz\", \"a=foo\"})",
|
||||
" A hierarchicallyUnsorted();",
|
||||
"",
|
||||
" @JsonPropertyOrder({\"field2\", \"field1\"})",
|
||||
" A dto();",
|
||||
"",
|
||||
" @ApiImplicitParams({@ApiImplicitParam(\"p2\"), @ApiImplicitParam(\"p1\")})",
|
||||
" A firstEndpoint();",
|
||||
"",
|
||||
" @Parameters({@Parameter(name = \"p2\"), @Parameter(name = \"p1\")})",
|
||||
" A secondEndpoint();",
|
||||
"",
|
||||
" @XmlType(propOrder = {\"field2\", \"field1\"})",
|
||||
" class XmlTypeDummy {}",
|
||||
"",
|
||||
" @PropertySource({\"field2\", \"field1\"})",
|
||||
" class PropertySourceDummy {}",
|
||||
"",
|
||||
" @TestPropertySource(locations = {\"field2\", \"field1\"})",
|
||||
" class FirstTestPropertySourceDummy {}",
|
||||
"",
|
||||
" @TestPropertySource({\"field2\", \"field1\"})",
|
||||
" class SecondTestPropertySourceDummy {}",
|
||||
"}")
|
||||
"""
|
||||
import static java.math.RoundingMode.DOWN;
|
||||
import static java.math.RoundingMode.UP;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import java.math.RoundingMode;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
interface A {
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
int[] ints() default {};
|
||||
|
||||
Class<?>[] cls() default {};
|
||||
|
||||
RoundingMode[] enums() default {};
|
||||
|
||||
Bar[] anns() default {};
|
||||
}
|
||||
|
||||
@interface Bar {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@Foo({})
|
||||
A noString();
|
||||
|
||||
@Foo({"a"})
|
||||
A oneString();
|
||||
|
||||
@Foo({"a", "b"})
|
||||
A sortedStrings();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo({"b", "a"})
|
||||
A unsortedString();
|
||||
|
||||
@Foo({"ab", "Ac"})
|
||||
A sortedStringCaseInsensitive();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo({"ac", "Ab"})
|
||||
A unsortedStringCaseInsensitive();
|
||||
|
||||
@Foo({"A", "a"})
|
||||
A sortedStringCaseInsensitiveWithTotalOrderFallback();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo({"a", "A"})
|
||||
A unsortedStringCaseInsensitiveWithTotalOrderFallback();
|
||||
|
||||
@Foo(ints = {})
|
||||
A noInts();
|
||||
|
||||
@Foo(ints = {0})
|
||||
A oneInt();
|
||||
|
||||
@Foo(ints = {0, 1})
|
||||
A sortedInts();
|
||||
|
||||
@Foo(ints = {1, 0})
|
||||
A unsortedInts();
|
||||
|
||||
@Foo(cls = {})
|
||||
A noClasses();
|
||||
|
||||
@Foo(cls = {int.class})
|
||||
A oneClass();
|
||||
|
||||
@Foo(cls = {int.class, long.class})
|
||||
A sortedClasses();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo(cls = {long.class, int.class})
|
||||
A unsortedClasses();
|
||||
|
||||
@Foo(enums = {})
|
||||
A noEnums();
|
||||
|
||||
@Foo(enums = {DOWN})
|
||||
A oneEnum();
|
||||
|
||||
@Foo(enums = {DOWN, UP})
|
||||
A sortedEnums();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo(enums = {UP, DOWN})
|
||||
A unsortedEnums();
|
||||
|
||||
@Foo(anns = {})
|
||||
A noAnns();
|
||||
|
||||
@Foo(anns = {@Bar("a")})
|
||||
A oneAnn();
|
||||
|
||||
@Foo(anns = {@Bar("a"), @Bar("b")})
|
||||
A sortedAnns();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
A unsortedAnns();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo(anns = {@Bar("a"), @Bar({"b", "a"})})
|
||||
A unsortedInnderAnns();
|
||||
|
||||
@Foo({"a=foo", "a.b=bar", "a.c=baz"})
|
||||
A hierarchicallySorted();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo({"a.b=bar", "a.c=baz", "a=foo"})
|
||||
A hierarchicallyUnsorted();
|
||||
|
||||
@JsonPropertyOrder({"field2", "field1"})
|
||||
A dto();
|
||||
|
||||
@ApiImplicitParams({@ApiImplicitParam("p2"), @ApiImplicitParam("p1")})
|
||||
A firstEndpoint();
|
||||
|
||||
@Parameters({@Parameter(name = "p2"), @Parameter(name = "p1")})
|
||||
A secondEndpoint();
|
||||
|
||||
@XmlType(propOrder = {"field2", "field1"})
|
||||
class XmlTypeDummy {}
|
||||
|
||||
@PropertySource({"field2", "field1"})
|
||||
class PropertySourceDummy {}
|
||||
|
||||
@TestPropertySource(locations = {"field2", "field1"})
|
||||
class FirstTestPropertySourceDummy {}
|
||||
|
||||
@TestPropertySource({"field2", "field1"})
|
||||
class SecondTestPropertySourceDummy {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -164,78 +166,82 @@ final class LexicographicalAnnotationAttributeListingTest {
|
||||
LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.math.RoundingMode.DOWN;",
|
||||
"import static java.math.RoundingMode.UP;",
|
||||
"",
|
||||
"import java.math.RoundingMode;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" Class<?>[] cls() default {};",
|
||||
"",
|
||||
" RoundingMode[] enums() default {};",
|
||||
"",
|
||||
" Bar[] anns() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Bar {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Foo({\" \", \"\", \"b\", \"a\"})",
|
||||
" A unsortedString();",
|
||||
"",
|
||||
" @Foo(cls = {long.class, int.class})",
|
||||
" A unsortedClasses();",
|
||||
"",
|
||||
" @Foo(enums = {UP, DOWN})",
|
||||
" A unsortedEnums();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" A unsortedAnns();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"a\"), @Bar({\"b\", \"a\"})})",
|
||||
" A unsortedInnderAnns();",
|
||||
"}")
|
||||
"""
|
||||
import static java.math.RoundingMode.DOWN;
|
||||
import static java.math.RoundingMode.UP;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
|
||||
interface A {
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
Class<?>[] cls() default {};
|
||||
|
||||
RoundingMode[] enums() default {};
|
||||
|
||||
Bar[] anns() default {};
|
||||
}
|
||||
|
||||
@interface Bar {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@Foo({" ", "", "b", "a"})
|
||||
A unsortedString();
|
||||
|
||||
@Foo(cls = {long.class, int.class})
|
||||
A unsortedClasses();
|
||||
|
||||
@Foo(enums = {UP, DOWN})
|
||||
A unsortedEnums();
|
||||
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
A unsortedAnns();
|
||||
|
||||
@Foo(anns = {@Bar("a"), @Bar({"b", "a"})})
|
||||
A unsortedInnderAnns();
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static java.math.RoundingMode.DOWN;",
|
||||
"import static java.math.RoundingMode.UP;",
|
||||
"",
|
||||
"import java.math.RoundingMode;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" Class<?>[] cls() default {};",
|
||||
"",
|
||||
" RoundingMode[] enums() default {};",
|
||||
"",
|
||||
" Bar[] anns() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Bar {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Foo({\"\", \" \", \"a\", \"b\"})",
|
||||
" A unsortedString();",
|
||||
"",
|
||||
" @Foo(cls = {int.class, long.class})",
|
||||
" A unsortedClasses();",
|
||||
"",
|
||||
" @Foo(enums = {DOWN, UP})",
|
||||
" A unsortedEnums();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"a\"), @Bar(\"b\")})",
|
||||
" A unsortedAnns();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"a\"), @Bar({\"a\", \"b\"})})",
|
||||
" A unsortedInnderAnns();",
|
||||
"}")
|
||||
"""
|
||||
import static java.math.RoundingMode.DOWN;
|
||||
import static java.math.RoundingMode.UP;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
|
||||
interface A {
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
Class<?>[] cls() default {};
|
||||
|
||||
RoundingMode[] enums() default {};
|
||||
|
||||
Bar[] anns() default {};
|
||||
}
|
||||
|
||||
@interface Bar {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@Foo({"", " ", "a", "b"})
|
||||
A unsortedString();
|
||||
|
||||
@Foo(cls = {int.class, long.class})
|
||||
A unsortedClasses();
|
||||
|
||||
@Foo(enums = {DOWN, UP})
|
||||
A unsortedEnums();
|
||||
|
||||
@Foo(anns = {@Bar("a"), @Bar("b")})
|
||||
A unsortedAnns();
|
||||
|
||||
@Foo(anns = {@Bar("a"), @Bar({"a", "b"})})
|
||||
A unsortedInnderAnns();
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -249,48 +255,50 @@ final class LexicographicalAnnotationAttributeListingTest {
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value"))
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" String[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Bar {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" String[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Baz {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" String[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({\"b\", \"a\"})",
|
||||
" A fooValue();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(value2 = {\"b\", \"a\"})",
|
||||
" A fooValue2();",
|
||||
"",
|
||||
" @Bar({\"b\", \"a\"})",
|
||||
" A barValue();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Bar(value2 = {\"b\", \"a\"})",
|
||||
" A barValue2();",
|
||||
"",
|
||||
" @Baz({\"b\", \"a\"})",
|
||||
" A bazValue();",
|
||||
"",
|
||||
" @Baz(value2 = {\"b\", \"a\"})",
|
||||
" A bazValue2();",
|
||||
"}")
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
interface A {
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
String[] value2() default {};
|
||||
}
|
||||
|
||||
@interface Bar {
|
||||
String[] value() default {};
|
||||
|
||||
String[] value2() default {};
|
||||
}
|
||||
|
||||
@interface Baz {
|
||||
String[] value() default {};
|
||||
|
||||
String[] value2() default {};
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo({"b", "a"})
|
||||
A fooValue();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo(value2 = {"b", "a"})
|
||||
A fooValue2();
|
||||
|
||||
@Bar({"b", "a"})
|
||||
A barValue();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Bar(value2 = {"b", "a"})
|
||||
A barValue2();
|
||||
|
||||
@Baz({"b", "a"})
|
||||
A bazValue();
|
||||
|
||||
@Baz(value2 = {"b", "a"})
|
||||
A bazValue2();
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,122 +11,124 @@ final class LexicographicalAnnotationListingTest {
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationListing.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.lang.annotation.ElementType;",
|
||||
"import java.lang.annotation.Repeatable;",
|
||||
"import java.lang.annotation.Target;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @Repeatable(Foos.class)",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" int[] ints() default {};",
|
||||
"",
|
||||
" Bar[] anns() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.METHOD)",
|
||||
" @interface Bar {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Baz {",
|
||||
" String[] str() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Foos {",
|
||||
" Foo[] value();",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.TYPE_USE)",
|
||||
" @interface FooTypeUse {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.TYPE_USE)",
|
||||
" @interface BarTypeUse {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo",
|
||||
" @Bar",
|
||||
" A unsortedSimpleCase();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo()",
|
||||
" @Bar()",
|
||||
" A unsortedWithParens();",
|
||||
"",
|
||||
" @Foo()",
|
||||
" A onlyOneAnnotation();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Foo()",
|
||||
" A sortedAnnotationsOneWithParens();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo",
|
||||
" @Baz",
|
||||
" @Bar",
|
||||
" A threeUnsortedAnnotationsSameInitialLetter();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Bar",
|
||||
" @Foo()",
|
||||
" @Baz",
|
||||
" A firstOrderedWithTwoUnsortedAnnotations();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Baz",
|
||||
" @Foo()",
|
||||
" A threeSortedAnnotations();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({\"b\"})",
|
||||
" @Bar({\"a\"})",
|
||||
" A unsortedWithStringAttributes();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Baz(str = {\"a\", \"b\"})",
|
||||
" @Foo(ints = {1, 0})",
|
||||
" @Bar",
|
||||
" A unsortedWithAttributes();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Bar",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" @Baz",
|
||||
" A unsortedWithNestedBar();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Baz",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" A sortedWithNestedBar();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" @Foo(ints = {1, 2})",
|
||||
" @Foo({\"b\"})",
|
||||
" A sortedRepeatableAnnotation();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" @Bar",
|
||||
" @Foo(ints = {1, 2})",
|
||||
" A unsortedRepeatableAnnotation();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" default @FooTypeUse @BarTypeUse A unsortedTypeAnnotations() {",
|
||||
" return null;",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Baz",
|
||||
" @Bar",
|
||||
" default @FooTypeUse @BarTypeUse A unsortedTypeUseAndOtherAnnotations() {",
|
||||
" return null;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
interface A {
|
||||
@Repeatable(Foos.class)
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
int[] ints() default {};
|
||||
|
||||
Bar[] anns() default {};
|
||||
}
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@interface Bar {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@interface Baz {
|
||||
String[] str() default {};
|
||||
}
|
||||
|
||||
@interface Foos {
|
||||
Foo[] value();
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface FooTypeUse {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface BarTypeUse {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo
|
||||
@Bar
|
||||
A unsortedSimpleCase();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo()
|
||||
@Bar()
|
||||
A unsortedWithParens();
|
||||
|
||||
@Foo()
|
||||
A onlyOneAnnotation();
|
||||
|
||||
@Bar
|
||||
@Foo()
|
||||
A sortedAnnotationsOneWithParens();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo
|
||||
@Baz
|
||||
@Bar
|
||||
A threeUnsortedAnnotationsSameInitialLetter();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Bar
|
||||
@Foo()
|
||||
@Baz
|
||||
A firstOrderedWithTwoUnsortedAnnotations();
|
||||
|
||||
@Bar
|
||||
@Baz
|
||||
@Foo()
|
||||
A threeSortedAnnotations();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo({"b"})
|
||||
@Bar({"a"})
|
||||
A unsortedWithStringAttributes();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Baz(str = {"a", "b"})
|
||||
@Foo(ints = {1, 0})
|
||||
@Bar
|
||||
A unsortedWithAttributes();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Bar
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
@Baz
|
||||
A unsortedWithNestedBar();
|
||||
|
||||
@Bar
|
||||
@Baz
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
A sortedWithNestedBar();
|
||||
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
@Foo(ints = {1, 2})
|
||||
@Foo({"b"})
|
||||
A sortedRepeatableAnnotation();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
@Bar
|
||||
@Foo(ints = {1, 2})
|
||||
A unsortedRepeatableAnnotation();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
default @FooTypeUse @BarTypeUse A unsortedTypeAnnotations() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@Baz
|
||||
@Bar
|
||||
default @FooTypeUse @BarTypeUse A unsortedTypeUseAndOtherAnnotations() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -135,166 +137,170 @@ final class LexicographicalAnnotationListingTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(LexicographicalAnnotationListing.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.lang.annotation.ElementType;",
|
||||
"import java.lang.annotation.Repeatable;",
|
||||
"import java.lang.annotation.Target;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @Repeatable(Foos.class)",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" int[] ints() default {};",
|
||||
"",
|
||||
" Bar[] anns() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.METHOD)",
|
||||
" @interface Bar {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Baz {",
|
||||
" String[] str() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Foos {",
|
||||
" Foo[] value();",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.TYPE_USE)",
|
||||
" @interface FooTypeUse {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.TYPE_USE)",
|
||||
" @interface BarTypeUse {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Bar",
|
||||
" A singleAnnotation();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Foo",
|
||||
" A sortedAnnotations();",
|
||||
"",
|
||||
" @Foo",
|
||||
" @Bar",
|
||||
" A unsortedAnnotations();",
|
||||
"",
|
||||
" @Foo()",
|
||||
" @Baz()",
|
||||
" @Bar",
|
||||
" A unsortedAnnotationsWithSomeParens();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Baz(str = {\"a\", \"b\"})",
|
||||
" @Foo()",
|
||||
" A unsortedAnnotationsOneContainingAttributes();",
|
||||
"",
|
||||
" @Baz(str = {\"a\", \"b\"})",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" @Bar({\"b\"})",
|
||||
" A unsortedAnnotationsWithAttributes();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" @Foo(ints = {1, 2})",
|
||||
" @Foo({\"b\"})",
|
||||
" A sortedRepeatableAnnotation();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" @Bar",
|
||||
" @Foo(ints = {1, 2})",
|
||||
" A unsortedRepeatableAnnotation();",
|
||||
"",
|
||||
" @Baz",
|
||||
" @Bar",
|
||||
" default @FooTypeUse @BarTypeUse A unsortedWithTypeUseAnnotations() {",
|
||||
" return null;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
interface A {
|
||||
@Repeatable(Foos.class)
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
int[] ints() default {};
|
||||
|
||||
Bar[] anns() default {};
|
||||
}
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@interface Bar {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@interface Baz {
|
||||
String[] str() default {};
|
||||
}
|
||||
|
||||
@interface Foos {
|
||||
Foo[] value();
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface FooTypeUse {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface BarTypeUse {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@Bar
|
||||
A singleAnnotation();
|
||||
|
||||
@Bar
|
||||
@Foo
|
||||
A sortedAnnotations();
|
||||
|
||||
@Foo
|
||||
@Bar
|
||||
A unsortedAnnotations();
|
||||
|
||||
@Foo()
|
||||
@Baz()
|
||||
@Bar
|
||||
A unsortedAnnotationsWithSomeParens();
|
||||
|
||||
@Bar
|
||||
@Baz(str = {"a", "b"})
|
||||
@Foo()
|
||||
A unsortedAnnotationsOneContainingAttributes();
|
||||
|
||||
@Baz(str = {"a", "b"})
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
@Bar({"b"})
|
||||
A unsortedAnnotationsWithAttributes();
|
||||
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
@Foo(ints = {1, 2})
|
||||
@Foo({"b"})
|
||||
A sortedRepeatableAnnotation();
|
||||
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
@Bar
|
||||
@Foo(ints = {1, 2})
|
||||
A unsortedRepeatableAnnotation();
|
||||
|
||||
@Baz
|
||||
@Bar
|
||||
default @FooTypeUse @BarTypeUse A unsortedWithTypeUseAnnotations() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import java.lang.annotation.ElementType;",
|
||||
"import java.lang.annotation.Repeatable;",
|
||||
"import java.lang.annotation.Target;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @Repeatable(Foos.class)",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" int[] ints() default {};",
|
||||
"",
|
||||
" Bar[] anns() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.METHOD)",
|
||||
" @interface Bar {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Baz {",
|
||||
" String[] str() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @interface Foos {",
|
||||
" Foo[] value();",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.TYPE_USE)",
|
||||
" @interface FooTypeUse {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Target(ElementType.TYPE_USE)",
|
||||
" @interface BarTypeUse {",
|
||||
" String[] value() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @Bar",
|
||||
" A singleAnnotation();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Foo",
|
||||
" A sortedAnnotations();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Foo",
|
||||
" A unsortedAnnotations();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Baz()",
|
||||
" @Foo()",
|
||||
" A unsortedAnnotationsWithSomeParens();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Baz(str = {\"a\", \"b\"})",
|
||||
" @Foo()",
|
||||
" A unsortedAnnotationsOneContainingAttributes();",
|
||||
"",
|
||||
" @Bar({\"b\"})",
|
||||
" @Baz(str = {\"a\", \"b\"})",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" A unsortedAnnotationsWithAttributes();",
|
||||
"",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" @Foo(ints = {1, 2})",
|
||||
" @Foo({\"b\"})",
|
||||
" A sortedRepeatableAnnotation();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
|
||||
" @Foo(ints = {1, 2})",
|
||||
" A unsortedRepeatableAnnotation();",
|
||||
"",
|
||||
" @Bar",
|
||||
" @Baz",
|
||||
" default @BarTypeUse @FooTypeUse A unsortedWithTypeUseAnnotations() {",
|
||||
" return null;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
interface A {
|
||||
@Repeatable(Foos.class)
|
||||
@interface Foo {
|
||||
String[] value() default {};
|
||||
|
||||
int[] ints() default {};
|
||||
|
||||
Bar[] anns() default {};
|
||||
}
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@interface Bar {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@interface Baz {
|
||||
String[] str() default {};
|
||||
}
|
||||
|
||||
@interface Foos {
|
||||
Foo[] value();
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface FooTypeUse {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@interface BarTypeUse {
|
||||
String[] value() default {};
|
||||
}
|
||||
|
||||
@Bar
|
||||
A singleAnnotation();
|
||||
|
||||
@Bar
|
||||
@Foo
|
||||
A sortedAnnotations();
|
||||
|
||||
@Bar
|
||||
@Foo
|
||||
A unsortedAnnotations();
|
||||
|
||||
@Bar
|
||||
@Baz()
|
||||
@Foo()
|
||||
A unsortedAnnotationsWithSomeParens();
|
||||
|
||||
@Bar
|
||||
@Baz(str = {"a", "b"})
|
||||
@Foo()
|
||||
A unsortedAnnotationsOneContainingAttributes();
|
||||
|
||||
@Bar({"b"})
|
||||
@Baz(str = {"a", "b"})
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
A unsortedAnnotationsWithAttributes();
|
||||
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
@Foo(ints = {1, 2})
|
||||
@Foo({"b"})
|
||||
A sortedRepeatableAnnotation();
|
||||
|
||||
@Bar
|
||||
@Foo(anns = {@Bar("b"), @Bar("a")})
|
||||
@Foo(ints = {1, 2})
|
||||
A unsortedRepeatableAnnotation();
|
||||
|
||||
@Bar
|
||||
@Baz
|
||||
default @BarTypeUse @FooTypeUse A unsortedWithTypeUseAnnotations() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,308 +11,310 @@ final class MethodReferenceUsageTest {
|
||||
CompilationTestHelper.newInstance(MethodReferenceUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.Streams;",
|
||||
"import java.util.HashMap;",
|
||||
"import java.util.Map;",
|
||||
"import java.util.function.IntConsumer;",
|
||||
"import java.util.function.IntFunction;",
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final Stream<Integer> s = Stream.of(1);",
|
||||
" private final Map<Integer, Integer> m = new HashMap<>();",
|
||||
" private final Runnable thrower =",
|
||||
" () -> {",
|
||||
" throw new RuntimeException();",
|
||||
" };",
|
||||
"",
|
||||
" void unaryExternalStaticFunctionCalls() {",
|
||||
" s.forEach(String::valueOf);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.forEach(v -> String.valueOf(v));",
|
||||
" s.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (v) -> {",
|
||||
" String.valueOf(v);",
|
||||
" });",
|
||||
" s.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (Integer v) -> {",
|
||||
" {",
|
||||
" String.valueOf(v);",
|
||||
" }",
|
||||
" });",
|
||||
" s.forEach(",
|
||||
" v -> {",
|
||||
" String.valueOf(v);",
|
||||
" String.valueOf(v);",
|
||||
" });",
|
||||
"",
|
||||
" s.map(String::valueOf);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.map(v -> String.valueOf(v));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.map((v) -> (String.valueOf(v)));",
|
||||
" s.map(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (Integer v) -> {",
|
||||
" return String.valueOf(v);",
|
||||
" });",
|
||||
" s.map(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (final Integer v) -> {",
|
||||
" return (String.valueOf(v));",
|
||||
" });",
|
||||
" s.map(",
|
||||
" v -> {",
|
||||
" String.valueOf(v);",
|
||||
" return String.valueOf(v);",
|
||||
" });",
|
||||
"",
|
||||
" s.findFirst().orElseGet(() -> Integer.valueOf(\"0\"));",
|
||||
" m.forEach((k, v) -> String.valueOf(v));",
|
||||
" m.forEach((k, v) -> String.valueOf(k));",
|
||||
" }",
|
||||
"",
|
||||
" void binaryExternalInstanceFunctionCalls() {",
|
||||
" m.forEach(m::put);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" m.forEach((k, v) -> m.put(k, v));",
|
||||
" m.forEach((k, v) -> m.put(v, k));",
|
||||
" m.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (Integer k, Integer v) -> {",
|
||||
" m.put(k, v);",
|
||||
" });",
|
||||
" m.forEach(",
|
||||
" (k, v) -> {",
|
||||
" m.put(k, k);",
|
||||
" });",
|
||||
" m.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (final Integer k, final Integer v) -> {",
|
||||
" {",
|
||||
" m.put(k, v);",
|
||||
" }",
|
||||
" });",
|
||||
" m.forEach(",
|
||||
" (k, v) -> {",
|
||||
" {",
|
||||
" m.put(v, v);",
|
||||
" }",
|
||||
" });",
|
||||
" m.forEach((k, v) -> new HashMap<Integer, Integer>().put(k, v));",
|
||||
" m.forEach(",
|
||||
" (k, v) -> {",
|
||||
" m.put(k, v);",
|
||||
" m.put(k, v);",
|
||||
" });",
|
||||
"",
|
||||
" Streams.zip(s, s, m::put);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Streams.zip(s, s, (a, b) -> m.put(a, b));",
|
||||
" Streams.zip(s, s, (a, b) -> m.put(b, a));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Streams.zip(s, s, (Integer a, Integer b) -> (m.put(a, b)));",
|
||||
" Streams.zip(s, s, (a, b) -> (m.put(a, a)));",
|
||||
" Streams.zip(",
|
||||
" s,",
|
||||
" s,",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (final Integer a, final Integer b) -> {",
|
||||
" return m.put(a, b);",
|
||||
" });",
|
||||
" Streams.zip(",
|
||||
" s,",
|
||||
" s,",
|
||||
" (a, b) -> {",
|
||||
" return m.put(b, b);",
|
||||
" });",
|
||||
" Streams.zip(",
|
||||
" s,",
|
||||
" s,",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (a, b) -> {",
|
||||
" return (m.put(a, b));",
|
||||
" });",
|
||||
" Streams.zip(",
|
||||
" s,",
|
||||
" s,",
|
||||
" (a, b) -> {",
|
||||
" return (m.put(b, a));",
|
||||
" });",
|
||||
" Streams.zip(",
|
||||
" s,",
|
||||
" s,",
|
||||
" (a, b) -> {",
|
||||
" m.put(a, b);",
|
||||
" return m.put(a, b);",
|
||||
" });",
|
||||
" }",
|
||||
"",
|
||||
" void nullaryExternalInstanceFunctionCalls() {",
|
||||
" s.map(Integer::doubleValue);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.map(i -> i.doubleValue());",
|
||||
" s.map(i -> i.toString());",
|
||||
" s.map(i -> s.toString());",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of(int.class).filter(c -> c.isEnum());",
|
||||
" Stream.of((Class<?>) int.class).filter(Class::isEnum);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of((Class<?>) int.class).filter(c -> c.isEnum());",
|
||||
" }",
|
||||
"",
|
||||
" void localFunctionCalls() {",
|
||||
" s.forEach(v -> ivoid0());",
|
||||
" s.forEach(v -> iint0());",
|
||||
" s.forEach(v -> svoid0());",
|
||||
" s.forEach(v -> sint0());",
|
||||
"",
|
||||
" s.forEach(this::ivoid1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.forEach(v -> ivoid1(v));",
|
||||
" s.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" v -> {",
|
||||
" ivoid1(v);",
|
||||
" });",
|
||||
" s.forEach(this::iint1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.forEach(v -> iint1(v));",
|
||||
" s.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" v -> {",
|
||||
" iint1(v);",
|
||||
" });",
|
||||
"",
|
||||
" s.forEach(A::svoid1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.forEach(v -> svoid1(v));",
|
||||
" s.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" v -> {",
|
||||
" svoid1(v);",
|
||||
" });",
|
||||
" s.forEach(A::sint1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.forEach(v -> sint1(v));",
|
||||
" s.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" v -> {",
|
||||
" sint1(v);",
|
||||
" });",
|
||||
"",
|
||||
" s.forEach(v -> ivoid2(v, v));",
|
||||
" s.forEach(v -> iint2(v, v));",
|
||||
" s.forEach(v -> svoid2(v, v));",
|
||||
" s.forEach(v -> sint2(v, v));",
|
||||
"",
|
||||
" m.forEach((k, v) -> ivoid0());",
|
||||
" m.forEach((k, v) -> iint0());",
|
||||
" m.forEach((k, v) -> svoid0());",
|
||||
" m.forEach((k, v) -> sint0());",
|
||||
"",
|
||||
" m.forEach(this::ivoid2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" m.forEach((k, v) -> ivoid2(k, v));",
|
||||
" m.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (k, v) -> {",
|
||||
" ivoid2(k, v);",
|
||||
" });",
|
||||
" m.forEach(this::iint2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" m.forEach((k, v) -> iint2(k, v));",
|
||||
" m.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (k, v) -> {",
|
||||
" iint2(k, v);",
|
||||
" });",
|
||||
"",
|
||||
" m.forEach(A::svoid2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" m.forEach((k, v) -> svoid2(k, v));",
|
||||
" m.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (k, v) -> {",
|
||||
" svoid2(k, v);",
|
||||
" });",
|
||||
" m.forEach(A::sint2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" m.forEach((k, v) -> sint2(k, v));",
|
||||
" m.forEach(",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" (k, v) -> {",
|
||||
" sint2(k, v);",
|
||||
" });",
|
||||
" }",
|
||||
"",
|
||||
" void functionCallsWhoseReplacementWouldBeAmbiguous() {",
|
||||
" receiver(",
|
||||
" i -> {",
|
||||
" Integer.toString(i);",
|
||||
" });",
|
||||
" }",
|
||||
"",
|
||||
" void assortedOtherEdgeCases() {",
|
||||
" s.forEach(v -> String.valueOf(v.toString()));",
|
||||
" TernaryOp o1 = (a, b, c) -> String.valueOf(a);",
|
||||
" TernaryOp o2 = (a, b, c) -> String.valueOf(b);",
|
||||
" TernaryOp o3 = (a, b, c) -> String.valueOf(c);",
|
||||
" TernaryOp o4 = (a, b, c) -> c.concat(a);",
|
||||
" TernaryOp o5 = (a, b, c) -> c.concat(b);",
|
||||
" TernaryOp o6 = (a, b, c) -> a.concat(c);",
|
||||
" TernaryOp o7 = (a, b, c) -> b.concat(c);",
|
||||
" }",
|
||||
"",
|
||||
" void receiver(IntFunction<?> op) {}",
|
||||
"",
|
||||
" void receiver(IntConsumer op) {}",
|
||||
"",
|
||||
" void ivoid0() {}",
|
||||
"",
|
||||
" void ivoid1(int a) {}",
|
||||
"",
|
||||
" void ivoid2(int a, int b) {}",
|
||||
"",
|
||||
" int iint0() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" int iint1(int a) {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" int iint2(int a, int b) {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" static void svoid0() {}",
|
||||
"",
|
||||
" static void svoid1(int a) {}",
|
||||
"",
|
||||
" static void svoid2(int a, int b) {}",
|
||||
"",
|
||||
" static void svoid3(int a, int b, int c) {}",
|
||||
"",
|
||||
" static int sint0() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" static int sint1(int a) {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" static int sint2(int a, int b) {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" interface TernaryOp {",
|
||||
" String collect(String a, String b, String c);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.Streams;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
private final Stream<Integer> s = Stream.of(1);
|
||||
private final Map<Integer, Integer> m = new HashMap<>();
|
||||
private final Runnable thrower =
|
||||
() -> {
|
||||
throw new RuntimeException();
|
||||
};
|
||||
|
||||
void unaryExternalStaticFunctionCalls() {
|
||||
s.forEach(String::valueOf);
|
||||
// BUG: Diagnostic contains:
|
||||
s.forEach(v -> String.valueOf(v));
|
||||
s.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
(v) -> {
|
||||
String.valueOf(v);
|
||||
});
|
||||
s.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
(Integer v) -> {
|
||||
{
|
||||
String.valueOf(v);
|
||||
}
|
||||
});
|
||||
s.forEach(
|
||||
v -> {
|
||||
String.valueOf(v);
|
||||
String.valueOf(v);
|
||||
});
|
||||
|
||||
s.map(String::valueOf);
|
||||
// BUG: Diagnostic contains:
|
||||
s.map(v -> String.valueOf(v));
|
||||
// BUG: Diagnostic contains:
|
||||
s.map((v) -> (String.valueOf(v)));
|
||||
s.map(
|
||||
// BUG: Diagnostic contains:
|
||||
(Integer v) -> {
|
||||
return String.valueOf(v);
|
||||
});
|
||||
s.map(
|
||||
// BUG: Diagnostic contains:
|
||||
(final Integer v) -> {
|
||||
return (String.valueOf(v));
|
||||
});
|
||||
s.map(
|
||||
v -> {
|
||||
String.valueOf(v);
|
||||
return String.valueOf(v);
|
||||
});
|
||||
|
||||
s.findFirst().orElseGet(() -> Integer.valueOf("0"));
|
||||
m.forEach((k, v) -> String.valueOf(v));
|
||||
m.forEach((k, v) -> String.valueOf(k));
|
||||
}
|
||||
|
||||
void binaryExternalInstanceFunctionCalls() {
|
||||
m.forEach(m::put);
|
||||
// BUG: Diagnostic contains:
|
||||
m.forEach((k, v) -> m.put(k, v));
|
||||
m.forEach((k, v) -> m.put(v, k));
|
||||
m.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
(Integer k, Integer v) -> {
|
||||
m.put(k, v);
|
||||
});
|
||||
m.forEach(
|
||||
(k, v) -> {
|
||||
m.put(k, k);
|
||||
});
|
||||
m.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
(final Integer k, final Integer v) -> {
|
||||
{
|
||||
m.put(k, v);
|
||||
}
|
||||
});
|
||||
m.forEach(
|
||||
(k, v) -> {
|
||||
{
|
||||
m.put(v, v);
|
||||
}
|
||||
});
|
||||
m.forEach((k, v) -> new HashMap<Integer, Integer>().put(k, v));
|
||||
m.forEach(
|
||||
(k, v) -> {
|
||||
m.put(k, v);
|
||||
m.put(k, v);
|
||||
});
|
||||
|
||||
Streams.zip(s, s, m::put);
|
||||
// BUG: Diagnostic contains:
|
||||
Streams.zip(s, s, (a, b) -> m.put(a, b));
|
||||
Streams.zip(s, s, (a, b) -> m.put(b, a));
|
||||
// BUG: Diagnostic contains:
|
||||
Streams.zip(s, s, (Integer a, Integer b) -> (m.put(a, b)));
|
||||
Streams.zip(s, s, (a, b) -> (m.put(a, a)));
|
||||
Streams.zip(
|
||||
s,
|
||||
s,
|
||||
// BUG: Diagnostic contains:
|
||||
(final Integer a, final Integer b) -> {
|
||||
return m.put(a, b);
|
||||
});
|
||||
Streams.zip(
|
||||
s,
|
||||
s,
|
||||
(a, b) -> {
|
||||
return m.put(b, b);
|
||||
});
|
||||
Streams.zip(
|
||||
s,
|
||||
s,
|
||||
// BUG: Diagnostic contains:
|
||||
(a, b) -> {
|
||||
return (m.put(a, b));
|
||||
});
|
||||
Streams.zip(
|
||||
s,
|
||||
s,
|
||||
(a, b) -> {
|
||||
return (m.put(b, a));
|
||||
});
|
||||
Streams.zip(
|
||||
s,
|
||||
s,
|
||||
(a, b) -> {
|
||||
m.put(a, b);
|
||||
return m.put(a, b);
|
||||
});
|
||||
}
|
||||
|
||||
void nullaryExternalInstanceFunctionCalls() {
|
||||
s.map(Integer::doubleValue);
|
||||
// BUG: Diagnostic contains:
|
||||
s.map(i -> i.doubleValue());
|
||||
s.map(i -> i.toString());
|
||||
s.map(i -> s.toString());
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Stream.of(int.class).filter(c -> c.isEnum());
|
||||
Stream.of((Class<?>) int.class).filter(Class::isEnum);
|
||||
// BUG: Diagnostic contains:
|
||||
Stream.of((Class<?>) int.class).filter(c -> c.isEnum());
|
||||
}
|
||||
|
||||
void localFunctionCalls() {
|
||||
s.forEach(v -> ivoid0());
|
||||
s.forEach(v -> iint0());
|
||||
s.forEach(v -> svoid0());
|
||||
s.forEach(v -> sint0());
|
||||
|
||||
s.forEach(this::ivoid1);
|
||||
// BUG: Diagnostic contains:
|
||||
s.forEach(v -> ivoid1(v));
|
||||
s.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
v -> {
|
||||
ivoid1(v);
|
||||
});
|
||||
s.forEach(this::iint1);
|
||||
// BUG: Diagnostic contains:
|
||||
s.forEach(v -> iint1(v));
|
||||
s.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
v -> {
|
||||
iint1(v);
|
||||
});
|
||||
|
||||
s.forEach(A::svoid1);
|
||||
// BUG: Diagnostic contains:
|
||||
s.forEach(v -> svoid1(v));
|
||||
s.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
v -> {
|
||||
svoid1(v);
|
||||
});
|
||||
s.forEach(A::sint1);
|
||||
// BUG: Diagnostic contains:
|
||||
s.forEach(v -> sint1(v));
|
||||
s.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
v -> {
|
||||
sint1(v);
|
||||
});
|
||||
|
||||
s.forEach(v -> ivoid2(v, v));
|
||||
s.forEach(v -> iint2(v, v));
|
||||
s.forEach(v -> svoid2(v, v));
|
||||
s.forEach(v -> sint2(v, v));
|
||||
|
||||
m.forEach((k, v) -> ivoid0());
|
||||
m.forEach((k, v) -> iint0());
|
||||
m.forEach((k, v) -> svoid0());
|
||||
m.forEach((k, v) -> sint0());
|
||||
|
||||
m.forEach(this::ivoid2);
|
||||
// BUG: Diagnostic contains:
|
||||
m.forEach((k, v) -> ivoid2(k, v));
|
||||
m.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
(k, v) -> {
|
||||
ivoid2(k, v);
|
||||
});
|
||||
m.forEach(this::iint2);
|
||||
// BUG: Diagnostic contains:
|
||||
m.forEach((k, v) -> iint2(k, v));
|
||||
m.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
(k, v) -> {
|
||||
iint2(k, v);
|
||||
});
|
||||
|
||||
m.forEach(A::svoid2);
|
||||
// BUG: Diagnostic contains:
|
||||
m.forEach((k, v) -> svoid2(k, v));
|
||||
m.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
(k, v) -> {
|
||||
svoid2(k, v);
|
||||
});
|
||||
m.forEach(A::sint2);
|
||||
// BUG: Diagnostic contains:
|
||||
m.forEach((k, v) -> sint2(k, v));
|
||||
m.forEach(
|
||||
// BUG: Diagnostic contains:
|
||||
(k, v) -> {
|
||||
sint2(k, v);
|
||||
});
|
||||
}
|
||||
|
||||
void functionCallsWhoseReplacementWouldBeAmbiguous() {
|
||||
receiver(
|
||||
i -> {
|
||||
Integer.toString(i);
|
||||
});
|
||||
}
|
||||
|
||||
void assortedOtherEdgeCases() {
|
||||
s.forEach(v -> String.valueOf(v.toString()));
|
||||
TernaryOp o1 = (a, b, c) -> String.valueOf(a);
|
||||
TernaryOp o2 = (a, b, c) -> String.valueOf(b);
|
||||
TernaryOp o3 = (a, b, c) -> String.valueOf(c);
|
||||
TernaryOp o4 = (a, b, c) -> c.concat(a);
|
||||
TernaryOp o5 = (a, b, c) -> c.concat(b);
|
||||
TernaryOp o6 = (a, b, c) -> a.concat(c);
|
||||
TernaryOp o7 = (a, b, c) -> b.concat(c);
|
||||
}
|
||||
|
||||
void receiver(IntFunction<?> op) {}
|
||||
|
||||
void receiver(IntConsumer op) {}
|
||||
|
||||
void ivoid0() {}
|
||||
|
||||
void ivoid1(int a) {}
|
||||
|
||||
void ivoid2(int a, int b) {}
|
||||
|
||||
int iint0() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iint1(int a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iint2(int a, int b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void svoid0() {}
|
||||
|
||||
static void svoid1(int a) {}
|
||||
|
||||
static void svoid2(int a, int b) {}
|
||||
|
||||
static void svoid3(int a, int b, int c) {}
|
||||
|
||||
static int sint0() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sint1(int a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sint2(int a, int b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
interface TernaryOp {
|
||||
String collect(String a, String b, String c);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -321,111 +323,115 @@ final class MethodReferenceUsageTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(MethodReferenceUsage.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.Collections.emptyList;",
|
||||
"",
|
||||
"import java.util.Collections;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Map;",
|
||||
"import java.util.function.IntSupplier;",
|
||||
"import java.util.function.Supplier;",
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" static class B extends A {",
|
||||
" final A a = new B();",
|
||||
" final B b = new B();",
|
||||
"",
|
||||
" IntSupplier intSup;",
|
||||
" Supplier<List<?>> listSup;",
|
||||
"",
|
||||
" void m() {",
|
||||
" intSup = () -> a.iint0();",
|
||||
" intSup = () -> b.iint0();",
|
||||
" intSup = () -> this.iint0();",
|
||||
" intSup = () -> super.iint0();",
|
||||
"",
|
||||
" intSup = () -> a.sint0();",
|
||||
" intSup = () -> b.sint0();",
|
||||
" intSup = () -> this.sint0();",
|
||||
" intSup = () -> super.sint0();",
|
||||
" intSup = () -> A.sint0();",
|
||||
" intSup = () -> B.sint0();",
|
||||
"",
|
||||
" listSup = () -> Collections.emptyList();",
|
||||
" listSup = () -> emptyList();",
|
||||
"",
|
||||
" Stream.of((Class<?>) int.class).filter(c -> c.isEnum());",
|
||||
" Stream.of((Map<?, ?>) null).map(Map::keySet).map(s -> s.size());",
|
||||
" }",
|
||||
"",
|
||||
" @Override",
|
||||
" int iint0() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" int iint0() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" static int sint0() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
static class B extends A {
|
||||
final A a = new B();
|
||||
final B b = new B();
|
||||
|
||||
IntSupplier intSup;
|
||||
Supplier<List<?>> listSup;
|
||||
|
||||
void m() {
|
||||
intSup = () -> a.iint0();
|
||||
intSup = () -> b.iint0();
|
||||
intSup = () -> this.iint0();
|
||||
intSup = () -> super.iint0();
|
||||
|
||||
intSup = () -> a.sint0();
|
||||
intSup = () -> b.sint0();
|
||||
intSup = () -> this.sint0();
|
||||
intSup = () -> super.sint0();
|
||||
intSup = () -> A.sint0();
|
||||
intSup = () -> B.sint0();
|
||||
|
||||
listSup = () -> Collections.emptyList();
|
||||
listSup = () -> emptyList();
|
||||
|
||||
Stream.of((Class<?>) int.class).filter(c -> c.isEnum());
|
||||
Stream.of((Map<?, ?>) null).map(Map::keySet).map(s -> s.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
int iint0() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int iint0() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sint0() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static java.util.Collections.emptyList;",
|
||||
"",
|
||||
"import java.util.Collections;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Map;",
|
||||
"import java.util.Set;",
|
||||
"import java.util.function.IntSupplier;",
|
||||
"import java.util.function.Supplier;",
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" static class B extends A {",
|
||||
" final A a = new B();",
|
||||
" final B b = new B();",
|
||||
"",
|
||||
" IntSupplier intSup;",
|
||||
" Supplier<List<?>> listSup;",
|
||||
"",
|
||||
" void m() {",
|
||||
" intSup = a::iint0;",
|
||||
" intSup = b::iint0;",
|
||||
" intSup = this::iint0;",
|
||||
" intSup = super::iint0;",
|
||||
"",
|
||||
" intSup = () -> a.sint0();",
|
||||
" intSup = () -> b.sint0();",
|
||||
" intSup = () -> this.sint0();",
|
||||
" intSup = () -> super.sint0();",
|
||||
" intSup = A::sint0;",
|
||||
" intSup = B::sint0;",
|
||||
"",
|
||||
" listSup = Collections::emptyList;",
|
||||
" listSup = Collections::emptyList;",
|
||||
"",
|
||||
" Stream.of((Class<?>) int.class).filter(Class::isEnum);",
|
||||
" Stream.of((Map<?, ?>) null).map(Map::keySet).map(Set::size);",
|
||||
" }",
|
||||
"",
|
||||
" @Override",
|
||||
" int iint0() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" int iint0() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" static int sint0() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
static class B extends A {
|
||||
final A a = new B();
|
||||
final B b = new B();
|
||||
|
||||
IntSupplier intSup;
|
||||
Supplier<List<?>> listSup;
|
||||
|
||||
void m() {
|
||||
intSup = a::iint0;
|
||||
intSup = b::iint0;
|
||||
intSup = this::iint0;
|
||||
intSup = super::iint0;
|
||||
|
||||
intSup = () -> a.sint0();
|
||||
intSup = () -> b.sint0();
|
||||
intSup = () -> this.sint0();
|
||||
intSup = () -> super.sint0();
|
||||
intSup = A::sint0;
|
||||
intSup = B::sint0;
|
||||
|
||||
listSup = Collections::emptyList;
|
||||
listSup = Collections::emptyList;
|
||||
|
||||
Stream.of((Class<?>) int.class).filter(Class::isEnum);
|
||||
Stream.of((Map<?, ?>) null).map(Map::keySet).map(Set::size);
|
||||
}
|
||||
|
||||
@Override
|
||||
int iint0() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int iint0() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sint0() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,86 +11,88 @@ final class MockitoMockClassReferenceTest {
|
||||
CompilationTestHelper.newInstance(MockitoMockClassReference.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.mockito.Mockito.mock;",
|
||||
"import static org.mockito.Mockito.spy;",
|
||||
"import static org.mockito.Mockito.withSettings;",
|
||||
"",
|
||||
"import java.util.List;",
|
||||
"import java.util.Objects;",
|
||||
"import org.mockito.invocation.InvocationOnMock;",
|
||||
"",
|
||||
"class A {",
|
||||
" {",
|
||||
" Double d = Objects.requireNonNullElseGet(null, () -> mock(Double.class));",
|
||||
" Double d2 =",
|
||||
" Objects.requireNonNullElseGet(",
|
||||
" null,",
|
||||
" () -> {",
|
||||
" return mock(Double.class);",
|
||||
" });",
|
||||
" }",
|
||||
"",
|
||||
" void m() {",
|
||||
" Number variableMock = 42;",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variableMock = mock(Number.class);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variableMock = mock(Number.class, \"name\");",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variableMock = mock(Number.class, InvocationOnMock::callRealMethod);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variableMock = mock(Number.class, withSettings());",
|
||||
" variableMock = mock(Integer.class);",
|
||||
" variableMock = 42;",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" List rawMock = mock(List.class);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" List<String> genericMock = mock(List.class);",
|
||||
" var varMock = mock(Integer.class);",
|
||||
" Class<? extends Number> numberType = Integer.class;",
|
||||
" Number variableTypeMock = mock(numberType);",
|
||||
" Object subtypeMock = mock(Integer.class);",
|
||||
"",
|
||||
" Number variableSpy = 42;",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" variableSpy = spy(Number.class);",
|
||||
" variableSpy = spy(Integer.class);",
|
||||
" variableSpy = 42;",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" List rawSpy = spy(List.class);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" List<String> genericSpy = spy(List.class);",
|
||||
" var varSpy = spy(Integer.class);",
|
||||
" Number variableTypeSpy = spy(numberType);",
|
||||
" Object subtypeSpy = spy(Integer.class);",
|
||||
" Object objectSpy = spy(new Object());",
|
||||
"",
|
||||
" Objects.hash(mock(Integer.class));",
|
||||
" Integer i = mock(mock(Integer.class));",
|
||||
" String s = new String(mock(String.class));",
|
||||
" }",
|
||||
"",
|
||||
" Double getDoubleMock() {",
|
||||
" return Objects.requireNonNullElseGet(",
|
||||
" null,",
|
||||
" () -> {",
|
||||
" return mock(Double.class);",
|
||||
" });",
|
||||
" }",
|
||||
"",
|
||||
" Integer getIntegerMock() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" return mock(Integer.class);",
|
||||
" }",
|
||||
"",
|
||||
" <T> T getGenericMock(Class<T> clazz) {",
|
||||
" return mock(clazz);",
|
||||
" }",
|
||||
"",
|
||||
" Number getSubTypeMock() {",
|
||||
" return mock(Integer.class);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
|
||||
class A {
|
||||
{
|
||||
Double d = Objects.requireNonNullElseGet(null, () -> mock(Double.class));
|
||||
Double d2 =
|
||||
Objects.requireNonNullElseGet(
|
||||
null,
|
||||
() -> {
|
||||
return mock(Double.class);
|
||||
});
|
||||
}
|
||||
|
||||
void m() {
|
||||
Number variableMock = 42;
|
||||
// BUG: Diagnostic contains:
|
||||
variableMock = mock(Number.class);
|
||||
// BUG: Diagnostic contains:
|
||||
variableMock = mock(Number.class, "name");
|
||||
// BUG: Diagnostic contains:
|
||||
variableMock = mock(Number.class, InvocationOnMock::callRealMethod);
|
||||
// BUG: Diagnostic contains:
|
||||
variableMock = mock(Number.class, withSettings());
|
||||
variableMock = mock(Integer.class);
|
||||
variableMock = 42;
|
||||
// BUG: Diagnostic contains:
|
||||
List rawMock = mock(List.class);
|
||||
// BUG: Diagnostic contains:
|
||||
List<String> genericMock = mock(List.class);
|
||||
var varMock = mock(Integer.class);
|
||||
Class<? extends Number> numberType = Integer.class;
|
||||
Number variableTypeMock = mock(numberType);
|
||||
Object subtypeMock = mock(Integer.class);
|
||||
|
||||
Number variableSpy = 42;
|
||||
// BUG: Diagnostic contains:
|
||||
variableSpy = spy(Number.class);
|
||||
variableSpy = spy(Integer.class);
|
||||
variableSpy = 42;
|
||||
// BUG: Diagnostic contains:
|
||||
List rawSpy = spy(List.class);
|
||||
// BUG: Diagnostic contains:
|
||||
List<String> genericSpy = spy(List.class);
|
||||
var varSpy = spy(Integer.class);
|
||||
Number variableTypeSpy = spy(numberType);
|
||||
Object subtypeSpy = spy(Integer.class);
|
||||
Object objectSpy = spy(new Object());
|
||||
|
||||
Objects.hash(mock(Integer.class));
|
||||
Integer i = mock(mock(Integer.class));
|
||||
String s = new String(mock(String.class));
|
||||
}
|
||||
|
||||
Double getDoubleMock() {
|
||||
return Objects.requireNonNullElseGet(
|
||||
null,
|
||||
() -> {
|
||||
return mock(Double.class);
|
||||
});
|
||||
}
|
||||
|
||||
Integer getIntegerMock() {
|
||||
// BUG: Diagnostic contains:
|
||||
return mock(Integer.class);
|
||||
}
|
||||
|
||||
<T> T getGenericMock(Class<T> clazz) {
|
||||
return mock(clazz);
|
||||
}
|
||||
|
||||
Number getSubTypeMock() {
|
||||
return mock(Integer.class);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -99,38 +101,42 @@ final class MockitoMockClassReferenceTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(MockitoMockClassReference.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.mockito.Mockito.mock;",
|
||||
"import static org.mockito.Mockito.spy;",
|
||||
"import static org.mockito.Mockito.withSettings;",
|
||||
"",
|
||||
"import org.mockito.invocation.InvocationOnMock;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Number simpleMock = mock(Number.class);",
|
||||
" Number namedMock = mock(Number.class, \"name\");",
|
||||
" Number customAnswerMock = mock(Number.class, InvocationOnMock::callRealMethod);",
|
||||
" Number customSettingsMock = mock(Number.class, withSettings());",
|
||||
" Number simpleSpy = spy(Number.class);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Number simpleMock = mock(Number.class);
|
||||
Number namedMock = mock(Number.class, "name");
|
||||
Number customAnswerMock = mock(Number.class, InvocationOnMock::callRealMethod);
|
||||
Number customSettingsMock = mock(Number.class, withSettings());
|
||||
Number simpleSpy = spy(Number.class);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static org.mockito.Mockito.mock;",
|
||||
"import static org.mockito.Mockito.spy;",
|
||||
"import static org.mockito.Mockito.withSettings;",
|
||||
"",
|
||||
"import org.mockito.invocation.InvocationOnMock;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Number simpleMock = mock();",
|
||||
" Number namedMock = mock(\"name\");",
|
||||
" Number customAnswerMock = mock(InvocationOnMock::callRealMethod);",
|
||||
" Number customSettingsMock = mock(withSettings());",
|
||||
" Number simpleSpy = spy();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Number simpleMock = mock();
|
||||
Number namedMock = mock("name");
|
||||
Number customAnswerMock = mock(InvocationOnMock::callRealMethod);
|
||||
Number customSettingsMock = mock(withSettings());
|
||||
Number simpleSpy = spy();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,40 +11,42 @@ final class MockitoStubbingTest {
|
||||
CompilationTestHelper.newInstance(MockitoStubbing.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.mockito.ArgumentMatchers.eq;",
|
||||
"import static org.mockito.ArgumentMatchers.notNull;",
|
||||
"import static org.mockito.Mockito.doAnswer;",
|
||||
"import static org.mockito.Mockito.mock;",
|
||||
"",
|
||||
"import java.util.function.BiConsumer;",
|
||||
"import java.util.function.Consumer;",
|
||||
"import org.mockito.ArgumentMatchers;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Runnable runnable = mock(Runnable.class);",
|
||||
" doAnswer(inv -> null).when(runnable).run();",
|
||||
"",
|
||||
" Consumer<String> consumer = mock(Consumer.class);",
|
||||
" doAnswer(inv -> null).when(consumer).accept(\"foo\");",
|
||||
" doAnswer(inv -> null).when(consumer).accept(notNull());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" doAnswer(inv -> null).when(consumer).accept(ArgumentMatchers.eq(\"foo\"));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" doAnswer(inv -> null).when(consumer).accept(eq(toString()));",
|
||||
"",
|
||||
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
|
||||
" doAnswer(inv -> null).when(biConsumer).accept(0, \"foo\");",
|
||||
" doAnswer(inv -> null).when(biConsumer).accept(eq(0), notNull());",
|
||||
" doAnswer(inv -> null).when(biConsumer).accept(notNull(), eq(\"foo\"));",
|
||||
" doAnswer(inv -> null)",
|
||||
" .when(biConsumer)",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" .accept(ArgumentMatchers.eq(0), ArgumentMatchers.eq(\"foo\"));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.notNull;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Runnable runnable = mock(Runnable.class);
|
||||
doAnswer(inv -> null).when(runnable).run();
|
||||
|
||||
Consumer<String> consumer = mock(Consumer.class);
|
||||
doAnswer(inv -> null).when(consumer).accept("foo");
|
||||
doAnswer(inv -> null).when(consumer).accept(notNull());
|
||||
// BUG: Diagnostic contains:
|
||||
doAnswer(inv -> null).when(consumer).accept(ArgumentMatchers.eq("foo"));
|
||||
// BUG: Diagnostic contains:
|
||||
doAnswer(inv -> null).when(consumer).accept(eq(toString()));
|
||||
|
||||
BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);
|
||||
doAnswer(inv -> null).when(biConsumer).accept(0, "foo");
|
||||
doAnswer(inv -> null).when(biConsumer).accept(eq(0), notNull());
|
||||
doAnswer(inv -> null).when(biConsumer).accept(notNull(), eq("foo"));
|
||||
doAnswer(inv -> null)
|
||||
.when(biConsumer)
|
||||
// BUG: Diagnostic contains:
|
||||
.accept(ArgumentMatchers.eq(0), ArgumentMatchers.eq("foo"));
|
||||
// BUG: Diagnostic contains:
|
||||
doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -53,48 +55,52 @@ final class MockitoStubbingTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(MockitoStubbing.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.mockito.ArgumentMatchers.eq;",
|
||||
"import static org.mockito.Mockito.doAnswer;",
|
||||
"import static org.mockito.Mockito.mock;",
|
||||
"",
|
||||
"import java.util.function.BiConsumer;",
|
||||
"import java.util.function.Consumer;",
|
||||
"import org.mockito.ArgumentMatchers;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Consumer<String> consumer = mock(Consumer.class);",
|
||||
" doAnswer(inv -> null).when(consumer).accept(ArgumentMatchers.eq(\"foo\"));",
|
||||
" doAnswer(inv -> null).when(consumer).accept(eq(toString()));",
|
||||
"",
|
||||
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
|
||||
" doAnswer(inv -> null)",
|
||||
" .when(biConsumer)",
|
||||
" .accept(ArgumentMatchers.eq(0), ArgumentMatchers.eq(\"foo\"));",
|
||||
" doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Consumer<String> consumer = mock(Consumer.class);
|
||||
doAnswer(inv -> null).when(consumer).accept(ArgumentMatchers.eq("foo"));
|
||||
doAnswer(inv -> null).when(consumer).accept(eq(toString()));
|
||||
|
||||
BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);
|
||||
doAnswer(inv -> null)
|
||||
.when(biConsumer)
|
||||
.accept(ArgumentMatchers.eq(0), ArgumentMatchers.eq("foo"));
|
||||
doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static org.mockito.ArgumentMatchers.eq;",
|
||||
"import static org.mockito.Mockito.doAnswer;",
|
||||
"import static org.mockito.Mockito.mock;",
|
||||
"",
|
||||
"import java.util.function.BiConsumer;",
|
||||
"import java.util.function.Consumer;",
|
||||
"import org.mockito.ArgumentMatchers;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Consumer<String> consumer = mock(Consumer.class);",
|
||||
" doAnswer(inv -> null).when(consumer).accept(\"foo\");",
|
||||
" doAnswer(inv -> null).when(consumer).accept(toString());",
|
||||
"",
|
||||
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
|
||||
" doAnswer(inv -> null).when(biConsumer).accept(0, \"foo\");",
|
||||
" doAnswer(inv -> null).when(biConsumer).accept(hashCode(), toString());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Consumer<String> consumer = mock(Consumer.class);
|
||||
doAnswer(inv -> null).when(consumer).accept("foo");
|
||||
doAnswer(inv -> null).when(consumer).accept(toString());
|
||||
|
||||
BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);
|
||||
doAnswer(inv -> null).when(biConsumer).accept(0, "foo");
|
||||
doAnswer(inv -> null).when(biConsumer).accept(hashCode(), toString());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,18 +9,20 @@ final class MongoDBTextFilterUsageTest {
|
||||
CompilationTestHelper.newInstance(MongoDBTextFilterUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.mongodb.client.model.Filters;",
|
||||
"import com.mongodb.client.model.TextSearchOptions;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Filters.eq(\"foo\", \"bar\");",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Filters.text(\"foo\");",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Filters.text(\"foo\", new TextSearchOptions());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.mongodb.client.model.Filters;
|
||||
import com.mongodb.client.model.TextSearchOptions;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Filters.eq("foo", "bar");
|
||||
// BUG: Diagnostic contains:
|
||||
Filters.text("foo");
|
||||
// BUG: Diagnostic contains:
|
||||
Filters.text("foo", new TextSearchOptions());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,31 +9,33 @@ final class NestedOptionalsTest {
|
||||
CompilationTestHelper.newInstance(NestedOptionals.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Optional;",
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Optional.empty();",
|
||||
" Optional.of(1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Optional.of(Optional.empty());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Optional.of(Optional.of(1));",
|
||||
"",
|
||||
" Optional.ofNullable(null);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Optional.ofNullable((Optional) null);",
|
||||
"",
|
||||
" Optional.of(\"foo\").map(String::length);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Optional.of(\"foo\").map(Optional::of);",
|
||||
"",
|
||||
" Stream.of(\"foo\").findFirst();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of(\"foo\").map(Optional::of).findFirst();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Optional.empty();
|
||||
Optional.of(1);
|
||||
// BUG: Diagnostic contains:
|
||||
Optional.of(Optional.empty());
|
||||
// BUG: Diagnostic contains:
|
||||
Optional.of(Optional.of(1));
|
||||
|
||||
Optional.ofNullable(null);
|
||||
// BUG: Diagnostic contains:
|
||||
Optional.ofNullable((Optional) null);
|
||||
|
||||
Optional.of("foo").map(String::length);
|
||||
// BUG: Diagnostic contains:
|
||||
Optional.of("foo").map(Optional::of);
|
||||
|
||||
Stream.of("foo").findFirst();
|
||||
// BUG: Diagnostic contains:
|
||||
Stream.of("foo").map(Optional::of).findFirst();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,29 +9,31 @@ final class NestedPublishersTest {
|
||||
CompilationTestHelper.newInstance(NestedPublishers.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import org.reactivestreams.Publisher;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.GroupedFlux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Mono.empty();",
|
||||
" Flux.just(1);",
|
||||
" Flux.just(1, 2).groupBy(i -> i).map(groupedFlux -> (GroupedFlux) groupedFlux);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.just(Mono.empty());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(Flux.empty());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.just((Flux) Flux.just(1));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just((Publisher) Mono.just(1));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.just(1).map(Mono::just);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.GroupedFlux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Mono.empty();
|
||||
Flux.just(1);
|
||||
Flux.just(1, 2).groupBy(i -> i).map(groupedFlux -> (GroupedFlux) groupedFlux);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Mono.just(Mono.empty());
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(Flux.empty());
|
||||
// BUG: Diagnostic contains:
|
||||
Mono.just((Flux) Flux.just(1));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just((Publisher) Mono.just(1));
|
||||
// BUG: Diagnostic contains:
|
||||
Mono.just(1).map(Mono::just);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,95 +11,97 @@ final class NonEmptyMonoTest {
|
||||
CompilationTestHelper.newInstance(NonEmptyMono.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
"import static java.util.function.Function.identity;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableMap;",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.HashMap;",
|
||||
"import java.util.List;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Mono.just(1).defaultIfEmpty(2);",
|
||||
" Mono.just(1).single();",
|
||||
" Mono.just(1).switchIfEmpty(Mono.just(2));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).all(x -> true).defaultIfEmpty(true);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).any(x -> true).single();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collect(toImmutableList()).switchIfEmpty(Mono.just(ImmutableList.of()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collect(ArrayList::new, List::add).defaultIfEmpty(new ArrayList<>());",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectList().single();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectMap(identity()).switchIfEmpty(Mono.just(ImmutableMap.of()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectMap(identity(), identity()).defaultIfEmpty(ImmutableMap.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectMap(identity(), identity(), HashMap::new).single();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectMultimap(identity()).switchIfEmpty(Mono.just(ImmutableMap.of()));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectMultimap(identity(), identity()).defaultIfEmpty(ImmutableMap.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectMultimap(identity(), identity(), HashMap::new).single();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectSortedList().defaultIfEmpty(ImmutableList.of());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collectSortedList((o1, o2) -> 0).single();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).count().switchIfEmpty(Mono.just(2L));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).elementAt(0).defaultIfEmpty(1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).elementAt(0, 2).single();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).hasElement(2).switchIfEmpty(Mono.just(true));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).hasElements().defaultIfEmpty(true);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).last().single();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).last(2).switchIfEmpty(Mono.just(3));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).reduceWith(() -> 0, Integer::sum).defaultIfEmpty(2);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).single().single();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).single(2).switchIfEmpty(Mono.just(3));",
|
||||
"",
|
||||
" Flux.just(1).reduce(Integer::sum).defaultIfEmpty(2);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).reduce(2, Integer::sum).single();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.just(1).defaultIfEmpty(1).switchIfEmpty(Mono.just(2));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.just(1).hasElement().defaultIfEmpty(true);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.just(1).single().single();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static java.util.function.Function.identity;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Mono.just(1).defaultIfEmpty(2);
|
||||
Mono.just(1).single();
|
||||
Mono.just(1).switchIfEmpty(Mono.just(2));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).all(x -> true).defaultIfEmpty(true);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).any(x -> true).single();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collect(toImmutableList()).switchIfEmpty(Mono.just(ImmutableList.of()));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collect(ArrayList::new, List::add).defaultIfEmpty(new ArrayList<>());
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectList().single();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectMap(identity()).switchIfEmpty(Mono.just(ImmutableMap.of()));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectMap(identity(), identity()).defaultIfEmpty(ImmutableMap.of());
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectMap(identity(), identity(), HashMap::new).single();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectMultimap(identity()).switchIfEmpty(Mono.just(ImmutableMap.of()));
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectMultimap(identity(), identity()).defaultIfEmpty(ImmutableMap.of());
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectMultimap(identity(), identity(), HashMap::new).single();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectSortedList().defaultIfEmpty(ImmutableList.of());
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).collectSortedList((o1, o2) -> 0).single();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).count().switchIfEmpty(Mono.just(2L));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).elementAt(0).defaultIfEmpty(1);
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).elementAt(0, 2).single();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).hasElement(2).switchIfEmpty(Mono.just(true));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).hasElements().defaultIfEmpty(true);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).last().single();
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).last(2).switchIfEmpty(Mono.just(3));
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).reduceWith(() -> 0, Integer::sum).defaultIfEmpty(2);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).single().single();
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).single(2).switchIfEmpty(Mono.just(3));
|
||||
|
||||
Flux.just(1).reduce(Integer::sum).defaultIfEmpty(2);
|
||||
// BUG: Diagnostic contains:
|
||||
Flux.just(1).reduce(2, Integer::sum).single();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Mono.just(1).defaultIfEmpty(1).switchIfEmpty(Mono.just(2));
|
||||
// BUG: Diagnostic contains:
|
||||
Mono.just(1).hasElement().defaultIfEmpty(true);
|
||||
// BUG: Diagnostic contains:
|
||||
Mono.just(1).single().single();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -108,42 +110,46 @@ final class NonEmptyMonoTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(NonEmptyMono.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(toImmutableList()).single();",
|
||||
" Flux.just(1).collect(toImmutableList()).defaultIfEmpty(ImmutableList.of());",
|
||||
" Flux.just(1).collect(toImmutableList()).switchIfEmpty(Mono.just(ImmutableList.of()));",
|
||||
"",
|
||||
" Mono.just(2).hasElement().single();",
|
||||
" Mono.just(2).hasElement().defaultIfEmpty(true);",
|
||||
" Mono.just(2).hasElement().switchIfEmpty(Mono.just(true));",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).collect(toImmutableList()).single();
|
||||
Flux.just(1).collect(toImmutableList()).defaultIfEmpty(ImmutableList.of());
|
||||
Flux.just(1).collect(toImmutableList()).switchIfEmpty(Mono.just(ImmutableList.of()));
|
||||
|
||||
Mono.just(2).hasElement().single();
|
||||
Mono.just(2).hasElement().defaultIfEmpty(true);
|
||||
Mono.just(2).hasElement().switchIfEmpty(Mono.just(true));
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(toImmutableList());",
|
||||
" Flux.just(1).collect(toImmutableList());",
|
||||
" Flux.just(1).collect(toImmutableList());",
|
||||
"",
|
||||
" Mono.just(2).hasElement();",
|
||||
" Mono.just(2).hasElement();",
|
||||
" Mono.just(2).hasElement();",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Flux.just(1).collect(toImmutableList());
|
||||
Flux.just(1).collect(toImmutableList());
|
||||
Flux.just(1).collect(toImmutableList());
|
||||
|
||||
Mono.just(2).hasElement();
|
||||
Mono.just(2).hasElement();
|
||||
Mono.just(2).hasElement();
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,71 +40,73 @@ final class NonStaticImportTest {
|
||||
CompilationTestHelper.newInstance(NonStaticImport.class, getClass())
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static com.google.common.base.Strings.nullToEmpty;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static com.google.common.collect.ImmutableList.copyOf;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.lang.Integer.MAX_VALUE;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.lang.Integer.MIN_VALUE;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.time.Clock.systemUTC;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.time.Instant.MIN;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.time.ZoneOffset.SHORT_IDS;",
|
||||
"import static java.time.ZoneOffset.UTC;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.util.Collections.min;",
|
||||
"import static java.util.Locale.ENGLISH;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.util.Locale.ROOT;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.util.Optional.empty;",
|
||||
"import static pkg.A.WithMethodThatIsSelectivelyFlagged.list;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.time.Instant;",
|
||||
"import java.time.ZoneOffset;",
|
||||
"import java.util.Locale;",
|
||||
"import java.util.Map;",
|
||||
"import pkg.A.Wrapper.ZERO;",
|
||||
"",
|
||||
"class A {",
|
||||
" private Integer MIN_VALUE = 12;",
|
||||
"",
|
||||
" void m() {",
|
||||
" nullToEmpty(null);",
|
||||
" copyOf(ImmutableList.of());",
|
||||
" int max = MAX_VALUE;",
|
||||
" int min = MIN_VALUE;",
|
||||
" systemUTC();",
|
||||
" Instant minInstant = MIN;",
|
||||
" Map<String, String> shortIds = SHORT_IDS;",
|
||||
" ZoneOffset utc = UTC;",
|
||||
" min(ImmutableSet.of());",
|
||||
" Locale english = ENGLISH;",
|
||||
" Locale root = ROOT;",
|
||||
" empty();",
|
||||
"",
|
||||
" list();",
|
||||
" new ZERO();",
|
||||
" }",
|
||||
"",
|
||||
" static final class WithMethodThatIsSelectivelyFlagged {",
|
||||
" static ImmutableList<String> list() {",
|
||||
" return ImmutableList.of();",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" static final class Wrapper {",
|
||||
" static final class ZERO {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
import static com.google.common.base.Strings.nullToEmpty;
|
||||
// BUG: Diagnostic contains:
|
||||
import static com.google.common.collect.ImmutableList.copyOf;
|
||||
// BUG: Diagnostic contains:
|
||||
import static java.lang.Integer.MAX_VALUE;
|
||||
// BUG: Diagnostic contains:
|
||||
import static java.lang.Integer.MIN_VALUE;
|
||||
// BUG: Diagnostic contains:
|
||||
import static java.time.Clock.systemUTC;
|
||||
// BUG: Diagnostic contains:
|
||||
import static java.time.Instant.MIN;
|
||||
// BUG: Diagnostic contains:
|
||||
import static java.time.ZoneOffset.SHORT_IDS;
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
// BUG: Diagnostic contains:
|
||||
import static java.util.Collections.min;
|
||||
import static java.util.Locale.ENGLISH;
|
||||
// BUG: Diagnostic contains:
|
||||
import static java.util.Locale.ROOT;
|
||||
// BUG: Diagnostic contains:
|
||||
import static java.util.Optional.empty;
|
||||
import static pkg.A.WithMethodThatIsSelectivelyFlagged.list;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import pkg.A.Wrapper.ZERO;
|
||||
|
||||
class A {
|
||||
private Integer MIN_VALUE = 12;
|
||||
|
||||
void m() {
|
||||
nullToEmpty(null);
|
||||
copyOf(ImmutableList.of());
|
||||
int max = MAX_VALUE;
|
||||
int min = MIN_VALUE;
|
||||
systemUTC();
|
||||
Instant minInstant = MIN;
|
||||
Map<String, String> shortIds = SHORT_IDS;
|
||||
ZoneOffset utc = UTC;
|
||||
min(ImmutableSet.of());
|
||||
Locale english = ENGLISH;
|
||||
Locale root = ROOT;
|
||||
empty();
|
||||
|
||||
list();
|
||||
new ZERO();
|
||||
}
|
||||
|
||||
static final class WithMethodThatIsSelectivelyFlagged {
|
||||
static ImmutableList<String> list() {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
||||
|
||||
static final class Wrapper {
|
||||
static final class ZERO {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -113,84 +115,88 @@ final class NonStaticImportTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(NonStaticImport.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.copyOf;",
|
||||
"import static com.google.common.collect.ImmutableSet.of;",
|
||||
"import static java.time.Clock.systemUTC;",
|
||||
"import static java.time.Instant.MAX;",
|
||||
"import static java.time.Instant.MIN;",
|
||||
"import static java.util.Collections.min;",
|
||||
"import static java.util.Locale.ROOT;",
|
||||
"import static java.util.Optional.empty;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.time.Clock;",
|
||||
"import java.time.Instant;",
|
||||
"import java.util.Locale;",
|
||||
"import java.util.Optional;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" systemUTC();",
|
||||
" Clock.systemUTC();",
|
||||
"",
|
||||
" Optional<Integer> o1 = empty();",
|
||||
" Optional<Integer> o2 = Optional.empty();",
|
||||
"",
|
||||
" Object l1 = copyOf(ImmutableList.of());",
|
||||
" Object l2 = ImmutableList.copyOf(ImmutableList.of());",
|
||||
"",
|
||||
" Locale lo1 = ROOT;",
|
||||
" Locale lo2 = Locale.ROOT;",
|
||||
"",
|
||||
" Instant i1 = MIN;",
|
||||
" Instant i2 = MAX;",
|
||||
"",
|
||||
" ImmutableSet.of(min(of()));",
|
||||
" }",
|
||||
"",
|
||||
" private static final class WithCustomConstant {",
|
||||
" private static final Instant MIN = Instant.EPOCH;",
|
||||
" private static final Instant OTHER = MIN;",
|
||||
" private static final Instant OTHER_MAX = MAX;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableList.copyOf;
|
||||
import static com.google.common.collect.ImmutableSet.of;
|
||||
import static java.time.Clock.systemUTC;
|
||||
import static java.time.Instant.MAX;
|
||||
import static java.time.Instant.MIN;
|
||||
import static java.util.Collections.min;
|
||||
import static java.util.Locale.ROOT;
|
||||
import static java.util.Optional.empty;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
systemUTC();
|
||||
Clock.systemUTC();
|
||||
|
||||
Optional<Integer> o1 = empty();
|
||||
Optional<Integer> o2 = Optional.empty();
|
||||
|
||||
Object l1 = copyOf(ImmutableList.of());
|
||||
Object l2 = ImmutableList.copyOf(ImmutableList.of());
|
||||
|
||||
Locale lo1 = ROOT;
|
||||
Locale lo2 = Locale.ROOT;
|
||||
|
||||
Instant i1 = MIN;
|
||||
Instant i2 = MAX;
|
||||
|
||||
ImmutableSet.of(min(of()));
|
||||
}
|
||||
|
||||
private static final class WithCustomConstant {
|
||||
private static final Instant MIN = Instant.EPOCH;
|
||||
private static final Instant OTHER = MIN;
|
||||
private static final Instant OTHER_MAX = MAX;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.time.Clock;",
|
||||
"import java.time.Instant;",
|
||||
"import java.util.Collections;",
|
||||
"import java.util.Locale;",
|
||||
"import java.util.Optional;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Clock.systemUTC();",
|
||||
" Clock.systemUTC();",
|
||||
"",
|
||||
" Optional<Integer> o1 = Optional.empty();",
|
||||
" Optional<Integer> o2 = Optional.empty();",
|
||||
"",
|
||||
" Object l1 = ImmutableList.copyOf(ImmutableList.of());",
|
||||
" Object l2 = ImmutableList.copyOf(ImmutableList.of());",
|
||||
"",
|
||||
" Locale lo1 = Locale.ROOT;",
|
||||
" Locale lo2 = Locale.ROOT;",
|
||||
"",
|
||||
" Instant i1 = Instant.MIN;",
|
||||
" Instant i2 = Instant.MAX;",
|
||||
"",
|
||||
" ImmutableSet.of(Collections.min(ImmutableSet.of()));",
|
||||
" }",
|
||||
"",
|
||||
" private static final class WithCustomConstant {",
|
||||
" private static final Instant MIN = Instant.EPOCH;",
|
||||
" private static final Instant OTHER = MIN;",
|
||||
" private static final Instant OTHER_MAX = Instant.MAX;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Clock.systemUTC();
|
||||
Clock.systemUTC();
|
||||
|
||||
Optional<Integer> o1 = Optional.empty();
|
||||
Optional<Integer> o2 = Optional.empty();
|
||||
|
||||
Object l1 = ImmutableList.copyOf(ImmutableList.of());
|
||||
Object l2 = ImmutableList.copyOf(ImmutableList.of());
|
||||
|
||||
Locale lo1 = Locale.ROOT;
|
||||
Locale lo2 = Locale.ROOT;
|
||||
|
||||
Instant i1 = Instant.MIN;
|
||||
Instant i2 = Instant.MAX;
|
||||
|
||||
ImmutableSet.of(Collections.min(ImmutableSet.of()));
|
||||
}
|
||||
|
||||
private static final class WithCustomConstant {
|
||||
private static final Instant MIN = Instant.EPOCH;
|
||||
private static final Instant OTHER = MIN;
|
||||
private static final Instant OTHER_MAX = Instant.MAX;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,21 +15,23 @@ final class RedundantStringConversionTest {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = o.toString();",
|
||||
"",
|
||||
" String[] m() {",
|
||||
" return new String[] {",
|
||||
" o.toString(),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s.toString(),",
|
||||
" String.valueOf(o),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.valueOf(s),",
|
||||
" };",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
private final Object o = new Object();
|
||||
private final String s = o.toString();
|
||||
|
||||
String[] m() {
|
||||
return new String[] {
|
||||
o.toString(),
|
||||
// BUG: Diagnostic contains:
|
||||
s.toString(),
|
||||
String.valueOf(o),
|
||||
// BUG: Diagnostic contains:
|
||||
String.valueOf(s),
|
||||
};
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -38,59 +40,61 @@ final class RedundantStringConversionTest {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.math.BigInteger;",
|
||||
"import java.util.Objects;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final BigInteger i = BigInteger.ZERO;",
|
||||
"",
|
||||
" void m1() {",
|
||||
" String s = i.toString();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += this.toString();",
|
||||
" s += super.toString();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += i.toString();",
|
||||
" s += i.toString(16);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Objects.toString(i);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Objects.toString(null);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += String.valueOf(i);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += String.valueOf(0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += String.valueOf((String) null);",
|
||||
" s += String.valueOf(null);",
|
||||
" s += String.valueOf(new char[0]);",
|
||||
" s += String.valueOf(new char[0], 0, 0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Boolean.toString(false);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Byte.toString((byte) 0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Character.toString((char) 0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Short.toString((short) 0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Integer.toString(0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Long.toString(0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Float.toString((float) 0.0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s += Double.toString(0.0);",
|
||||
" }",
|
||||
"",
|
||||
" void m2() {",
|
||||
" int i = 0;",
|
||||
" i += 1;",
|
||||
" i -= 1;",
|
||||
" i *= 1;",
|
||||
" i /= 1;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.math.BigInteger;
|
||||
import java.util.Objects;
|
||||
|
||||
class A {
|
||||
private final BigInteger i = BigInteger.ZERO;
|
||||
|
||||
void m1() {
|
||||
String s = i.toString();
|
||||
// BUG: Diagnostic contains:
|
||||
s += this.toString();
|
||||
s += super.toString();
|
||||
// BUG: Diagnostic contains:
|
||||
s += i.toString();
|
||||
s += i.toString(16);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Objects.toString(i);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Objects.toString(null);
|
||||
// BUG: Diagnostic contains:
|
||||
s += String.valueOf(i);
|
||||
// BUG: Diagnostic contains:
|
||||
s += String.valueOf(0);
|
||||
// BUG: Diagnostic contains:
|
||||
s += String.valueOf((String) null);
|
||||
s += String.valueOf(null);
|
||||
s += String.valueOf(new char[0]);
|
||||
s += String.valueOf(new char[0], 0, 0);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Boolean.toString(false);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Byte.toString((byte) 0);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Character.toString((char) 0);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Short.toString((short) 0);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Integer.toString(0);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Long.toString(0);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Float.toString((float) 0.0);
|
||||
// BUG: Diagnostic contains:
|
||||
s += Double.toString(0.0);
|
||||
}
|
||||
|
||||
void m2() {
|
||||
int i = 0;
|
||||
i += 1;
|
||||
i -= 1;
|
||||
i *= 1;
|
||||
i /= 1;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -99,93 +103,95 @@ final class RedundantStringConversionTest {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.math.BigInteger;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final BigInteger i = BigInteger.ZERO;",
|
||||
" private final String s = i.toString();",
|
||||
"",
|
||||
" String[] m1() {",
|
||||
" return new String[] {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + this.toString(),",
|
||||
" s + super.toString(),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + i.toString(),",
|
||||
" s + i.toString(16),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + String.valueOf(i),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + String.valueOf(0),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + String.valueOf((String) null),",
|
||||
" s + String.valueOf(null),",
|
||||
" s + String.valueOf(new char[0]),",
|
||||
" s + String.valueOf(new char[0], 0, 0),",
|
||||
" //",
|
||||
" 42 + this.toString(),",
|
||||
" 42 + super.toString(),",
|
||||
" 42 + i.toString(),",
|
||||
" 42 + i.toString(16),",
|
||||
" 42 + String.valueOf(i),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" 42 + String.valueOf((String) null),",
|
||||
" 42 + String.valueOf(null),",
|
||||
" 42 + String.valueOf(new char[0]),",
|
||||
" 42 + String.valueOf(new char[0], 0, 0),",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.toString() + s,",
|
||||
" super.toString() + s,",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" i.toString() + s,",
|
||||
" i.toString(16) + s,",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.valueOf(i) + s,",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.valueOf(0) + s,",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.valueOf((String) null) + s,",
|
||||
" String.valueOf(null) + s,",
|
||||
" String.valueOf(new char[0]) + s,",
|
||||
" String.valueOf(new char[0], 0, 0) + s,",
|
||||
" //",
|
||||
" this.toString() + 42,",
|
||||
" super.toString() + 42,",
|
||||
" i.toString() + 42,",
|
||||
" i.toString(16) + 42,",
|
||||
" String.valueOf(i) + 42,",
|
||||
" String.valueOf(0) + 42,",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.valueOf((String) null) + 42,",
|
||||
" String.valueOf(null) + 42,",
|
||||
" String.valueOf(new char[0]) + 42,",
|
||||
" String.valueOf(new char[0], 0, 0) + 42,",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.toString() + this.toString(),",
|
||||
" super.toString() + super.toString(),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" i.toString() + i.toString(),",
|
||||
" i.toString(16) + i.toString(16),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.valueOf(i) + String.valueOf(i),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.valueOf(0) + String.valueOf(0),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.valueOf((String) null) + String.valueOf((String) null),",
|
||||
" String.valueOf(null) + String.valueOf(null),",
|
||||
" String.valueOf(new char[0]) + String.valueOf(new char[0]),",
|
||||
" String.valueOf(new char[0], 0, 0) + String.valueOf(new char[0], 0, 0),",
|
||||
" };",
|
||||
" }",
|
||||
"",
|
||||
" int[] m2() {",
|
||||
" return new int[] {",
|
||||
" 1 + 1, 1 - 1, 1 * 1, 1 / 1,",
|
||||
" };",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.math.BigInteger;
|
||||
|
||||
class A {
|
||||
private final BigInteger i = BigInteger.ZERO;
|
||||
private final String s = i.toString();
|
||||
|
||||
String[] m1() {
|
||||
return new String[] {
|
||||
// BUG: Diagnostic contains:
|
||||
s + this.toString(),
|
||||
s + super.toString(),
|
||||
// BUG: Diagnostic contains:
|
||||
s + i.toString(),
|
||||
s + i.toString(16),
|
||||
// BUG: Diagnostic contains:
|
||||
s + String.valueOf(i),
|
||||
// BUG: Diagnostic contains:
|
||||
s + String.valueOf(0),
|
||||
// BUG: Diagnostic contains:
|
||||
s + String.valueOf((String) null),
|
||||
s + String.valueOf(null),
|
||||
s + String.valueOf(new char[0]),
|
||||
s + String.valueOf(new char[0], 0, 0),
|
||||
//
|
||||
42 + this.toString(),
|
||||
42 + super.toString(),
|
||||
42 + i.toString(),
|
||||
42 + i.toString(16),
|
||||
42 + String.valueOf(i),
|
||||
// BUG: Diagnostic contains:
|
||||
42 + String.valueOf((String) null),
|
||||
42 + String.valueOf(null),
|
||||
42 + String.valueOf(new char[0]),
|
||||
42 + String.valueOf(new char[0], 0, 0),
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
this.toString() + s,
|
||||
super.toString() + s,
|
||||
// BUG: Diagnostic contains:
|
||||
i.toString() + s,
|
||||
i.toString(16) + s,
|
||||
// BUG: Diagnostic contains:
|
||||
String.valueOf(i) + s,
|
||||
// BUG: Diagnostic contains:
|
||||
String.valueOf(0) + s,
|
||||
// BUG: Diagnostic contains:
|
||||
String.valueOf((String) null) + s,
|
||||
String.valueOf(null) + s,
|
||||
String.valueOf(new char[0]) + s,
|
||||
String.valueOf(new char[0], 0, 0) + s,
|
||||
//
|
||||
this.toString() + 42,
|
||||
super.toString() + 42,
|
||||
i.toString() + 42,
|
||||
i.toString(16) + 42,
|
||||
String.valueOf(i) + 42,
|
||||
String.valueOf(0) + 42,
|
||||
// BUG: Diagnostic contains:
|
||||
String.valueOf((String) null) + 42,
|
||||
String.valueOf(null) + 42,
|
||||
String.valueOf(new char[0]) + 42,
|
||||
String.valueOf(new char[0], 0, 0) + 42,
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
this.toString() + this.toString(),
|
||||
super.toString() + super.toString(),
|
||||
// BUG: Diagnostic contains:
|
||||
i.toString() + i.toString(),
|
||||
i.toString(16) + i.toString(16),
|
||||
// BUG: Diagnostic contains:
|
||||
String.valueOf(i) + String.valueOf(i),
|
||||
// BUG: Diagnostic contains:
|
||||
String.valueOf(0) + String.valueOf(0),
|
||||
// BUG: Diagnostic contains:
|
||||
String.valueOf((String) null) + String.valueOf((String) null),
|
||||
String.valueOf(null) + String.valueOf(null),
|
||||
String.valueOf(new char[0]) + String.valueOf(new char[0]),
|
||||
String.valueOf(new char[0], 0, 0) + String.valueOf(new char[0], 0, 0),
|
||||
};
|
||||
}
|
||||
|
||||
int[] m2() {
|
||||
return new int[] {
|
||||
1 + 1, 1 - 1, 1 * 1, 1 / 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -194,52 +200,54 @@ final class RedundantStringConversionTest {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.math.BigInteger;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final BigInteger i = BigInteger.ZERO;",
|
||||
" private final String s = i.toString();",
|
||||
"",
|
||||
" void m() {",
|
||||
" StringBuilder sb = new StringBuilder();",
|
||||
"",
|
||||
" sb.append(1);",
|
||||
" sb.append(i);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" sb.append(i.toString());",
|
||||
" sb.append(i.toString(16));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" sb.append(String.valueOf(i));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" sb.append(String.valueOf(0));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" sb.append(String.valueOf((String) null));",
|
||||
" sb.append(String.valueOf(null));",
|
||||
" sb.append(String.valueOf(new char[0]));",
|
||||
" sb.append(String.valueOf(new char[0], 0, 0));",
|
||||
" sb.append(s);",
|
||||
" sb.append(\"constant\");",
|
||||
"",
|
||||
" sb.insert(0, 1);",
|
||||
" sb.insert(0, i);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" sb.insert(0, i.toString());",
|
||||
" sb.insert(0, i.toString(16));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" sb.insert(0, String.valueOf(i));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" sb.insert(0, String.valueOf(0));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" sb.insert(0, String.valueOf((String) null));",
|
||||
" sb.insert(0, String.valueOf(null));",
|
||||
" sb.insert(0, String.valueOf(new char[0]));",
|
||||
" sb.insert(0, String.valueOf(new char[0], 0, 0));",
|
||||
" sb.insert(0, s);",
|
||||
" sb.insert(0, \"constant\");",
|
||||
"",
|
||||
" sb.replace(0, 1, i.toString());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.math.BigInteger;
|
||||
|
||||
class A {
|
||||
private final BigInteger i = BigInteger.ZERO;
|
||||
private final String s = i.toString();
|
||||
|
||||
void m() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(1);
|
||||
sb.append(i);
|
||||
// BUG: Diagnostic contains:
|
||||
sb.append(i.toString());
|
||||
sb.append(i.toString(16));
|
||||
// BUG: Diagnostic contains:
|
||||
sb.append(String.valueOf(i));
|
||||
// BUG: Diagnostic contains:
|
||||
sb.append(String.valueOf(0));
|
||||
// BUG: Diagnostic contains:
|
||||
sb.append(String.valueOf((String) null));
|
||||
sb.append(String.valueOf(null));
|
||||
sb.append(String.valueOf(new char[0]));
|
||||
sb.append(String.valueOf(new char[0], 0, 0));
|
||||
sb.append(s);
|
||||
sb.append("constant");
|
||||
|
||||
sb.insert(0, 1);
|
||||
sb.insert(0, i);
|
||||
// BUG: Diagnostic contains:
|
||||
sb.insert(0, i.toString());
|
||||
sb.insert(0, i.toString(16));
|
||||
// BUG: Diagnostic contains:
|
||||
sb.insert(0, String.valueOf(i));
|
||||
// BUG: Diagnostic contains:
|
||||
sb.insert(0, String.valueOf(0));
|
||||
// BUG: Diagnostic contains:
|
||||
sb.insert(0, String.valueOf((String) null));
|
||||
sb.insert(0, String.valueOf(null));
|
||||
sb.insert(0, String.valueOf(new char[0]));
|
||||
sb.insert(0, String.valueOf(new char[0], 0, 0));
|
||||
sb.insert(0, s);
|
||||
sb.insert(0, "constant");
|
||||
|
||||
sb.replace(0, 1, i.toString());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -249,43 +257,45 @@ final class RedundantStringConversionTest {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Formattable;",
|
||||
"import java.util.Locale;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final Locale locale = Locale.ROOT;",
|
||||
" private final Formattable f = (formatter, flags, width, precision) -> {};",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = o.toString();",
|
||||
"",
|
||||
" void m() {",
|
||||
" String.format(s, f);",
|
||||
" String.format(s, o);",
|
||||
" String.format(s, s);",
|
||||
" String.format(s, f.toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(s, o.toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(s, String.valueOf(o));",
|
||||
"",
|
||||
" String.format(locale, s, f);",
|
||||
" String.format(locale, s, o);",
|
||||
" String.format(locale, s, s);",
|
||||
" String.format(locale, s, f.toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(locale, s, o.toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(locale, s, String.valueOf(o));",
|
||||
"",
|
||||
" String.format(o.toString(), o);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(s.toString(), o);",
|
||||
" String.format(locale.toString(), s, o);",
|
||||
" String.format(locale, o.toString(), o);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" String.format(locale, s.toString(), o);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.Formattable;
|
||||
import java.util.Locale;
|
||||
|
||||
class A {
|
||||
private final Locale locale = Locale.ROOT;
|
||||
private final Formattable f = (formatter, flags, width, precision) -> {};
|
||||
private final Object o = new Object();
|
||||
private final String s = o.toString();
|
||||
|
||||
void m() {
|
||||
String.format(s, f);
|
||||
String.format(s, o);
|
||||
String.format(s, s);
|
||||
String.format(s, f.toString());
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(s, o.toString());
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(s, String.valueOf(o));
|
||||
|
||||
String.format(locale, s, f);
|
||||
String.format(locale, s, o);
|
||||
String.format(locale, s, s);
|
||||
String.format(locale, s, f.toString());
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(locale, s, o.toString());
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(locale, s, String.valueOf(o));
|
||||
|
||||
String.format(o.toString(), o);
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(s.toString(), o);
|
||||
String.format(locale.toString(), s, o);
|
||||
String.format(locale, o.toString(), o);
|
||||
// BUG: Diagnostic contains:
|
||||
String.format(locale, s.toString(), o);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -294,58 +304,60 @@ final class RedundantStringConversionTest {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
"import static com.google.common.base.Preconditions.checkNotNull;",
|
||||
"import static com.google.common.base.Preconditions.checkState;",
|
||||
"import static com.google.common.base.Verify.verify;",
|
||||
"import static com.google.common.base.Verify.verifyNotNull;",
|
||||
"",
|
||||
"import java.util.Formattable;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final Formattable f = (formatter, flags, width, precision) -> {};",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = o.toString();",
|
||||
"",
|
||||
" void m() {",
|
||||
" checkState(true, s, f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkState(true, s, f.toString());",
|
||||
" checkState(true, f.toString(), f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkState(true, s.toString(), f);",
|
||||
"",
|
||||
" checkArgument(true, s, f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkArgument(true, s, f.toString());",
|
||||
" checkArgument(true, f.toString(), f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkArgument(true, s.toString(), f);",
|
||||
"",
|
||||
" checkNotNull(o, s, f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkNotNull(o, s, f.toString());",
|
||||
" checkNotNull(o, f.toString(), f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" checkNotNull(o, s.toString(), f);",
|
||||
" checkNotNull(o.toString(), s, f);",
|
||||
"",
|
||||
" verify(true, s, f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" verify(true, s, f.toString());",
|
||||
" verify(true, f.toString(), f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" verify(true, s.toString(), f);",
|
||||
"",
|
||||
" verifyNotNull(o, s, f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" verifyNotNull(o, s, f.toString());",
|
||||
" verifyNotNull(o, f.toString(), f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" verifyNotNull(o, s.toString(), f);",
|
||||
" verifyNotNull(o.toString(), s, f);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static com.google.common.base.Verify.verifyNotNull;
|
||||
|
||||
import java.util.Formattable;
|
||||
|
||||
class A {
|
||||
private final Formattable f = (formatter, flags, width, precision) -> {};
|
||||
private final Object o = new Object();
|
||||
private final String s = o.toString();
|
||||
|
||||
void m() {
|
||||
checkState(true, s, f);
|
||||
// BUG: Diagnostic contains:
|
||||
checkState(true, s, f.toString());
|
||||
checkState(true, f.toString(), f);
|
||||
// BUG: Diagnostic contains:
|
||||
checkState(true, s.toString(), f);
|
||||
|
||||
checkArgument(true, s, f);
|
||||
// BUG: Diagnostic contains:
|
||||
checkArgument(true, s, f.toString());
|
||||
checkArgument(true, f.toString(), f);
|
||||
// BUG: Diagnostic contains:
|
||||
checkArgument(true, s.toString(), f);
|
||||
|
||||
checkNotNull(o, s, f);
|
||||
// BUG: Diagnostic contains:
|
||||
checkNotNull(o, s, f.toString());
|
||||
checkNotNull(o, f.toString(), f);
|
||||
// BUG: Diagnostic contains:
|
||||
checkNotNull(o, s.toString(), f);
|
||||
checkNotNull(o.toString(), s, f);
|
||||
|
||||
verify(true, s, f);
|
||||
// BUG: Diagnostic contains:
|
||||
verify(true, s, f.toString());
|
||||
verify(true, f.toString(), f);
|
||||
// BUG: Diagnostic contains:
|
||||
verify(true, s.toString(), f);
|
||||
|
||||
verifyNotNull(o, s, f);
|
||||
// BUG: Diagnostic contains:
|
||||
verifyNotNull(o, s, f.toString());
|
||||
verifyNotNull(o, f.toString(), f);
|
||||
// BUG: Diagnostic contains:
|
||||
verifyNotNull(o, s.toString(), f);
|
||||
verifyNotNull(o.toString(), s, f);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -354,53 +366,55 @@ final class RedundantStringConversionTest {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Formattable;",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"import org.slf4j.MarkerFactory;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
"",
|
||||
" private final Marker marker = MarkerFactory.getMarker(A.class.getName());",
|
||||
" private final Formattable f = (formatter, flags, width, precision) -> {};",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = f.toString();",
|
||||
" private final Throwable t = new Throwable();",
|
||||
"",
|
||||
" void m() {",
|
||||
" LOG.trace(s, f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(s, f.toString());",
|
||||
" LOG.info(s, t.toString());",
|
||||
" LOG.warn(s, o, t.toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.error(s, o.toString(), t.toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace(s, t.toString(), o);",
|
||||
"",
|
||||
" LOG.trace(marker, s, f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(marker, s, f.toString());",
|
||||
" LOG.info(marker, s, t.toString());",
|
||||
" LOG.warn(marker, s, o, t.toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.error(marker, s, o.toString(), t.toString());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace(marker, s, t.toString(), o);",
|
||||
"",
|
||||
" LOG.trace(f.toString(), f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(s.toString(), f);",
|
||||
" LOG.info(t.toString(), f);",
|
||||
" LOG.warn(marker.toString(), s, f);",
|
||||
" LOG.error(marker, o.toString(), f);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace(marker, s.toString(), f);",
|
||||
" LOG.debug(marker, t.toString(), f);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.Formattable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
|
||||
class A {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(A.class);
|
||||
|
||||
private final Marker marker = MarkerFactory.getMarker(A.class.getName());
|
||||
private final Formattable f = (formatter, flags, width, precision) -> {};
|
||||
private final Object o = new Object();
|
||||
private final String s = f.toString();
|
||||
private final Throwable t = new Throwable();
|
||||
|
||||
void m() {
|
||||
LOG.trace(s, f);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug(s, f.toString());
|
||||
LOG.info(s, t.toString());
|
||||
LOG.warn(s, o, t.toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.error(s, o.toString(), t.toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace(s, t.toString(), o);
|
||||
|
||||
LOG.trace(marker, s, f);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug(marker, s, f.toString());
|
||||
LOG.info(marker, s, t.toString());
|
||||
LOG.warn(marker, s, o, t.toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.error(marker, s, o.toString(), t.toString());
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace(marker, s, t.toString(), o);
|
||||
|
||||
LOG.trace(f.toString(), f);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug(s.toString(), f);
|
||||
LOG.info(t.toString(), f);
|
||||
LOG.warn(marker.toString(), s, f);
|
||||
LOG.error(marker, o.toString(), f);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace(marker, s.toString(), f);
|
||||
LOG.debug(marker, t.toString(), f);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -412,91 +426,93 @@ final class RedundantStringConversionTest {
|
||||
"-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)"))
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.math.RoundingMode;",
|
||||
"import java.util.Objects;",
|
||||
"",
|
||||
"class A {",
|
||||
" static class B {",
|
||||
" String name() {",
|
||||
" return toString();",
|
||||
" }",
|
||||
"",
|
||||
" static String toString(int i) {",
|
||||
" return Integer.toString(i);",
|
||||
" }",
|
||||
"",
|
||||
" static String toString(int i, int j) {",
|
||||
" return Integer.toString(i * j);",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" enum E {",
|
||||
" ELEM;",
|
||||
"",
|
||||
" public String toString() {",
|
||||
" return \"__\" + name() + \"__\";",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" private final B b = new B();",
|
||||
" private final String s = b.toString();",
|
||||
"",
|
||||
" String[] builtin() {",
|
||||
" return new String[] {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + b.toString(),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Objects.toString(b),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + String.valueOf(b),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Boolean.toString(false),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Byte.toString((byte) 0),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Character.toString((char) 0),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Short.toString((short) 0),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Integer.toString(0),",
|
||||
" s + Integer.toString(0, 16),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Long.toString(0),",
|
||||
" s + Long.toString(0, 16),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Float.toString((float) 0.0),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + Double.toString(0.0),",
|
||||
" };",
|
||||
" }",
|
||||
"",
|
||||
" String[] custom() {",
|
||||
" return new String[] {",
|
||||
" s + b.name(),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + RoundingMode.UP.name(),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + mode().name(),",
|
||||
" s + A.name(),",
|
||||
" s + A.toString(42),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" s + B.toString(42),",
|
||||
" s + B.toString(42, 42),",
|
||||
" };",
|
||||
" }",
|
||||
"",
|
||||
" static String name() {",
|
||||
" return A.class.toString();",
|
||||
" }",
|
||||
"",
|
||||
" RoundingMode mode() {",
|
||||
" return RoundingMode.UP;",
|
||||
" }",
|
||||
"",
|
||||
" static String toString(int i) {",
|
||||
" return Integer.toString(i);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Objects;
|
||||
|
||||
class A {
|
||||
static class B {
|
||||
String name() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
static String toString(int i) {
|
||||
return Integer.toString(i);
|
||||
}
|
||||
|
||||
static String toString(int i, int j) {
|
||||
return Integer.toString(i * j);
|
||||
}
|
||||
}
|
||||
|
||||
enum E {
|
||||
ELEM;
|
||||
|
||||
public String toString() {
|
||||
return "__" + name() + "__";
|
||||
}
|
||||
}
|
||||
|
||||
private final B b = new B();
|
||||
private final String s = b.toString();
|
||||
|
||||
String[] builtin() {
|
||||
return new String[] {
|
||||
// BUG: Diagnostic contains:
|
||||
s + b.toString(),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Objects.toString(b),
|
||||
// BUG: Diagnostic contains:
|
||||
s + String.valueOf(b),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Boolean.toString(false),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Byte.toString((byte) 0),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Character.toString((char) 0),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Short.toString((short) 0),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Integer.toString(0),
|
||||
s + Integer.toString(0, 16),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Long.toString(0),
|
||||
s + Long.toString(0, 16),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Float.toString((float) 0.0),
|
||||
// BUG: Diagnostic contains:
|
||||
s + Double.toString(0.0),
|
||||
};
|
||||
}
|
||||
|
||||
String[] custom() {
|
||||
return new String[] {
|
||||
s + b.name(),
|
||||
// BUG: Diagnostic contains:
|
||||
s + RoundingMode.UP.name(),
|
||||
// BUG: Diagnostic contains:
|
||||
s + mode().name(),
|
||||
s + A.name(),
|
||||
s + A.toString(42),
|
||||
// BUG: Diagnostic contains:
|
||||
s + B.toString(42),
|
||||
s + B.toString(42, 42),
|
||||
};
|
||||
}
|
||||
|
||||
static String name() {
|
||||
return A.class.toString();
|
||||
}
|
||||
|
||||
RoundingMode mode() {
|
||||
return RoundingMode.UP;
|
||||
}
|
||||
|
||||
static String toString(int i) {
|
||||
return Integer.toString(i);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -505,32 +521,36 @@ final class RedundantStringConversionTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = o.toString();",
|
||||
"",
|
||||
" void m() {",
|
||||
" String v1 = s.toString();",
|
||||
" String v2 = \"foo\".toString();",
|
||||
" String v3 = v2 + super.toString();",
|
||||
" String v4 = 42 + String.valueOf((String) null);",
|
||||
" String.format(\"%s\", o.toString());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
private final Object o = new Object();
|
||||
private final String s = o.toString();
|
||||
|
||||
void m() {
|
||||
String v1 = s.toString();
|
||||
String v2 = "foo".toString();
|
||||
String v3 = v2 + super.toString();
|
||||
String v4 = 42 + String.valueOf((String) null);
|
||||
String.format("%s", o.toString());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = o.toString();",
|
||||
"",
|
||||
" void m() {",
|
||||
" String v1 = s;",
|
||||
" String v2 = \"foo\";",
|
||||
" String v3 = v2 + super.toString();",
|
||||
" String v4 = 42 + (String) null;",
|
||||
" String.format(\"%s\", o);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
private final Object o = new Object();
|
||||
private final String s = o.toString();
|
||||
|
||||
void m() {
|
||||
String v1 = s;
|
||||
String v2 = "foo";
|
||||
String v3 = v2 + super.toString();
|
||||
String v4 = 42 + (String) null;
|
||||
String.format("%s", o);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,23 +11,25 @@ final class RefasterAnyOfUsageTest {
|
||||
CompilationTestHelper.newInstance(RefasterAnyOfUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"",
|
||||
"class A {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Refaster.anyOf();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" return Refaster.anyOf(str);",
|
||||
" }",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" Object before2(String str, Object obj) {",
|
||||
" return Refaster.anyOf(str, obj);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
|
||||
class A {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
// BUG: Diagnostic contains:
|
||||
Refaster.anyOf();
|
||||
// BUG: Diagnostic contains:
|
||||
return Refaster.anyOf(str);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
Object before2(String str, Object obj) {
|
||||
return Refaster.anyOf(str, obj);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -36,28 +38,32 @@ final class RefasterAnyOfUsageTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterAnyOfUsage.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"",
|
||||
"class A {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" Refaster.anyOf();",
|
||||
" return Refaster.anyOf(str);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
|
||||
class A {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
Refaster.anyOf();
|
||||
return Refaster.anyOf(str);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.Refaster;",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"",
|
||||
"class A {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" Refaster.anyOf();",
|
||||
" return str;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
|
||||
class A {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
Refaster.anyOf();
|
||||
return str;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,121 +11,129 @@ final class RefasterRuleModifiersTest {
|
||||
CompilationTestHelper.newInstance(RefasterRuleModifiers.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"",
|
||||
"final class A {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"",
|
||||
" String nonRefasterMethod(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"",
|
||||
" static final class Inner {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
|
||||
final class A {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
String nonRefasterMethod(String str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
static final class Inner {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"B.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"import com.google.errorprone.refaster.annotation.Placeholder;",
|
||||
"",
|
||||
"abstract class B<I, O> {",
|
||||
" @Placeholder",
|
||||
" abstract O someFunction(I input);",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" String before(I input) {",
|
||||
" return String.valueOf(someFunction(input));",
|
||||
" }",
|
||||
"",
|
||||
" abstract static class Inner<I, O> {",
|
||||
" @Placeholder",
|
||||
" abstract O someFunction(I input);",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" String before(I input) {",
|
||||
" return String.valueOf(someFunction(input));",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
|
||||
abstract class B<I, O> {
|
||||
@Placeholder
|
||||
abstract O someFunction(I input);
|
||||
|
||||
@BeforeTemplate
|
||||
String before(I input) {
|
||||
return String.valueOf(someFunction(input));
|
||||
}
|
||||
|
||||
abstract static class Inner<I, O> {
|
||||
@Placeholder
|
||||
abstract O someFunction(I input);
|
||||
|
||||
@BeforeTemplate
|
||||
String before(I input) {
|
||||
return String.valueOf(someFunction(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"C.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"class C {",
|
||||
" @BeforeTemplate",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" final String beforeFinal(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private String beforePrivate(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" public String beforePublic(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" static String beforeStatic(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" synchronized String beforeSynchronized(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" abstract static class AbstractInner {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" static class NonFinalInner {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" final class NonStaticInner {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
class C {
|
||||
@BeforeTemplate
|
||||
// BUG: Diagnostic contains:
|
||||
final String beforeFinal(String str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
// BUG: Diagnostic contains:
|
||||
private String beforePrivate(String str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
// BUG: Diagnostic contains:
|
||||
public String beforePublic(String str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
// BUG: Diagnostic contains:
|
||||
static String beforeStatic(String str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
// BUG: Diagnostic contains:
|
||||
synchronized String beforeSynchronized(String str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
abstract static class AbstractInner {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
static class NonFinalInner {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
final class NonStaticInner {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"D.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"abstract class D {",
|
||||
" @BeforeTemplate",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" protected String beforeProtected(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
abstract class D {
|
||||
@BeforeTemplate
|
||||
// BUG: Diagnostic contains:
|
||||
protected String beforeProtected(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -134,70 +142,78 @@ final class RefasterRuleModifiersTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterRuleModifiers.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"",
|
||||
"class A {",
|
||||
" @BeforeTemplate",
|
||||
" private static String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
|
||||
class A {
|
||||
@BeforeTemplate
|
||||
private static String before(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"",
|
||||
"final class A {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
|
||||
final class A {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addInputLines(
|
||||
"B.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"import com.google.errorprone.refaster.annotation.Placeholder;",
|
||||
"",
|
||||
"final class B {",
|
||||
" abstract class WithoutPlaceholder {",
|
||||
" @BeforeTemplate",
|
||||
" protected synchronized String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" abstract class WithPlaceholder<I, O> {",
|
||||
" @Placeholder",
|
||||
" public abstract O someFunction(I input);",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" public final String before(I input) {",
|
||||
" return String.valueOf(someFunction(input));",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
|
||||
final class B {
|
||||
abstract class WithoutPlaceholder {
|
||||
@BeforeTemplate
|
||||
protected synchronized String before(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class WithPlaceholder<I, O> {
|
||||
@Placeholder
|
||||
public abstract O someFunction(I input);
|
||||
|
||||
@BeforeTemplate
|
||||
public final String before(I input) {
|
||||
return String.valueOf(someFunction(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"B.java",
|
||||
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
|
||||
"import com.google.errorprone.refaster.annotation.Placeholder;",
|
||||
"",
|
||||
"final class B {",
|
||||
" static final class WithoutPlaceholder {",
|
||||
" @BeforeTemplate",
|
||||
" String before(String str) {",
|
||||
" return str;",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" abstract static class WithPlaceholder<I, O> {",
|
||||
" @Placeholder",
|
||||
" abstract O someFunction(I input);",
|
||||
"",
|
||||
" @BeforeTemplate",
|
||||
" String before(I input) {",
|
||||
" return String.valueOf(someFunction(input));",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
|
||||
final class B {
|
||||
static final class WithoutPlaceholder {
|
||||
@BeforeTemplate
|
||||
String before(String str) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class WithPlaceholder<I, O> {
|
||||
@Placeholder
|
||||
abstract O someFunction(I input);
|
||||
|
||||
@BeforeTemplate
|
||||
String before(I input) {
|
||||
return String.valueOf(someFunction(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,133 +9,135 @@ final class RequestMappingAnnotationTest {
|
||||
CompilationTestHelper.newInstance(RequestMappingAnnotation.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import jakarta.servlet.http.HttpServletRequest;",
|
||||
"import jakarta.servlet.http.HttpServletResponse;",
|
||||
"import java.io.InputStream;",
|
||||
"import java.time.ZoneId;",
|
||||
"import java.util.Locale;",
|
||||
"import java.util.TimeZone;",
|
||||
"import org.springframework.http.HttpMethod;",
|
||||
"import org.springframework.ui.Model;",
|
||||
"import org.springframework.validation.BindingResult;",
|
||||
"import org.springframework.web.bind.annotation.DeleteMapping;",
|
||||
"import org.springframework.web.bind.annotation.GetMapping;",
|
||||
"import org.springframework.web.bind.annotation.PatchMapping;",
|
||||
"import org.springframework.web.bind.annotation.PathVariable;",
|
||||
"import org.springframework.web.bind.annotation.PostMapping;",
|
||||
"import org.springframework.web.bind.annotation.PutMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestAttribute;",
|
||||
"import org.springframework.web.bind.annotation.RequestBody;",
|
||||
"import org.springframework.web.bind.annotation.RequestHeader;",
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestParam;",
|
||||
"import org.springframework.web.bind.annotation.RequestPart;",
|
||||
"import org.springframework.web.context.request.NativeWebRequest;",
|
||||
"import org.springframework.web.context.request.WebRequest;",
|
||||
"import org.springframework.web.server.ServerWebExchange;",
|
||||
"import org.springframework.web.util.UriBuilder;",
|
||||
"import org.springframework.web.util.UriComponentsBuilder;",
|
||||
"",
|
||||
"interface A {",
|
||||
" A noMapping();",
|
||||
"",
|
||||
" A noMapping(String param);",
|
||||
"",
|
||||
" @DeleteMapping",
|
||||
" A properNoParameters();",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A properPathVariable(@PathVariable String param);",
|
||||
"",
|
||||
" @PatchMapping",
|
||||
" A properRequestAttribute(@RequestAttribute String attribute);",
|
||||
"",
|
||||
" @PostMapping",
|
||||
" A properRequestBody(@RequestBody String body);",
|
||||
"",
|
||||
" @PutMapping",
|
||||
" A properRequestHeader(@RequestHeader String header);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properRequestParam(@RequestParam String param);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properRequestPart(@RequestPart String part);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properInputStream(InputStream input);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properZoneId(ZoneId zoneId);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properLocale(Locale locale);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properTimeZone(TimeZone timeZone);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properHttpServletRequest(HttpServletRequest request);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properHttpServletResponse(HttpServletResponse response);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properHttpMethod(HttpMethod method);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properModel(Model model);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properBindingResult(BindingResult result);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properNativeWebRequest(NativeWebRequest request);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properWebRequest(WebRequest request);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properServerWebExchange(ServerWebExchange exchange);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properServerUriBuilder(UriBuilder builder);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" A properServerUriComponentsBuilder(UriComponentsBuilder builder);",
|
||||
"",
|
||||
" @DeleteMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A delete(String param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A get(String param);",
|
||||
"",
|
||||
" @PatchMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A patch(String param);",
|
||||
"",
|
||||
" @PostMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A post(String param);",
|
||||
"",
|
||||
" @PutMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A put(String param);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A requestMultiple(String param, String param2);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A requestFirstParamViolation(String param, @PathVariable String param2);",
|
||||
"",
|
||||
" @RequestMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A requestSecondParamViolation(@RequestBody String param, String param2);",
|
||||
"}")
|
||||
"""
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.util.UriBuilder;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
interface A {
|
||||
A noMapping();
|
||||
|
||||
A noMapping(String param);
|
||||
|
||||
@DeleteMapping
|
||||
A properNoParameters();
|
||||
|
||||
@GetMapping
|
||||
A properPathVariable(@PathVariable String param);
|
||||
|
||||
@PatchMapping
|
||||
A properRequestAttribute(@RequestAttribute String attribute);
|
||||
|
||||
@PostMapping
|
||||
A properRequestBody(@RequestBody String body);
|
||||
|
||||
@PutMapping
|
||||
A properRequestHeader(@RequestHeader String header);
|
||||
|
||||
@RequestMapping
|
||||
A properRequestParam(@RequestParam String param);
|
||||
|
||||
@RequestMapping
|
||||
A properRequestPart(@RequestPart String part);
|
||||
|
||||
@RequestMapping
|
||||
A properInputStream(InputStream input);
|
||||
|
||||
@RequestMapping
|
||||
A properZoneId(ZoneId zoneId);
|
||||
|
||||
@RequestMapping
|
||||
A properLocale(Locale locale);
|
||||
|
||||
@RequestMapping
|
||||
A properTimeZone(TimeZone timeZone);
|
||||
|
||||
@RequestMapping
|
||||
A properHttpServletRequest(HttpServletRequest request);
|
||||
|
||||
@RequestMapping
|
||||
A properHttpServletResponse(HttpServletResponse response);
|
||||
|
||||
@RequestMapping
|
||||
A properHttpMethod(HttpMethod method);
|
||||
|
||||
@RequestMapping
|
||||
A properModel(Model model);
|
||||
|
||||
@RequestMapping
|
||||
A properBindingResult(BindingResult result);
|
||||
|
||||
@RequestMapping
|
||||
A properNativeWebRequest(NativeWebRequest request);
|
||||
|
||||
@RequestMapping
|
||||
A properWebRequest(WebRequest request);
|
||||
|
||||
@RequestMapping
|
||||
A properServerWebExchange(ServerWebExchange exchange);
|
||||
|
||||
@RequestMapping
|
||||
A properServerUriBuilder(UriBuilder builder);
|
||||
|
||||
@RequestMapping
|
||||
A properServerUriComponentsBuilder(UriComponentsBuilder builder);
|
||||
|
||||
@DeleteMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A delete(String param);
|
||||
|
||||
@GetMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A get(String param);
|
||||
|
||||
@PatchMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A patch(String param);
|
||||
|
||||
@PostMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A post(String param);
|
||||
|
||||
@PutMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A put(String param);
|
||||
|
||||
@RequestMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A requestMultiple(String param, String param2);
|
||||
|
||||
@RequestMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A requestFirstParamViolation(String param, @PathVariable String param2);
|
||||
|
||||
@RequestMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A requestSecondParamViolation(@RequestBody String param, String param2);
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,55 +9,57 @@ final class RequestParamTypeTest {
|
||||
CompilationTestHelper.newInstance(RequestParamType.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableBiMap;",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableMap;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Map;",
|
||||
"import java.util.Set;",
|
||||
"import org.jspecify.annotations.Nullable;",
|
||||
"import org.springframework.web.bind.annotation.DeleteMapping;",
|
||||
"import org.springframework.web.bind.annotation.GetMapping;",
|
||||
"import org.springframework.web.bind.annotation.PostMapping;",
|
||||
"import org.springframework.web.bind.annotation.PutMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestBody;",
|
||||
"import org.springframework.web.bind.annotation.RequestParam;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @PostMapping",
|
||||
" A properRequestParam(@RequestBody String body);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A properRequestParam(@RequestParam int param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A properRequestParam(@RequestParam List<String> param);",
|
||||
"",
|
||||
" @PostMapping",
|
||||
" A properRequestParam(@RequestBody String body, @RequestParam Set<String> param);",
|
||||
"",
|
||||
" @PutMapping",
|
||||
" A properRequestParam(@RequestBody String body, @RequestParam Map<String, String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A get(@RequestParam ImmutableBiMap<String, String> param);",
|
||||
"",
|
||||
" @PostMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A post(@Nullable @RequestParam ImmutableList<String> param);",
|
||||
"",
|
||||
" @PutMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A put(@RequestBody String body, @RequestParam ImmutableSet<String> param);",
|
||||
"",
|
||||
" @DeleteMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A delete(@RequestBody String body, @RequestParam ImmutableMap<String, String> param);",
|
||||
"",
|
||||
" void negative(ImmutableSet<Integer> set, ImmutableMap<String, String> map);",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
interface A {
|
||||
@PostMapping
|
||||
A properRequestParam(@RequestBody String body);
|
||||
|
||||
@GetMapping
|
||||
A properRequestParam(@RequestParam int param);
|
||||
|
||||
@GetMapping
|
||||
A properRequestParam(@RequestParam List<String> param);
|
||||
|
||||
@PostMapping
|
||||
A properRequestParam(@RequestBody String body, @RequestParam Set<String> param);
|
||||
|
||||
@PutMapping
|
||||
A properRequestParam(@RequestBody String body, @RequestParam Map<String, String> param);
|
||||
|
||||
@GetMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A get(@RequestParam ImmutableBiMap<String, String> param);
|
||||
|
||||
@PostMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A post(@Nullable @RequestParam ImmutableList<String> param);
|
||||
|
||||
@PutMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A put(@RequestBody String body, @RequestParam ImmutableSet<String> param);
|
||||
|
||||
@DeleteMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A delete(@RequestBody String body, @RequestParam ImmutableMap<String, String> param);
|
||||
|
||||
void negative(ImmutableSet<Integer> set, ImmutableMap<String, String> map);
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -68,47 +70,49 @@ final class RequestParamTypeTest {
|
||||
"-XepOpt:RequestParamType:SupportedCustomTypes=com.google.common.collect.ImmutableSet,com.google.common.collect.ImmutableSortedMultiset")
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableBiMap;",
|
||||
"import com.google.common.collect.ImmutableCollection;",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableMap;",
|
||||
"import com.google.common.collect.ImmutableMultiset;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.common.collect.ImmutableSortedMultiset;",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
"import org.springframework.web.bind.annotation.GetMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestParam;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableCollection(@RequestParam ImmutableCollection<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableList(@RequestParam ImmutableList<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A immutableSet(@RequestParam ImmutableSet<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A immutableSortedSet(@RequestParam ImmutableSortedSet<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableMultiset(@RequestParam ImmutableMultiset<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A immutableSortedMultiset(@RequestParam ImmutableSortedMultiset<String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableMap(@RequestParam ImmutableMap<String, String> param);",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" A immutableBiMap(@RequestParam ImmutableBiMap<String, String> param);",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedMultiset;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
interface A {
|
||||
@GetMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A immutableCollection(@RequestParam ImmutableCollection<String> param);
|
||||
|
||||
@GetMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A immutableList(@RequestParam ImmutableList<String> param);
|
||||
|
||||
@GetMapping
|
||||
A immutableSet(@RequestParam ImmutableSet<String> param);
|
||||
|
||||
@GetMapping
|
||||
A immutableSortedSet(@RequestParam ImmutableSortedSet<String> param);
|
||||
|
||||
@GetMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A immutableMultiset(@RequestParam ImmutableMultiset<String> param);
|
||||
|
||||
@GetMapping
|
||||
A immutableSortedMultiset(@RequestParam ImmutableSortedMultiset<String> param);
|
||||
|
||||
@GetMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A immutableMap(@RequestParam ImmutableMap<String, String> param);
|
||||
|
||||
@GetMapping
|
||||
// BUG: Diagnostic contains:
|
||||
A immutableBiMap(@RequestParam ImmutableBiMap<String, String> param);
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,80 +11,82 @@ final class Slf4jLogStatementTest {
|
||||
CompilationTestHelper.newInstance(Slf4jLogStatement.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"import org.slf4j.MarkerFactory;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final String FMT0 = \"format-string-without-placeholders\";",
|
||||
" private static final String FMT1 = \"format-string-with-{}-placeholder\";",
|
||||
" private static final String FMT2 = \"format-string-with-{}-{}-placeholders\";",
|
||||
" private static final String FMT_ERR = \"format-string-with-%s-placeholder\";",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
"",
|
||||
" private final Marker marker = MarkerFactory.getMarker(A.class.getName());",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = o.toString();",
|
||||
" private final Throwable t = new Throwable();",
|
||||
"",
|
||||
" void m() {",
|
||||
" LOG.trace(s);",
|
||||
" LOG.debug(s, o);",
|
||||
" LOG.info(s, t);",
|
||||
" LOG.warn(s, o, t);",
|
||||
" LOG.error(marker, s);",
|
||||
" LOG.trace(marker, s, o);",
|
||||
" LOG.debug(marker, s, t);",
|
||||
" LOG.info(marker, s, o, t);",
|
||||
"",
|
||||
" LOG.warn(FMT0);",
|
||||
" // BUG: Diagnostic contains: Log statement contains 0 placeholders, but specifies 1 matching",
|
||||
" // argument(s)",
|
||||
" LOG.error(FMT0, o);",
|
||||
" LOG.trace(FMT0, t);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(FMT0, o, t);",
|
||||
" LOG.info(marker, FMT0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.warn(marker, FMT0, o);",
|
||||
" LOG.error(marker, FMT0, t);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace(marker, FMT0, o, t);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: Log statement contains 1 placeholders, but specifies 0 matching",
|
||||
" // argument(s)",
|
||||
" LOG.debug(FMT1);",
|
||||
" LOG.info(FMT1, o);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.warn(FMT1, t);",
|
||||
" LOG.error(FMT1, o, t);",
|
||||
" // BUG: Diagnostic contains: Log statement contains 1 placeholders, but specifies 2 matching",
|
||||
" // argument(s)",
|
||||
" LOG.trace(FMT1, o, o);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(FMT1, o, o, t);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.info(marker, FMT1);",
|
||||
" LOG.warn(marker, FMT1, o);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.error(marker, FMT1, t);",
|
||||
" LOG.trace(marker, FMT1, o, t);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(marker, FMT1, o, o);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.info(marker, FMT1, o, o, t);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: SLF4J log statement placeholders are of the form `{}`, not `%s`",
|
||||
" LOG.warn(FMT_ERR);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.error(FMT_ERR, t);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.trace(FMT_ERR, o);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LOG.debug(FMT_ERR, o, t);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
|
||||
class A {
|
||||
private static final String FMT0 = "format-string-without-placeholders";
|
||||
private static final String FMT1 = "format-string-with-{}-placeholder";
|
||||
private static final String FMT2 = "format-string-with-{}-{}-placeholders";
|
||||
private static final String FMT_ERR = "format-string-with-%s-placeholder";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(A.class);
|
||||
|
||||
private final Marker marker = MarkerFactory.getMarker(A.class.getName());
|
||||
private final Object o = new Object();
|
||||
private final String s = o.toString();
|
||||
private final Throwable t = new Throwable();
|
||||
|
||||
void m() {
|
||||
LOG.trace(s);
|
||||
LOG.debug(s, o);
|
||||
LOG.info(s, t);
|
||||
LOG.warn(s, o, t);
|
||||
LOG.error(marker, s);
|
||||
LOG.trace(marker, s, o);
|
||||
LOG.debug(marker, s, t);
|
||||
LOG.info(marker, s, o, t);
|
||||
|
||||
LOG.warn(FMT0);
|
||||
// BUG: Diagnostic contains: Log statement contains 0 placeholders, but specifies 1 matching
|
||||
// argument(s)
|
||||
LOG.error(FMT0, o);
|
||||
LOG.trace(FMT0, t);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug(FMT0, o, t);
|
||||
LOG.info(marker, FMT0);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.warn(marker, FMT0, o);
|
||||
LOG.error(marker, FMT0, t);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace(marker, FMT0, o, t);
|
||||
|
||||
// BUG: Diagnostic contains: Log statement contains 1 placeholders, but specifies 0 matching
|
||||
// argument(s)
|
||||
LOG.debug(FMT1);
|
||||
LOG.info(FMT1, o);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.warn(FMT1, t);
|
||||
LOG.error(FMT1, o, t);
|
||||
// BUG: Diagnostic contains: Log statement contains 1 placeholders, but specifies 2 matching
|
||||
// argument(s)
|
||||
LOG.trace(FMT1, o, o);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug(FMT1, o, o, t);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.info(marker, FMT1);
|
||||
LOG.warn(marker, FMT1, o);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.error(marker, FMT1, t);
|
||||
LOG.trace(marker, FMT1, o, t);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug(marker, FMT1, o, o);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.info(marker, FMT1, o, o, t);
|
||||
|
||||
// BUG: Diagnostic contains: SLF4J log statement placeholders are of the form `{}`, not `%s`
|
||||
LOG.warn(FMT_ERR);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.error(FMT_ERR, t);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.trace(FMT_ERR, o);
|
||||
// BUG: Diagnostic contains:
|
||||
LOG.debug(FMT_ERR, o, t);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -94,50 +96,54 @@ final class Slf4jLogStatementTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(Slf4jLogStatement.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"import org.slf4j.MarkerFactory;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final String FMT_ERR = \"format-string-with-%s-placeholder\";",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
"",
|
||||
" private final Marker marker = MarkerFactory.getMarker(A.class.getName());",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = o.toString();",
|
||||
" private final Throwable t = new Throwable();",
|
||||
"",
|
||||
" void m() {",
|
||||
" LOG.error(FMT_ERR, o);",
|
||||
" LOG.error(\"format-string-with-'%s'-placeholder\", o);",
|
||||
" LOG.error(\"format-string-with-\\\"%s\\\"-placeholder\", o);",
|
||||
" LOG.error(\"format-string-with-%s\" + \"-placeholder\", o);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
|
||||
class A {
|
||||
private static final String FMT_ERR = "format-string-with-%s-placeholder";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(A.class);
|
||||
|
||||
private final Marker marker = MarkerFactory.getMarker(A.class.getName());
|
||||
private final Object o = new Object();
|
||||
private final String s = o.toString();
|
||||
private final Throwable t = new Throwable();
|
||||
|
||||
void m() {
|
||||
LOG.error(FMT_ERR, o);
|
||||
LOG.error("format-string-with-'%s'-placeholder", o);
|
||||
LOG.error("format-string-with-\\"%s\\"-placeholder", o);
|
||||
LOG.error("format-string-with-%s" + "-placeholder", o);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"import org.slf4j.MarkerFactory;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final String FMT_ERR = \"format-string-with-%s-placeholder\";",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
"",
|
||||
" private final Marker marker = MarkerFactory.getMarker(A.class.getName());",
|
||||
" private final Object o = new Object();",
|
||||
" private final String s = o.toString();",
|
||||
" private final Throwable t = new Throwable();",
|
||||
"",
|
||||
" void m() {",
|
||||
" LOG.error(FMT_ERR, o);",
|
||||
" LOG.error(\"format-string-with-'{}'-placeholder\", o);",
|
||||
" LOG.error(\"format-string-with-\\\"{}\\\"-placeholder\", o);",
|
||||
" LOG.error(\"format-string-with-{}\" + \"-placeholder\", o);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
|
||||
class A {
|
||||
private static final String FMT_ERR = "format-string-with-%s-placeholder";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(A.class);
|
||||
|
||||
private final Marker marker = MarkerFactory.getMarker(A.class.getName());
|
||||
private final Object o = new Object();
|
||||
private final String s = o.toString();
|
||||
private final Throwable t = new Throwable();
|
||||
|
||||
void m() {
|
||||
LOG.error(FMT_ERR, o);
|
||||
LOG.error("format-string-with-'{}'-placeholder", o);
|
||||
LOG.error("format-string-with-\\"{}\\"-placeholder", o);
|
||||
LOG.error("format-string-with-{}" + "-placeholder", o);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,75 +11,77 @@ final class SpringMvcAnnotationTest {
|
||||
CompilationTestHelper.newInstance(SpringMvcAnnotation.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.DELETE;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.GET;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.HEAD;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.PATCH;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.POST;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.PUT;",
|
||||
"",
|
||||
"import org.springframework.web.bind.annotation.DeleteMapping;",
|
||||
"import org.springframework.web.bind.annotation.GetMapping;",
|
||||
"import org.springframework.web.bind.annotation.PatchMapping;",
|
||||
"import org.springframework.web.bind.annotation.PostMapping;",
|
||||
"import org.springframework.web.bind.annotation.PutMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestMethod;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @RequestMapping",
|
||||
" A simple();",
|
||||
"",
|
||||
" @RequestMapping(method = {})",
|
||||
" A explicitDefault();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @RequestMapping(method = RequestMethod.GET)",
|
||||
" A get();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @RequestMapping(method = {RequestMethod.POST})",
|
||||
" A post();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @RequestMapping(method = {PUT})",
|
||||
" A put();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @RequestMapping(method = {DELETE})",
|
||||
" A delete();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @RequestMapping(method = {PATCH})",
|
||||
" A patch();",
|
||||
"",
|
||||
" @RequestMapping(method = HEAD)",
|
||||
" A head();",
|
||||
"",
|
||||
" @RequestMapping(method = RequestMethod.OPTIONS)",
|
||||
" A options();",
|
||||
"",
|
||||
" @RequestMapping(method = {GET, POST})",
|
||||
" A simpleMix();",
|
||||
"",
|
||||
" @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})",
|
||||
" A verboseMix();",
|
||||
"",
|
||||
" @DeleteMapping",
|
||||
" A properDelete();",
|
||||
"",
|
||||
" @GetMapping",
|
||||
" A properGet();",
|
||||
"",
|
||||
" @PatchMapping",
|
||||
" A properPatch();",
|
||||
"",
|
||||
" @PostMapping",
|
||||
" A properPost();",
|
||||
"",
|
||||
" @PutMapping",
|
||||
" A properPut();",
|
||||
"}")
|
||||
"""
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.HEAD;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.PATCH;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
|
||||
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
interface A {
|
||||
@RequestMapping
|
||||
A simple();
|
||||
|
||||
@RequestMapping(method = {})
|
||||
A explicitDefault();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
A get();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@RequestMapping(method = {RequestMethod.POST})
|
||||
A post();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@RequestMapping(method = {PUT})
|
||||
A put();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@RequestMapping(method = {DELETE})
|
||||
A delete();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@RequestMapping(method = {PATCH})
|
||||
A patch();
|
||||
|
||||
@RequestMapping(method = HEAD)
|
||||
A head();
|
||||
|
||||
@RequestMapping(method = RequestMethod.OPTIONS)
|
||||
A options();
|
||||
|
||||
@RequestMapping(method = {GET, POST})
|
||||
A simpleMix();
|
||||
|
||||
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
|
||||
A verboseMix();
|
||||
|
||||
@DeleteMapping
|
||||
A properDelete();
|
||||
|
||||
@GetMapping
|
||||
A properGet();
|
||||
|
||||
@PatchMapping
|
||||
A properPatch();
|
||||
|
||||
@PostMapping
|
||||
A properPost();
|
||||
|
||||
@PutMapping
|
||||
A properPut();
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -88,66 +90,70 @@ final class SpringMvcAnnotationTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(SpringMvcAnnotation.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.PATCH;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.POST;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.PUT;",
|
||||
"",
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestMethod;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @RequestMapping(method = RequestMethod.GET)",
|
||||
" A simple();",
|
||||
"",
|
||||
" @RequestMapping(path = \"/foo/bar\", method = POST)",
|
||||
" A prefixed();",
|
||||
"",
|
||||
" @RequestMapping(",
|
||||
" method = {RequestMethod.DELETE},",
|
||||
" path = \"/foo/bar\")",
|
||||
" A suffixed();",
|
||||
"",
|
||||
" @RequestMapping(",
|
||||
" path = \"/foo/bar\",",
|
||||
" method = {PUT},",
|
||||
" consumes = {\"a\", \"b\"})",
|
||||
" A surrounded();",
|
||||
"",
|
||||
" @RequestMapping(method = {PATCH})",
|
||||
" A curly();",
|
||||
"}")
|
||||
"""
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.PATCH;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
interface A {
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
A simple();
|
||||
|
||||
@RequestMapping(path = "/foo/bar", method = POST)
|
||||
A prefixed();
|
||||
|
||||
@RequestMapping(
|
||||
method = {RequestMethod.DELETE},
|
||||
path = "/foo/bar")
|
||||
A suffixed();
|
||||
|
||||
@RequestMapping(
|
||||
path = "/foo/bar",
|
||||
method = {PUT},
|
||||
consumes = {"a", "b"})
|
||||
A surrounded();
|
||||
|
||||
@RequestMapping(method = {PATCH})
|
||||
A curly();
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.PATCH;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.POST;",
|
||||
"import static org.springframework.web.bind.annotation.RequestMethod.PUT;",
|
||||
"",
|
||||
"import org.springframework.web.bind.annotation.DeleteMapping;",
|
||||
"import org.springframework.web.bind.annotation.GetMapping;",
|
||||
"import org.springframework.web.bind.annotation.PatchMapping;",
|
||||
"import org.springframework.web.bind.annotation.PostMapping;",
|
||||
"import org.springframework.web.bind.annotation.PutMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestMapping;",
|
||||
"import org.springframework.web.bind.annotation.RequestMethod;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @GetMapping()",
|
||||
" A simple();",
|
||||
"",
|
||||
" @PostMapping(path = \"/foo/bar\")",
|
||||
" A prefixed();",
|
||||
"",
|
||||
" @DeleteMapping(path = \"/foo/bar\")",
|
||||
" A suffixed();",
|
||||
"",
|
||||
" @PutMapping(",
|
||||
" path = \"/foo/bar\",",
|
||||
" consumes = {\"a\", \"b\"})",
|
||||
" A surrounded();",
|
||||
"",
|
||||
" @PatchMapping()",
|
||||
" A curly();",
|
||||
"}")
|
||||
"""
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.PATCH;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
|
||||
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
interface A {
|
||||
@GetMapping()
|
||||
A simple();
|
||||
|
||||
@PostMapping(path = "/foo/bar")
|
||||
A prefixed();
|
||||
|
||||
@DeleteMapping(path = "/foo/bar")
|
||||
A suffixed();
|
||||
|
||||
@PutMapping(
|
||||
path = "/foo/bar",
|
||||
consumes = {"a", "b"})
|
||||
A surrounded();
|
||||
|
||||
@PatchMapping()
|
||||
A curly();
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,83 +34,85 @@ final class StaticImportTest {
|
||||
CompilationTestHelper.newInstance(StaticImport.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableMap.toImmutableMap;",
|
||||
"import static com.google.common.collect.ImmutableSet.toImmutableSet;",
|
||||
"import static java.nio.charset.StandardCharsets.UTF_8;",
|
||||
"import static java.util.function.Predicate.not;",
|
||||
"import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;",
|
||||
"",
|
||||
"import com.google.common.base.Predicates;",
|
||||
"import com.google.common.collect.ImmutableMap;",
|
||||
"import com.google.common.collect.ImmutableMultiset;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.errorprone.refaster.ImportPolicy;",
|
||||
"import com.google.errorprone.refaster.annotation.UseImportPolicy;",
|
||||
"import java.nio.charset.StandardCharsets;",
|
||||
"import java.time.ZoneOffset;",
|
||||
"import java.util.Optional;",
|
||||
"import java.util.UUID;",
|
||||
"import java.util.function.Predicate;",
|
||||
"import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;",
|
||||
"import org.springframework.http.MediaType;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableMap.toImmutableMap(v -> v, v -> v);",
|
||||
" ImmutableMap.<String, String, String>toImmutableMap(v -> v, v -> v);",
|
||||
" toImmutableMap(v -> v, v -> v);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSet.toImmutableSet();",
|
||||
" ImmutableSet.<String>toImmutableSet();",
|
||||
" toImmutableSet();",
|
||||
"",
|
||||
" // Not flagged because we define `#toImmutableMultiset` below.",
|
||||
" ImmutableMultiset.toImmutableMultiset();",
|
||||
" ImmutableMultiset.<String>toImmutableMultiset();",
|
||||
" toImmutableMultiset();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Predicate.not(null);",
|
||||
" not(null);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Predicates.alwaysTrue();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Predicates.alwaysFalse();",
|
||||
" // Not flagged because of `java.util.function.Predicate.not` import.",
|
||||
" Predicates.not(null);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" UUID uuid = UUID.randomUUID();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Object o1 = StandardCharsets.UTF_8;",
|
||||
" Object o2 = UTF_8;",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Object e1 = WebEnvironment.RANDOM_PORT;",
|
||||
" Object e2 = RANDOM_PORT;",
|
||||
"",
|
||||
" // Not flagged because `MediaType.ALL` is exempted.",
|
||||
" MediaType t1 = MediaType.ALL;",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" MediaType t2 = MediaType.APPLICATION_JSON;",
|
||||
"",
|
||||
" Optional.empty();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ZoneOffset zo1 = ZoneOffset.UTC;",
|
||||
" ZoneOffset zo2 = ZoneOffset.MIN;",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @UseImportPolicy(ImportPolicy.IMPORT_TOP_LEVEL)",
|
||||
" void refasterAfterTemplate() {}",
|
||||
"",
|
||||
" void toImmutableMultiset() {}",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableMap.toImmutableMap(v -> v, v -> v);
|
||||
ImmutableMap.<String, String, String>toImmutableMap(v -> v, v -> v);
|
||||
toImmutableMap(v -> v, v -> v);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSet.toImmutableSet();
|
||||
ImmutableSet.<String>toImmutableSet();
|
||||
toImmutableSet();
|
||||
|
||||
// Not flagged because we define `#toImmutableMultiset` below.
|
||||
ImmutableMultiset.toImmutableMultiset();
|
||||
ImmutableMultiset.<String>toImmutableMultiset();
|
||||
toImmutableMultiset();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Predicate.not(null);
|
||||
not(null);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Predicates.alwaysTrue();
|
||||
// BUG: Diagnostic contains:
|
||||
Predicates.alwaysFalse();
|
||||
// Not flagged because of `java.util.function.Predicate.not` import.
|
||||
Predicates.not(null);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Object o1 = StandardCharsets.UTF_8;
|
||||
Object o2 = UTF_8;
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Object e1 = WebEnvironment.RANDOM_PORT;
|
||||
Object e2 = RANDOM_PORT;
|
||||
|
||||
// Not flagged because `MediaType.ALL` is exempted.
|
||||
MediaType t1 = MediaType.ALL;
|
||||
// BUG: Diagnostic contains:
|
||||
MediaType t2 = MediaType.APPLICATION_JSON;
|
||||
|
||||
Optional.empty();
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
ZoneOffset zo1 = ZoneOffset.UTC;
|
||||
ZoneOffset zo2 = ZoneOffset.MIN;
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@UseImportPolicy(ImportPolicy.IMPORT_TOP_LEVEL)
|
||||
void refasterAfterTemplate() {}
|
||||
|
||||
void toImmutableMultiset() {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -119,154 +121,158 @@ final class StaticImportTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(StaticImport.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.function.Predicate.not;",
|
||||
"",
|
||||
"import com.google.common.base.Predicates;",
|
||||
"import com.google.common.collect.ImmutableMap;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.errorprone.BugPattern;",
|
||||
"import com.google.errorprone.BugPattern.SeverityLevel;",
|
||||
"import java.nio.charset.StandardCharsets;",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.Collections;",
|
||||
"import java.util.Objects;",
|
||||
"import java.util.regex.Pattern;",
|
||||
"import org.junit.jupiter.params.provider.Arguments;",
|
||||
"import org.springframework.boot.test.context.SpringBootTest;",
|
||||
"import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;",
|
||||
"import org.springframework.format.annotation.DateTimeFormat;",
|
||||
"import org.springframework.format.annotation.DateTimeFormat.ISO;",
|
||||
"import org.springframework.http.MediaType;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m1() {",
|
||||
" ImmutableMap.toImmutableMap(v -> v, v -> v);",
|
||||
" ImmutableMap.<String, String, String>toImmutableMap(v -> v, v -> v);",
|
||||
"",
|
||||
" ImmutableSet.toImmutableSet();",
|
||||
" ImmutableSet.<String>toImmutableSet();",
|
||||
"",
|
||||
" Collections.disjoint(ImmutableSet.of(), ImmutableSet.of());",
|
||||
" Collections.reverse(new ArrayList<>());",
|
||||
"",
|
||||
" Predicates.not(null);",
|
||||
" not(null);",
|
||||
"",
|
||||
" Arguments.arguments(\"foo\");",
|
||||
"",
|
||||
" Objects.requireNonNull(\"bar\");",
|
||||
"",
|
||||
" Object o = StandardCharsets.UTF_8;",
|
||||
"",
|
||||
" ImmutableSet.of(",
|
||||
" MediaType.ALL,",
|
||||
" MediaType.APPLICATION_XHTML_XML,",
|
||||
" MediaType.TEXT_HTML,",
|
||||
" MediaType.valueOf(\"image/webp\"));",
|
||||
"",
|
||||
" Pattern.compile(\"\", Pattern.CASE_INSENSITIVE);",
|
||||
" }",
|
||||
"",
|
||||
" void m2(",
|
||||
" @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) String date,",
|
||||
" @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) String dateTime,",
|
||||
" @DateTimeFormat(iso = DateTimeFormat.ISO.TIME) String time) {}",
|
||||
"",
|
||||
" void m3(",
|
||||
" @DateTimeFormat(iso = ISO.DATE) String date,",
|
||||
" @DateTimeFormat(iso = ISO.DATE_TIME) String dateTime,",
|
||||
" @DateTimeFormat(iso = ISO.TIME) String time) {}",
|
||||
"",
|
||||
" @BugPattern(",
|
||||
" summary = \"\",",
|
||||
" linkType = BugPattern.LinkType.NONE,",
|
||||
" severity = SeverityLevel.SUGGESTION,",
|
||||
" tags = BugPattern.StandardTags.SIMPLIFICATION)",
|
||||
" static final class TestBugPattern {}",
|
||||
"",
|
||||
" @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)",
|
||||
" final class Test {}",
|
||||
"}")
|
||||
"""
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
class A {
|
||||
void m1() {
|
||||
ImmutableMap.toImmutableMap(v -> v, v -> v);
|
||||
ImmutableMap.<String, String, String>toImmutableMap(v -> v, v -> v);
|
||||
|
||||
ImmutableSet.toImmutableSet();
|
||||
ImmutableSet.<String>toImmutableSet();
|
||||
|
||||
Collections.disjoint(ImmutableSet.of(), ImmutableSet.of());
|
||||
Collections.reverse(new ArrayList<>());
|
||||
|
||||
Predicates.not(null);
|
||||
not(null);
|
||||
|
||||
Arguments.arguments("foo");
|
||||
|
||||
Objects.requireNonNull("bar");
|
||||
|
||||
Object o = StandardCharsets.UTF_8;
|
||||
|
||||
ImmutableSet.of(
|
||||
MediaType.ALL,
|
||||
MediaType.APPLICATION_XHTML_XML,
|
||||
MediaType.TEXT_HTML,
|
||||
MediaType.valueOf("image/webp"));
|
||||
|
||||
Pattern.compile("", Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
void m2(
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE) String date,
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) String dateTime,
|
||||
@DateTimeFormat(iso = DateTimeFormat.ISO.TIME) String time) {}
|
||||
|
||||
void m3(
|
||||
@DateTimeFormat(iso = ISO.DATE) String date,
|
||||
@DateTimeFormat(iso = ISO.DATE_TIME) String dateTime,
|
||||
@DateTimeFormat(iso = ISO.TIME) String time) {}
|
||||
|
||||
@BugPattern(
|
||||
summary = "",
|
||||
linkType = BugPattern.LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = BugPattern.StandardTags.SIMPLIFICATION)
|
||||
static final class TestBugPattern {}
|
||||
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
final class Test {}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableMap.toImmutableMap;",
|
||||
"import static com.google.common.collect.ImmutableSet.toImmutableSet;",
|
||||
"import static com.google.errorprone.BugPattern.LinkType.NONE;",
|
||||
"import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;",
|
||||
"import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;",
|
||||
"import static java.nio.charset.StandardCharsets.UTF_8;",
|
||||
"import static java.util.Collections.disjoint;",
|
||||
"import static java.util.Collections.reverse;",
|
||||
"import static java.util.Objects.requireNonNull;",
|
||||
"import static java.util.function.Predicate.not;",
|
||||
"import static java.util.regex.Pattern.CASE_INSENSITIVE;",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;",
|
||||
"import static org.springframework.format.annotation.DateTimeFormat.ISO.DATE;",
|
||||
"import static org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME;",
|
||||
"import static org.springframework.format.annotation.DateTimeFormat.ISO.TIME;",
|
||||
"import static org.springframework.http.MediaType.APPLICATION_XHTML_XML;",
|
||||
"import static org.springframework.http.MediaType.TEXT_HTML;",
|
||||
"",
|
||||
"import com.google.common.base.Predicates;",
|
||||
"import com.google.common.collect.ImmutableMap;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.errorprone.BugPattern;",
|
||||
"import com.google.errorprone.BugPattern.SeverityLevel;",
|
||||
"import java.nio.charset.StandardCharsets;",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.Collections;",
|
||||
"import java.util.Objects;",
|
||||
"import java.util.regex.Pattern;",
|
||||
"import org.junit.jupiter.params.provider.Arguments;",
|
||||
"import org.springframework.boot.test.context.SpringBootTest;",
|
||||
"import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;",
|
||||
"import org.springframework.format.annotation.DateTimeFormat;",
|
||||
"import org.springframework.format.annotation.DateTimeFormat.ISO;",
|
||||
"import org.springframework.http.MediaType;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m1() {",
|
||||
" toImmutableMap(v -> v, v -> v);",
|
||||
" ImmutableMap.<String, String, String>toImmutableMap(v -> v, v -> v);",
|
||||
"",
|
||||
" toImmutableSet();",
|
||||
" ImmutableSet.<String>toImmutableSet();",
|
||||
"",
|
||||
" disjoint(ImmutableSet.of(), ImmutableSet.of());",
|
||||
" reverse(new ArrayList<>());",
|
||||
"",
|
||||
" Predicates.not(null);",
|
||||
" not(null);",
|
||||
"",
|
||||
" arguments(\"foo\");",
|
||||
"",
|
||||
" requireNonNull(\"bar\");",
|
||||
"",
|
||||
" Object o = UTF_8;",
|
||||
"",
|
||||
" ImmutableSet.of(",
|
||||
" MediaType.ALL, APPLICATION_XHTML_XML, TEXT_HTML, MediaType.valueOf(\"image/webp\"));",
|
||||
"",
|
||||
" Pattern.compile(\"\", CASE_INSENSITIVE);",
|
||||
" }",
|
||||
"",
|
||||
" void m2(",
|
||||
" @DateTimeFormat(iso = DATE) String date,",
|
||||
" @DateTimeFormat(iso = DATE_TIME) String dateTime,",
|
||||
" @DateTimeFormat(iso = TIME) String time) {}",
|
||||
"",
|
||||
" void m3(",
|
||||
" @DateTimeFormat(iso = DATE) String date,",
|
||||
" @DateTimeFormat(iso = DATE_TIME) String dateTime,",
|
||||
" @DateTimeFormat(iso = TIME) String time) {}",
|
||||
"",
|
||||
" @BugPattern(summary = \"\", linkType = NONE, severity = SUGGESTION, tags = SIMPLIFICATION)",
|
||||
" static final class TestBugPattern {}",
|
||||
"",
|
||||
" @SpringBootTest(webEnvironment = RANDOM_PORT)",
|
||||
" final class Test {}",
|
||||
"}")
|
||||
"""
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Collections.disjoint;
|
||||
import static java.util.Collections.reverse;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
import static org.springframework.format.annotation.DateTimeFormat.ISO.DATE;
|
||||
import static org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME;
|
||||
import static org.springframework.format.annotation.DateTimeFormat.ISO.TIME;
|
||||
import static org.springframework.http.MediaType.APPLICATION_XHTML_XML;
|
||||
import static org.springframework.http.MediaType.TEXT_HTML;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
class A {
|
||||
void m1() {
|
||||
toImmutableMap(v -> v, v -> v);
|
||||
ImmutableMap.<String, String, String>toImmutableMap(v -> v, v -> v);
|
||||
|
||||
toImmutableSet();
|
||||
ImmutableSet.<String>toImmutableSet();
|
||||
|
||||
disjoint(ImmutableSet.of(), ImmutableSet.of());
|
||||
reverse(new ArrayList<>());
|
||||
|
||||
Predicates.not(null);
|
||||
not(null);
|
||||
|
||||
arguments("foo");
|
||||
|
||||
requireNonNull("bar");
|
||||
|
||||
Object o = UTF_8;
|
||||
|
||||
ImmutableSet.of(
|
||||
MediaType.ALL, APPLICATION_XHTML_XML, TEXT_HTML, MediaType.valueOf("image/webp"));
|
||||
|
||||
Pattern.compile("", CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
void m2(
|
||||
@DateTimeFormat(iso = DATE) String date,
|
||||
@DateTimeFormat(iso = DATE_TIME) String dateTime,
|
||||
@DateTimeFormat(iso = TIME) String time) {}
|
||||
|
||||
void m3(
|
||||
@DateTimeFormat(iso = DATE) String date,
|
||||
@DateTimeFormat(iso = DATE_TIME) String dateTime,
|
||||
@DateTimeFormat(iso = TIME) String time) {}
|
||||
|
||||
@BugPattern(summary = "", linkType = NONE, severity = SUGGESTION, tags = SIMPLIFICATION)
|
||||
static final class TestBugPattern {}
|
||||
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||
final class Test {}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,43 +14,45 @@ final class StringJoinTest {
|
||||
.expectErrorMessage("join", m -> m.contains("Prefer `String#join` over `String#format`"))
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Formattable;",
|
||||
"import java.util.Locale;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" String.join(\"-\", getClass().getName());",
|
||||
" String.format(getClass().getName(), getClass().getName());",
|
||||
" String.format(Locale.ROOT, \"%s\", getClass().getName());",
|
||||
" String.format(\"%20s\", getClass().getName());",
|
||||
" // BUG: Diagnostic matches: valueOf",
|
||||
" String.format(\"%s\", getClass().getName());",
|
||||
" // BUG: Diagnostic matches: valueOf",
|
||||
" String.format(\"%s\", hashCode());",
|
||||
" String.format(\"%s\", (Formattable) null);",
|
||||
" String.format(\"-%s\", getClass().getName());",
|
||||
" String.format(\"%s-\", getClass().getName());",
|
||||
" String.format(\"-%s-\", getClass().getName());",
|
||||
" // BUG: Diagnostic matches: join",
|
||||
" String.format(\"%s%s\", getClass().getName(), getClass().getName());",
|
||||
" // BUG: Diagnostic matches: join",
|
||||
" String.format(\"%s%s\", getClass().getName(), hashCode());",
|
||||
" // BUG: Diagnostic matches: join",
|
||||
" String.format(\"%s%s\", hashCode(), getClass().getName());",
|
||||
" String.format(\"%s%s\", getClass().getName(), (Formattable) null);",
|
||||
" String.format(\"%s%s\", (Formattable) null, getClass().getName());",
|
||||
" String.format(\"%s%s\", getClass().getName());",
|
||||
" // BUG: Diagnostic matches: join",
|
||||
" String.format(\"%s-%s\", getClass().getName(), getClass().getName());",
|
||||
" // BUG: Diagnostic matches: join",
|
||||
" String.format(\"%saa%s\", getClass().getName(), getClass().getName());",
|
||||
" String.format(\"%s%%%s\", getClass().getName(), getClass().getName());",
|
||||
" // BUG: Diagnostic matches: join",
|
||||
" String.format(\"%s_%s_%s\", getClass().getName(), getClass().getName(), getClass().getName());",
|
||||
" String.format(\"%s_%s_%s\", getClass().getName(), getClass().getName());",
|
||||
" String.format(\"%s_%s-%s\", getClass().getName(), getClass().getName(), getClass().getName());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.Formattable;
|
||||
import java.util.Locale;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
String.join("-", getClass().getName());
|
||||
String.format(getClass().getName(), getClass().getName());
|
||||
String.format(Locale.ROOT, "%s", getClass().getName());
|
||||
String.format("%20s", getClass().getName());
|
||||
// BUG: Diagnostic matches: valueOf
|
||||
String.format("%s", getClass().getName());
|
||||
// BUG: Diagnostic matches: valueOf
|
||||
String.format("%s", hashCode());
|
||||
String.format("%s", (Formattable) null);
|
||||
String.format("-%s", getClass().getName());
|
||||
String.format("%s-", getClass().getName());
|
||||
String.format("-%s-", getClass().getName());
|
||||
// BUG: Diagnostic matches: join
|
||||
String.format("%s%s", getClass().getName(), getClass().getName());
|
||||
// BUG: Diagnostic matches: join
|
||||
String.format("%s%s", getClass().getName(), hashCode());
|
||||
// BUG: Diagnostic matches: join
|
||||
String.format("%s%s", hashCode(), getClass().getName());
|
||||
String.format("%s%s", getClass().getName(), (Formattable) null);
|
||||
String.format("%s%s", (Formattable) null, getClass().getName());
|
||||
String.format("%s%s", getClass().getName());
|
||||
// BUG: Diagnostic matches: join
|
||||
String.format("%s-%s", getClass().getName(), getClass().getName());
|
||||
// BUG: Diagnostic matches: join
|
||||
String.format("%saa%s", getClass().getName(), getClass().getName());
|
||||
String.format("%s%%%s", getClass().getName(), getClass().getName());
|
||||
// BUG: Diagnostic matches: join
|
||||
String.format("%s_%s_%s", getClass().getName(), getClass().getName(), getClass().getName());
|
||||
String.format("%s_%s_%s", getClass().getName(), getClass().getName());
|
||||
String.format("%s_%s-%s", getClass().getName(), getClass().getName(), getClass().getName());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -59,32 +61,36 @@ final class StringJoinTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(StringJoin.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" String.format(\"%s\", getClass().getName());",
|
||||
" String.format(\"%s%s\", getClass().getName(), getClass().getName());",
|
||||
" String.format(\"%s%s\", getClass().getName(), hashCode());",
|
||||
" String.format(\"%s%s\", hashCode(), getClass().getName());",
|
||||
" String.format(\"%s-%s\", getClass().getName(), getClass().getName());",
|
||||
" String.format(\"%saa%s\", getClass().getName(), getClass().getName());",
|
||||
" String.format(\"%s\\\"%s\", getClass().getName(), getClass().getName());",
|
||||
" String.format(\"%s_%s_%s\", getClass().getName(), getClass().getName(), getClass().getName());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
void m() {
|
||||
String.format("%s", getClass().getName());
|
||||
String.format("%s%s", getClass().getName(), getClass().getName());
|
||||
String.format("%s%s", getClass().getName(), hashCode());
|
||||
String.format("%s%s", hashCode(), getClass().getName());
|
||||
String.format("%s-%s", getClass().getName(), getClass().getName());
|
||||
String.format("%saa%s", getClass().getName(), getClass().getName());
|
||||
String.format("%s\\"%s", getClass().getName(), getClass().getName());
|
||||
String.format("%s_%s_%s", getClass().getName(), getClass().getName(), getClass().getName());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" String.valueOf(getClass().getName());",
|
||||
" String.join(\"\", getClass().getName(), getClass().getName());",
|
||||
" String.join(\"\", getClass().getName(), String.valueOf(hashCode()));",
|
||||
" String.join(\"\", String.valueOf(hashCode()), getClass().getName());",
|
||||
" String.join(\"-\", getClass().getName(), getClass().getName());",
|
||||
" String.join(\"aa\", getClass().getName(), getClass().getName());",
|
||||
" String.join(\"\\\"\", getClass().getName(), getClass().getName());",
|
||||
" String.join(\"_\", getClass().getName(), getClass().getName(), getClass().getName());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
void m() {
|
||||
String.valueOf(getClass().getName());
|
||||
String.join("", getClass().getName(), getClass().getName());
|
||||
String.join("", getClass().getName(), String.valueOf(hashCode()));
|
||||
String.join("", String.valueOf(hashCode()), getClass().getName());
|
||||
String.join("-", getClass().getName(), getClass().getName());
|
||||
String.join("aa", getClass().getName(), getClass().getName());
|
||||
String.join("\\"", getClass().getName(), getClass().getName());
|
||||
String.join("_", getClass().getName(), getClass().getName(), getClass().getName());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,110 +9,112 @@ final class TimeZoneUsageTest {
|
||||
CompilationTestHelper.newInstance(TimeZoneUsage.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static java.time.ZoneOffset.UTC;",
|
||||
"",
|
||||
"import java.time.Clock;",
|
||||
"import java.time.Duration;",
|
||||
"import java.time.Instant;",
|
||||
"import java.time.LocalDate;",
|
||||
"import java.time.LocalDateTime;",
|
||||
"import java.time.LocalTime;",
|
||||
"import java.time.OffsetDateTime;",
|
||||
"import java.time.OffsetTime;",
|
||||
"import java.time.ZoneId;",
|
||||
"import java.time.ZonedDateTime;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Clock clock = Clock.fixed(Instant.EPOCH, UTC);",
|
||||
" clock.instant();",
|
||||
" clock.millis();",
|
||||
" Clock.offset(clock, Duration.ZERO);",
|
||||
" Clock.tick(clock, Duration.ZERO);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.systemUTC();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.systemDefaultZone();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.system(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.tickMillis(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.tickMinutes(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.tickSeconds(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" clock.getZone();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" clock.withZone(UTC);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Instant.now();",
|
||||
" // This is equivalent to `clock.instant()`, which is fine.",
|
||||
" Instant.now(clock);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDate.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDate.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDate.now(UTC);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDateTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDateTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDateTime.now(UTC);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalTime.now(UTC);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetDateTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetDateTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetDateTime.now(UTC);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetTime.now(UTC);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ZonedDateTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ZonedDateTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ZonedDateTime.now(UTC);",
|
||||
" }",
|
||||
"",
|
||||
" abstract class ForwardingClock extends Clock {",
|
||||
" private final Clock clock;",
|
||||
"",
|
||||
" ForwardingClock(Clock clock) {",
|
||||
" this.clock = clock;",
|
||||
" }",
|
||||
"",
|
||||
" @Override",
|
||||
" public ZoneId getZone() {",
|
||||
" return clock.getZone();",
|
||||
" }",
|
||||
"",
|
||||
" @Override",
|
||||
" public Clock withZone(ZoneId zone) {",
|
||||
" return clock.withZone(zone);",
|
||||
" }",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
Clock clock = Clock.fixed(Instant.EPOCH, UTC);
|
||||
clock.instant();
|
||||
clock.millis();
|
||||
Clock.offset(clock, Duration.ZERO);
|
||||
Clock.tick(clock, Duration.ZERO);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Clock.systemUTC();
|
||||
// BUG: Diagnostic contains:
|
||||
Clock.systemDefaultZone();
|
||||
// BUG: Diagnostic contains:
|
||||
Clock.system(UTC);
|
||||
// BUG: Diagnostic contains:
|
||||
Clock.tickMillis(UTC);
|
||||
// BUG: Diagnostic contains:
|
||||
Clock.tickMinutes(UTC);
|
||||
// BUG: Diagnostic contains:
|
||||
Clock.tickSeconds(UTC);
|
||||
// BUG: Diagnostic contains:
|
||||
clock.getZone();
|
||||
// BUG: Diagnostic contains:
|
||||
clock.withZone(UTC);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
Instant.now();
|
||||
// This is equivalent to `clock.instant()`, which is fine.
|
||||
Instant.now(clock);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LocalDate.now();
|
||||
// BUG: Diagnostic contains:
|
||||
LocalDate.now(clock);
|
||||
// BUG: Diagnostic contains:
|
||||
LocalDate.now(UTC);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LocalDateTime.now();
|
||||
// BUG: Diagnostic contains:
|
||||
LocalDateTime.now(clock);
|
||||
// BUG: Diagnostic contains:
|
||||
LocalDateTime.now(UTC);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
LocalTime.now();
|
||||
// BUG: Diagnostic contains:
|
||||
LocalTime.now(clock);
|
||||
// BUG: Diagnostic contains:
|
||||
LocalTime.now(UTC);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
OffsetDateTime.now();
|
||||
// BUG: Diagnostic contains:
|
||||
OffsetDateTime.now(clock);
|
||||
// BUG: Diagnostic contains:
|
||||
OffsetDateTime.now(UTC);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
OffsetTime.now();
|
||||
// BUG: Diagnostic contains:
|
||||
OffsetTime.now(clock);
|
||||
// BUG: Diagnostic contains:
|
||||
OffsetTime.now(UTC);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
ZonedDateTime.now();
|
||||
// BUG: Diagnostic contains:
|
||||
ZonedDateTime.now(clock);
|
||||
// BUG: Diagnostic contains:
|
||||
ZonedDateTime.now(UTC);
|
||||
}
|
||||
|
||||
abstract class ForwardingClock extends Clock {
|
||||
private final Clock clock;
|
||||
|
||||
ForwardingClock(Clock clock) {
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZoneId getZone() {
|
||||
return clock.getZone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clock withZone(ZoneId zone) {
|
||||
return clock.withZone(zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,38 +19,40 @@ final class ConflictDetectionTest {
|
||||
CompilationTestHelper.newInstance(RenameBlockerFlagger.class, getClass())
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import static pkg.A.B.method3t;",
|
||||
"",
|
||||
"import pkg.A.method4t;",
|
||||
"",
|
||||
"class A {",
|
||||
" void method1() {",
|
||||
" method3t();",
|
||||
" method4(method4t.class);",
|
||||
" }",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: a method named `method2t` is already defined in this class or a",
|
||||
" // supertype",
|
||||
" void method2() {}",
|
||||
"",
|
||||
" void method2t() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: `method3t` is already statically imported",
|
||||
" void method3() {}",
|
||||
"",
|
||||
" void method4(Object o) {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: `int` is not a valid identifier",
|
||||
" void in() {}",
|
||||
"",
|
||||
" static class B {",
|
||||
" static void method3t() {}",
|
||||
" }",
|
||||
"",
|
||||
" class method4t {}",
|
||||
"}")
|
||||
"""
|
||||
package pkg;
|
||||
|
||||
import static pkg.A.B.method3t;
|
||||
|
||||
import pkg.A.method4t;
|
||||
|
||||
class A {
|
||||
void method1() {
|
||||
method3t();
|
||||
method4(method4t.class);
|
||||
}
|
||||
|
||||
// BUG: Diagnostic contains: a method named `method2t` is already defined in this class or a
|
||||
// supertype
|
||||
void method2() {}
|
||||
|
||||
void method2t() {}
|
||||
|
||||
// BUG: Diagnostic contains: `method3t` is already statically imported
|
||||
void method3() {}
|
||||
|
||||
void method4(Object o) {}
|
||||
|
||||
// BUG: Diagnostic contains: `int` is not a valid identifier
|
||||
void in() {}
|
||||
|
||||
static class B {
|
||||
static void method3t() {}
|
||||
}
|
||||
|
||||
class method4t {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,153 +51,165 @@ final class MethodMatcherFactoryTest {
|
||||
CompilationTestHelper.newInstance(MatchedMethodsFlagger.class, getClass())
|
||||
.addSourceLines(
|
||||
"com/example/A.java",
|
||||
"package com.example;",
|
||||
"",
|
||||
"public class A {",
|
||||
" public void m1() {}",
|
||||
"",
|
||||
" public void m1(String s) {}",
|
||||
"",
|
||||
" public void m1(int i, int j) {}",
|
||||
"",
|
||||
" public void m2() {}",
|
||||
"",
|
||||
" public void m2(String s) {}",
|
||||
"",
|
||||
" public void m2(int i, int j) {}",
|
||||
"",
|
||||
" public void m3() {}",
|
||||
"",
|
||||
" public void m3(String s) {}",
|
||||
"",
|
||||
" public void m3(int i, int j) {}",
|
||||
"}")
|
||||
"""
|
||||
package com.example;
|
||||
|
||||
public class A {
|
||||
public void m1() {}
|
||||
|
||||
public void m1(String s) {}
|
||||
|
||||
public void m1(int i, int j) {}
|
||||
|
||||
public void m2() {}
|
||||
|
||||
public void m2(String s) {}
|
||||
|
||||
public void m2(int i, int j) {}
|
||||
|
||||
public void m3() {}
|
||||
|
||||
public void m3(String s) {}
|
||||
|
||||
public void m3(int i, int j) {}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"com/example/B.java",
|
||||
"package com.example;",
|
||||
"",
|
||||
"public class B {",
|
||||
" public void m1() {}",
|
||||
"",
|
||||
" public void m1(String s) {}",
|
||||
"",
|
||||
" public void m1(int i, int j) {}",
|
||||
"",
|
||||
" public void m2() {}",
|
||||
"",
|
||||
" public void m2(String s) {}",
|
||||
"",
|
||||
" public void m2(int i, int j) {}",
|
||||
"",
|
||||
" public void m3() {}",
|
||||
"",
|
||||
" public void m3(String s) {}",
|
||||
"",
|
||||
" public void m3(int i, int j) {}",
|
||||
"}")
|
||||
"""
|
||||
package com.example;
|
||||
|
||||
public class B {
|
||||
public void m1() {}
|
||||
|
||||
public void m1(String s) {}
|
||||
|
||||
public void m1(int i, int j) {}
|
||||
|
||||
public void m2() {}
|
||||
|
||||
public void m2(String s) {}
|
||||
|
||||
public void m2(int i, int j) {}
|
||||
|
||||
public void m3() {}
|
||||
|
||||
public void m3(String s) {}
|
||||
|
||||
public void m3(int i, int j) {}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"com/example/sub/A.java",
|
||||
"package com.example.sub;",
|
||||
"",
|
||||
"public class A {",
|
||||
" public static void m1() {}",
|
||||
"",
|
||||
" public static void m1(String s) {}",
|
||||
"",
|
||||
" public static void m1(int i, int j) {}",
|
||||
"",
|
||||
" public static void m2() {}",
|
||||
"",
|
||||
" public static void m2(String s) {}",
|
||||
"",
|
||||
" public static void m2(int i, int j) {}",
|
||||
"",
|
||||
" public static void m3() {}",
|
||||
"",
|
||||
" public static void m3(String s) {}",
|
||||
"",
|
||||
" public static void m3(int i, int j) {}",
|
||||
"}")
|
||||
"""
|
||||
package com.example.sub;
|
||||
|
||||
public class A {
|
||||
public static void m1() {}
|
||||
|
||||
public static void m1(String s) {}
|
||||
|
||||
public static void m1(int i, int j) {}
|
||||
|
||||
public static void m2() {}
|
||||
|
||||
public static void m2(String s) {}
|
||||
|
||||
public static void m2(int i, int j) {}
|
||||
|
||||
public static void m3() {}
|
||||
|
||||
public static void m3(String s) {}
|
||||
|
||||
public static void m3(int i, int j) {}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"com/example/sub/B.java",
|
||||
"package com.example.sub;",
|
||||
"",
|
||||
"public class B {",
|
||||
" public static void m1() {}",
|
||||
"",
|
||||
" public static void m1(String s) {}",
|
||||
"",
|
||||
" public static void m1(int i, int j) {}",
|
||||
"",
|
||||
" public static void m2() {}",
|
||||
"",
|
||||
" public static void m2(String s) {}",
|
||||
"",
|
||||
" public static void m2(int i, int j) {}",
|
||||
"",
|
||||
" public static void m3() {}",
|
||||
"",
|
||||
" public static void m3(String s) {}",
|
||||
"",
|
||||
" public static void m3(int i, int j) {}",
|
||||
"}")
|
||||
"""
|
||||
package com.example.sub;
|
||||
|
||||
public class B {
|
||||
public static void m1() {}
|
||||
|
||||
public static void m1(String s) {}
|
||||
|
||||
public static void m1(int i, int j) {}
|
||||
|
||||
public static void m2() {}
|
||||
|
||||
public static void m2(String s) {}
|
||||
|
||||
public static void m2(int i, int j) {}
|
||||
|
||||
public static void m3() {}
|
||||
|
||||
public static void m3(String s) {}
|
||||
|
||||
public static void m3(int i, int j) {}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"External.java",
|
||||
"import com.example.A;",
|
||||
"import com.example.sub.B;",
|
||||
"",
|
||||
"public class External {",
|
||||
" void invocations() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" new A().m1();",
|
||||
" new A().m1(\"\");",
|
||||
" new A().m1(0, 0);",
|
||||
" new A().m2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" new A().m2(\"\");",
|
||||
" new A().m2(0, 0);",
|
||||
" new A().m3();",
|
||||
" new A().m3(\"\");",
|
||||
" new A().m3(0, 0);",
|
||||
" B.m1();",
|
||||
" B.m1(\"\");",
|
||||
" B.m1(0, 0);",
|
||||
" B.m2();",
|
||||
" B.m2(\"\");",
|
||||
" B.m2(0, 0);",
|
||||
" B.m3();",
|
||||
" B.m3(\"\");",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" B.m3(0, 0);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.example.A;
|
||||
import com.example.sub.B;
|
||||
|
||||
public class External {
|
||||
void invocations() {
|
||||
// BUG: Diagnostic contains:
|
||||
new A().m1();
|
||||
new A().m1("");
|
||||
new A().m1(0, 0);
|
||||
new A().m2();
|
||||
// BUG: Diagnostic contains:
|
||||
new A().m2("");
|
||||
new A().m2(0, 0);
|
||||
new A().m3();
|
||||
new A().m3("");
|
||||
new A().m3(0, 0);
|
||||
B.m1();
|
||||
B.m1("");
|
||||
B.m1(0, 0);
|
||||
B.m2();
|
||||
B.m2("");
|
||||
B.m2(0, 0);
|
||||
B.m3();
|
||||
B.m3("");
|
||||
// BUG: Diagnostic contains:
|
||||
B.m3(0, 0);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addSourceLines(
|
||||
"ExternalWithDifferentPackages.java",
|
||||
"import com.example.B;",
|
||||
"import com.example.sub.A;",
|
||||
"",
|
||||
"public class ExternalWithDifferentPackages {",
|
||||
" void invocations() {",
|
||||
" A.m1();",
|
||||
" A.m1(\"\");",
|
||||
" A.m1(0, 0);",
|
||||
" A.m2();",
|
||||
" A.m2(\"\");",
|
||||
" A.m2(0, 0);",
|
||||
" A.m3();",
|
||||
" A.m3(\"\");",
|
||||
" A.m3(0, 0);",
|
||||
" new B().m1();",
|
||||
" new B().m1(\"\");",
|
||||
" new B().m1(0, 0);",
|
||||
" new B().m2();",
|
||||
" new B().m2(\"\");",
|
||||
" new B().m2(0, 0);",
|
||||
" new B().m3();",
|
||||
" new B().m3(\"\");",
|
||||
" new B().m3(0, 0);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.example.B;
|
||||
import com.example.sub.A;
|
||||
|
||||
public class ExternalWithDifferentPackages {
|
||||
void invocations() {
|
||||
A.m1();
|
||||
A.m1("");
|
||||
A.m1(0, 0);
|
||||
A.m2();
|
||||
A.m2("");
|
||||
A.m2(0, 0);
|
||||
A.m3();
|
||||
A.m3("");
|
||||
A.m3(0, 0);
|
||||
new B().m1();
|
||||
new B().m1("");
|
||||
new B().m1(0, 0);
|
||||
new B().m2();
|
||||
new B().m2("");
|
||||
new B().m2(0, 0);
|
||||
new B().m3();
|
||||
new B().m3("");
|
||||
new B().m3(0, 0);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,24 +27,26 @@ final class MoreASTHelpersTest {
|
||||
CompilationTestHelper.newInstance(FindMethodsTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" // BUG: Diagnostic contains: {foo=1, bar=2, baz=0}",
|
||||
" void foo() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: {foo=1, bar=2, baz=0}",
|
||||
" void bar() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: {foo=1, bar=2, baz=0}",
|
||||
" void bar(int i) {}",
|
||||
"",
|
||||
" static class B {",
|
||||
" // BUG: Diagnostic contains: {foo=0, bar=1, baz=1}",
|
||||
" void bar() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: {foo=0, bar=1, baz=1}",
|
||||
" void baz() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
// BUG: Diagnostic contains: {foo=1, bar=2, baz=0}
|
||||
void foo() {}
|
||||
|
||||
// BUG: Diagnostic contains: {foo=1, bar=2, baz=0}
|
||||
void bar() {}
|
||||
|
||||
// BUG: Diagnostic contains: {foo=1, bar=2, baz=0}
|
||||
void bar(int i) {}
|
||||
|
||||
static class B {
|
||||
// BUG: Diagnostic contains: {foo=0, bar=1, baz=1}
|
||||
void bar() {}
|
||||
|
||||
// BUG: Diagnostic contains: {foo=0, bar=1, baz=1}
|
||||
void baz() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -53,24 +55,26 @@ final class MoreASTHelpersTest {
|
||||
CompilationTestHelper.newInstance(MethodExistsTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" // BUG: Diagnostic contains: {foo=true, bar=true, baz=false}",
|
||||
" void foo() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: {foo=true, bar=true, baz=false}",
|
||||
" void bar() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: {foo=true, bar=true, baz=false}",
|
||||
" void bar(int i) {}",
|
||||
"",
|
||||
" static class B {",
|
||||
" // BUG: Diagnostic contains: {foo=false, bar=true, baz=true}",
|
||||
" void bar() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: {foo=false, bar=true, baz=true}",
|
||||
" void baz() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
// BUG: Diagnostic contains: {foo=true, bar=true, baz=false}
|
||||
void foo() {}
|
||||
|
||||
// BUG: Diagnostic contains: {foo=true, bar=true, baz=false}
|
||||
void bar() {}
|
||||
|
||||
// BUG: Diagnostic contains: {foo=true, bar=true, baz=false}
|
||||
void bar(int i) {}
|
||||
|
||||
static class B {
|
||||
// BUG: Diagnostic contains: {foo=false, bar=true, baz=true}
|
||||
void bar() {}
|
||||
|
||||
// BUG: Diagnostic contains: {foo=false, bar=true, baz=true}
|
||||
void baz() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -79,42 +83,44 @@ final class MoreASTHelpersTest {
|
||||
CompilationTestHelper.newInstance(FindMethodReturnTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" {",
|
||||
" toString();",
|
||||
" }",
|
||||
"",
|
||||
" String topLevelMethod() {",
|
||||
" // BUG: Diagnostic contains: topLevelMethod",
|
||||
" toString();",
|
||||
" // BUG: Diagnostic contains: topLevelMethod",
|
||||
" return toString();",
|
||||
" }",
|
||||
"",
|
||||
" Stream<String> anotherMethod() {",
|
||||
" // BUG: Diagnostic contains: anotherMethod",
|
||||
" return Stream.of(1)",
|
||||
" .map(",
|
||||
" n -> {",
|
||||
" toString();",
|
||||
" return toString();",
|
||||
" });",
|
||||
" }",
|
||||
"",
|
||||
" void recursiveMethod(Runnable r) {",
|
||||
" // BUG: Diagnostic contains: recursiveMethod",
|
||||
" recursiveMethod(",
|
||||
" new Runnable() {",
|
||||
" @Override",
|
||||
" public void run() {",
|
||||
" // BUG: Diagnostic contains: run",
|
||||
" toString();",
|
||||
" }",
|
||||
" });",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
{
|
||||
toString();
|
||||
}
|
||||
|
||||
String topLevelMethod() {
|
||||
// BUG: Diagnostic contains: topLevelMethod
|
||||
toString();
|
||||
// BUG: Diagnostic contains: topLevelMethod
|
||||
return toString();
|
||||
}
|
||||
|
||||
Stream<String> anotherMethod() {
|
||||
// BUG: Diagnostic contains: anotherMethod
|
||||
return Stream.of(1)
|
||||
.map(
|
||||
n -> {
|
||||
toString();
|
||||
return toString();
|
||||
});
|
||||
}
|
||||
|
||||
void recursiveMethod(Runnable r) {
|
||||
// BUG: Diagnostic contains: recursiveMethod
|
||||
recursiveMethod(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// BUG: Diagnostic contains: run
|
||||
toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -123,17 +129,19 @@ final class MoreASTHelpersTest {
|
||||
CompilationTestHelper.newInstance(AreSameTypeTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" void negative1(String a, Integer b) {}",
|
||||
"",
|
||||
" void negative2(Integer a, Number b) {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void positive1(String a, String b) {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" void positive2(Iterable<String> a, Iterable<Integer> b) {}",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
void negative1(String a, Integer b) {}
|
||||
|
||||
void negative2(Integer a, Number b) {}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
void positive1(String a, String b) {}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
void positive2(Iterable<String> a, Iterable<Integer> b) {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,56 +27,58 @@ final class MoreJUnitMatchersTest {
|
||||
CompilationTestHelper.newInstance(MethodMatchersTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"",
|
||||
"import java.util.stream.Stream;",
|
||||
"import org.junit.jupiter.api.AfterAll;",
|
||||
"import org.junit.jupiter.api.AfterEach;",
|
||||
"import org.junit.jupiter.api.BeforeAll;",
|
||||
"import org.junit.jupiter.api.BeforeEach;",
|
||||
"import org.junit.jupiter.api.RepeatedTest;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"import org.junit.jupiter.params.provider.Arguments;",
|
||||
"import org.junit.jupiter.params.provider.MethodSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" @BeforeAll",
|
||||
" // BUG: Diagnostic contains: SETUP_OR_TEARDOWN_METHOD",
|
||||
" public void beforeAll() {}",
|
||||
"",
|
||||
" @BeforeEach",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: TEST_METHOD, SETUP_OR_TEARDOWN_METHOD",
|
||||
" protected void beforeEachAndTest() {}",
|
||||
"",
|
||||
" @AfterEach",
|
||||
" // BUG: Diagnostic contains: SETUP_OR_TEARDOWN_METHOD",
|
||||
" private void afterEach() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" // BUG: Diagnostic contains: SETUP_OR_TEARDOWN_METHOD",
|
||||
" private void afterAll() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: TEST_METHOD",
|
||||
" void test() {}",
|
||||
"",
|
||||
" private static Stream<Arguments> booleanArgs() {",
|
||||
" return Stream.of(arguments(false), arguments(true));",
|
||||
" }",
|
||||
"",
|
||||
" @ParameterizedTest",
|
||||
" @MethodSource(\"booleanArgs\")",
|
||||
" // BUG: Diagnostic contains: TEST_METHOD, HAS_METHOD_SOURCE",
|
||||
" void parameterizedTest(boolean b) {}",
|
||||
"",
|
||||
" @RepeatedTest(2)",
|
||||
" // BUG: Diagnostic contains: TEST_METHOD",
|
||||
" private void repeatedTest() {}",
|
||||
"",
|
||||
" private void unannotatedMethod() {}",
|
||||
"}")
|
||||
"""
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.RepeatedTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class A {
|
||||
@BeforeAll
|
||||
// BUG: Diagnostic contains: SETUP_OR_TEARDOWN_METHOD
|
||||
public void beforeAll() {}
|
||||
|
||||
@BeforeEach
|
||||
@Test
|
||||
// BUG: Diagnostic contains: TEST_METHOD, SETUP_OR_TEARDOWN_METHOD
|
||||
protected void beforeEachAndTest() {}
|
||||
|
||||
@AfterEach
|
||||
// BUG: Diagnostic contains: SETUP_OR_TEARDOWN_METHOD
|
||||
private void afterEach() {}
|
||||
|
||||
@AfterAll
|
||||
// BUG: Diagnostic contains: SETUP_OR_TEARDOWN_METHOD
|
||||
private void afterAll() {}
|
||||
|
||||
@Test
|
||||
// BUG: Diagnostic contains: TEST_METHOD
|
||||
void test() {}
|
||||
|
||||
private static Stream<Arguments> booleanArgs() {
|
||||
return Stream.of(arguments(false), arguments(true));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("booleanArgs")
|
||||
// BUG: Diagnostic contains: TEST_METHOD, HAS_METHOD_SOURCE
|
||||
void parameterizedTest(boolean b) {}
|
||||
|
||||
@RepeatedTest(2)
|
||||
// BUG: Diagnostic contains: TEST_METHOD
|
||||
private void repeatedTest() {}
|
||||
|
||||
private void unannotatedMethod() {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -85,32 +87,34 @@ final class MoreJUnitMatchersTest {
|
||||
CompilationTestHelper.newInstance(MethodSourceFactoryNamesTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.params.provider.MethodSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" @MethodSource",
|
||||
" // BUG: Diagnostic contains: [matchingMethodSource]",
|
||||
" void matchingMethodSource(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource(\"myValueFactory\")",
|
||||
" // BUG: Diagnostic contains: [myValueFactory]",
|
||||
" void singleCustomMethodSource(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource({",
|
||||
" \"nullary()\",",
|
||||
" \"nullary()\",",
|
||||
" \"\",",
|
||||
" \"withStringParam(java.lang.String)\",",
|
||||
" \"paramsUnspecified\"",
|
||||
" })",
|
||||
" // BUG: Diagnostic contains: [nullary, nullary, multipleMethodSources, withStringParam,",
|
||||
" // paramsUnspecified]",
|
||||
" void multipleMethodSources(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource({\"foo\", \"()\", \"bar\"})",
|
||||
" // BUG: Diagnostic contains: [foo, , bar]",
|
||||
" void methodSourceWithoutName(boolean b) {}",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class A {
|
||||
@MethodSource
|
||||
// BUG: Diagnostic contains: [matchingMethodSource]
|
||||
void matchingMethodSource(boolean b) {}
|
||||
|
||||
@MethodSource("myValueFactory")
|
||||
// BUG: Diagnostic contains: [myValueFactory]
|
||||
void singleCustomMethodSource(boolean b) {}
|
||||
|
||||
@MethodSource({
|
||||
"nullary()",
|
||||
"nullary()",
|
||||
"",
|
||||
"withStringParam(java.lang.String)",
|
||||
"paramsUnspecified"
|
||||
})
|
||||
// BUG: Diagnostic contains: [nullary, nullary, multipleMethodSources, withStringParam,
|
||||
// paramsUnspecified]
|
||||
void multipleMethodSources(boolean b) {}
|
||||
|
||||
@MethodSource({"foo", "()", "bar"})
|
||||
// BUG: Diagnostic contains: [foo, , bar]
|
||||
void methodSourceWithoutName(boolean b) {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -119,49 +123,51 @@ final class MoreJUnitMatchersTest {
|
||||
CompilationTestHelper.newInstance(MethodSourceFactoryDescriptorsTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.params.provider.MethodSource;",
|
||||
"",
|
||||
"class A {",
|
||||
" @MethodSource",
|
||||
" // BUG: Diagnostic contains: [matchingMethodSource]",
|
||||
" void matchingMethodSource(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource()",
|
||||
" // BUG: Diagnostic contains: [matchingMethodSourceWithParens]",
|
||||
" void matchingMethodSourceWithParens(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource(\"\")",
|
||||
" // BUG: Diagnostic contains: [matchingMethodSourceMadeExplicit]",
|
||||
" void matchingMethodSourceMadeExplicit(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource({\"\"})",
|
||||
" // BUG: Diagnostic contains: [matchingMethodSourceMadeExplicitWithParens]",
|
||||
" void matchingMethodSourceMadeExplicitWithParens(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource({})",
|
||||
" // BUG: Diagnostic contains: []",
|
||||
" void noMethodSources(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource(\"myValueFactory\")",
|
||||
" // BUG: Diagnostic contains: [myValueFactory]",
|
||||
" void singleCustomMethodSource(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource({\"firstValueFactory\", \"secondValueFactory\"})",
|
||||
" // BUG: Diagnostic contains: [firstValueFactory, secondValueFactory]",
|
||||
" void twoCustomMethodSources(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource({\"myValueFactory\", \"\"})",
|
||||
" // BUG: Diagnostic contains: [myValueFactory, customAndMatchingMethodSources]",
|
||||
" void customAndMatchingMethodSources(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource({\"factory\", \"\", \"factory\", \"\"})",
|
||||
" // BUG: Diagnostic contains: [factory, repeatedMethodSources, factory, repeatedMethodSources]",
|
||||
" void repeatedMethodSources(boolean b) {}",
|
||||
"",
|
||||
" @MethodSource({\"nullary()\", \"withStringParam(java.lang.String)\"})",
|
||||
" // BUG: Diagnostic contains: [nullary(), withStringParam(java.lang.String)]",
|
||||
" void methodSourcesWithParameterSpecification(boolean b) {}",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class A {
|
||||
@MethodSource
|
||||
// BUG: Diagnostic contains: [matchingMethodSource]
|
||||
void matchingMethodSource(boolean b) {}
|
||||
|
||||
@MethodSource()
|
||||
// BUG: Diagnostic contains: [matchingMethodSourceWithParens]
|
||||
void matchingMethodSourceWithParens(boolean b) {}
|
||||
|
||||
@MethodSource("")
|
||||
// BUG: Diagnostic contains: [matchingMethodSourceMadeExplicit]
|
||||
void matchingMethodSourceMadeExplicit(boolean b) {}
|
||||
|
||||
@MethodSource({""})
|
||||
// BUG: Diagnostic contains: [matchingMethodSourceMadeExplicitWithParens]
|
||||
void matchingMethodSourceMadeExplicitWithParens(boolean b) {}
|
||||
|
||||
@MethodSource({})
|
||||
// BUG: Diagnostic contains: []
|
||||
void noMethodSources(boolean b) {}
|
||||
|
||||
@MethodSource("myValueFactory")
|
||||
// BUG: Diagnostic contains: [myValueFactory]
|
||||
void singleCustomMethodSource(boolean b) {}
|
||||
|
||||
@MethodSource({"firstValueFactory", "secondValueFactory"})
|
||||
// BUG: Diagnostic contains: [firstValueFactory, secondValueFactory]
|
||||
void twoCustomMethodSources(boolean b) {}
|
||||
|
||||
@MethodSource({"myValueFactory", ""})
|
||||
// BUG: Diagnostic contains: [myValueFactory, customAndMatchingMethodSources]
|
||||
void customAndMatchingMethodSources(boolean b) {}
|
||||
|
||||
@MethodSource({"factory", "", "factory", ""})
|
||||
// BUG: Diagnostic contains: [factory, repeatedMethodSources, factory, repeatedMethodSources]
|
||||
void repeatedMethodSources(boolean b) {}
|
||||
|
||||
@MethodSource({"nullary()", "withStringParam(java.lang.String)"})
|
||||
// BUG: Diagnostic contains: [nullary(), withStringParam(java.lang.String)]
|
||||
void methodSourcesWithParameterSpecification(boolean b) {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,32 +26,34 @@ final class MoreMatchersTest {
|
||||
CompilationTestHelper.newInstance(HasMetaAnnotationTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import org.junit.jupiter.api.AfterAll;",
|
||||
"import org.junit.jupiter.api.RepeatedTest;",
|
||||
"import org.junit.jupiter.api.Test;",
|
||||
"import org.junit.jupiter.api.TestTemplate;",
|
||||
"import org.junit.jupiter.params.ParameterizedTest;",
|
||||
"",
|
||||
"class A {",
|
||||
" void negative1() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" void negative2() {}",
|
||||
"",
|
||||
" @AfterAll",
|
||||
" void negative3() {}",
|
||||
"",
|
||||
" @TestTemplate",
|
||||
" void negative4() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @ParameterizedTest",
|
||||
" void positive1() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @RepeatedTest(2)",
|
||||
" void positive2() {}",
|
||||
"}")
|
||||
"""
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.RepeatedTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestTemplate;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
||||
class A {
|
||||
void negative1() {}
|
||||
|
||||
@Test
|
||||
void negative2() {}
|
||||
|
||||
@AfterAll
|
||||
void negative3() {}
|
||||
|
||||
@TestTemplate
|
||||
void negative4() {}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@ParameterizedTest
|
||||
void positive1() {}
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
@RepeatedTest(2)
|
||||
void positive2() {}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -60,33 +62,35 @@ final class MoreMatchersTest {
|
||||
CompilationTestHelper.newInstance(IsSubTypeOfTestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.common.collect.ImmutableSortedSet;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" ImmutableSet.of(\"foo\");",
|
||||
" ImmutableSortedSet.of(\"foo\");",
|
||||
" ImmutableList.of(\"foo\");",
|
||||
" ImmutableList.of(1);",
|
||||
" ImmutableList.of(1.0);",
|
||||
" ImmutableList.of((Number) 1);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSet.of(1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSet.of(1.0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSet.of((Number) 1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSortedSet.of(1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSortedSet.of(1.0);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableSortedSet.of((Number) 1);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
|
||||
class A {
|
||||
void m() {
|
||||
ImmutableSet.of("foo");
|
||||
ImmutableSortedSet.of("foo");
|
||||
ImmutableList.of("foo");
|
||||
ImmutableList.of(1);
|
||||
ImmutableList.of(1.0);
|
||||
ImmutableList.of((Number) 1);
|
||||
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSet.of(1);
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSet.of(1.0);
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSet.of((Number) 1);
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSortedSet.of(1);
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSortedSet.of(1.0);
|
||||
// BUG: Diagnostic contains:
|
||||
ImmutableSortedSet.of((Number) 1);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -96,11 +100,13 @@ final class MoreMatchersTest {
|
||||
.withClasspath()
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" System.out.println(toString());",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
class A {
|
||||
void m() {
|
||||
System.out.println(toString());
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,91 +30,93 @@ final class MoreTypesTest {
|
||||
CompilationTestHelper.newInstance(SubtypeFlagger.class, getClass())
|
||||
.addSourceLines(
|
||||
"/A.java",
|
||||
"import java.util.Collection;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Map;",
|
||||
"import java.util.Optional;",
|
||||
"import java.util.Set;",
|
||||
"",
|
||||
"class A<S, T> {",
|
||||
" void m() {",
|
||||
" Object object = factory();",
|
||||
" A a = factory();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: [Number, ? super Number, Integer, ? super Integer]",
|
||||
" int integer = factory();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: [String]",
|
||||
" String string = factory();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: [Optional]",
|
||||
" Optional rawOptional = factory();",
|
||||
" // BUG: Diagnostic contains: [Optional, Optional<?>]",
|
||||
" Optional<S> optionalOfS = factory();",
|
||||
" // BUG: Diagnostic contains: [Optional, Optional<?>]",
|
||||
" Optional<T> optionalOfT = factory();",
|
||||
" // BUG: Diagnostic contains: [Optional, Optional<?>, Optional<Number>]",
|
||||
" Optional<Number> optionalOfNumber = factory();",
|
||||
" // BUG: Diagnostic contains: [Optional, Optional<?>]",
|
||||
" Optional<Integer> optionalOfInteger = factory();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: [Collection]",
|
||||
" Collection rawCollection = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<Number>, Collection<? super",
|
||||
" // Number>, Collection<? extends Number>, Collection<? super Integer>]",
|
||||
" Collection<Number> collectionOfNumber = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>,",
|
||||
" // Collection<Integer>, Collection<? super Integer>, Collection<? extends Integer>]",
|
||||
" Collection<Integer> collectionOfInteger = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>]",
|
||||
" Collection<Short> collectionOfShort = factory();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: [Collection, List]",
|
||||
" List rawList = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<Number>, Collection<? super",
|
||||
" // Number>, Collection<? extends Number>, Collection<? super Integer>, List, List<?>,",
|
||||
" // List<Number>, List<? super Number>, List<? extends Number>, List<? super Integer>]",
|
||||
" List<Number> listOfNumber = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>,",
|
||||
" // Collection<Integer>, Collection<? super Integer>, Collection<? extends Integer>, List,",
|
||||
" // List<?>, List<? extends Number>, List<Integer>, List<? super Integer>, List<? extends",
|
||||
" // Integer>]",
|
||||
" List<Integer> listOfInteger = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>, List,",
|
||||
" // List<?>, List<? extends Number>]",
|
||||
" List<Short> listOfShort = factory();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: [Collection]",
|
||||
" Set rawSet = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<Number>, Collection<? super",
|
||||
" // Number>, Collection<? extends Number>, Collection<? super Integer>]",
|
||||
" Set<Number> setOfNumber = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>,",
|
||||
" // Collection<Integer>, Collection<? super Integer>, Collection<? extends Integer>]",
|
||||
" Set<Integer> setOfInteger = factory();",
|
||||
" // BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>]",
|
||||
" Set<Short> setOfShort = factory();",
|
||||
"",
|
||||
" Map rawMap = factory();",
|
||||
" Map<Number, Collection<Number>> mapFromNumberToCollectionOfNumber = factory();",
|
||||
" Map<Number, Collection<Short>> mapFromNumberToCollectionOfShort = factory();",
|
||||
" Map<Number, Collection<Integer>> mapFromNumberToCollectionOfInteger = factory();",
|
||||
" // BUG: Diagnostic contains: [Map<String, ? extends Collection<? super Short>>]",
|
||||
" Map<String, Collection<Number>> mapFromStringToCollectionOfNumber = factory();",
|
||||
" // BUG: Diagnostic contains: [Map<String, ? extends Collection<? super Short>>]",
|
||||
" Map<String, Collection<Short>> mapFromStringToCollectionOfShort = factory();",
|
||||
" Map<String, Collection<Integer>> mapFromStringToCollectionOfInteger = factory();",
|
||||
" // BUG: Diagnostic contains: [Map<String, ? extends Collection<? super Short>>]",
|
||||
" Map<String, List<Number>> mapFromStringToListOfNumber = factory();",
|
||||
" // BUG: Diagnostic contains: [Map<String, ? extends Collection<? super Short>>]",
|
||||
" Map<String, List<Short>> mapFromStringToListOfShort = factory();",
|
||||
" Map<String, List<Integer>> mapFromStringToListOfInteger = factory();",
|
||||
" }",
|
||||
"",
|
||||
" private <T> T factory() {",
|
||||
" return null;",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
class A<S, T> {
|
||||
void m() {
|
||||
Object object = factory();
|
||||
A a = factory();
|
||||
|
||||
// BUG: Diagnostic contains: [Number, ? super Number, Integer, ? super Integer]
|
||||
int integer = factory();
|
||||
|
||||
// BUG: Diagnostic contains: [String]
|
||||
String string = factory();
|
||||
|
||||
// BUG: Diagnostic contains: [Optional]
|
||||
Optional rawOptional = factory();
|
||||
// BUG: Diagnostic contains: [Optional, Optional<?>]
|
||||
Optional<S> optionalOfS = factory();
|
||||
// BUG: Diagnostic contains: [Optional, Optional<?>]
|
||||
Optional<T> optionalOfT = factory();
|
||||
// BUG: Diagnostic contains: [Optional, Optional<?>, Optional<Number>]
|
||||
Optional<Number> optionalOfNumber = factory();
|
||||
// BUG: Diagnostic contains: [Optional, Optional<?>]
|
||||
Optional<Integer> optionalOfInteger = factory();
|
||||
|
||||
// BUG: Diagnostic contains: [Collection]
|
||||
Collection rawCollection = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<Number>, Collection<? super
|
||||
// Number>, Collection<? extends Number>, Collection<? super Integer>]
|
||||
Collection<Number> collectionOfNumber = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>,
|
||||
// Collection<Integer>, Collection<? super Integer>, Collection<? extends Integer>]
|
||||
Collection<Integer> collectionOfInteger = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>]
|
||||
Collection<Short> collectionOfShort = factory();
|
||||
|
||||
// BUG: Diagnostic contains: [Collection, List]
|
||||
List rawList = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<Number>, Collection<? super
|
||||
// Number>, Collection<? extends Number>, Collection<? super Integer>, List, List<?>,
|
||||
// List<Number>, List<? super Number>, List<? extends Number>, List<? super Integer>]
|
||||
List<Number> listOfNumber = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>,
|
||||
// Collection<Integer>, Collection<? super Integer>, Collection<? extends Integer>, List,
|
||||
// List<?>, List<? extends Number>, List<Integer>, List<? super Integer>, List<? extends
|
||||
// Integer>]
|
||||
List<Integer> listOfInteger = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>, List,
|
||||
// List<?>, List<? extends Number>]
|
||||
List<Short> listOfShort = factory();
|
||||
|
||||
// BUG: Diagnostic contains: [Collection]
|
||||
Set rawSet = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<Number>, Collection<? super
|
||||
// Number>, Collection<? extends Number>, Collection<? super Integer>]
|
||||
Set<Number> setOfNumber = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>,
|
||||
// Collection<Integer>, Collection<? super Integer>, Collection<? extends Integer>]
|
||||
Set<Integer> setOfInteger = factory();
|
||||
// BUG: Diagnostic contains: [Collection, Collection<?>, Collection<? extends Number>]
|
||||
Set<Short> setOfShort = factory();
|
||||
|
||||
Map rawMap = factory();
|
||||
Map<Number, Collection<Number>> mapFromNumberToCollectionOfNumber = factory();
|
||||
Map<Number, Collection<Short>> mapFromNumberToCollectionOfShort = factory();
|
||||
Map<Number, Collection<Integer>> mapFromNumberToCollectionOfInteger = factory();
|
||||
// BUG: Diagnostic contains: [Map<String, ? extends Collection<? super Short>>]
|
||||
Map<String, Collection<Number>> mapFromStringToCollectionOfNumber = factory();
|
||||
// BUG: Diagnostic contains: [Map<String, ? extends Collection<? super Short>>]
|
||||
Map<String, Collection<Short>> mapFromStringToCollectionOfShort = factory();
|
||||
Map<String, Collection<Integer>> mapFromStringToCollectionOfInteger = factory();
|
||||
// BUG: Diagnostic contains: [Map<String, ? extends Collection<? super Short>>]
|
||||
Map<String, List<Number>> mapFromStringToListOfNumber = factory();
|
||||
// BUG: Diagnostic contains: [Map<String, ? extends Collection<? super Short>>]
|
||||
Map<String, List<Short>> mapFromStringToListOfShort = factory();
|
||||
Map<String, List<Integer>> mapFromStringToListOfInteger = factory();
|
||||
}
|
||||
|
||||
private <T> T factory() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,92 +5,136 @@ import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.ReturnTreeMatcher;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.ReturnTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import javax.lang.model.element.Name;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledForJreRange;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
final class SourceCodeTest {
|
||||
@DisabledForJreRange(max = JRE.JAVA_14)
|
||||
@Test
|
||||
void isTextBlock() {
|
||||
CompilationTestHelper.newInstance(TextBlockFlagger.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"""
|
||||
class A {
|
||||
String negative1() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
String negative2() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
String positive1() {
|
||||
// BUG: Diagnostic contains:
|
||||
return ""\"
|
||||
foo
|
||||
""\";
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteWithTrailingWhitespaceAnnotations() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
DeleteWithTrailingWhitespaceTestChecker.class, getClass())
|
||||
.addInputLines("AnnotationToBeDeleted.java", "@interface AnnotationToBeDeleted {}")
|
||||
.addInputLines(
|
||||
"AnnotationToBeDeleted.java",
|
||||
"""
|
||||
@interface AnnotationToBeDeleted {}
|
||||
""")
|
||||
.expectUnchanged()
|
||||
.addInputLines(
|
||||
"AnotherAnnotationToBeDeleted.java", "@interface AnotherAnnotationToBeDeleted {}")
|
||||
"AnotherAnnotationToBeDeleted.java",
|
||||
"""
|
||||
@interface AnotherAnnotationToBeDeleted {}
|
||||
""")
|
||||
.expectUnchanged()
|
||||
.addInputLines(
|
||||
"AnnotationDeletions.java",
|
||||
"interface AnnotationDeletions {",
|
||||
" class SoleAnnotation {",
|
||||
" @AnnotationToBeDeleted",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"",
|
||||
" class FirstAnnotation {",
|
||||
" @AnnotationToBeDeleted",
|
||||
" @Deprecated",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"",
|
||||
" class MiddleAnnotation {",
|
||||
" @Deprecated",
|
||||
" @AnnotationToBeDeleted",
|
||||
" @SuppressWarnings(\"foo\")",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"",
|
||||
" class LastAnnotation {",
|
||||
" @Deprecated",
|
||||
" @AnnotationToBeDeleted",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"",
|
||||
" class MultipleAnnotations {",
|
||||
" @AnnotationToBeDeleted",
|
||||
" @AnotherAnnotationToBeDeleted",
|
||||
" @Deprecated",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
interface AnnotationDeletions {
|
||||
class SoleAnnotation {
|
||||
@AnnotationToBeDeleted
|
||||
void m() {}
|
||||
}
|
||||
|
||||
class FirstAnnotation {
|
||||
@AnnotationToBeDeleted
|
||||
@Deprecated
|
||||
void m() {}
|
||||
}
|
||||
|
||||
class MiddleAnnotation {
|
||||
@Deprecated
|
||||
@AnnotationToBeDeleted
|
||||
@SuppressWarnings("foo")
|
||||
void m() {}
|
||||
}
|
||||
|
||||
class LastAnnotation {
|
||||
@Deprecated
|
||||
@AnnotationToBeDeleted
|
||||
void m() {}
|
||||
}
|
||||
|
||||
class MultipleAnnotations {
|
||||
@AnnotationToBeDeleted
|
||||
@AnotherAnnotationToBeDeleted
|
||||
@Deprecated
|
||||
void m() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"AnnotationDeletions.java",
|
||||
"interface AnnotationDeletions {",
|
||||
" class SoleAnnotation {",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"",
|
||||
" class FirstAnnotation {",
|
||||
" @Deprecated",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"",
|
||||
" class MiddleAnnotation {",
|
||||
" @Deprecated",
|
||||
" @SuppressWarnings(\"foo\")",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"",
|
||||
" class LastAnnotation {",
|
||||
" @Deprecated",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"",
|
||||
" class MultipleAnnotations {",
|
||||
" @Deprecated",
|
||||
" void m() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
interface AnnotationDeletions {
|
||||
class SoleAnnotation {
|
||||
void m() {}
|
||||
}
|
||||
|
||||
class FirstAnnotation {
|
||||
@Deprecated
|
||||
void m() {}
|
||||
}
|
||||
|
||||
class MiddleAnnotation {
|
||||
@Deprecated
|
||||
@SuppressWarnings("foo")
|
||||
void m() {}
|
||||
}
|
||||
|
||||
class LastAnnotation {
|
||||
@Deprecated
|
||||
void m() {}
|
||||
}
|
||||
|
||||
class MultipleAnnotations {
|
||||
@Deprecated
|
||||
void m() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -100,66 +144,70 @@ final class SourceCodeTest {
|
||||
DeleteWithTrailingWhitespaceTestChecker.class, getClass())
|
||||
.addInputLines(
|
||||
"MethodDeletions.java",
|
||||
"interface MethodDeletions {",
|
||||
" class SoleMethod {",
|
||||
" void methodToBeDeleted() {}",
|
||||
" }",
|
||||
"",
|
||||
" class FirstMethod {",
|
||||
" void methodToBeDeleted() {}",
|
||||
"",
|
||||
" void finalMethod() {}",
|
||||
" }",
|
||||
"",
|
||||
" class MiddleMethod {",
|
||||
" void initialMethod() {}",
|
||||
"",
|
||||
" void methodToBeDeleted() {}",
|
||||
"",
|
||||
" void finalMethod() {}",
|
||||
" }",
|
||||
"",
|
||||
" class LastMethod {",
|
||||
" void initialMethod() {}",
|
||||
"",
|
||||
" void methodToBeDeleted() {}",
|
||||
" }",
|
||||
"",
|
||||
" class MultipleMethods {",
|
||||
" void method1ToBeDeleted() {}",
|
||||
"",
|
||||
" void method2ToBeDeleted() {}",
|
||||
"",
|
||||
" void middleMethod() {}",
|
||||
"",
|
||||
" void method3ToBeDeleted() {}",
|
||||
"",
|
||||
" void method4ToBeDeleted() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
interface MethodDeletions {
|
||||
class SoleMethod {
|
||||
void methodToBeDeleted() {}
|
||||
}
|
||||
|
||||
class FirstMethod {
|
||||
void methodToBeDeleted() {}
|
||||
|
||||
void finalMethod() {}
|
||||
}
|
||||
|
||||
class MiddleMethod {
|
||||
void initialMethod() {}
|
||||
|
||||
void methodToBeDeleted() {}
|
||||
|
||||
void finalMethod() {}
|
||||
}
|
||||
|
||||
class LastMethod {
|
||||
void initialMethod() {}
|
||||
|
||||
void methodToBeDeleted() {}
|
||||
}
|
||||
|
||||
class MultipleMethods {
|
||||
void method1ToBeDeleted() {}
|
||||
|
||||
void method2ToBeDeleted() {}
|
||||
|
||||
void middleMethod() {}
|
||||
|
||||
void method3ToBeDeleted() {}
|
||||
|
||||
void method4ToBeDeleted() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"MethodDeletions.java",
|
||||
"interface MethodDeletions {",
|
||||
" class SoleMethod {}",
|
||||
"",
|
||||
" class FirstMethod {",
|
||||
" void finalMethod() {}",
|
||||
" }",
|
||||
"",
|
||||
" class MiddleMethod {",
|
||||
" void initialMethod() {}",
|
||||
"",
|
||||
" void finalMethod() {}",
|
||||
" }",
|
||||
"",
|
||||
" class LastMethod {",
|
||||
" void initialMethod() {}",
|
||||
" }",
|
||||
"",
|
||||
" class MultipleMethods {",
|
||||
" void middleMethod() {}",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
interface MethodDeletions {
|
||||
class SoleMethod {}
|
||||
|
||||
class FirstMethod {
|
||||
void finalMethod() {}
|
||||
}
|
||||
|
||||
class MiddleMethod {
|
||||
void initialMethod() {}
|
||||
|
||||
void finalMethod() {}
|
||||
}
|
||||
|
||||
class LastMethod {
|
||||
void initialMethod() {}
|
||||
}
|
||||
|
||||
class MultipleMethods {
|
||||
void middleMethod() {}
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -168,30 +216,34 @@ final class SourceCodeTest {
|
||||
BugCheckerRefactoringTestHelper.newInstance(UnwrapMethodInvocationTestChecker.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"",
|
||||
"class A {",
|
||||
" Object[] m() {",
|
||||
" return new Object[][] {",
|
||||
" {ImmutableList.of()},",
|
||||
" {ImmutableList.of(1)},",
|
||||
" {com.google.common.collect.ImmutableList.of(1, 2)},",
|
||||
" {",
|
||||
" 0, /*a*/",
|
||||
" ImmutableList /*b*/./*c*/ <Integer> /*d*/of /*e*/(/*f*/ 1 /*g*/, /*h*/ 2 /*i*/) /*j*/",
|
||||
" }",
|
||||
" };",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
class A {
|
||||
Object[] m() {
|
||||
return new Object[][] {
|
||||
{ImmutableList.of()},
|
||||
{ImmutableList.of(1)},
|
||||
{com.google.common.collect.ImmutableList.of(1, 2)},
|
||||
{
|
||||
0, /*a*/
|
||||
ImmutableList /*b*/./*c*/ <Integer> /*d*/of /*e*/(/*f*/ 1 /*g*/, /*h*/ 2 /*i*/) /*j*/
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"",
|
||||
"class A {",
|
||||
" Object[] m() {",
|
||||
" return new Object[][] {{}, {1}, {1, 2}, {0, /*a*/ /*f*/ 1 /*g*/, /*h*/ 2 /*i*/ /*j*/}};",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
class A {
|
||||
Object[] m() {
|
||||
return new Object[][] {{}, {1}, {1, 2}, {0, /*a*/ /*f*/ 1 /*g*/, /*h*/ 2 /*i*/ /*j*/}};
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -201,33 +253,53 @@ final class SourceCodeTest {
|
||||
UnwrapMethodInvocationDroppingWhitespaceAndCommentsTestChecker.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"",
|
||||
"class A {",
|
||||
" Object[] m() {",
|
||||
" return new Object[][] {",
|
||||
" {ImmutableList.of()},",
|
||||
" {ImmutableList.of(1)},",
|
||||
" {com.google.common.collect.ImmutableList.of(1, 2)},",
|
||||
" {",
|
||||
" 0, /*a*/",
|
||||
" ImmutableList /*b*/./*c*/ <Integer> /*d*/of /*e*/(/*f*/ 1 /*g*/, /*h*/ 2 /*i*/) /*j*/",
|
||||
" }",
|
||||
" };",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
class A {
|
||||
Object[] m() {
|
||||
return new Object[][] {
|
||||
{ImmutableList.of()},
|
||||
{ImmutableList.of(1)},
|
||||
{com.google.common.collect.ImmutableList.of(1, 2)},
|
||||
{
|
||||
0, /*a*/
|
||||
ImmutableList /*b*/./*c*/ <Integer> /*d*/of /*e*/(/*f*/ 1 /*g*/, /*h*/ 2 /*i*/) /*j*/
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
""")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"",
|
||||
"class A {",
|
||||
" Object[] m() {",
|
||||
" return new Object[][] {{}, {1}, {1, 2}, {0, /*a*/ 1, 2 /*j*/}};",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
class A {
|
||||
Object[] m() {
|
||||
return new Object[][] {{}, {1}, {1, 2}, {0, /*a*/ 1, 2 /*j*/}};
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that delegates to {@link SourceCode#isTextBlock(ExpressionTree,
|
||||
* VisitorState)}.
|
||||
*/
|
||||
@BugPattern(summary = "Interacts with `SourceCode` for testing purposes", severity = ERROR)
|
||||
public static final class TextBlockFlagger extends BugChecker implements ReturnTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Description matchReturn(ReturnTree tree, VisitorState state) {
|
||||
return SourceCode.isTextBlock(tree.getExpression(), state)
|
||||
? describeMatch(tree)
|
||||
: Description.NO_MATCH;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that uses {@link SourceCode#deleteWithTrailingWhitespace(Tree,
|
||||
* VisitorState)} to suggest the deletion of annotations and methods with a name containing
|
||||
|
||||
@@ -23,8 +23,10 @@ final class ThirdPartyLibraryTest {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"// BUG: Diagnostic contains: ASSERTJ: true, GUAVA: true, REACTOR: true",
|
||||
"class A {}")
|
||||
"""
|
||||
// BUG: Diagnostic contains: ASSERTJ: true, GUAVA: true, REACTOR: true
|
||||
class A {}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -33,18 +35,20 @@ final class ThirdPartyLibraryTest {
|
||||
CompilationTestHelper.newInstance(TestChecker.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import org.assertj.core.api.Assertions;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"// BUG: Diagnostic contains: ASSERTJ: true, GUAVA: true, REACTOR: true",
|
||||
"class A {",
|
||||
" void m(Class<?> clazz) {",
|
||||
" m(Assertions.class);",
|
||||
" m(ImmutableList.class);",
|
||||
" m(Flux.class);",
|
||||
" }",
|
||||
"}")
|
||||
"""
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
// BUG: Diagnostic contains: ASSERTJ: true, GUAVA: true, REACTOR: true
|
||||
class A {
|
||||
void m(Class<?> clazz) {
|
||||
m(Assertions.class);
|
||||
m(ImmutableList.class);
|
||||
m(Flux.class);
|
||||
}
|
||||
}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -54,8 +58,10 @@ final class ThirdPartyLibraryTest {
|
||||
.withClasspath(ImmutableList.class, Flux.class)
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"// BUG: Diagnostic contains: ASSERTJ: false, GUAVA: true, REACTOR: true",
|
||||
"class A {}")
|
||||
"""
|
||||
// BUG: Diagnostic contains: ASSERTJ: false, GUAVA: true, REACTOR: true
|
||||
class A {}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@@ -65,9 +71,11 @@ final class ThirdPartyLibraryTest {
|
||||
.withClasspath()
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"// BUG: Diagnostic contains: ASSERTJ: false, GUAVA: false, REACTOR:",
|
||||
"// false",
|
||||
"class A {}")
|
||||
"""
|
||||
// BUG: Diagnostic contains: ASSERTJ: false, GUAVA: false, REACTOR:
|
||||
// false
|
||||
class A {}
|
||||
""")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
|
||||
140
openai-coder/README.md
Normal file
140
openai-coder/README.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# OpenAI Coder
|
||||
|
||||
A command line utility that queries OpenAI for code fixes based on error and
|
||||
warning messages extracted from Maven build output.
|
||||
|
||||
## Open topics and ideas.
|
||||
|
||||
* Apply suggstions from https://clig.dev/.
|
||||
* Review ideas from
|
||||
http://catb.org/~esr/writings/taoup/html/ch10s05.html#id2948149 (e.g. `-b`).
|
||||
* Add support for an interactive mode, in which the user is prompted to
|
||||
confirm an identified issue before sending it to OpenAI.
|
||||
* In case multiple issues are reported against a single file, the user
|
||||
should be able to (a) select which issue(s) to send to OpenAI and (b)
|
||||
whether to batch the requests.
|
||||
* The user should be able to accept or reject the OpenAI response.
|
||||
* The user should be able to (re)try with a higher or lower temperature.
|
||||
* If a change is accepted, the user may opt to resubmit the modified file
|
||||
with a (new) subset of the reported issues.
|
||||
* The user should be able to modify the OpenAI request payload before
|
||||
sending it.
|
||||
|
||||
(Check whether this can be done with Picocli (see below); otherwise check
|
||||
out [JLine](https://jline.github.io/jline3/).)
|
||||
* Integrate with [Picocli](https://picocli.info/) (or similar) to make the
|
||||
command line interface more user-friendly.
|
||||
* Add a `--dry-run` flag that only prints the issues that would be reported
|
||||
to OpenAI.
|
||||
* Add a `--verbose` flag that prints the OpenAI request and response
|
||||
payloads, or some abstraction thereof.
|
||||
* Add a `--no-interactive` flag that does not prompt the user to confirm
|
||||
the issue before sending it to OpenAI.
|
||||
* Add flags to include/exclude certain types of issues and files from being
|
||||
processed.
|
||||
* Add a `--help` flag that prints a help message.
|
||||
* Add a `--run-to-fix <command>` (name TBD) flag that repeatedly runs the
|
||||
given command in a sub-process and processes the output until either no
|
||||
further issues are reported, or no further fixes are found. (For this we
|
||||
could use `ProcessBuilder`.)
|
||||
* Add a `--git-safe` (name TBD) flag that only processes files that are
|
||||
tracked by Git and that have not been modified.
|
||||
* Add a `--format <format>` flag that allows the user to specify the
|
||||
format of the input. E.g. `--format maven` (default), `--format
|
||||
errorprone`, `--format sarif`, etc.
|
||||
* Add a `--patch-context <lines>` flag that allows the user to specify the
|
||||
number of lines of context to include in presented unified patches.
|
||||
* Create a binary image using [GraalVM](https://www.graalvm.org/).
|
||||
* Add support for sending a suitable subset of the code to OpenAI, so as (a) to
|
||||
better deal with the token limit and (b) potentially reduce cost. This might
|
||||
take the form of using the line numbers of the issue to extract code section,
|
||||
as well as any relevant context. E.g. by replacing the source of irrelevant
|
||||
members with a unique placeholder. When the response is received, the
|
||||
placeholders are replaced with the original code.
|
||||
* Add support for parsing other formats (next to Maven build output). E.g.
|
||||
Sarif.
|
||||
* Add support for a mode in which a file (or if we can pull it off: a group of
|
||||
files) is explicitly specified to be processed using instructions entered
|
||||
interactively or non-interactively.
|
||||
* Introduce an `IssueExtractor` for Error Prone test compiler output.
|
||||
* Write an `IssueExtractor` for the output of the `dependency:analyze` Maven
|
||||
goal:
|
||||
```
|
||||
[INFO] --- dependency:3.5.0:analyze-only (analyze-dependencies) @ openai-coder ---
|
||||
[WARNING] Used undeclared dependencies found:
|
||||
[WARNING] com.google.code.findbugs:jsr305:jar:3.0.2:compile
|
||||
[WARNING] com.theokanning.openai-gpt3-java:api:jar:0.12.0:compile
|
||||
[WARNING] org.junit.jupiter:junit-jupiter-api:jar:5.9.2:test
|
||||
[WARNING] io.github.java-diff-utils:java-diff-utils:jar:4.0:compile
|
||||
[WARNING] Unused declared dependencies found:
|
||||
[WARNING] com.fasterxml.jackson.core:jackson-databind:jar:2.14.2:compile
|
||||
[WARNING] tech.picnic.error-prone-support:refaster-runner:jar:0.9.1-SNAPSHOT:compile
|
||||
[WARNING] com.google.errorprone:error_prone_check_api:jar:2.18.0:compile
|
||||
[WARNING] com.google.errorprone:error_prone_annotation:jar:2.18.0:compile
|
||||
[WARNING] com.google.errorprone:error_prone_test_helpers:jar:2.18.0:compile
|
||||
[WARNING] org.springframework:spring-core:jar:5.3.26:compile
|
||||
```
|
||||
This could e.g. be transformed to:
|
||||
```
|
||||
[INFO] --- dependency:3.5.0:analyze-only (analyze-dependencies) @ openai-coder ---
|
||||
[WARNING] Used undeclared dependencies found:
|
||||
[WARNING] com.google.code.findbugs:jsr305:jar:3.0.2:compile
|
||||
[WARNING] com.theokanning.openai-gpt3-java:api:jar:0.12.0:compile
|
||||
[WARNING] org.junit.jupiter:junit-jupiter-api:jar:5.9.2:test
|
||||
[WARNING] io.github.java-diff-utils:java-diff-utils:jar:4.0:compile
|
||||
[WARNING] Unused declared dependencies found:
|
||||
[WARNING] com.fasterxml.jackson.core:jackson-databind:jar:2.14.2:compile
|
||||
[WARNING] tech.picnic.error-prone-support:refaster-runner:jar:0.9.1-SNAPSHOT:compile
|
||||
[WARNING] com.google.errorprone:error_prone_check_api:jar:2.18.0:compile
|
||||
[WARNING] com.google.errorprone:error_prone_annotation:jar:2.18.0:compile
|
||||
[WARNING] com.google.errorprone:error_prone_test_helpers:jar:2.18.0:compile
|
||||
[WARNING] org.springframework:spring-core:jar:5.3.26:compile
|
||||
```
|
||||
(Though `type` and `version` can then conditionally be omitted.)
|
||||
|
||||
The problem: the relevant `pom.xml` file is not available in the Maven
|
||||
output. It could be inferred from the preceding `dependency:analyze` line,
|
||||
but that line is logged at the `INFO` level, which is not extracted by
|
||||
the `LogLineExtractor`.
|
||||
|
||||
# Interactive mode API ideation
|
||||
|
||||
For each file, the user is presented with a list of issues:
|
||||
|
||||
```
|
||||
Issues in `/path/to/File.java`:
|
||||
1. Issue 1.
|
||||
2. Issue 2.
|
||||
3. Issue 3.
|
||||
|
||||
Action [submit]: <prompt>
|
||||
```
|
||||
|
||||
Upon submitting the issues to OpenAI, the user is presented with a unified
|
||||
patch of the suggested changes:
|
||||
|
||||
```
|
||||
Suggested changes:
|
||||
<diff>
|
||||
|
||||
Action [apply]: <prompt>
|
||||
```
|
||||
|
||||
Commands:
|
||||
|
||||
- If empty, then apply the appropriate default, depending on context:
|
||||
- If the most recent prompt listed the issues, then submit all issues to
|
||||
OpenAI (`submit`).
|
||||
- If the most recent prompt listed the suggested fixes, then apply the
|
||||
suggested fixes (`apply`).
|
||||
- `h`/`help`: Print help message.
|
||||
- `i`/`issues`: Print list of issues.
|
||||
- `s`/`submit [<issue>, ...]`: Submit all or the given issues to OpenAI.
|
||||
- `a`/`apply`: Apply the suggested changes:
|
||||
- If no changes have yet been suggested, then print a message and prompt
|
||||
again.
|
||||
- If changes have been suggested, then apply them, print a message and move
|
||||
on to the next file.
|
||||
- `q`/`quit`: Quit the program.
|
||||
- `n`/`next`: Skip the current file.
|
||||
- `p`/`prev`/`previous`: Go back to the previous file.
|
||||
110
openai-coder/pom.xml
Normal file
110
openai-coder/pom.xml
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.9.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openai-coder</artifactId>
|
||||
|
||||
<name>Picnic :: Error Prone Support :: OpenAI Coder</name>
|
||||
<description>Experimental tools that integrate with the OpenAI API.</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-runner</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.jimfs</groupId>
|
||||
<artifactId>jimfs</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.theokanning.openai-gpt3-java</groupId>
|
||||
<artifactId>service</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.picocli</groupId>
|
||||
<artifactId>picocli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.picocli</groupId>
|
||||
<artifactId>picocli-shell-jline3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.fusesource.jansi</groupId>
|
||||
<artifactId>jansi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jline</groupId>
|
||||
<artifactId>jline</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,160 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.WillClose;
|
||||
import javax.annotation.WillNotClose;
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Parameters;
|
||||
import tech.picnic.errorprone.openai.IssueExtractor.Issue;
|
||||
|
||||
@Command(name = "", mixinStandardHelpOptions = true, description = "OpenAI Coder CLI.")
|
||||
public final class AiCoder {
|
||||
/** The name of the environment variable containing the OpenAI token. */
|
||||
private static final String OPENAI_TOKEN_VARIABLE = "OPENAI_TOKEN";
|
||||
|
||||
private final OpenAi openAi;
|
||||
private final PrintStream out;
|
||||
private final PrintStream err;
|
||||
|
||||
private AiCoder(OpenAi openAi, @WillNotClose PrintStream out, @WillNotClose PrintStream err) {
|
||||
this.openAi = openAi;
|
||||
this.out = out;
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "process-build-output",
|
||||
mixinStandardHelpOptions = true,
|
||||
showEndOfOptionsDelimiterInUsageHelp = true,
|
||||
description = "Attempts to resolve issues extracted from build output.")
|
||||
void processBuildOutput(
|
||||
@Option(
|
||||
names = {"-a", "--auto-fix"},
|
||||
description = "Submit all issues to OpenAI and accept the results.")
|
||||
boolean autoFix,
|
||||
@Option(
|
||||
names = {"-c", "--command"},
|
||||
description =
|
||||
"Interpret the positional arguments as a command to be executed, rather than output files.")
|
||||
boolean command,
|
||||
@Parameters(description = "The files containing the build output or the command to run.")
|
||||
List<String> filesOrCommand) {
|
||||
// XXX: Replace this code.
|
||||
if (autoFix) {
|
||||
// XXX: Implement auto-fixing.
|
||||
System.out.println("Auto-fixing issues in " + filesOrCommand);
|
||||
} else {
|
||||
// XXX: Implement analyzing.
|
||||
System.out.println("Analyzing issues in " + filesOrCommand);
|
||||
}
|
||||
|
||||
Supplier<ImmutableSet<Issue<Path>>> issueSupplier =
|
||||
command
|
||||
? () -> extractIssues(ImmutableList.copyOf(filesOrCommand), out, err)
|
||||
: () ->
|
||||
filesOrCommand.stream()
|
||||
.flatMap(f -> extractIssues(Path.of(f)).stream())
|
||||
.collect(toImmutableSet());
|
||||
|
||||
InteractiveBuildOutputProcessor.run(openAi, issueSupplier);
|
||||
}
|
||||
|
||||
private static ImmutableSet<Issue<Path>> extractIssues(
|
||||
ImmutableList<String> command, PrintStream out, PrintStream err) {
|
||||
try {
|
||||
// XXX: If `ctrl-c` is pressed while the command is running, then seemingly JLine does't
|
||||
// intercept it. Investigate.
|
||||
Process process = new ProcessBuilder(command).start();
|
||||
|
||||
StringBuilder collectedOutput = new StringBuilder();
|
||||
try (InputStream processOutput = process.getInputStream();
|
||||
BufferedReader output = new BufferedReader(new InputStreamReader(processOutput, UTF_8))) {
|
||||
String line = null;
|
||||
for (line = output.readLine(); line != null; line = output.readLine()) {
|
||||
out.println(line);
|
||||
collectedOutput.append(line).append('\n');
|
||||
}
|
||||
process.waitFor();
|
||||
// XXX: Report the exit code?
|
||||
// XXX: Process the output.
|
||||
} catch (InterruptedException e) {
|
||||
err.println("Interrupted while waiting for process to finish.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
// XXX: This `ByteArrayInputStream` usage is dodgy. Review.
|
||||
return extractIssues(new ByteArrayInputStream(collectedOutput.toString().getBytes(UTF_8)));
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(
|
||||
String.format(
|
||||
"Failed to execute or parse result of command '%s'", String.join(" ", command)),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
private static ImmutableSet<Issue<Path>> extractIssues(Path file) {
|
||||
try (InputStream is = Files.newInputStream(file)) {
|
||||
return extractIssues(is);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(String.format("Failed to parse file '%s'", file), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static ImmutableSet<Issue<Path>> extractIssues(@WillClose InputStream inputStream)
|
||||
throws IOException {
|
||||
// XXX: Here and elsewhere: should we allow the cwd to be changed?
|
||||
IssueExtractor<Path> issueExtractor =
|
||||
new PathResolvingIssueExtractor(
|
||||
new PathFinder(FileSystems.getDefault(), Path.of("")),
|
||||
new SelectFirstIssueExtractor<>(
|
||||
ImmutableSet.of(
|
||||
new MavenCheckstyleIssueExtractor(), new PlexusCompilerIssueExtractor())));
|
||||
|
||||
return LogLineExtractor.mavenErrorAndWarningExtractor().extract(inputStream).stream()
|
||||
.flatMap(issueExtractor::extract)
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
AnsiConsole.systemInstall();
|
||||
try {
|
||||
String openAiToken = System.getenv(OPENAI_TOKEN_VARIABLE);
|
||||
if (openAiToken == null) {
|
||||
AnsiConsole.err().printf("Environment variable %s not set.%n", OPENAI_TOKEN_VARIABLE);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
try (OpenAi openAi = OpenAi.create(openAiToken)) {
|
||||
System.exit(createCommandLine(openAi).execute(args));
|
||||
}
|
||||
} finally {
|
||||
AnsiConsole.systemUninstall();
|
||||
}
|
||||
}
|
||||
|
||||
private static CommandLine createCommandLine(OpenAi openAi) {
|
||||
CommandLine commandLine =
|
||||
new CommandLine(new AiCoder(openAi, AnsiConsole.out(), AnsiConsole.err()));
|
||||
commandLine.getCommandSpec().version(AiCoder.class.getPackage().getImplementationVersion());
|
||||
return commandLine;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.Streams;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.openai.IssueExtractor.Issue;
|
||||
|
||||
public final class AiPatcher {
|
||||
private static final Pattern FILE_LOCATION_MARKER =
|
||||
Pattern.compile("^(.*?\\.java):\\[(\\d+)(?:,(\\d+))?\\] ");
|
||||
// XXX: Rename
|
||||
private static final String OPENAI_TOKEN_VARIABLE = "openapi_token";
|
||||
@Nullable private static final String OPENAI_TOKEN = System.getenv(OPENAI_TOKEN_VARIABLE);
|
||||
|
||||
// Allow a custom source lookup directory to be specified.
|
||||
// Group by file.
|
||||
public static void main(String... args) {
|
||||
if (OPENAI_TOKEN == null) {
|
||||
System.err.printf(
|
||||
"OpenAI API token not found in environment variable '%s'.%n", OPENAI_TOKEN_VARIABLE);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
suggestFixes(
|
||||
getIssuesByFile(LogLineExtractor.mavenErrorAndWarningExtractor().extract(System.in)));
|
||||
} catch (IOException e) {
|
||||
// XXX: Fix
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// Explicitly exit to prevent `mvn exec:java` from handing due to long-lived OkHTTP threads.
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static void suggestFixes(ImmutableSetMultimap<Path, String> issuesByFile)
|
||||
throws IOException {
|
||||
try (OpenAi openAi = OpenAi.create(OPENAI_TOKEN)) {
|
||||
for (Map.Entry<Path, Set<String>> e : Multimaps.asMap(issuesByFile).entrySet()) {
|
||||
suggestFixes(e.getKey(), e.getValue(), openAi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void suggestFixes(Path file, Set<String> issueDescriptions, OpenAi openAi)
|
||||
throws IOException {
|
||||
// XXX: Cleanup
|
||||
|
||||
String originalCode = Files.readString(file);
|
||||
|
||||
if (file.toString().contains("RefasterRuleCollection")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String instruction =
|
||||
Streams.mapWithIndex(
|
||||
issueDescriptions.stream(),
|
||||
(description, index) -> String.format("%s. %s", index + 1, description))
|
||||
.collect(joining("\n", "Resolve the following issues:\n", "\n"));
|
||||
|
||||
System.out.println("Instruction: " + instruction);
|
||||
|
||||
if (true) {
|
||||
// return;
|
||||
}
|
||||
|
||||
// XXX: Handle case with too much input/output (tokens).
|
||||
// XXX: Handle error messages.
|
||||
|
||||
String result = openAi.requestEdit(originalCode, instruction);
|
||||
|
||||
// XXX: !!! Don't create diff in patch mode; just apply the patch.
|
||||
System.out.printf("Fix for %s:%n", Diffs.unifiedDiff(originalCode, result, file.toString()));
|
||||
}
|
||||
|
||||
private static ImmutableSetMultimap<Path, String> getIssuesByFile(List<String> logMessages) {
|
||||
// XXX: Allow the path to be specified.
|
||||
IssueExtractor<Path> issueExtractor =
|
||||
new PathResolvingIssueExtractor(
|
||||
new PathFinder(FileSystems.getDefault(), Path.of("")),
|
||||
new SelectFirstIssueExtractor<>(
|
||||
ImmutableSet.of(
|
||||
new MavenCheckstyleIssueExtractor(), new PlexusCompilerIssueExtractor())));
|
||||
|
||||
return logMessages.stream()
|
||||
.flatMap(issueExtractor::extract)
|
||||
.collect(toImmutableSetMultimap(Issue::file, Issue::description));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import static org.fusesource.jansi.Ansi.ansi;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.UnifiedDiffUtils;
|
||||
import com.github.difflib.algorithm.DiffException;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.google.common.base.Splitter;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
final class Diffs {
|
||||
private Diffs() {}
|
||||
|
||||
// XXX: Review cross-platform newline usage.
|
||||
static String unifiedDiff(String before, String after, String path) {
|
||||
return String.join("\n", generateUnifiedDiffLines(before, after, path));
|
||||
}
|
||||
|
||||
// XXX: Review cross-platform newline usage.
|
||||
// XXX: Test!
|
||||
// XXX: Name?
|
||||
static void printUnifiedDiff(String before, String after, Path path, PrintWriter out) {
|
||||
for (String line : generateUnifiedDiffLines(before, after, path.toString())) {
|
||||
if (line.startsWith("+")) {
|
||||
out.println(ansi().fgGreen().a(line).reset());
|
||||
} else if (line.startsWith("-")) {
|
||||
out.println(ansi().fgRed().a(line).reset());
|
||||
} else if (line.startsWith("@@")) {
|
||||
out.println(ansi().fgYellow().a(line).reset());
|
||||
} else {
|
||||
out.println(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> generateUnifiedDiffLines(String before, String after, String path) {
|
||||
List<String> originalLines = Splitter.on('\n').splitToList(before);
|
||||
List<String> replacementLines = Splitter.on('\n').splitToList(after);
|
||||
|
||||
Patch<String> diff;
|
||||
try {
|
||||
diff = DiffUtils.diff(originalLines, replacementLines);
|
||||
} catch (DiffException e) {
|
||||
throw new IllegalStateException("Failed to create diff", e);
|
||||
}
|
||||
|
||||
return UnifiedDiffUtils.generateUnifiedDiff(path, path, originalLines, diff, 3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
// XXX: Use or drop.
|
||||
final class FileEditSuggester {
|
||||
private final OpenAi openAi;
|
||||
|
||||
FileEditSuggester(OpenAi openAi) {
|
||||
this.openAi = openAi;
|
||||
}
|
||||
|
||||
ImmutableList<EditSuggestion> suggestEdits(String fileContent) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
record EditSuggestion(String replacement, String unifiedPatch) {}
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Comparator.comparingInt;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.fusesource.jansi.Ansi.ansi;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.Streams;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.IntStream;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import org.fusesource.jansi.Ansi;
|
||||
import org.jline.console.SystemRegistry;
|
||||
import org.jline.console.impl.SystemRegistryImpl;
|
||||
import org.jline.keymap.KeyMap;
|
||||
import org.jline.reader.EndOfFileException;
|
||||
import org.jline.reader.LineReader;
|
||||
import org.jline.reader.LineReaderBuilder;
|
||||
import org.jline.reader.MaskingCallback;
|
||||
import org.jline.reader.Parser;
|
||||
import org.jline.reader.Reference;
|
||||
import org.jline.reader.UserInterruptException;
|
||||
import org.jline.reader.impl.DefaultParser;
|
||||
import org.jline.terminal.Terminal;
|
||||
import org.jline.terminal.TerminalBuilder;
|
||||
import org.jline.widget.TailTipWidgets;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.HelpCommand;
|
||||
import picocli.CommandLine.Parameters;
|
||||
import picocli.shell.jline3.PicocliCommands;
|
||||
import picocli.shell.jline3.PicocliCommands.PicocliCommandsFactory;
|
||||
import tech.picnic.errorprone.openai.IssueExtractor.Issue;
|
||||
|
||||
// XXX: Review whether to enable a *subset* of JLine's built-ins. See
|
||||
// https://github.com/remkop/picocli/tree/main/picocli-shell-jline3#jline-316-and-picocli-44-example.
|
||||
// XXX: Consider utilizing `less` for paging. See
|
||||
// https://github.com/jline/jline3/wiki/Nano-and-Less-Customization.
|
||||
// XXX: Should we even support those `files.isEmpty()` cases?
|
||||
// XXX: Allow issues to be dropped?
|
||||
// XXX: Mark files modified/track modification count?
|
||||
// XXX: List full diff over multiple rounds?
|
||||
// XXX: Allow submission of a custom instruction.
|
||||
@Command(name = "")
|
||||
@NotThreadSafe
|
||||
final class InteractiveBuildOutputProcessor {
|
||||
private final OpenAi openAi;
|
||||
private final PrintWriter out;
|
||||
private final Supplier<ImmutableSet<Issue<Path>>> issueSupplier;
|
||||
private ImmutableList<FileIssues> files = ImmutableList.of();
|
||||
private int currentIndex = 0;
|
||||
|
||||
InteractiveBuildOutputProcessor(
|
||||
OpenAi openAi, PrintWriter output, Supplier<ImmutableSet<Issue<Path>>> issueSupplier) {
|
||||
this.openAi = openAi;
|
||||
this.out = output;
|
||||
this.issueSupplier = issueSupplier;
|
||||
}
|
||||
|
||||
// XXX: Replace `Supplier<ImmutableSet<Issue<Path>>>` with a custom type that exposes the issue
|
||||
// source and can be configured?
|
||||
public static void run(OpenAi openAi, Supplier<ImmutableSet<Issue<Path>>> issueSupplier) {
|
||||
try (Terminal terminal = TerminalBuilder.terminal()) {
|
||||
InteractiveBuildOutputProcessor processor =
|
||||
new InteractiveBuildOutputProcessor(openAi, terminal.writer(), issueSupplier);
|
||||
|
||||
PicocliCommandsFactory factory = new PicocliCommandsFactory();
|
||||
factory.setTerminal(terminal);
|
||||
|
||||
CommandLine commandLine = new CommandLine(processor, factory);
|
||||
PicocliCommands commands = new PicocliCommands(commandLine);
|
||||
|
||||
Parser parser = new DefaultParser();
|
||||
|
||||
SystemRegistry systemRegistry =
|
||||
new SystemRegistryImpl(parser, terminal, () -> Path.of("").toAbsolutePath(), null);
|
||||
systemRegistry.setCommandRegistries(commands);
|
||||
systemRegistry.register("help", commands);
|
||||
|
||||
LineReader reader =
|
||||
LineReaderBuilder.builder()
|
||||
.terminal(terminal)
|
||||
.completer(systemRegistry.completer())
|
||||
.parser(parser)
|
||||
.build();
|
||||
new TailTipWidgets(
|
||||
reader, systemRegistry::commandDescription, 5, TailTipWidgets.TipType.COMPLETER)
|
||||
.enable();
|
||||
reader.getKeyMaps().get("main").bind(new Reference("tailtip-toggle"), KeyMap.ctrl('t'));
|
||||
|
||||
processor.restart();
|
||||
while (true) {
|
||||
try {
|
||||
systemRegistry.cleanUp();
|
||||
systemRegistry.execute(
|
||||
reader.readLine(processor.prompt(), null, (MaskingCallback) null, null));
|
||||
} catch (UserInterruptException e) {
|
||||
/* User pressed Ctrl+C. */
|
||||
} catch (EndOfFileException e) {
|
||||
/* User pressed Ctrl+D. */
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
systemRegistry.trace(e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to create terminal", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Command(aliases = "r", subcommands = HelpCommand.class, description = "Restarts issue analysis.")
|
||||
void restart() {
|
||||
files =
|
||||
Multimaps.asMap(Multimaps.index(issueSupplier.get(), Issue::file)).values().stream()
|
||||
.map(fileIssues -> FileIssues.of(ImmutableList.copyOf(fileIssues)))
|
||||
.collect(toImmutableList());
|
||||
currentIndex = 0;
|
||||
issues();
|
||||
}
|
||||
|
||||
@Command(aliases = "i", subcommands = HelpCommand.class, description = "List issues.")
|
||||
void issues() {
|
||||
if (files.isEmpty()) {
|
||||
out.println(ansi().fgRed().a("No issues.").reset());
|
||||
return;
|
||||
}
|
||||
|
||||
renderIssueDetails(files.get(currentIndex));
|
||||
}
|
||||
|
||||
// XXX: Review `throws` clause.
|
||||
// XXX: Allow to submit a custom instruction.
|
||||
@Command(aliases = "s", subcommands = HelpCommand.class, description = "Submit issues to OpenAI.")
|
||||
void submit(
|
||||
@Parameters(description = "The subset of issues to submit (default: all)") @Nullable
|
||||
Set<Integer> issueNumbers)
|
||||
throws IOException {
|
||||
if (files.isEmpty()) {
|
||||
out.println(ansi().fgRed().a("No issues.").reset());
|
||||
return;
|
||||
}
|
||||
|
||||
FileIssues fileIssues = files.get(currentIndex);
|
||||
if (issueNumbers != null) {
|
||||
for (int i : issueNumbers) {
|
||||
if (i <= 0 || i > fileIssues.issues().size()) {
|
||||
out.println(ansi().fgRed().a("Invalid issue number: " + i).reset());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImmutableList<Issue<Path>> allIssues = fileIssues.issues();
|
||||
ImmutableList<Issue<Path>> selectedIssues =
|
||||
issueNumbers == null
|
||||
? allIssues
|
||||
: issueNumbers.stream().map(n -> allIssues.get(n - 1)).collect(toImmutableList());
|
||||
|
||||
// XXX: Use `ansi()` and a separate thread to show a spinner.
|
||||
out.println("Submitting issue(s) OpenAI...");
|
||||
|
||||
String originalCode = Files.readString(fileIssues.file());
|
||||
String instruction =
|
||||
Streams.mapWithIndex(
|
||||
selectedIssues.stream(),
|
||||
(description, index) -> String.format("%s. %s", index + 1, description))
|
||||
.collect(joining("\n", "Resolve the following issues:\n", "\n"));
|
||||
String result = openAi.requestEdit(originalCode, instruction);
|
||||
|
||||
fileIssues.setProposal(result);
|
||||
|
||||
Diffs.printUnifiedDiff(originalCode, result, fileIssues.relativeFile(), out);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = "a",
|
||||
subcommands = HelpCommand.class,
|
||||
description = "Apply the changes suggested by OpenAI")
|
||||
void apply() {
|
||||
if (files.isEmpty()) {
|
||||
out.println(ansi().fgRed().a("No issues.").reset());
|
||||
return;
|
||||
}
|
||||
|
||||
FileIssues fileIssues = files.get(currentIndex);
|
||||
fileIssues
|
||||
.proposal()
|
||||
.ifPresentOrElse(
|
||||
proposal -> {
|
||||
try {
|
||||
// XXX: Apply the result only if it applies cleanly! Consider using the diff.
|
||||
Files.writeString(fileIssues.file(), proposal);
|
||||
out.println(ansi().fgGreen().a("Applied changes.").reset());
|
||||
} catch (IOException e) {
|
||||
out.println(ansi().fgRed().a("Failed to apply changes"));
|
||||
e.printStackTrace(out);
|
||||
out.print(ansi().reset());
|
||||
}
|
||||
},
|
||||
() ->
|
||||
out.println(
|
||||
ansi().fgRed().a("No changes generated yet; run `submit` first.").reset()));
|
||||
next();
|
||||
}
|
||||
|
||||
@Command(aliases = "n", subcommands = HelpCommand.class, description = "Move to the next issue.")
|
||||
void next() {
|
||||
if (currentIndex < files.size() - 1) {
|
||||
currentIndex++;
|
||||
issues();
|
||||
} else {
|
||||
out.println("No next issue.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = "p",
|
||||
subcommands = HelpCommand.class,
|
||||
description = "Move to the previous issue.")
|
||||
void previous() {
|
||||
if (currentIndex > 0) {
|
||||
currentIndex--;
|
||||
issues();
|
||||
} else {
|
||||
out.println("No previous issue.");
|
||||
}
|
||||
}
|
||||
|
||||
String prompt() {
|
||||
if (files.isEmpty()) {
|
||||
return ansi().fgRed().a("No issues").reset().a('>').toString();
|
||||
}
|
||||
|
||||
return ansi()
|
||||
.fgCyan()
|
||||
.a(files.get(currentIndex).relativeFile())
|
||||
.reset()
|
||||
.a(" (")
|
||||
.bold()
|
||||
.a(currentIndex + 1)
|
||||
.a('/')
|
||||
.a(files.size())
|
||||
.boldOff()
|
||||
.a(")>")
|
||||
.toString();
|
||||
}
|
||||
|
||||
private void renderIssueDetails(FileIssues fileIssues) {
|
||||
out.println(ansi().a("Issues for ").fgCyan().a(fileIssues.relativeFile()).reset().a(':'));
|
||||
renderIssueContext(fileIssues);
|
||||
renderIssues(fileIssues);
|
||||
// XXX: Here, also list the currently suggested patch, if already generated.
|
||||
// (...and not yet submitted?)
|
||||
}
|
||||
|
||||
private void renderIssueContext(FileIssues fileIssues) {
|
||||
ImmutableMap<Integer, ImmutableSet<Integer>> issueLines =
|
||||
fileIssues.issues().stream()
|
||||
.filter(issue -> issue.line().isPresent())
|
||||
.collect(
|
||||
toImmutableMap(
|
||||
issue -> issue.line().getAsInt(),
|
||||
issue ->
|
||||
issue.column().isPresent()
|
||||
? ImmutableSet.of(issue.column().getAsInt())
|
||||
: ImmutableSet.of(),
|
||||
(a, b) -> ImmutableSet.<Integer>builder().addAll(a).addAll(b).build()));
|
||||
|
||||
// XXX: Make context configurable.
|
||||
// XXX: This would be nicer with a `RangeSet`, but then we'd hit
|
||||
// https://github.com/google/guava/issues/3033.
|
||||
ImmutableSet<Integer> ranges =
|
||||
issueLines.keySet().stream()
|
||||
.flatMap(line -> IntStream.range(line - 3, line + 4).boxed())
|
||||
.collect(toImmutableSet());
|
||||
|
||||
boolean printedCode = false;
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(fileIssues.file(), UTF_8);
|
||||
for (int i = 1; i <= lines.size(); i++) {
|
||||
int salience =
|
||||
(ranges.contains(i - 1) ? 1 : 0)
|
||||
+ (ranges.contains(i) ? 1 : 0)
|
||||
+ (ranges.contains(i + 1) ? 1 : 0);
|
||||
if (salience > 1) {
|
||||
String line = lines.get(i - 1);
|
||||
out.print(ansi().fgYellow().a(String.format(Locale.ROOT, "%4d: ", i)).reset());
|
||||
out.println(
|
||||
issueLines.containsKey(i) ? highlightIssueLine(line, issueLines.get(i)) : line);
|
||||
printedCode = true;
|
||||
} else if (salience > 0 && printedCode) {
|
||||
out.println(ansi().fgBlue().a(".....").reset());
|
||||
printedCode = false;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
// XXX: Review.
|
||||
throw new UncheckedIOException("Failed to read file", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Ansi highlightIssueLine(String line, ImmutableSet<Integer> positions) {
|
||||
Ansi ansi = ansi().fgRed();
|
||||
for (int i = 0; i < line.length(); i++) {
|
||||
if (positions.contains(i + 1)) {
|
||||
ansi.bold().a(line.charAt(i)).boldOff();
|
||||
} else {
|
||||
ansi.a(line.charAt(i));
|
||||
}
|
||||
}
|
||||
return ansi.reset();
|
||||
}
|
||||
|
||||
private void renderIssues(FileIssues fileIssues) {
|
||||
ImmutableList<Issue<Path>> issues = fileIssues.issues();
|
||||
for (int i = 0; i < issues.size(); i++) {
|
||||
out.println(
|
||||
ansi()
|
||||
.fgBlue()
|
||||
.format(String.format(Locale.ROOT, "%4d. ", i + 1))
|
||||
.reset()
|
||||
.a(issues.get(i).description()));
|
||||
}
|
||||
}
|
||||
|
||||
private static final class FileIssues {
|
||||
private final Path file;
|
||||
private final ImmutableList<Issue<Path>> issues;
|
||||
private Optional<String> proposal = Optional.empty();
|
||||
|
||||
FileIssues(Path file, ImmutableList<Issue<Path>> issues) {
|
||||
this.file = file;
|
||||
this.issues = issues;
|
||||
checkArgument(
|
||||
issues.stream().allMatch(issue -> issue.file().equals(file)),
|
||||
"Issues must all reference the same file");
|
||||
}
|
||||
|
||||
static FileIssues of(ImmutableList<Issue<Path>> issues) {
|
||||
return new FileIssues(
|
||||
issues.stream()
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("No issues provided"))
|
||||
.file(),
|
||||
ImmutableList.sortedCopyOf(
|
||||
comparingInt((Issue<Path> issue) -> issue.line().orElse(-1))
|
||||
.thenComparingInt(issue -> issue.column().orElse(-1)),
|
||||
issues));
|
||||
}
|
||||
|
||||
Path file() {
|
||||
return file;
|
||||
}
|
||||
|
||||
Path relativeFile() {
|
||||
return file.getFileSystem().getPath("").toAbsolutePath().relativize(file);
|
||||
}
|
||||
|
||||
ImmutableList<Issue<Path>> issues() {
|
||||
return issues;
|
||||
}
|
||||
|
||||
void setProposal(String proposal) {
|
||||
this.proposal = Optional.of(proposal);
|
||||
}
|
||||
|
||||
Optional<String> proposal() {
|
||||
return proposal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Interface of types that implement a procedure to extract {@link Issue}s from a given string.
|
||||
*
|
||||
* @param <F> The type used to describe the location of files against which an issue is reported.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
interface IssueExtractor<F> {
|
||||
/** Extracts zero or more {@link Issue}s from the given string. */
|
||||
Stream<Issue<F>> extract(String str);
|
||||
|
||||
// XXX: Move to separate file?
|
||||
record Issue<F>(F file, OptionalInt line, OptionalInt column, String message) {
|
||||
<T> Issue<T> withFile(T file) {
|
||||
return new Issue<>(file, line, column, message);
|
||||
}
|
||||
|
||||
Issue<F> withMessage(String message) {
|
||||
return new Issue<>(file, line, column, message);
|
||||
}
|
||||
|
||||
String description() {
|
||||
return line().isEmpty()
|
||||
? message()
|
||||
: column().isEmpty()
|
||||
? String.format("Line %s: %s", line().getAsInt(), message())
|
||||
: String.format(
|
||||
"Line %s, column %s: %s", line().getAsInt(), column().getAsInt(), message());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.WillClose;
|
||||
|
||||
// XXX: Document that this is about extracting multi-line log messages.
|
||||
// XXX: Some Maven plugins emit an `INFO` message before printing a sequence of WARN/ERROR messages.
|
||||
// As-is this class will drop the leading message and chop up the rest. We should fix this.
|
||||
final class LogLineExtractor {
|
||||
// XXX: document that this much match an issue log level as well.
|
||||
private final Pattern logLineStartMarker;
|
||||
private final ImmutableSet<String> issueLogLevels;
|
||||
|
||||
private LogLineExtractor(Pattern logLineStartMarker, ImmutableSet<String> issueLogLevels) {
|
||||
this.logLineStartMarker = logLineStartMarker;
|
||||
this.issueLogLevels = issueLogLevels;
|
||||
}
|
||||
|
||||
static LogLineExtractor mavenErrorAndWarningExtractor() {
|
||||
// XXX: Move the pattern to a constant.
|
||||
return new LogLineExtractor(
|
||||
Pattern.compile("^\\[([A-Z]+)\\] "), ImmutableSet.of("ERROR", "WARNING"));
|
||||
}
|
||||
|
||||
ImmutableList<String> extract(@WillClose InputStream logs) throws IOException {
|
||||
List<String> messages = new ArrayList<>();
|
||||
|
||||
boolean shouldRead = false;
|
||||
StringBuilder nextMessage = new StringBuilder();
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(logs, UTF_8))) {
|
||||
for (String line = br.readLine(); line != null; line = br.readLine()) {
|
||||
Optional<String> logLevel = getLogLevel(line);
|
||||
|
||||
if (logLevel.isPresent()) {
|
||||
if (!nextMessage.isEmpty()) {
|
||||
messages.add(nextMessage.toString());
|
||||
nextMessage.setLength(0);
|
||||
}
|
||||
|
||||
shouldRead = issueLogLevels.contains(logLevel.orElseThrow());
|
||||
}
|
||||
|
||||
if (shouldRead) {
|
||||
if (!nextMessage.isEmpty()) {
|
||||
nextMessage.append(System.lineSeparator());
|
||||
}
|
||||
|
||||
// XXX: This `+ 3` is hacky. Do better.
|
||||
nextMessage.append(
|
||||
logLevel.isPresent() ? line.substring(logLevel.orElseThrow().length() + 3) : line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldRead && !nextMessage.isEmpty()) {
|
||||
messages.add(nextMessage.toString());
|
||||
}
|
||||
|
||||
return ImmutableList.copyOf(messages);
|
||||
}
|
||||
|
||||
private Optional<String> getLogLevel(String logLine) {
|
||||
return Optional.of(logLineStartMarker.matcher(logLine))
|
||||
.filter(Matcher::find)
|
||||
.map(m -> m.group(1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* An {@link IssueExtractor} that recognizes Checkstyle violations as reported by the Maven
|
||||
* CheckStyle Plugin
|
||||
*
|
||||
* @see <a
|
||||
* href="https://github.com/apache/maven-checkstyle-plugin/blob/997f1e4148ae6c0b399ed2a306a5cc8b365083b8/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleViolationCheckMojo.java#L728-L735">Maven
|
||||
* CheckStyle Plugin message format</a>
|
||||
*/
|
||||
final class MavenCheckstyleIssueExtractor implements IssueExtractor<String> {
|
||||
private static final Pattern LOG_LINE_FORMAT =
|
||||
Pattern.compile(
|
||||
"^(?<file>.+?):\\[(?<line>\\d+)(?:,(?<column>\\d+))?\\] \\(.+?\\) (?<message>\\S+?: .+)$",
|
||||
Pattern.DOTALL);
|
||||
|
||||
private final IssueExtractor<String> delegate = new RegexIssueExtractor(LOG_LINE_FORMAT);
|
||||
|
||||
@Override
|
||||
public Stream<Issue<String>> extract(String str) {
|
||||
return delegate.extract(str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.theokanning.openai.completion.chat.ChatCompletionRequest;
|
||||
import com.theokanning.openai.completion.chat.ChatMessage;
|
||||
import com.theokanning.openai.service.OpenAiService;
|
||||
import java.time.Duration;
|
||||
|
||||
/** A class that exposes a number of high-level OpenAI-based operations. */
|
||||
// XXX: Make final.
|
||||
// XXX: Implement exponential backoff.
|
||||
public final class OpenAi implements AutoCloseable {
|
||||
// XXX: Rename.
|
||||
@VisibleForTesting static final String OPENAI_TOKEN_VARIABLE = "openapi_token";
|
||||
// XXX: Make configurable?
|
||||
private static final Duration OPENAI_API_TIMEOUT = Duration.ofSeconds(120);
|
||||
|
||||
private final OpenAiService openAiService;
|
||||
|
||||
private OpenAi(OpenAiService openAiService) {
|
||||
this.openAiService = openAiService;
|
||||
}
|
||||
|
||||
static OpenAi create() {
|
||||
String openApiToken = System.getenv(OPENAI_TOKEN_VARIABLE);
|
||||
checkState(openApiToken != null, "Environment variable '%s' not set", OPENAI_TOKEN_VARIABLE);
|
||||
return create(openApiToken);
|
||||
}
|
||||
|
||||
static OpenAi create(String openAiToken) {
|
||||
return new OpenAi(new OpenAiService(openAiToken, OPENAI_API_TIMEOUT));
|
||||
}
|
||||
|
||||
// XXX: Support multiple alternatives?
|
||||
// XXX: Improve error handling (catch `OpenAiHttpException`, expose its message and the backing
|
||||
// HTTP error code).
|
||||
String requestEdit(String input, String instruction) {
|
||||
// return openAiService
|
||||
// .createEdit(
|
||||
// EditRequest.builder()
|
||||
// .input(input)
|
||||
// .model("code-davinci-edit-001")
|
||||
// .instruction(instruction)
|
||||
// .temperature(0.0)
|
||||
// .build())
|
||||
// .getChoices()
|
||||
// .get(0)
|
||||
// .getText();
|
||||
|
||||
// XXX: Replace the `replace` hacks.
|
||||
// XXX: The method signature is more generic than what this code does.
|
||||
return openAiService
|
||||
.createChatCompletion(
|
||||
ChatCompletionRequest.builder()
|
||||
.messages(
|
||||
ImmutableList.of(
|
||||
new ChatMessage(
|
||||
"system",
|
||||
"""
|
||||
You are an expert Java developer. You can only respond with Java code.
|
||||
The user reports build issues, and you suggest solutions.
|
||||
"""),
|
||||
new ChatMessage(
|
||||
"user",
|
||||
"""
|
||||
This is my code:
|
||||
|
||||
XXX
|
||||
|
||||
These are my build errors:
|
||||
YYY
|
||||
|
||||
###
|
||||
|
||||
Please update the code to fix these errors. Requirements:
|
||||
- Just write the new code. Don't explain yourself.
|
||||
- Do not leave out unchanged parts of the code. So do not shorten your answer by including "X remains unchanged" lines.
|
||||
- Do not leave out or resolve code comments.
|
||||
- Omit Markdown code formatting.
|
||||
"""
|
||||
.replace("XXX", input)
|
||||
.replace("YYY", instruction))))
|
||||
.model("gpt-4-1106-preview")
|
||||
.temperature(0.0)
|
||||
.build())
|
||||
.getChoices()
|
||||
.get(0)
|
||||
.getMessage()
|
||||
.getContent();
|
||||
}
|
||||
|
||||
// XXX: Improve error handling, including checking the finish reason.
|
||||
String requestChatCompletion(String instruction) {
|
||||
return openAiService
|
||||
.createChatCompletion(
|
||||
ChatCompletionRequest.builder()
|
||||
.messages(
|
||||
ImmutableList.of(
|
||||
new ChatMessage("system", "You are an expert Java developer"),
|
||||
new ChatMessage("user", instruction)))
|
||||
.model("gpt-4-1106-preview")
|
||||
.temperature(0.0)
|
||||
.build())
|
||||
.getChoices()
|
||||
.get(0)
|
||||
.getMessage()
|
||||
.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
openAiService.shutdownExecutor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
final class PathFinder {
|
||||
private final FileSystem fileSystem;
|
||||
private final Path projectRoot;
|
||||
|
||||
PathFinder(FileSystem fileSystem, Path projectRoot) {
|
||||
this.fileSystem = fileSystem;
|
||||
this.projectRoot = projectRoot.toAbsolutePath();
|
||||
}
|
||||
|
||||
Optional<Path> findPath(String pathSuffix) {
|
||||
Path path = projectRoot.resolve(pathSuffix);
|
||||
if (Files.exists(path)) {
|
||||
return Optional.of(path);
|
||||
}
|
||||
|
||||
PathMatcher matcher = fileSystem.getPathMatcher("glob:**" + pathSuffix);
|
||||
|
||||
List<Path> inexactMatches = new ArrayList<>();
|
||||
try {
|
||||
Files.walkFileTree(
|
||||
projectRoot,
|
||||
new SimpleFileVisitor<>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||
if (matcher.matches(file)) {
|
||||
inexactMatches.add(file);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("File walk failure", e);
|
||||
}
|
||||
|
||||
// XXX: Log if not exactly one match? Could use SLF4J + SimpleLogger on the exec:java classpath.
|
||||
// XXX: Alternatively, if this code is absorbed int `PathResolvingIssueExtractor`, then perhaps
|
||||
// this issue could be reflected in the returned `Issue`. (How is TBD.)
|
||||
return Optional.of(inexactMatches)
|
||||
.filter(matches -> matches.size() == 1)
|
||||
.map(Iterables::getOnlyElement);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package tech.picnic.errorprone.openai;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* An {@link IssueExtractor} that resolves delegates to another {@link IssueExtractor} and resolves
|
||||
* the extracted file paths.
|
||||
*
|
||||
* <p>For example, if the delegate extracts issues with relative file paths, this extractor will
|
||||
* resolve those paths to absolute paths.
|
||||
*/
|
||||
final class PathResolvingIssueExtractor implements IssueExtractor<Path> {
|
||||
// XXX: Do we then need `PathFinder` to be a separate class?
|
||||
private final PathFinder pathFinder;
|
||||
private final IssueExtractor<String> delegate;
|
||||
|
||||
PathResolvingIssueExtractor(PathFinder pathFinder, IssueExtractor<String> delegate) {
|
||||
this.pathFinder = pathFinder;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Issue<Path>> extract(String str) {
|
||||
return delegate
|
||||
.extract(str)
|
||||
.flatMap(issue -> pathFinder.findPath(issue.file()).map(issue::withFile).stream());
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user