Compare commits

...

44 Commits

Author SHA1 Message Date
Ivan Babiankou
db3cf7d0b8 very last try 2022-08-05 17:39:42 +02:00
Ivan Babiankou
50db75df52 Hmm, what is the difference? 2022-08-05 17:04:13 +02:00
Ivan Babiankou
8ca6982154 Revert performance tweaks 2022-08-05 16:57:47 +02:00
Ivan Babiankou
b8962fdba6 GIVE ME MORE 2022-08-05 16:41:53 +02:00
Ivan Babiankou
3fd83852fb Drop -Xmx 2022-08-05 16:29:53 +02:00
Ivan Babiankou
0ed60fe726 more builds 2022-08-05 16:20:45 +02:00
Ivan Babiankou
6fc4c8c43c trigger more builds 2022-08-05 16:20:08 +02:00
Ivan Babiankou
3921884481 build this branch 2022-08-05 16:01:24 +02:00
Stephan Schroevers
10369e2624 Speed up the build
The build is sped up in two ways:
1. By tweaking the JVM flags passed to the main process.
2. By tweaking the JVM flags passed to the forked Surefire processes.

(cherry picked from commit cf34951eff29d73d6d1aa99679e205e50a28586a)
2022-08-05 16:00:42 +02:00
Rick Ossendrijver
708c8affcf Apply suggestions 2022-08-05 16:00:42 +02:00
Pieter Dirk Soels
0fa9541db6 Remove argument to print versions as we already did so in another step 2022-08-05 16:00:42 +02:00
Stephan Schroevers
5b261045d1 More cleanup 2022-08-05 16:00:42 +02:00
Stephan Schroevers
8be8730fd4 Build all PR branches 2022-08-05 16:00:42 +02:00
Stephan Schroevers
b12b2e8ebc Rename file, run parallel build 2022-08-05 16:00:42 +02:00
Stephan Schroevers
13567d23e4 Suggestions 2022-08-05 16:00:42 +02:00
Rick Ossendrijver
78cabb58c1 PSM-1324 Apply suggestion 2022-08-05 16:00:42 +02:00
Rick Ossendrijver
812787544a PSM-1324 Apply feedback 2022-08-05 16:00:42 +02:00
Rick Ossendrijver
f35a1fba53 Migrate from Travis CI to GitHub Actions 2022-08-05 16:00:42 +02:00
Picnic-Bot
78035644dc Upgrade NullAway 0.9.8 -> 0.9.9 (#175)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/compare/v0.9.8...v0.9.9
2022-08-05 09:10:49 +02:00
Picnic-Bot
ef67d41512 Upgrade pitest-maven-plugin 1.9.2 -> 1.9.3 (#159)
See:
- https://github.com/hcoles/pitest/releases/tag/1.9.3
- https://github.com/hcoles/pitest/compare/1.9.2...1.9.3
2022-08-04 16:53:54 +02:00
Picnic-Bot
4cecff923a Upgrade Checker Framework Annotations 3.23.0 -> 3.24.0 (#174)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.24.0
- https://github.com/typetools/checker-framework/compare/checker-framework-3.23.0...checker-framework-3.24.0
2022-08-04 08:10:10 +02:00
Stephan Schroevers
38a57db994 Introduce ErrorProneTestHelperSourceFormat check (#147)
This new checker inspects inline code passed to `CompilationTestHelper` and
`BugCheckerRefactoringTestHelper` instances. It requires that this code is
properly formatted and that its imports are organized. Only code that
represents the expected output of a refactoring operation is allowed to have
unused imports, as most `BugChecker`s do not (and are not able to) remove
imports that become obsolete as a result of applying their suggested fix(es).
2022-08-03 21:47:31 +02:00
Stephan Schroevers
336557cf8e Introduce apply-error-prone-suggestions.sh (#171)
This script compiles the code using Error Prone and applies its suggestions. 
The set of checks applied can optionally be restricted by name.
2022-08-03 17:05:38 +02:00
Picnic-Bot
9055dfff19 Upgrade Checkstyle 10.3.1 -> 10.3.2 (#173)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.3.2
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.3.1...checkstyle-10.3.2
2022-08-02 12:26:40 +02:00
Rick Ossendrijver
3712a15195 Implement workaround for MCOMPILER-503 (#149)
By moving around some annotation processor classpath entries we ensure that the
`maven-compiler-plugin` uses the appropriate version of Error Prone.

See https://issues.apache.org/jira/browse/MCOMPILER-503
2022-08-02 09:36:46 +02:00
Picnic-Bot
9d487e4a88 Upgrade New Relic Java Agent 7.8.0 -> 7.9.0 (#168)
See:
- https://github.com/newrelic/newrelic-java-agent/releases/tag/v7.9.0
- https://github.com/newrelic/newrelic-java-agent/compare/v7.8.0...v7.9.0
2022-08-01 17:35:58 +02:00
Picnic-Bot
b2b086761c Upgrade JUnit Jupiter 5.8.2 -> 5.9.0 (#167)
See:
- https://junit.org/junit5/docs/current/release-notes/index.html
- https://github.com/junit-team/junit5/releases/tag/r5.9.0
- https://github.com/junit-team/junit5/compare/r5.8.2...r5.9.0
2022-08-01 17:27:08 +02:00
Picnic-Bot
ff64247b6d Upgrade maven-resources-plugin 3.2.0 -> 3.3.0 (#166)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MRESOURCES%20AND%20fixVersion%20%3E%203.2.0%20AND%20fixVersion%20%3C%3D%203.3.0
- https://github.com/apache/maven-resources-plugin/compare/maven-resources-plugin-3.2.0...maven-resources-plugin-3.3.0
2022-08-01 17:15:19 +02:00
Picnic-Bot
bc7443c72d Upgrade maven-install-plugin 3.0.0 -> 3.0.1 (#164)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MINSTALL%20AND%20fixVersion%20%3E%20%203.0.0%20AND%20fixVersion%20%3C%3D%203.0.1
- https://github.com/apache/maven-install-plugin/compare/maven-install-plugin-3.0.0...maven-install-plugin-3.0.1
2022-08-01 16:21:54 +02:00
Picnic-Bot
abf4d68fba Upgrade extra-enforcer-rules 1.6.0 -> 1.6.1 (#165)
See:
- https://github.com/mojohaus/extra-enforcer-rules/releases/tag/extra-enforcer-rules-1.6.1
- https://github.com/mojohaus/extra-enforcer-rules/compare/extra-enforcer-rules-1.6.0...extra-enforcer-rules-1.6.1
2022-08-01 16:20:24 +02:00
Picnic-Bot
5c5f7d849e Upgrade Guava 31.0.1-jre -> 31.1-jre (#77)
See:
- https://guava.dev/releases/31.1-jre/api/diffs/
- https://github.com/google/guava/releases/tag/v31.1
- https://github.com/google/guava/compare/v31.0.1...v31.1
2022-08-01 14:48:56 +02:00
Picnic-Bot
65c4694936 Upgrade Error Prone 2.10.0 -> 2.14.0 (#76)
This also requires the upgrade of errorprone-slf4j 0.1.4 -> 0.1.12.

See:
- https://github.com/google/error-prone/releases/tag/v2.11.0
- https://github.com/google/error-prone/releases/tag/v2.12.0
- https://github.com/google/error-prone/releases/tag/v2.12.1
- https://github.com/google/error-prone/releases/tag/v2.13.0
- https://github.com/google/error-prone/releases/tag/v2.13.1
- https://github.com/google/error-prone/releases/tag/v2.14.0
- https://github.com/google/error-prone/compare/v2.10.0...v2.14.0
- https://github.com/PicnicSupermarket/error-prone/compare/v2.10.0-picnic-3...v2.14.0-picnic-2
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.5
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.6
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.7
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.8
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.9
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.10
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.11
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.12
- https://github.com/KengoTODA/errorprone-slf4j/compare/v0.1.4...v0.1.12
2022-07-31 15:50:16 +02:00
Picnic-Bot
a45291c7d8 Upgrade Spring Boot 2.7.1 -> 2.7.2 (#163)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v2.7.2
- https://github.com/spring-projects/spring-boot/compare/v2.7.1...v2.7.2
2022-07-30 15:11:37 +02:00
Picnic-Bot
71012f31ab Upgrade swagger-annotations 2.2.1 -> 2.2.2 (#162)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.2
- https://github.com/swagger-api/swagger-core/compare/v2.2.1...v2.2.2
2022-07-30 14:43:54 +02:00
Picnic-Bot
6e0905c033 Upgrade maven-install-plugin 2.5.2 -> 3.0.0 (#161)
See: 
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MINSTALL%20AND%20fixVersion%20%3E%20%202.5.2%20AND%20fixVersion%20%3C%3D%203.0.0
- https://github.com/apache/maven-install-plugin/compare/maven-install-plugin-2.5.2...maven-install-plugin-3.0.0
2022-07-21 09:01:43 +02:00
Picnic-Bot
af5ac85428 Upgrade maven-deploy-plugin 2.8.2 -> 3.0.0 (#160)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MDEPLOY%20AND%20fixVersion%20%3E%202.8.2%20AND%20fixVersion%20%3C%3D%203.0.0
- https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-2.8.2...maven-deploy-plugin-3.0.0
2022-07-21 08:49:42 +02:00
Picnic-Bot
0329c25f78 Upgrade sortpom-maven-plugin 3.1.3 -> 3.2.0 (#157)
See:
- https://github.com/Ekryd/sortpom/wiki/Versions
- https://github.com/Ekryd/sortpom/releases/tag/sortpom-parent-3.2.0
- https://github.com/Ekryd/sortpom/compare/sortpom-parent-3.1.3...sortpom-parent-3.2.0
2022-07-21 08:04:22 +02:00
Picnic-Bot
9e67e2b795 Upgrade Spring 5.3.21 -> 5.3.22 (#155)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v5.3.22
- https://github.com/spring-projects/spring-framework/compare/v5.3.21...v5.3.22
2022-07-15 14:52:27 +02:00
Picnic-Bot
4bafea05f4 Upgrade Project Reactor 2020.0.20 -> 2020.0.21 (#154)
See:
- https://github.com/reactor/reactor/releases/tag/2020.0.21
- https://github.com/reactor/reactor/compare/2020.0.20...2020.0.21
2022-07-15 08:46:21 +02:00
Picnic-Bot
8ce9cab2dd Upgrade Checker Framework Annotations 3.22.2 -> 3.23.0 (#153)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.23.0
- https://github.com/typetools/checker-framework/compare/checker-framework-3.22.2...checker-framework-3.23.0
2022-07-13 07:34:25 +02:00
Pieter Dirk Soels
ae30625524 Clarify MapToNullable Refaster template (#150) 2022-07-12 12:54:22 +02:00
Picnic-Bot
dc0046ebfc Upgrade extra-enforcer-rules 1.5.1 -> 1.6.0 (#152)
See:
- https://github.com/mojohaus/extra-enforcer-rules/releases/tag/extra-enforcer-rules-1.6.0
- https://github.com/mojohaus/extra-enforcer-rules/compare/extra-enforcer-rules-1.5.1...extra-enforcer-rules-1.6.0
2022-07-12 11:41:23 +02:00
Picnic-Bot
ad6d774818 Upgrade pitest-maven-plugin 1.9.0 -> 1.9.2 (#151)
See:
- https://github.com/hcoles/pitest/releases/tag/1.9.1
- https://github.com/hcoles/pitest/releases/tag/1.9.2
- https://github.com/hcoles/pitest/compare/1.9.0...1.9.2
2022-07-12 11:11:30 +02:00
Stephan Schroevers
405f5874ac Apply Checkstyle to Refaster test resources (#146)
Similar to formatting the `*TemplatesTest{In,Out}put.java` files to enforce
certain style aspects, this is expected to reduce future code review effort.

The test code changes were applied to appease the
`SimplifyBooleanExpression` check.
2022-07-06 13:39:59 +02:00
50 changed files with 1923 additions and 703 deletions

38
.github/workflows/build.yaml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Build and verify
on:
pull_request:
push:
branches:
- 'master'
- 'ibabiankou/experiments'
jobs:
build:
runs-on: ubuntu-22.04
strategy:
matrix:
jdk: [ 11.0.16, 17.0.4 ]
steps:
# We run the build twice for each supported JDK: once against the
# original Error Prone release, using only Error Prone checks available
# on Maven Central, and once against the Picnic Error Prone fork,
# additionally enabling all checks defined in this project and any
# Error Prone checks available only from other artifact repositories.
- name: Check out code
uses: actions/checkout@v3.0.2
- name: Set up JDK
uses: actions/setup-java@v3.4.1
with:
java-version: ${{ matrix.jdk }}
distribution: temurin
cache: maven
- name: Display build environment details
run: mvn --version
- name: Build project against vanilla Error Prone
run: mvn -T1C install
- name: Build project with self-check against Error Prone fork
run: mvn -T1C clean verify -Perror-prone-fork -Pnon-maven-central -Pself-check -s settings.xml
- name: Remove project snapshots
run: mvn build-helper:remove-project-artifact
# XXX: Enable Codecov once we "go public".
# XXX: Enable SonarCloud once we "go public".

1
.mvn/maven.config Normal file
View File

@@ -0,0 +1 @@
--batch-mode --errors --strict-checksums

View File

@@ -1,38 +0,0 @@
---
dist: bionic
language: java
jdk: openjdk11
addons:
sonarcloud:
organization: picnic-technologies
token: "${SONARCLOUD_TOKEN}"
install:
- mvn io.takari:maven:wrapper
script:
# We run the build twice: once against the original Error Prone release,
# using only Error Prone checks available on Maven Central, and once against
# the Picnic Error Prone fork, additionally enabling all checks defined in
# this project and any Error Prone checks available only from other artifact
# repositories.
- ./mvnw clean install
- ./mvnw clean install -Perror-prone-fork -Pnon-maven-central -Pself-check -s settings.xml
# XXX: Enable SonarCloud once we "go public".
# ./mvnw jacoco:prepare-agent surefire:test jacoco:report sonar:sonar
- ./mvnw jacoco:prepare-agent surefire:test jacoco:report
before_cache:
# Don't cache the artifacts we just generated, for multiple reasons: (1) we
# shouldn't need them next time around and (2) if we do, that indicates a
# dependency issue which might otherwise go unnoticed until next time we bump
# the project's version (i.e., when tagging).
- find "${HOME}/.m2/repository" -depth -name '*-SNAPSHOT' -exec rm -r '{}' \;
cache:
directories:
# The local Maven repository in which third party dependencies are stored.
- ${HOME}/.m2/repository
# The Takari Maven Wrapper's storage for downloaded Maven distributions.
- ${HOME}/.m2/wrapper
# The SonarQube analysis cache.
- ${HOME}/.sonar/cache
# XXX: Enable Codecov once we "go public".
#after_success:
# - bash <(curl -s https://codecov.io/bash)

View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Compiles the code using Error Prone and applies its suggestions. The set of
# checks applied can optionally be restricted by name.
#
# As this script may modify the project's code, it is important to execute it
# in a clean Git working directory.
set -e -u -o pipefail
if [ "${#}" -gt 1 ]; then
echo "Usage: ./$(basename "${0}") [PatchChecks]"
exit 1
fi
patchChecks=${1:-}
mvn clean test-compile fmt:format \
-T 1.0C \
-Perror-prone \
-Perror-prone-fork \
-Ppatch \
-Pself-check \
-Derror-prone.patch-checks="${patchChecks}" \
-Dverification.skip

View File

@@ -76,6 +76,10 @@
<artifactId>javac</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.googlejavaformat</groupId>
<artifactId>google-java-format</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>

View File

@@ -8,6 +8,7 @@ import static com.google.errorprone.matchers.Matchers.annotations;
import static com.google.errorprone.matchers.Matchers.isType;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
@@ -43,7 +44,7 @@ public final class AutowiredConstructorCheck extends BugChecker implements Class
return Description.NO_MATCH;
}
List<AnnotationTree> annotations =
ImmutableList<AnnotationTree> annotations =
AUTOWIRED_ANNOTATION
.multiMatchResult(Iterables.getOnlyElement(constructors), state)
.matchingNodes();

View File

@@ -0,0 +1,161 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
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 java.util.stream.Collectors.joining;
import com.google.auto.service.AutoService;
import com.google.common.base.Splitter;
import com.google.errorprone.BugPattern;
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.util.ASTHelpers;
import com.google.googlejavaformat.java.Formatter;
import com.google.googlejavaformat.java.FormatterException;
import com.google.googlejavaformat.java.ImportOrderer;
import com.google.googlejavaformat.java.JavaFormatterOptions.Style;
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 java.util.List;
import java.util.Optional;
/**
* A {@link BugChecker} which flags improperly formatted Error Prone test code.
*
* <p>All test code should be formatted in accordance with Google Java Format's {@link Formatter}
* output, and imports should be ordered according to the {@link Style#GOOGLE Google} style.
*
* <p>This checker inspects inline code passed to {@code
* com.google.errorprone.CompilationTestHelper} and {@code
* com.google.errorprone.BugCheckerRefactoringTestHelper}. It requires that this code is properly
* formatted and that its imports are organized. Only code that represents the expected output of a
* refactoring operation is allowed to have unused imports, as most {@link BugChecker}s do not (and
* 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: 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.
@AutoService(BugChecker.class)
@BugPattern(
name = "ErrorProneTestHelperSourceFormat",
summary = "Test code should follow the Google Java style",
linkType = NONE,
severity = SUGGESTION,
tags = STYLE)
public final class ErrorProneTestHelperSourceFormatCheck extends BugChecker
implements MethodInvocationTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Formatter FORMATTER = new Formatter();
private static final Matcher<ExpressionTree> INPUT_SOURCE_ACCEPTING_METHOD =
anyOf(
instanceMethod()
.onDescendantOf("com.google.errorprone.CompilationTestHelper")
.named("addSourceLines"),
instanceMethod()
.onDescendantOf("com.google.errorprone.BugCheckerRefactoringTestHelper")
.named("addInputLines"));
private static final Matcher<ExpressionTree> OUTPUT_SOURCE_ACCEPTING_METHOD =
instanceMethod()
.onDescendantOf("com.google.errorprone.BugCheckerRefactoringTestHelper.ExpectOutput")
.named("addOutputLines");
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
boolean isOutputSource = OUTPUT_SOURCE_ACCEPTING_METHOD.matches(tree, state);
if (!isOutputSource && !INPUT_SOURCE_ACCEPTING_METHOD.matches(tree, state)) {
return Description.NO_MATCH;
}
List<? extends ExpressionTree> sourceLines =
tree.getArguments().subList(1, tree.getArguments().size());
if (sourceLines.isEmpty()) {
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))
.orElse(Description.NO_MATCH);
}
private Description flagFormattingIssues(
int startPos, int endPos, String source, boolean retainUnusedImports, VisitorState state) {
Tree methodInvocation = state.getPath().getLeaf();
String formatted;
try {
formatted = formatSourceCode(source, retainUnusedImports).trim();
} catch (FormatterException e) {
return buildDescription(methodInvocation)
.setMessage(String.format("Source code is malformed: %s", e.getMessage()))
.build();
}
if (source.trim().equals(formatted)) {
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);
}
/*
* The code isn't properly formatted; replace all lines with the properly formatted
* alternatives.
*/
return describeMatch(
methodInvocation,
SuggestedFix.replace(
startPos,
endPos,
Splitter.on('\n')
.splitToStream(formatted)
.map(state::getConstantExpression)
.collect(joining(", "))));
}
private static String formatSourceCode(String source, boolean retainUnusedImports)
throws FormatterException {
String withReorderedImports = ImportOrderer.reorderImports(source, Style.GOOGLE);
String withOptionallyRemovedImports =
retainUnusedImports
? withReorderedImports
: RemoveUnusedImports.removeUnusedImports(withReorderedImports);
return FORMATTER.formatSource(withOptionallyRemovedImports);
}
private static Optional<String> getConstantSourceCode(
List<? extends ExpressionTree> sourceLines) {
StringBuilder source = new StringBuilder();
for (ExpressionTree sourceLine : sourceLines) {
Object value = ASTHelpers.constValue(sourceLine);
if (value == null) {
return Optional.empty();
}
source.append(value).append('\n');
}
return Optional.of(source.toString());
}
}

View File

@@ -31,6 +31,7 @@ import com.sun.source.util.SimpleTreeVisitor;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;
/**
* A {@link BugChecker} which flags string concatenations that produce a format string; in such
@@ -210,6 +211,7 @@ public final class FormatStringConcatenationCheck extends BugChecker
this.formatSpecifier = formatSpecifier;
}
@Nullable
@Override
public Void visitBinary(BinaryTree tree, VisitorState state) {
if (tree.getKind() == Kind.PLUS && isStringTyped(tree, state)) {
@@ -222,11 +224,13 @@ public final class FormatStringConcatenationCheck extends BugChecker
return null;
}
@Nullable
@Override
public Void visitParenthesized(ParenthesizedTree tree, VisitorState state) {
return tree.getExpression().accept(this, state);
}
@Nullable
@Override
protected Void defaultAction(Tree tree, VisitorState state) {
appendExpression(tree);

View File

@@ -37,6 +37,7 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import javax.annotation.Nullable;
/**
* A {@link BugChecker} which flags annotation array listings which aren't sorted lexicographically.
@@ -171,18 +172,21 @@ public final class LexicographicalAnnotationAttributeListingCheck extends BugChe
ImmutableList.Builder<ImmutableList<String>> nodes = ImmutableList.builder();
new TreeScanner<Void, Void>() {
@Nullable
@Override
public Void visitIdentifier(IdentifierTree node, Void ctx) {
nodes.add(tokenize(node));
return super.visitIdentifier(node, ctx);
}
@Nullable
@Override
public Void visitLiteral(LiteralTree node, Void ctx) {
nodes.add(tokenize(node));
return super.visitLiteral(node, ctx);
}
@Nullable
@Override
public Void visitPrimitiveType(PrimitiveTypeTree node, Void ctx) {
nodes.add(tokenize(node));

View File

@@ -52,7 +52,7 @@ public final class LexicographicalAnnotationListingCheck extends BugChecker
Optional<Fix> fix = tryFixOrdering(originalOrdering, sortedAnnotations, state);
Description.Builder description = buildDescription(tree);
Description.Builder description = buildDescription(originalOrdering.get(0));
fix.ifPresent(description::addFix);
return description.build();
}

View File

@@ -166,11 +166,12 @@ public final class RefasterCheck extends BugChecker implements CompilationUnitTr
flags
.get(INCLUDED_TEMPLATES_PATTERN_FLAG)
.map(Pattern::compile)
.map(nameFilter -> filterCodeTransformers(allTransformers, nameFilter))
.<ImmutableCollection<CodeTransformer>>map(
nameFilter -> filterCodeTransformers(allTransformers, nameFilter))
.orElseGet(allTransformers::values));
}
private static ImmutableCollection<CodeTransformer> filterCodeTransformers(
private static ImmutableList<CodeTransformer> filterCodeTransformers(
ImmutableListMultimap<String, CodeTransformer> transformers, Pattern nameFilter) {
return transformers.entries().stream()
.filter(e -> nameFilter.matcher(e.getKey()).matches())

View File

@@ -75,7 +75,7 @@ public final class ScheduledTransactionTraceCheck extends BugChecker implements
return describeMatch(
traceAnnotation,
SuggestedFixes.updateAnnotationArgumentValues(
traceAnnotation, "dispatcher", ImmutableList.of("true"))
traceAnnotation, state, "dispatcher", ImmutableList.of("true"))
.build());
}

View File

@@ -59,7 +59,7 @@ public final class TimeZoneUsageCheck extends BugChecker implements MethodInvoca
LocalDateTime.class.getName(),
LocalTime.class.getName())
.named("now"),
staticMethod().onClassAny(Instant.class.getName()).named("now").withParameters());
staticMethod().onClassAny(Instant.class.getName()).named("now").withNoParameters());
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {

View File

@@ -268,9 +268,9 @@ final class AssertJThrowingCallableTemplates {
}
static final class AssertThatThrownByIOExceptionHasMessage {
@BeforeTemplate
@SuppressWarnings(
"AssertThatThrownByIOException" /* Matches strictly more specific expressions. */)
@BeforeTemplate
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
return assertThatIOException().isThrownBy(throwingCallable).withMessage(message);
}

View File

@@ -92,7 +92,7 @@ final class ImmutableListMultimapTemplates {
*/
static final class EntryToImmutableListMultimap<K, V> {
@BeforeTemplate
ImmutableMultimap<K, V> before(Map.Entry<? extends K, ? extends V> entry) {
ImmutableListMultimap<K, V> before(Map.Entry<? extends K, ? extends V> entry) {
return Refaster.anyOf(
ImmutableListMultimap.<K, V>builder().put(entry).build(),
Stream.of(entry)

View File

@@ -4,7 +4,6 @@ import static com.google.common.collect.ImmutableSortedMultiset.toImmutableSorte
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
import static java.util.Comparator.naturalOrder;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.ImmutableSortedMultiset;
import com.google.common.collect.Streams;
import com.google.errorprone.refaster.Refaster;
@@ -91,14 +90,14 @@ final class ImmutableSortedMultisetTemplates {
// `reverseOrder`.) Worth the hassle?
static final class IterableToImmutableSortedMultiset<T extends Comparable<? super T>> {
@BeforeTemplate
ImmutableMultiset<T> before(T[] iterable) {
ImmutableSortedMultiset<T> before(T[] iterable) {
return Refaster.anyOf(
ImmutableSortedMultiset.<T>naturalOrder().add(iterable).build(),
Arrays.stream(iterable).collect(toImmutableSortedMultiset(naturalOrder())));
}
@BeforeTemplate
ImmutableMultiset<T> before(Iterator<T> iterable) {
ImmutableSortedMultiset<T> before(Iterator<T> iterable) {
return Refaster.anyOf(
ImmutableSortedMultiset.copyOf(naturalOrder(), iterable),
ImmutableSortedMultiset.<T>naturalOrder().addAll(iterable).build(),
@@ -106,7 +105,7 @@ final class ImmutableSortedMultisetTemplates {
}
@BeforeTemplate
ImmutableMultiset<T> before(Iterable<T> iterable) {
ImmutableSortedMultiset<T> before(Iterable<T> iterable) {
return Refaster.anyOf(
ImmutableSortedMultiset.copyOf(naturalOrder(), iterable),
ImmutableSortedMultiset.<T>naturalOrder().addAll(iterable).build(),

View File

@@ -4,7 +4,6 @@ import static com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet;
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
import static java.util.Comparator.naturalOrder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Streams;
import com.google.errorprone.refaster.Refaster;
@@ -89,14 +88,14 @@ final class ImmutableSortedSetTemplates {
// `reverseOrder`.) Worth the hassle?
static final class IterableToImmutableSortedSet<T extends Comparable<? super T>> {
@BeforeTemplate
ImmutableSet<T> before(T[] iterable) {
ImmutableSortedSet<T> before(T[] iterable) {
return Refaster.anyOf(
ImmutableSortedSet.<T>naturalOrder().add(iterable).build(),
Arrays.stream(iterable).collect(toImmutableSortedSet(naturalOrder())));
}
@BeforeTemplate
ImmutableSet<T> before(Iterator<T> iterable) {
ImmutableSortedSet<T> before(Iterator<T> iterable) {
return Refaster.anyOf(
ImmutableSortedSet.copyOf(naturalOrder(), iterable),
ImmutableSortedSet.<T>naturalOrder().addAll(iterable).build(),
@@ -104,7 +103,7 @@ final class ImmutableSortedSetTemplates {
}
@BeforeTemplate
ImmutableSet<T> before(Iterable<T> iterable) {
ImmutableSortedSet<T> before(Iterable<T> iterable) {
return Refaster.anyOf(
ImmutableSortedSet.copyOf(naturalOrder(), iterable),
ImmutableSortedSet.<T>naturalOrder().addAll(iterable).build(),

View File

@@ -166,6 +166,11 @@ final class OptionalTemplates {
}
}
/**
* Prefer {@link Optional#map} over a {@link Optional#flatMap} which wraps the result of a
* transformation in an {@link Optional}; the former operation transforms {@code null} to {@link
* Optional#empty()}.
*/
abstract static class MapToNullable<T, S> {
@Placeholder
abstract S toNullableFunction(@MayOptionallyUse T element);

View File

@@ -112,7 +112,6 @@ final class AmbiguousJsonCreatorCheckTest {
" return new F(s);",
" }",
" }",
"",
"}")
.doTest();
}

View File

@@ -27,27 +27,34 @@ final class AutowiredConstructorCheckTest {
" }",
"",
" class B {",
" @Autowired void setProperty(Object o) {}",
" @Autowired",
" void setProperty(Object o) {}",
" }",
"",
" class C {",
" // BUG: Diagnostic contains:",
" @Autowired C() {}",
" @Autowired",
" C() {}",
" }",
"",
" class D {",
" // BUG: Diagnostic contains:",
" @Autowired D(String x) {}",
" @Autowired",
" D(String x) {}",
" }",
"",
" class E {",
" @Autowired E() {}",
" @Autowired",
" E() {}",
"",
" E(String x) {}",
" }",
"",
" class F {",
" F() {}",
" @Autowired F(String x) {}",
"",
" @Autowired",
" F(String x) {}",
" }",
"",
" class G {",
@@ -55,7 +62,8 @@ final class AutowiredConstructorCheckTest {
" }",
"",
" class H {",
" @SafeVarargs H(List<String>... lists) {}",
" @SafeVarargs",
" H(List<String>... lists) {}",
" }",
"}")
.doTest();
@@ -70,11 +78,14 @@ final class AutowiredConstructorCheckTest {
"",
"interface Container {",
" class A {",
" @Autowired @Deprecated A() {}",
" @Autowired",
" @Deprecated",
" A() {}",
" }",
"",
" class B {",
" @Autowired B(String x) {}",
" @Autowired",
" B(String x) {}",
" }",
"}")
.addOutputLines(
@@ -83,10 +94,13 @@ final class AutowiredConstructorCheckTest {
"",
"interface Container {",
" class A {",
" @Deprecated A() {}",
"",
" @Deprecated",
" A() {}",
" }",
"",
" class B {",
"",
" B(String x) {}",
" }",
"}")

View File

@@ -23,63 +23,110 @@ final class CanonicalAnnotationSyntaxCheckTest {
"interface A {",
" @interface Foo {",
" int[] value() default {};",
"",
" int[] value2() default {};",
" }",
"",
" @pkg.A.Foo A minimal1();",
" @A.Foo A minimal2();",
" @Foo A minimal3();",
" @pkg.A.Foo",
" A minimal1();",
"",
" @A.Foo",
" A minimal2();",
"",
" @Foo",
" A minimal3();",
"",
" // BUG: Diagnostic contains:",
" @pkg.A.Foo() A functional1();",
" @pkg.A.Foo()",
" A functional1();",
" // BUG: Diagnostic contains:",
" @A.Foo() A functional2();",
" @A.Foo()",
" A functional2();",
" // BUG: Diagnostic contains:",
" @Foo() A functional3();",
" @Foo()",
" A functional3();",
"",
" @pkg.A.Foo(1) A simple1();",
" @A.Foo(1) A simple2();",
" @Foo(1) A simple3();",
" @pkg.A.Foo(1)",
" A simple1();",
"",
" @A.Foo(1)",
" A simple2();",
"",
" @Foo(1)",
" A simple3();",
"",
" // BUG: Diagnostic contains:",
" @pkg.A.Foo({1}) A singleton1();",
" @pkg.A.Foo({1})",
" A singleton1();",
" // BUG: Diagnostic contains:",
" @A.Foo({1}) A singleton2();",
" @A.Foo({1})",
" A singleton2();",
" // BUG: Diagnostic contains:",
" @Foo({1}) A singleton3();",
" @Foo({1})",
" A singleton3();",
"",
" // BUG: Diagnostic contains:",
" @pkg.A.Foo(value = 1) A verbose1();",
" @pkg.A.Foo(value = 1)",
" A verbose1();",
" // BUG: Diagnostic contains:",
" @A.Foo(value = 1) A verbose2();",
" @A.Foo(value = 1)",
" A verbose2();",
" // BUG: Diagnostic contains:",
" @Foo(value = 1) A verbose3();",
" @Foo(value = 1)",
" A verbose3();",
"",
" @pkg.A.Foo(value2 = 2) A custom1();",
" @A.Foo(value2 = 2) A custom2();",
" @Foo(value2 = 2) A custom3();",
" @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();",
" @pkg.A.Foo(value2 = {2})",
" A customSingleton1();",
" // BUG: Diagnostic contains:",
" @A.Foo(value2 = {2}) A customSingleton2();",
" @A.Foo(value2 = {2})",
" A customSingleton2();",
" // BUG: Diagnostic contains:",
" @Foo(value2 = {2}) A customSingleton3();",
" @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(value2 = {2, 2})",
" A customPair1();",
"",
" @pkg.A.Foo(value = 1, value2 = 2) A extended1();",
" @A.Foo(value = 1, value2 = 2) A extended2();",
" @Foo(value = 1, value2 = 2) A extended3();",
" @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();",
" @pkg.A.Foo({",
" 1, 1,",
" })",
" A trailingComma1();",
" // BUG: Diagnostic contains:",
" @A.Foo({1, 1,}) A trailingComma2();",
" @A.Foo({",
" 1, 1,",
" })",
" A trailingComma2();",
" // BUG: Diagnostic contains:",
" @Foo({1, 1,}) A trailingComma3();",
" @Foo({",
" 1, 1,",
" })",
" A trailingComma3();",
"}")
.doTest();
}
@@ -96,28 +143,67 @@ final class CanonicalAnnotationSyntaxCheckTest {
"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()",
" A functional1();",
"",
" @pkg.A.Foo(value = \"foo\") A verbose1();",
" @A.Foo(value = \"a'b\") A verbose2();",
" @Foo(value = \"a\" + \"\\nb\") A verbose3();",
" @A.Foo()",
" A functional2();",
"",
" @pkg.A.Foo(value = {\"foo\"}) A moreVerbose1();",
" @A.Foo(value = {\"a'b\"}) A moreVerbose2();",
" @Foo(value = {\"a\" + \"\\nb\"}) A moreVerbose3();",
" @Foo()",
" A functional3();",
"",
" @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(value = \"foo\")",
" A verbose1();",
"",
" @pkg.A.Foo({\"foo\", \"bar\",}) A trailingComma1();",
" @A.Foo({\"a'b\", \"c'd\",}) A trailingComma2();",
" @Foo({\"a\" + \"\\nb\", \"c\" + \"\\nd\",}) A trailingComma3();",
" @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(
"out/pkg/A.java",
@@ -128,28 +214,60 @@ final class CanonicalAnnotationSyntaxCheckTest {
"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",
" A functional1();",
"",
" @pkg.A.Foo(\"foo\") A verbose1();",
" @A.Foo(\"a'b\") A verbose2();",
" @Foo(\"a\" + \"\\nb\") A verbose3();",
" @A.Foo",
" A functional2();",
"",
" @pkg.A.Foo(\"foo\") A moreVerbose1();",
" @A.Foo(\"a'b\") A moreVerbose2();",
" @Foo(\"a\" + \"\\nb\") A moreVerbose3();",
" @Foo",
" A functional3();",
"",
" @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\")",
" A verbose1();",
"",
" @pkg.A.Foo({\"foo\", \"bar\"}) A trailingComma1();",
" @A.Foo({\"a'b\", \"c'd\"}) A trailingComma2();",
" @Foo({\"a\" + \"\\nb\", \"c\" + \"\\nd\"}) A trailingComma3();",
" @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);
}

View File

@@ -19,12 +19,12 @@ final class CollectorMutabilityCheckTest {
.addSourceLines(
"A.java",
"import static com.google.common.collect.ImmutableList.toImmutableList;",
"import static com.google.common.collect.ImmutableSet.toImmutableSet;",
"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.toSet;",
"import static java.util.stream.Collectors.toMap;",
"import static java.util.stream.Collectors.toSet;",
"",
"import java.util.ArrayList;",
"import java.util.HashMap;",
@@ -137,7 +137,7 @@ final class CollectorMutabilityCheckTest {
"import reactor.core.publisher.Flux;",
"",
"class A {",
" void m() {",
" void m() {",
" Flux.just(1).collect(Collectors.toList());",
" Flux.just(2).collect(toList());",
"",
@@ -148,7 +148,7 @@ final class CollectorMutabilityCheckTest {
"",
" Stream.of(1).collect(Collectors.toSet());",
" Stream.of(2).collect(toSet());",
" }",
" }",
"}")
.addOutputLines(
"A.java",
@@ -165,18 +165,35 @@ final class CollectorMutabilityCheckTest {
"import reactor.core.publisher.Flux;",
"",
"class A {",
" void m() {",
" Flux.just(1).collect(toCollection(ArrayList::new));",
" Flux.just(2).collect(toCollection(ArrayList::new));",
" 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(\"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));",
" }",
" Stream.of(1).collect(toCollection(HashSet::new));",
" Stream.of(2).collect(toCollection(HashSet::new));",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}

View File

@@ -0,0 +1,151 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class ErrorProneTestHelperSourceFormatCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(ErrorProneTestHelperSourceFormatCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(
ErrorProneTestHelperSourceFormatCheck.class, getClass());
@Test
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
"import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;",
"import com.google.errorprone.CompilationTestHelper;",
"import tech.picnic.errorprone.bugpatterns.EmptyMethodCheck;",
"",
"class A {",
" private final CompilationTestHelper compilationTestHelper =",
" CompilationTestHelper.newInstance(EmptyMethodCheck.class, getClass());",
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethodCheck.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(\"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();
}
@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.
*/
refactoringTestHelper
.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.EmptyMethodCheck;",
"",
"class A {",
" private final CompilationTestHelper compilationTestHelper =",
" CompilationTestHelper.newInstance(EmptyMethodCheck.class, getClass());",
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethodCheck.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(",
" \"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.EmptyMethodCheck;",
"",
"class A {",
" private final CompilationTestHelper compilationTestHelper =",
" CompilationTestHelper.newInstance(EmptyMethodCheck.class, getClass());",
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethodCheck.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(",
" \"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);
}
}

View File

@@ -12,14 +12,14 @@ final class ExplicitEnumOrderingCheckTest {
compilationTestHelper
.addSourceLines(
"A.java",
"import static java.lang.annotation.RetentionPolicy.SOURCE;",
"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.Ordering;",
"import com.google.common.collect.ImmutableList;",
"import com.google.common.collect.Ordering;",
"import java.lang.annotation.RetentionPolicy;",
"import java.time.chrono.IsoEra;",
"",

View File

@@ -20,8 +20,8 @@ final class FluxFlatMapUsageCheckTest {
"A.java",
"import java.util.function.BiFunction;",
"import java.util.function.Function;",
"import reactor.core.publisher.Mono;",
"import reactor.core.publisher.Flux;",
"import reactor.core.publisher.Mono;",
"",
"class A {",
" void m() {",

View File

@@ -23,8 +23,8 @@ final class FormatStringConcatenationCheckTest {
"import static org.assertj.core.api.Assertions.assertThat;",
"import static org.assertj.core.api.SoftAssertions.assertSoftly;",
"",
"import java.util.Locale;",
"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;",
@@ -269,9 +269,9 @@ final class FormatStringConcatenationCheckTest {
" LOG.error(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.error((Marker) null,\"str \" + toString());",
" LOG.error((Marker) null, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.error((Marker) null,\"{} \" + toString(), \"arg\");",
" LOG.error((Marker) null, \"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.info(\"str \" + toString());",
@@ -279,9 +279,9 @@ final class FormatStringConcatenationCheckTest {
" LOG.info(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.info((Marker) null,\"str \" + toString());",
" LOG.info((Marker) null, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.info((Marker) null,\"{} \" + toString(), \"arg\");",
" LOG.info((Marker) null, \"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.trace(\"str \" + toString());",
@@ -289,9 +289,9 @@ final class FormatStringConcatenationCheckTest {
" LOG.trace(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.trace((Marker) null,\"str \" + toString());",
" LOG.trace((Marker) null, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.trace((Marker) null,\"{} \" + toString(), \"arg\");",
" LOG.trace((Marker) null, \"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.warn(\"str \" + toString());",
@@ -299,9 +299,9 @@ final class FormatStringConcatenationCheckTest {
" LOG.warn(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.warn((Marker) null,\"str \" + toString());",
" LOG.warn((Marker) null, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.warn((Marker) null,\"{} \" + toString(), \"arg\");",
" LOG.warn((Marker) null, \"{} \" + toString(), \"arg\");",
" }",
"}")
.doTest();
@@ -316,7 +316,6 @@ final class FormatStringConcatenationCheckTest {
"import static org.assertj.core.api.Assertions.assertThat;",
"",
"import java.util.Locale;",
"import java.util.Formatter;",
"import org.slf4j.Logger;",
"import org.slf4j.LoggerFactory;",
"import org.slf4j.Marker;",
@@ -366,7 +365,6 @@ final class FormatStringConcatenationCheckTest {
"import static org.assertj.core.api.Assertions.assertThat;",
"",
"import java.util.Locale;",
"import java.util.Formatter;",
"import org.slf4j.Logger;",
"import org.slf4j.LoggerFactory;",
"import org.slf4j.Marker;",
@@ -400,6 +398,7 @@ final class FormatStringConcatenationCheckTest {
" String.format(\"{} \" + toString(), \"arg\");",
" String.format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
" }",
"",
" void slf4j() {",
" LOG.debug(\"str {}\", toString());",
" LOG.debug((Marker) null, \"str {}\", toString());",

View File

@@ -121,8 +121,9 @@ final class IdentityConversionCheckTest {
" ImmutableBiMap<Object, Object> o1 = ImmutableBiMap.copyOf(ImmutableBiMap.of());",
" // BUG: Diagnostic contains:",
" ImmutableList<Object> o2 = ImmutableList.copyOf(ImmutableList.of());",
" // BUG: Diagnostic contains:",
" ImmutableListMultimap<Object, Object> o3 = ImmutableListMultimap.copyOf(ImmutableListMultimap.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:",
@@ -135,8 +136,9 @@ final class IdentityConversionCheckTest {
" ImmutableRangeSet<String> o8 = ImmutableRangeSet.copyOf(ImmutableRangeSet.of());",
" // BUG: Diagnostic contains:",
" ImmutableSet<Object> o9 = ImmutableSet.copyOf(ImmutableSet.of());",
" // BUG: Diagnostic contains:",
" ImmutableSetMultimap<Object, Object> o10 = ImmutableSetMultimap.copyOf(ImmutableSetMultimap.of());",
" ImmutableSetMultimap<Object, Object> o10 =",
" // BUG: Diagnostic contains:",
" ImmutableSetMultimap.copyOf(ImmutableSetMultimap.of());",
" // BUG: Diagnostic contains:",
" ImmutableTable<Object, Object, Object> o11 = ImmutableTable.copyOf(ImmutableTable.of());",
"",
@@ -171,8 +173,8 @@ final class IdentityConversionCheckTest {
"import com.google.common.collect.ImmutableCollection;",
"import com.google.common.collect.ImmutableList;",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Collection;",
"import java.util.ArrayList;",
"import java.util.Collection;",
"import org.reactivestreams.Publisher;",
"import reactor.adapter.rxjava.RxJava2Adapter;",
"import reactor.core.publisher.Flux;",
@@ -204,8 +206,7 @@ final class IdentityConversionCheckTest {
" Object o1 = ImmutableSet.copyOf(ImmutableList.of());",
" Object o2 = ImmutableSet.copyOf(ImmutableSet.of());",
"",
" when(\"foo\".contains(\"f\"))",
" .thenAnswer(inv-> ImmutableSet.copyOf(ImmutableList.of(1)));",
" when(\"foo\".contains(\"f\")).thenAnswer(inv -> ImmutableSet.copyOf(ImmutableList.of(1)));",
" }",
"",
" void bar(Publisher<Integer> publisher) {}",
@@ -217,8 +218,8 @@ final class IdentityConversionCheckTest {
"import com.google.common.collect.ImmutableCollection;",
"import com.google.common.collect.ImmutableList;",
"import com.google.common.collect.ImmutableSet;",
"import java.util.Collection;",
"import java.util.ArrayList;",
"import java.util.Collection;",
"import org.reactivestreams.Publisher;",
"import reactor.adapter.rxjava.RxJava2Adapter;",
"import reactor.core.publisher.Flux;",
@@ -250,8 +251,7 @@ final class IdentityConversionCheckTest {
" Object o1 = ImmutableSet.copyOf(ImmutableList.of());",
" Object o2 = ImmutableSet.of();",
"",
" when(\"foo\".contains(\"f\"))",
" .thenAnswer(inv-> ImmutableSet.copyOf(ImmutableList.of(1)));",
" when(\"foo\".contains(\"f\")).thenAnswer(inv -> ImmutableSet.copyOf(ImmutableList.of(1)));",
" }",
"",
" void bar(Publisher<Integer> publisher) {}",
@@ -269,9 +269,6 @@ final class IdentityConversionCheckTest {
"import com.google.common.collect.ImmutableList;",
"import com.google.common.collect.ImmutableSet;",
"import java.util.ArrayList;",
"import reactor.adapter.rxjava.RxJava2Adapter;",
"import reactor.core.publisher.Flux;",
"import reactor.core.publisher.Mono;",
"",
"public final class Foo {",
" public void foo() {",
@@ -288,9 +285,6 @@ final class IdentityConversionCheckTest {
"import com.google.common.collect.ImmutableList;",
"import com.google.common.collect.ImmutableSet;",
"import java.util.ArrayList;",
"import reactor.adapter.rxjava.RxJava2Adapter;",
"import reactor.core.publisher.Flux;",
"import reactor.core.publisher.Mono;",
"",
"public final class Foo {",
" public void foo() {",

View File

@@ -26,71 +26,137 @@ final class JUnitMethodDeclarationCheckTest {
"import org.junit.jupiter.params.ParameterizedTest;",
"",
"class A {",
" @BeforeAll void setUp1() {}",
" // BUG: Diagnostic contains:",
" @BeforeAll public void setUp2() {}",
" // BUG: Diagnostic contains:",
" @BeforeAll protected void setUp3() {}",
" // BUG: Diagnostic contains:",
" @BeforeAll private void setUp4() {}",
" {",
" arguments();",
" }",
"",
" @BeforeEach void setup5() {}",
" // BUG: Diagnostic contains:",
" @BeforeEach public void setUp6() {}",
" // BUG: Diagnostic contains:",
" @BeforeEach protected void setUp7() {}",
" // BUG: Diagnostic contains:",
" @BeforeEach private void setUp8() {}",
" @BeforeAll",
" void setUp1() {}",
"",
" @AfterEach void tearDown1() {}",
" @BeforeAll",
" // BUG: Diagnostic contains:",
" @AfterEach public void tearDown2() {}",
" // BUG: Diagnostic contains:",
" @AfterEach protected void tearDown3() {}",
" // BUG: Diagnostic contains:",
" @AfterEach private void tearDown4() {}",
" public void setUp2() {}",
"",
" @AfterAll void tearDown5() {}",
" @BeforeAll",
" // BUG: Diagnostic contains:",
" @AfterAll public void tearDown6() {}",
" // BUG: Diagnostic contains:",
" @AfterAll protected void tearDown7() {}",
" // BUG: Diagnostic contains:",
" @AfterAll private void tearDown8() {}",
" protected void setUp3() {}",
"",
" @Test void method1() {}",
" @BeforeAll",
" // BUG: Diagnostic contains:",
" @Test void testMethod2() {}",
" // BUG: Diagnostic contains:",
" @Test public void method3() {}",
" // BUG: Diagnostic contains:",
" @Test protected void method4() {}",
" // BUG: Diagnostic contains:",
" @Test private void method5() {}",
" private void setUp4() {}",
"",
" @ParameterizedTest void method6() {}",
" // BUG: Diagnostic contains:",
" @ParameterizedTest void testMethod7() {}",
" // BUG: Diagnostic contains:",
" @ParameterizedTest public void method8() {}",
" // BUG: Diagnostic contains:",
" @ParameterizedTest protected void method9() {}",
" // BUG: Diagnostic contains:",
" @ParameterizedTest private void method10() {}",
" @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 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() {}",
"",
" @BeforeEach @BeforeAll @AfterEach @AfterAll void testNonTestMethod1() {}",
" public void testNonTestMethod2() {}",
" protected void testNonTestMethod3() {}",
" private void testNonTestMethod4() {}",
" @Test void test5() {}",
"",
" // BUG: Diagnostic contains: (but note that a method named `overload` already exists in this class)",
" @Test void testOverload() {}",
" protected void testNonTestMethod3() {}",
"",
" private void testNonTestMethod4() {}",
"",
" @Test",
" void test5() {}",
"",
" @Test",
" // BUG: Diagnostic contains: (but note that a method named `overload` already exists in this",
" // class)",
" void testOverload() {}",
"",
" void overload() {}",
"",
" @Test",
" // BUG: Diagnostic contains: (but note that `arguments` is already statically imported)",
" @Test void testArguments() {}",
" void testArguments() {}",
"",
" @Test",
" // BUG: Diagnostic contains: (but note that `public` is a reserved keyword)",
" @Test void testPublic() {}",
" void testPublic() {}",
"}")
.addSourceLines(
"B.java",
@@ -102,41 +168,117 @@ final class JUnitMethodDeclarationCheckTest {
"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",
" @BeforeAll",
" void setUp1() {}",
"",
" @Override @BeforeEach void setup5() {}",
" @Override @BeforeEach public void setUp6() {}",
" @Override @BeforeEach protected void setUp7() {}",
" @Override",
" @BeforeAll",
" public void setUp2() {}",
"",
" @Override @AfterEach void tearDown1() {}",
" @Override @AfterEach public void tearDown2() {}",
" @Override @AfterEach protected void tearDown3() {}",
" @Override",
" @BeforeAll",
" protected void setUp3() {}",
"",
" @Override @AfterAll void tearDown5() {}",
" @Override @AfterAll public void tearDown6() {}",
" @Override @AfterAll protected void tearDown7() {}",
" @Override",
" @BeforeEach",
" void setup5() {}",
"",
" @Override @Test void method1() {}",
" @Override @Test void testMethod2() {}",
" @Override @Test public void method3() {}",
" @Override @Test protected void method4() {}",
" @Override",
" @BeforeEach",
" public void setUp6() {}",
"",
" @Override @ParameterizedTest void method6() {}",
" @Override @ParameterizedTest void testMethod7() {}",
" @Override @ParameterizedTest public void method8() {}",
" @Override @ParameterizedTest protected void method9() {}",
" @Override",
" @BeforeEach",
" protected void setUp7() {}",
"",
" @Override @BeforeEach @BeforeAll @AfterEach @AfterAll void testNonTestMethod1() {}",
" @Override public void testNonTestMethod2() {}",
" @Override protected void testNonTestMethod3() {}",
" @Override @Test void test5() {}",
" @Override",
" @AfterEach",
" void tearDown1() {}",
"",
" @Override @Test void testOverload() {}",
" @Override void overload() {}",
" @Override @Test void testArguments() {}",
" @Override @Test void testPublic() {}",
" @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 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 testOverload() {}",
"",
" @Override",
" void overload() {}",
"",
" @Override",
" @Test",
" void testArguments() {}",
"",
" @Override",
" @Test",
" void testPublic() {}",
"}")
.addSourceLines(
"C.java",
@@ -145,13 +287,19 @@ final class JUnitMethodDeclarationCheckTest {
"import org.junit.jupiter.api.Test;",
"",
"abstract class C {",
" @BeforeAll public void setUp() {}",
" @Test void testMethod1() {}",
" @BeforeAll",
" public void setUp() {}",
"",
" @Test",
" void testMethod1() {}",
"",
" @AfterAll",
" // BUG: Diagnostic contains:",
" @AfterAll private void tearDown() {}",
" private void tearDown() {}",
"",
" @Test",
" // BUG: Diagnostic contains:",
" @Test final void testMethod2() {}",
" final void testMethod2() {}",
"}")
.doTest();
}
@@ -172,22 +320,47 @@ final class JUnitMethodDeclarationCheckTest {
"import org.junit.jupiter.params.ParameterizedTest;",
"",
"class A {",
" @BeforeAll public void setUp1() {}",
" @BeforeEach protected void setUp2() {}",
" @AfterEach private void setUp3() {}",
" @AfterAll private void setUp4() {}",
" {",
" arguments();",
" }",
"",
" @Test void testFoo() {}",
" @ParameterizedTest void testBar() {}",
" @BeforeAll",
" public void setUp1() {}",
"",
" @Test public void baz() {}",
" @RepeatedTest(2) private void qux() {}",
" @ParameterizedTest protected void quux() {}",
" @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 testOverload() {}",
"",
" @Test public void testOverload() {}",
" void overload() {}",
" @Test protected void testArguments() {}",
" @Test private void testClass() {}",
"",
" @Test",
" protected void testArguments() {}",
"",
" @Test",
" private void testClass() {}",
"}")
.addOutputLines(
"out/A.java",
@@ -202,22 +375,47 @@ final class JUnitMethodDeclarationCheckTest {
"import org.junit.jupiter.params.ParameterizedTest;",
"",
"class A {",
" @BeforeAll void setUp1() {}",
" @BeforeEach void setUp2() {}",
" @AfterEach void setUp3() {}",
" @AfterAll void setUp4() {}",
" {",
" arguments();",
" }",
"",
" @Test void foo() {}",
" @ParameterizedTest void bar() {}",
" @BeforeAll",
" void setUp1() {}",
"",
" @Test void baz() {}",
" @RepeatedTest(2) void qux() {}",
" @ParameterizedTest void quux() {}",
" @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 testOverload() {}",
"",
" @Test void testOverload() {}",
" void overload() {}",
" @Test void testArguments() {}",
" @Test void testClass() {}",
"",
" @Test",
" void testArguments() {}",
"",
" @Test",
" void testClass() {}",
"}")
.doTest(TestMode.TEXT_MATCH);
}

View File

@@ -26,8 +26,8 @@ final class LexicographicalAnnotationAttributeListingCheckTest {
compilationTestHelper
.addSourceLines(
"A.java",
"import static java.math.RoundingMode.UP;",
"import static java.math.RoundingMode.DOWN;",
"import static java.math.RoundingMode.UP;",
"",
"import com.fasterxml.jackson.annotation.JsonPropertyOrder;",
"import io.swagger.annotations.ApiImplicitParam;",
@@ -40,9 +40,13 @@ final class LexicographicalAnnotationAttributeListingCheckTest {
"interface A {",
" @interface Foo {",
" String[] value() default {};",
"",
" int[] ints() default {};",
"",
" Class<?>[] cls() default {};",
"",
" RoundingMode[] enums() default {};",
"",
" Bar[] anns() default {};",
" }",
"",
@@ -50,50 +54,95 @@ final class LexicographicalAnnotationAttributeListingCheckTest {
" 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({})",
" A noString();",
"",
" @Foo(ints = {}) A noInts();",
" @Foo(ints = {0}) A oneInt();",
" @Foo(ints = {0, 1}) A sortedInts();",
" @Foo(ints = {1, 0}) A unsortedInts();",
" @Foo({\"a\"})",
" A oneString();",
"",
" @Foo(cls = {}) A noClasses();",
" @Foo(cls = {int.class}) A oneClass();",
" @Foo(cls = {int.class, long.class}) A sortedClasses();",
" @Foo({\"a\", \"b\"})",
" A sortedStrings();",
" // BUG: Diagnostic contains:",
" @Foo(cls = {long.class, int.class}) A unsortedClasses();",
" @Foo({\"b\", \"a\"})",
" A unsortedString();",
"",
" @Foo(enums = {}) A noEnums();",
" @Foo(enums = {DOWN}) A oneEnum();",
" @Foo(enums = {DOWN, UP}) A sortedEnums();",
" @Foo({\"ab\", \"Ac\"})",
" A sortedStringCaseInsensitive();",
" // BUG: Diagnostic contains:",
" @Foo(enums = {UP, DOWN}) A unsortedEnums();",
" @Foo({\"ac\", \"Ab\"})",
" A unsortedStringCaseInsensitive();",
"",
" @Foo(anns = {}) A noAnns();",
" @Foo(anns = {@Bar(\"a\")}) A oneAnn();",
" @Foo(anns = {@Bar(\"a\"), @Bar(\"b\")}) A sortedAnns();",
" @Foo({\"A\", \"a\"})",
" A sortedStringCaseInsensitiveWithTotalOrderFallback();",
" // 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\", \"A\"})",
" A unsortedStringCaseInsensitiveWithTotalOrderFallback();",
"",
" @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();",
" @Foo(ints = {})",
" A noInts();",
"",
" @JsonPropertyOrder({\"field2\", \"field1\"}) A dto();",
" @ApiImplicitParams({@ApiImplicitParam(\"p2\"), @ApiImplicitParam(\"p1\")}) A firstEndpoint();",
" @Parameters({@Parameter(name = \"p2\"), @Parameter(name = \"p1\")}) A secondEndpoint();",
" @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 Dummy {}",
@@ -109,16 +158,19 @@ final class LexicographicalAnnotationAttributeListingCheckTest {
refactoringTestHelper
.addInputLines(
"in/A.java",
"import static java.math.RoundingMode.UP;",
"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 {};",
" }",
"",
@@ -126,24 +178,36 @@ final class LexicographicalAnnotationAttributeListingCheckTest {
" 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();",
" @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(
"out/A.java",
"import static java.math.RoundingMode.UP;",
"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 {};",
" }",
"",
@@ -151,11 +215,20 @@ final class LexicographicalAnnotationAttributeListingCheckTest {
" 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();",
" @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);
}
@@ -171,28 +244,40 @@ final class LexicographicalAnnotationAttributeListingCheckTest {
"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();",
" @Foo({\"b\", \"a\"})",
" A fooValue();",
" // BUG: Diagnostic contains:",
" @Foo(value2 = {\"b\", \"a\"}) A fooValue2();",
" @Bar({\"b\", \"a\"}) A barValue();",
" @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();",
" @Bar(value2 = {\"b\", \"a\"})",
" A barValue2();",
"",
" @Baz({\"b\", \"a\"})",
" A bazValue();",
"",
" @Baz(value2 = {\"b\", \"a\"})",
" A bazValue2();",
"}")
.doTest();
}

View File

@@ -27,7 +27,9 @@ final class LexicographicalAnnotationListingCheckTest {
" @Repeatable(Foos.class)",
" @interface Foo {",
" String[] value() default {};",
"",
" int[] ints() default {};",
"",
" Bar[] anns() default {};",
" }",
"",
@@ -40,33 +42,70 @@ final class LexicographicalAnnotationListingCheckTest {
" }",
"",
" @interface Foos {",
" Foo[] value();",
" Foo[] value();",
" }",
"",
" // BUG: Diagnostic matches: X",
" @Foo @Bar A unsortedSimpleCase();",
" @Foo",
" @Bar",
" A unsortedSimpleCase();",
" // BUG: Diagnostic matches: X",
" @Foo() @Bar() A unsortedWithParens();",
" @Foo() A onlyOneAnnotation();",
" @Bar @Foo() A sortedAnnotationsOneWithParens();",
" @Foo()",
" @Bar()",
" A unsortedWithParens();",
"",
" @Foo()",
" A onlyOneAnnotation();",
"",
" @Bar",
" @Foo()",
" A sortedAnnotationsOneWithParens();",
"",
" // BUG: Diagnostic matches: X",
" @Foo @Baz @Bar A threeUnsortedAnnotationsSameInitialLetter();",
" @Foo",
" @Baz",
" @Bar",
" A threeUnsortedAnnotationsSameInitialLetter();",
" // BUG: Diagnostic matches: X",
" @Bar @Foo() @Baz A firstOrderedWithTwoUnsortedAnnotations();",
" @Bar @Baz @Foo() A threeSortedAnnotations();",
" @Bar",
" @Foo()",
" @Baz",
" A firstOrderedWithTwoUnsortedAnnotations();",
"",
" @Bar",
" @Baz",
" @Foo()",
" A threeSortedAnnotations();",
"",
" // BUG: Diagnostic matches: X",
" @Foo({\"b\"}) @Bar({\"a\"}) A unsortedWithStringAttributes();",
" @Foo({\"b\"})",
" @Bar({\"a\"})",
" A unsortedWithStringAttributes();",
" // BUG: Diagnostic matches: X",
" @Baz(str = {\"a\", \"b\"}) @Foo(ints = {1, 0}) @Bar A unsortedWithAttributes();",
" @Baz(str = {\"a\", \"b\"})",
" @Foo(ints = {1, 0})",
" @Bar",
" A unsortedWithAttributes();",
" // BUG: Diagnostic matches: X",
" @Bar @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Baz A unsortedWithNestedBar();",
" @Bar @Baz @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) A sortedWithNestedBar();",
" @Bar",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
" @Baz",
" A unsortedWithNestedBar();",
"",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Foo(ints = {1, 2}) @Foo({\"b\"}) A sortedRepeatableAnnotation();",
" @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 matches: X",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Bar @Foo(ints = {1, 2}) A unsortedRepeatableAnnotation();",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")})",
" @Bar",
" @Foo(ints = {1, 2})",
" A unsortedRepeatableAnnotation();",
"}")
.doTest();
}
@@ -77,11 +116,14 @@ final class LexicographicalAnnotationListingCheckTest {
.addInputLines(
"in/A.java",
"import java.lang.annotation.Repeatable;",
"",
"interface A {",
" @Repeatable(Foos.class)",
" @interface Foo {",
" String[] value() default {};",
"",
" int[] ints() default {};",
"",
" Bar[] anns() default {};",
" }",
"",
@@ -94,29 +136,56 @@ final class LexicographicalAnnotationListingCheckTest {
" }",
"",
" @interface Foos {",
" Foo[] value();",
" Foo[] value();",
" }",
"",
" @Bar A singleAnnotation();",
" @Bar @Foo A sortedAnnotations();",
" @Foo @Bar A unsortedAnnotations();",
" @Foo() @Baz() @Bar A unsortedAnnotationsWithSomeParens();",
" @Bar",
" A singleAnnotation();",
"",
" @Bar @Baz(str = {\"a\", \"b\"}) @Foo() A unsortedAnnotationsOneContainingAttributes();",
" @Baz(str = {\"a\", \"b\"}) @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Bar({\"b\"}) A unsortedAnnotationsWithAttributes();",
" @Bar",
" @Foo",
" A sortedAnnotations();",
"",
" @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();",
" @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();",
"}")
.addOutputLines(
"out/A.java",
"import java.lang.annotation.Repeatable;",
"",
"interface A {",
" @Repeatable(Foos.class)",
" @interface Foo {",
" String[] value() default {};",
"",
" int[] ints() default {};",
"",
" Bar[] anns() default {};",
" }",
"",
@@ -129,19 +198,44 @@ final class LexicographicalAnnotationListingCheckTest {
" }",
"",
" @interface Foos {",
" Foo[] value();",
" Foo[] value();",
" }",
" @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();",
" @Bar",
" A singleAnnotation();",
"",
" @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",
" @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();",
"}")
.doTest(TestMode.TEXT_MATCH);
}

View File

@@ -68,13 +68,21 @@ final class MethodMatcherFactoryTest {
"",
"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(
@@ -83,13 +91,21 @@ final class MethodMatcherFactoryTest {
"",
"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(
@@ -98,13 +114,21 @@ final class MethodMatcherFactoryTest {
"",
"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(
@@ -113,13 +137,21 @@ final class MethodMatcherFactoryTest {
"",
"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(

View File

@@ -17,37 +17,62 @@ final class MethodReferenceUsageCheckTest {
.addSourceLines(
"A.java",
"import com.google.common.collect.Streams;",
"import java.util.Map;",
"import java.util.HashMap;",
"import java.util.stream.Stream;",
"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(); };",
" private final Runnable thrower =",
" () -> {",
" throw new RuntimeException();",
" };",
"",
" void unaryExternalStaticFunctionCalls() {",
" s.forEach(String::valueOf);",
" // BUG: Diagnostic contains:",
" s.forEach(v -> String.valueOf(v));",
" // BUG: Diagnostic contains:",
" s.forEach((v) -> { String.valueOf(v); });",
" // BUG: Diagnostic contains:",
" s.forEach((Integer v) -> { { String.valueOf(v); } });",
" s.forEach(v -> { String.valueOf(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)));",
" // BUG: Diagnostic contains:",
" s.map((Integer v) -> { return String.valueOf(v); });",
" // BUG: Diagnostic contains:",
" s.map((final Integer v) -> { return (String.valueOf(v)); });",
" s.map(v -> { String.valueOf(v); return 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));",
@@ -59,14 +84,34 @@ final class MethodReferenceUsageCheckTest {
" // BUG: Diagnostic contains:",
" m.forEach((k, v) -> m.put(k, v));",
" m.forEach((k, v) -> m.put(v, k));",
" // BUG: Diagnostic contains:",
" m.forEach((Integer k, Integer v) -> { m.put(k, v); });",
" m.forEach((k, v) -> { m.put(k, k); });",
" // BUG: Diagnostic contains:",
" m.forEach((final Integer k, final Integer v) -> { { m.put(k, v); } });",
" m.forEach((k, v) -> { { m.put(v, v); } });",
" 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); });",
" m.forEach(",
" (k, v) -> {",
" m.put(k, v);",
" m.put(k, v);",
" });",
"",
" Streams.zip(s, s, m::put);",
" // BUG: Diagnostic contains:",
@@ -75,20 +120,45 @@ final class MethodReferenceUsageCheckTest {
" // 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)));",
" // BUG: Diagnostic contains:",
" Streams.zip(s, s, (final Integer a, final Integer b) -> { return m.put(a, b); });",
" Streams.zip(s, s, (a, b) -> { return m.put(b, b); });",
" // BUG: Diagnostic contains:",
" Streams.zip(s, s, (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); });",
" 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(Integer::toString)` is ambiguous
" s.map(i -> i.toString());",
" s.map(i -> s.toString());",
"",
@@ -108,24 +178,36 @@ final class MethodReferenceUsageCheckTest {
" s.forEach(this::ivoid1);",
" // BUG: Diagnostic contains:",
" s.forEach(v -> ivoid1(v));",
" // 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));",
" // 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));",
" // 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));",
" // 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));",
@@ -140,28 +222,43 @@ final class MethodReferenceUsageCheckTest {
" m.forEach(this::ivoid2);",
" // BUG: Diagnostic contains:",
" m.forEach((k, v) -> ivoid2(k, v));",
" // 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));",
" // 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));",
" // 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));",
" // 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); });",
" receiver(",
" i -> {",
" Integer.toString(i);",
" });",
" }",
"",
" void assortedOtherEdgeCases() {",
@@ -175,23 +272,47 @@ final class MethodReferenceUsageCheckTest {
" TernaryOp o7 = (a, b, c) -> b.concat(c);",
" }",
"",
" void receiver(IntFunction<?> op) { }",
" void receiver(IntConsumer op) { }",
" void receiver(IntFunction<?> 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; }",
" void receiver(IntConsumer op) {}",
"",
" 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; }",
" 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);",
@@ -210,9 +331,6 @@ final class MethodReferenceUsageCheckTest {
"import java.util.Collections;",
"import java.util.List;",
"import java.util.Map;",
// Don't import `java.util.Set`; it should be added.
"import java.util.function.IntConsumer;",
"import java.util.function.IntFunction;",
"import java.util.function.IntSupplier;",
"import java.util.function.Supplier;",
"import java.util.stream.Stream;",
@@ -245,12 +363,19 @@ final class MethodReferenceUsageCheckTest {
" Stream.of((Map<?, ?>) null).map(Map::keySet).map(s -> s.size());",
" }",
"",
" @Override int iint0() { return 0; }",
" @Override",
" int iint0() {",
" return 0;",
" }",
" }",
"",
" int iint0() { return 0; }",
" int iint0() {",
" return 0;",
" }",
"",
" static int sint0() { return 0; }",
" static int sint0() {",
" return 0;",
" }",
"}")
.addOutputLines(
"out/A.java",
@@ -260,8 +385,6 @@ final class MethodReferenceUsageCheckTest {
"import java.util.List;",
"import java.util.Map;",
"import java.util.Set;",
"import java.util.function.IntConsumer;",
"import java.util.function.IntFunction;",
"import java.util.function.IntSupplier;",
"import java.util.function.Supplier;",
"import java.util.stream.Stream;",
@@ -294,12 +417,19 @@ final class MethodReferenceUsageCheckTest {
" Stream.of((Map<?, ?>) null).map(Map::keySet).map(Set::size);",
" }",
"",
" @Override int iint0() { return 0; }",
" @Override",
" int iint0() {",
" return 0;",
" }",
" }",
"",
" int iint0() { return 0; }",
" int iint0() {",
" return 0;",
" }",
"",
" static int sint0() { return 0; }",
" static int sint0() {",
" return 0;",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}

View File

@@ -42,8 +42,10 @@ final class MockitoStubbingCheckTest {
" 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\"));",
" // BUG: Diagnostic contains:",
" doAnswer(inv -> null).when(biConsumer).accept(ArgumentMatchers.eq(0), ArgumentMatchers.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()));",
" }",
@@ -71,7 +73,9 @@ final class MockitoStubbingCheckTest {
" 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(ArgumentMatchers.eq(0), ArgumentMatchers.eq(\"foo\"));",
" doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));",
" }",
"}")

View File

@@ -99,10 +99,21 @@ final class PrimitiveComparisonCheckTest {
" cmp().thenComparingDouble(o -> Byte.valueOf((byte) 0));",
" }",
"",
" private Comparator<Object> cmp() { return null; }",
" private byte toPrimitive(Object o) { return 0; }",
" private Byte toBoxed(Object o) { return 0; }",
" private Function<Object, Byte> toBoxed() { return o -> 0; }",
" private Comparator<Object> cmp() {",
" return null;",
" }",
"",
" private byte toPrimitive(Object o) {",
" return 0;",
" }",
"",
" private Byte toBoxed(Object o) {",
" return 0;",
" }",
"",
" private Function<Object, Byte> toBoxed() {",
" return o -> 0;",
" }",
"}")
.doTest();
}
@@ -191,11 +202,25 @@ final class PrimitiveComparisonCheckTest {
" cmp().thenComparingDouble(o -> Integer.valueOf(0));",
" }",
"",
" private Comparator<Object> cmp() { return null; }",
" private int toPrimitive(Object o) { return 0; }",
" private Integer toBoxed(Object o) { return 0; }",
" private Function<Object, Integer> toBoxed() { return o -> 0; }",
" private ToIntFunction<Object> toPrimitive() { return o -> 0; }",
" private Comparator<Object> cmp() {",
" return null;",
" }",
"",
" private int toPrimitive(Object o) {",
" return 0;",
" }",
"",
" private Integer toBoxed(Object o) {",
" return 0;",
" }",
"",
" private Function<Object, Integer> toBoxed() {",
" return o -> 0;",
" }",
"",
" private ToIntFunction<Object> toPrimitive() {",
" return o -> 0;",
" }",
"}")
.doTest();
}
@@ -268,11 +293,25 @@ final class PrimitiveComparisonCheckTest {
" cmp().thenComparingDouble(o -> Long.valueOf(0));",
" }",
"",
" private Comparator<Object> cmp() { return null; }",
" private long toPrimitive(Object o) { return 0L; }",
" private Long toBoxed(Object o) { return 0L; }",
" private Function<Object, Long> toBoxed() { return o -> 0L; }",
" private ToLongFunction<Object> toPrimitive() { return o -> 0L; }",
" private Comparator<Object> cmp() {",
" return null;",
" }",
"",
" private long toPrimitive(Object o) {",
" return 0L;",
" }",
"",
" private Long toBoxed(Object o) {",
" return 0L;",
" }",
"",
" private Function<Object, Long> toBoxed() {",
" return o -> 0L;",
" }",
"",
" private ToLongFunction<Object> toPrimitive() {",
" return o -> 0L;",
" }",
"}")
.doTest();
}
@@ -326,10 +365,21 @@ final class PrimitiveComparisonCheckTest {
" cmp().thenComparingDouble(o -> Float.valueOf(0));",
" }",
"",
" private Comparator<Object> cmp() { return null; }",
" private float toPrimitive(Object o) { return 0.0f; }",
" private Float toBoxed(Object o) { return 0.0f; }",
" private Function<Object, Float> toBoxed() { return o -> 0.0f; }",
" private Comparator<Object> cmp() {",
" return null;",
" }",
"",
" private float toPrimitive(Object o) {",
" return 0.0f;",
" }",
"",
" private Float toBoxed(Object o) {",
" return 0.0f;",
" }",
"",
" private Function<Object, Float> toBoxed() {",
" return o -> 0.0f;",
" }",
"}")
.doTest();
}
@@ -386,11 +436,25 @@ final class PrimitiveComparisonCheckTest {
" cmp().thenComparingDouble(o -> Double.valueOf(0));",
" }",
"",
" private Comparator<Object> cmp() { return null; }",
" private double toPrimitive(Object o) { return 0.0; }",
" private Double toBoxed(Object o) { return 0.0; }",
" private Function<Object, Double> toBoxed() { return o -> 0.0; }",
" private ToDoubleFunction<Object> toPrimitive() { return o -> 0.0; }",
" private Comparator<Object> cmp() {",
" return null;",
" }",
"",
" private double toPrimitive(Object o) {",
" return 0.0;",
" }",
"",
" private Double toBoxed(Object o) {",
" return 0.0;",
" }",
"",
" private Function<Object, Double> toBoxed() {",
" return o -> 0.0;",
" }",
"",
" private ToDoubleFunction<Object> toPrimitive() {",
" return o -> 0.0;",
" }",
"}")
.doTest();
}
@@ -420,8 +484,13 @@ final class PrimitiveComparisonCheckTest {
" cmp().thenComparing(toStr(), cmp());",
" }",
"",
" private Comparator<Object> cmp() { return null; }",
" private Function<Object, String> toStr() { return String::valueOf; }",
" private Comparator<Object> cmp() {",
" return null;",
" }",
"",
" private Function<Object, String> toStr() {",
" return String::valueOf;",
" }",
"}")
.doTest();
}
@@ -692,22 +761,30 @@ final class PrimitiveComparisonCheckTest {
"import java.util.Comparator;",
"",
"interface A extends Comparable<A> {",
" Comparator<A> bCmp = Comparator.<A, A>comparing(o -> o).thenComparingInt(o -> Byte.valueOf((byte) 0));",
" Comparator<A> cCmp = Comparator.<A, A>comparing(o -> o).thenComparingInt(o -> Character.valueOf((char) 0));",
" Comparator<A> sCmp = Comparator.<A, A>comparing(o -> o).thenComparingInt(o -> Short.valueOf((short) 0));",
" Comparator<A> bCmp =",
" Comparator.<A, A>comparing(o -> o).thenComparingInt(o -> Byte.valueOf((byte) 0));",
" Comparator<A> cCmp =",
" Comparator.<A, A>comparing(o -> o).thenComparingInt(o -> Character.valueOf((char) 0));",
" Comparator<A> sCmp =",
" Comparator.<A, A>comparing(o -> o).thenComparingInt(o -> Short.valueOf((short) 0));",
" Comparator<A> iCmp = Comparator.<A, A>comparing(o -> o).thenComparingInt(o -> Integer.valueOf(0));",
" Comparator<A> lCmp = Comparator.<A, A>comparing(o -> o).thenComparingLong(o -> Long.valueOf(0));",
" Comparator<A> fCmp = Comparator.<A, A>comparing(o -> o).thenComparingDouble(o -> Float.valueOf(0));",
" Comparator<A> dCmp = Comparator.<A, A>comparing(o -> o).thenComparingDouble(o -> Double.valueOf(0));",
" Comparator<A> fCmp =",
" Comparator.<A, A>comparing(o -> o).thenComparingDouble(o -> Float.valueOf(0));",
" Comparator<A> dCmp =",
" Comparator.<A, A>comparing(o -> o).thenComparingDouble(o -> Double.valueOf(0));",
"}")
.addOutputLines(
"out/A.java",
"import java.util.Comparator;",
"",
"interface A extends Comparable<A> {",
" Comparator<A> bCmp = Comparator.<A, A>comparing(o -> o).thenComparing(o -> Byte.valueOf((byte) 0));",
" Comparator<A> cCmp = Comparator.<A, A>comparing(o -> o).thenComparing(o -> Character.valueOf((char) 0));",
" Comparator<A> sCmp = Comparator.<A, A>comparing(o -> o).thenComparing(o -> Short.valueOf((short) 0));",
" Comparator<A> bCmp =",
" Comparator.<A, A>comparing(o -> o).thenComparing(o -> Byte.valueOf((byte) 0));",
" Comparator<A> cCmp =",
" Comparator.<A, A>comparing(o -> o).thenComparing(o -> Character.valueOf((char) 0));",
" Comparator<A> sCmp =",
" Comparator.<A, A>comparing(o -> o).thenComparing(o -> Short.valueOf((short) 0));",
" Comparator<A> iCmp = Comparator.<A, A>comparing(o -> o).thenComparing(o -> Integer.valueOf(0));",
" Comparator<A> lCmp = Comparator.<A, A>comparing(o -> o).thenComparing(o -> Long.valueOf(0));",
" Comparator<A> fCmp = Comparator.<A, A>comparing(o -> o).thenComparing(o -> Float.valueOf(0));",

View File

@@ -124,7 +124,7 @@ final class RedundantStringConversionCheckTest {
" s + String.valueOf((String) null),",
" s + String.valueOf(null),",
" s + String.valueOf(new char[0]),",
"",
" //",
" 42 + this.toString(),",
" 42 + super.toString(),",
" 42 + i.toString(),",
@@ -147,7 +147,7 @@ final class RedundantStringConversionCheckTest {
" String.valueOf((String) null) + s,",
" String.valueOf(null) + s,",
" String.valueOf(new char[0]) + s,",
"",
" //",
" this.toString() + 42,",
" super.toString() + 42,",
" i.toString() + 42,",
@@ -175,10 +175,7 @@ final class RedundantStringConversionCheckTest {
"",
" int[] m2() {",
" return new int[] {",
" 1 + 1,",
" 1 - 1,",
" 1 * 1,",
" 1 / 1,",
" 1 + 1, 1 - 1, 1 * 1, 1 / 1,",
" };",
" }",
"}")
@@ -284,9 +281,9 @@ final class RedundantStringConversionCheckTest {
compilationTestHelper
.addSourceLines(
"A.java",
"import static com.google.common.base.Preconditions.checkState;",
"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;",
"",

View File

@@ -28,7 +28,6 @@ final class RequestMappingAnnotationCheckTest {
"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.RequestMethod;",
"import org.springframework.web.bind.annotation.RequestParam;",
"import org.springframework.web.context.request.NativeWebRequest;",
"import org.springframework.web.context.request.WebRequest;",
@@ -38,48 +37,91 @@ final class RequestMappingAnnotationCheckTest {
"",
"interface A {",
" A noMapping();",
"",
" A noMapping(String param);",
" @DeleteMapping A properNoParameters();",
" @GetMapping A properPathVariable(@PathVariable String param);",
" @PatchMapping A properRequestBody(@RequestBody String body);",
" @PostMapping A properRequestHeader(@RequestHeader String header);",
" @PutMapping A properRequestParam(@RequestParam String param);",
" @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 properNativeWebRequest(NativeWebRequest request);",
" @RequestMapping A properWebRequest(WebRequest request);",
" @RequestMapping A properServerWebExchange(ServerWebExchange exchange);",
" @RequestMapping A properServerUriBuilder(UriBuilder builder);",
" @RequestMapping A properServerUriComponentsBuilder(UriComponentsBuilder builder);",
"",
" // BUG: Diagnostic contains:",
" @DeleteMapping A delete(String param);",
" @DeleteMapping",
" A properNoParameters();",
"",
" // BUG: Diagnostic contains:",
" @GetMapping A get(String param);",
" @GetMapping",
" A properPathVariable(@PathVariable String param);",
"",
" // BUG: Diagnostic contains:",
" @PatchMapping A patch(String param);",
" @PatchMapping",
" A properRequestBody(@RequestBody String body);",
"",
" // BUG: Diagnostic contains:",
" @PostMapping A post(String param);",
" @PostMapping",
" A properRequestHeader(@RequestHeader String header);",
"",
" // BUG: Diagnostic contains:",
" @PutMapping A put(String param);",
" @PutMapping",
" A properRequestParam(@RequestParam String param);",
"",
" // BUG: Diagnostic contains:",
" @RequestMapping A requestMultiple(String param, String param2);",
" @RequestMapping",
" A properInputStream(InputStream input);",
"",
" // BUG: Diagnostic contains:",
" @RequestMapping A requestFirstParamViolation(String param, @PathVariable String param2);",
" @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 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:",
" @RequestMapping A requestSecondParamViolation(@RequestBody String param, String param2);",
" 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();
}

View File

@@ -28,23 +28,36 @@ final class RequestParamTypeCheckTest {
"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);",
" @PostMapping",
" A properRequestParam(@RequestBody String body);",
"",
" // BUG: Diagnostic contains:",
" @GetMapping A get(@RequestParam ImmutableBiMap<String, String> param);",
" @GetMapping",
" A properRequestParam(@RequestParam int param);",
"",
" // BUG: Diagnostic contains:",
" @PostMapping A post(@Nullable @RequestParam ImmutableList<String> param);",
" @GetMapping",
" A properRequestParam(@RequestParam List<String> param);",
"",
" // BUG: Diagnostic contains:",
" @PutMapping A put(@RequestBody String body, @RequestParam ImmutableSet<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:",
" @DeleteMapping A delete(@RequestBody String body, @RequestParam ImmutableMap<String, String> param);",
" 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);",
"}")

View File

@@ -4,8 +4,6 @@ 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 ScheduledTransactionTraceCheckTest {
private final CompilationTestHelper compilationTestHelper =
@@ -45,10 +43,7 @@ final class ScheduledTransactionTraceCheckTest {
.doTest();
}
// XXX: Enable this test for all JREs once https://github.com/google/error-prone/pull/2820 is
// merged and released.
@Test
@DisabledForJreRange(min = JRE.JAVA_12)
void replacement() {
refactoringTestHelper
.addInputLines(

View File

@@ -44,7 +44,8 @@ final class Slf4jLogStatementCheckTest {
" LOG.info(marker, s, o, t);",
"",
" LOG.warn(FMT0);",
" // BUG: Diagnostic contains: Log statement contains 0 placeholders, but specifies 1 matching argument(s)",
" // 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:",
@@ -56,13 +57,15 @@ final class Slf4jLogStatementCheckTest {
" // BUG: Diagnostic contains:",
" LOG.trace(marker, FMT0, o, t);",
"",
" // BUG: Diagnostic contains: Log statement contains 1 placeholders, but specifies 0 matching argument(s)",
" // 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)",
" // 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);",

View File

@@ -19,9 +19,9 @@ final class SpringMvcAnnotationCheckTest {
"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 static org.springframework.web.bind.annotation.RequestMethod.PATCH;",
"",
"import org.springframework.web.bind.annotation.DeleteMapping;",
"import org.springframework.web.bind.annotation.GetMapping;",
@@ -32,28 +32,53 @@ final class SpringMvcAnnotationCheckTest {
"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();",
" @RequestMapping",
" A simple();",
"",
" @DeleteMapping A properDelete();",
" @GetMapping A properGet();",
" @PatchMapping A properPatch();",
" @PostMapping A properPost();",
" @PutMapping A properPut();",
" @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();
}
@@ -71,11 +96,25 @@ final class SpringMvcAnnotationCheckTest {
"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();",
" @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(
"out/A.java",
@@ -92,11 +131,22 @@ final class SpringMvcAnnotationCheckTest {
"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();",
" @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);
}

View File

@@ -51,9 +51,8 @@ final class StaticImportCheckTest {
"import java.nio.charset.StandardCharsets;",
"import java.time.ZoneOffset;",
"import java.util.Optional;",
"import java.util.function.Predicate;",
"import java.util.UUID;",
"import org.springframework.boot.test.context.SpringBootTest;",
"import java.util.function.Predicate;",
"import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;",
"import org.springframework.http.MediaType;",
"",
@@ -135,10 +134,10 @@ final class StaticImportCheckTest {
"import java.util.Objects;",
"import java.util.regex.Pattern;",
"import org.junit.jupiter.params.provider.Arguments;",
"import org.springframework.format.annotation.DateTimeFormat;",
"import org.springframework.format.annotation.DateTimeFormat.ISO;",
"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 {",
@@ -181,15 +180,15 @@ final class StaticImportCheckTest {
" @DateTimeFormat(iso = ISO.TIME) String time) {}",
"",
" @BugPattern(",
" name = \"TestBugPattern\",",
" summary = \"\",",
" linkType = BugPattern.LinkType.NONE,",
" severity = SeverityLevel.SUGGESTION,",
" tags = BugPattern.StandardTags.SIMPLIFICATION)",
" name = \"TestBugPattern\",",
" summary = \"\",",
" linkType = BugPattern.LinkType.NONE,",
" severity = SeverityLevel.SUGGESTION,",
" tags = BugPattern.StandardTags.SIMPLIFICATION)",
" static final class TestBugPattern {}",
"",
" @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)",
" final class Test {}",
" @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)",
" final class Test {}",
"}")
.addOutputLines(
"out/A.java",
@@ -250,10 +249,7 @@ final class StaticImportCheckTest {
" Object o = UTF_8;",
"",
" ImmutableSet.of(",
" MediaType.ALL,",
" APPLICATION_XHTML_XML,",
" TEXT_HTML,",
" MediaType.valueOf(\"image/webp\"));",
" MediaType.ALL, APPLICATION_XHTML_XML, TEXT_HTML, MediaType.valueOf(\"image/webp\"));",
"",
" Pattern.compile(\"\", CASE_INSENSITIVE);",
" }",
@@ -269,15 +265,15 @@ final class StaticImportCheckTest {
" @DateTimeFormat(iso = TIME) String time) {}",
"",
" @BugPattern(",
" name = \"TestBugPattern\",",
" summary = \"\",",
" linkType = NONE,",
" severity = SUGGESTION,",
" tags = SIMPLIFICATION)",
" name = \"TestBugPattern\",",
" summary = \"\",",
" linkType = NONE,",
" severity = SUGGESTION,",
" tags = SIMPLIFICATION)",
" static final class TestBugPattern {}",
"",
" @SpringBootTest(webEnvironment = RANDOM_PORT)",
" final class Test {}",
" @SpringBootTest(webEnvironment = RANDOM_PORT)",
" final class Test {}",
"}")
.doTest(TestMode.TEXT_MATCH);
}

View File

@@ -7,11 +7,11 @@ import org.assertj.core.api.AbstractBooleanAssert;
final class AssertJBooleanTemplatesTest implements RefasterTemplateTestCase {
AbstractBooleanAssert<?> testAbstractBooleanAssertIsEqualTo() {
return assertThat(true).isNotEqualTo(!false);
return assertThat(true).isNotEqualTo(!Boolean.FALSE);
}
AbstractBooleanAssert<?> testAbstractBooleanAssertIsNotEqualTo() {
return assertThat(true).isEqualTo(!false);
return assertThat(true).isEqualTo(!Boolean.FALSE);
}
ImmutableSet<AbstractBooleanAssert<?>> testAbstractBooleanAssertIsTrue() {
@@ -23,7 +23,7 @@ final class AssertJBooleanTemplatesTest implements RefasterTemplateTestCase {
}
AbstractBooleanAssert<?> testAssertThatBooleanIsTrue() {
return assertThat(!true).isFalse();
return assertThat(!Boolean.TRUE).isFalse();
}
ImmutableSet<AbstractBooleanAssert<?>> testAbstractBooleanAssertIsFalse() {
@@ -35,6 +35,6 @@ final class AssertJBooleanTemplatesTest implements RefasterTemplateTestCase {
}
AbstractBooleanAssert<?> testAssertThatBooleanIsFalse() {
return assertThat(!true).isTrue();
return assertThat(!Boolean.TRUE).isTrue();
}
}

View File

@@ -7,11 +7,11 @@ import org.assertj.core.api.AbstractBooleanAssert;
final class AssertJBooleanTemplatesTest implements RefasterTemplateTestCase {
AbstractBooleanAssert<?> testAbstractBooleanAssertIsEqualTo() {
return assertThat(true).isEqualTo(false);
return assertThat(true).isEqualTo(Boolean.FALSE);
}
AbstractBooleanAssert<?> testAbstractBooleanAssertIsNotEqualTo() {
return assertThat(true).isNotEqualTo(false);
return assertThat(true).isNotEqualTo(Boolean.FALSE);
}
ImmutableSet<AbstractBooleanAssert<?>> testAbstractBooleanAssertIsTrue() {
@@ -23,7 +23,7 @@ final class AssertJBooleanTemplatesTest implements RefasterTemplateTestCase {
}
AbstractBooleanAssert<?> testAssertThatBooleanIsTrue() {
return assertThat(true).isTrue();
return assertThat(Boolean.TRUE).isTrue();
}
ImmutableSet<AbstractBooleanAssert<?>> testAbstractBooleanAssertIsFalse() {
@@ -35,6 +35,6 @@ final class AssertJBooleanTemplatesTest implements RefasterTemplateTestCase {
}
AbstractBooleanAssert<?> testAssertThatBooleanIsFalse() {
return assertThat(true).isFalse();
return assertThat(Boolean.TRUE).isFalse();
}
}

View File

@@ -60,10 +60,10 @@ final class AssortedTemplatesTest implements RefasterTemplateTestCase {
// XXX: Only the first statement is rewritten. Make smarter.
ImmutableSet<Boolean> testLogicalImplication() {
return ImmutableSet.of(
toString().isEmpty() || (!toString().isEmpty() && true),
!toString().isEmpty() || (toString().isEmpty() && true),
3 < 4 || (3 >= 4 && true),
3 >= 4 || (3 < 4 && true));
toString().isEmpty() || (!toString().isEmpty() && Boolean.TRUE),
!toString().isEmpty() || (toString().isEmpty() && Boolean.TRUE),
3 < 4 || (3 >= 4 && Boolean.TRUE),
3 >= 4 || (3 < 4 && Boolean.TRUE));
}
Stream<String> testUnboundedSingleElementStream() {

View File

@@ -62,10 +62,10 @@ final class AssortedTemplatesTest implements RefasterTemplateTestCase {
// XXX: Only the first statement is rewritten. Make smarter.
ImmutableSet<Boolean> testLogicalImplication() {
return ImmutableSet.of(
toString().isEmpty() || true,
!toString().isEmpty() || (toString().isEmpty() && true),
3 < 4 || (3 >= 4 && true),
3 >= 4 || (3 < 4 && true));
toString().isEmpty() || Boolean.TRUE,
!toString().isEmpty() || (toString().isEmpty() && Boolean.TRUE),
3 < 4 || (3 >= 4 && Boolean.TRUE),
3 >= 4 || (3 < 4 && Boolean.TRUE));
}
Stream<String> testUnboundedSingleElementStream() {

View File

@@ -27,13 +27,13 @@ final class EqualityTemplatesTest implements RefasterTemplateTestCase {
}
boolean testDoubleNegation() {
return !!true;
return !!Boolean.TRUE;
}
ImmutableSet<Boolean> testNegation() {
return ImmutableSet.of(
true ? !false : false,
!(true == false),
Boolean.TRUE ? !Boolean.FALSE : Boolean.FALSE,
!(Boolean.TRUE == Boolean.FALSE),
!((byte) 3 == (byte) 4),
!((short) 3 == (short) 4),
!(3 == 4),
@@ -45,8 +45,8 @@ final class EqualityTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<Boolean> testIndirectDoubleNegation() {
return ImmutableSet.of(
true ? false : !false,
!(true != false),
Boolean.TRUE ? Boolean.FALSE : !Boolean.FALSE,
!(Boolean.TRUE != Boolean.FALSE),
!((byte) 3 != (byte) 4),
!((short) 3 != (short) 4),
!(3 != 4),

View File

@@ -27,13 +27,13 @@ final class EqualityTemplatesTest implements RefasterTemplateTestCase {
}
boolean testDoubleNegation() {
return true;
return Boolean.TRUE;
}
ImmutableSet<Boolean> testNegation() {
return ImmutableSet.of(
true != false,
true != false,
Boolean.TRUE != Boolean.FALSE,
Boolean.TRUE != Boolean.FALSE,
(byte) 3 != (byte) 4,
(short) 3 != (short) 4,
3 != 4,
@@ -45,8 +45,8 @@ final class EqualityTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<Boolean> testIndirectDoubleNegation() {
return ImmutableSet.of(
true == false,
true == false,
Boolean.TRUE == Boolean.FALSE,
Boolean.TRUE == Boolean.FALSE,
(byte) 3 == (byte) 4,
(short) 3 == (short) 4,
3 == 4,

195
pom.xml
View File

@@ -75,11 +75,11 @@
arguments. In particular, JaCoCo relies on this for the configuration
of its Java agent. -->
<argLine>
<!-- Error Prone makes extensive use of unsupported
<!-- The JVM arguments specified in `.mvn/jvm.config` also apply to
test JVMs, as those are also non-interactive processess running
Error Prone, and thus similarly make extensive use of unsupported
`javac`-internal APIs, in some cases even reflectively inspecting
them. These APIs are accessed at compile time and when running
tests. The former case is covered by flags in `.mvn/jvm.config`;
the latter is covered here. -->
them. -->
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
@@ -93,9 +93,6 @@
<!-- The test JVMs are short-running. By disabling certain
expensive JIT optimizations we actually speed up most tests. -->
-XX:TieredStopAtLevel=1
<!-- We cap memory usage. This is primarily relevant for build agents,
but locally this should also be more than enough. -->
-Xmx512m
<!-- This argument cannot be set through Surefire's
'systemPropertyVariables' configuration setting. Setting the file
encoding is necessary because forked unit test invocations
@@ -134,16 +131,17 @@
<version.auto-service>1.0.1</version.auto-service>
<version.auto-value>1.9</version.auto-value>
<version.error-prone>${version.error-prone-orig}</version.error-prone>
<version.error-prone-fork>v${version.error-prone-orig}-picnic-3</version.error-prone-fork>
<version.error-prone-orig>2.10.0</version.error-prone-orig>
<version.error-prone-slf4j>0.1.4</version.error-prone-slf4j>
<version.error-prone-fork>v${version.error-prone-orig}-picnic-2</version.error-prone-fork>
<version.error-prone-orig>2.14.0</version.error-prone-orig>
<version.error-prone-slf4j>0.1.12</version.error-prone-slf4j>
<version.findbugs-format-string>3.0.0</version.findbugs-format-string>
<version.guava-beta-checker>1.0</version.guava-beta-checker>
<version.jdk>11</version.jdk>
<!-- XXX: Configure Renovate to open upgrade PRs for this property. -->
<version.maven>3.6.3</version.maven>
<version.mockito>4.6.1</version.mockito>
<version.nopen-checker>1.0.1</version.nopen-checker>
<version.nullaway>0.9.8</version.nullaway>
<version.nullaway>0.9.9</version.nullaway>
<!-- XXX: Two other dependencies are potentially of interest:
`com.palantir.assertj-automation:assertj-refaster-rules` and
`com.palantir.baseline:baseline-refaster-rules` contain Refaster rules
@@ -237,6 +235,11 @@
<artifactId>javac</artifactId>
<version>9+181-r4173-1</version>
</dependency>
<dependency>
<groupId>com.google.googlejavaformat</groupId>
<artifactId>google-java-format</artifactId>
<version>1.15.0</version>
</dependency>
<!-- Specified as a workaround for
https://github.com/mojohaus/versions-maven-plugin/issues/244. -->
<dependency>
@@ -247,7 +250,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-bom</artifactId>
<version>31.0.1-jre</version>
<version>31.1-jre</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -266,7 +269,7 @@
<dependency>
<groupId>com.newrelic.agent.java</groupId>
<artifactId>newrelic-api</artifactId>
<version>7.8.0</version>
<version>7.9.0</version>
</dependency>
<!-- Specified as a workaround for
https://github.com/mojohaus/versions-maven-plugin/issues/244. -->
@@ -292,7 +295,7 @@
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-bom</artifactId>
<version>2020.0.20</version>
<version>2020.0.21</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -309,7 +312,7 @@
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.2.1</version>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
@@ -346,12 +349,17 @@
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.22.2</version>
<version>3.24.0</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.8.2</version>
<version>5.9.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -375,14 +383,14 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>5.3.21</version>
<version>5.3.22</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.7.1</version>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
@@ -398,7 +406,7 @@
<plugin>
<groupId>com.github.ekryd.sortpom</groupId>
<artifactId>sortpom-maven-plugin</artifactId>
<version>3.1.3</version>
<version>3.2.0</version>
<configuration>
<createBackupFile>false</createBackupFile>
<encoding>${project.build.sourceEncoding}</encoding>
@@ -478,14 +486,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.takari</groupId>
<artifactId>maven</artifactId>
<version>0.7.7</version>
<configuration>
<maven>${version.maven}</maven>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
@@ -721,13 +721,17 @@
</sourceDirectories>
<testSourceDirectories>
<testSourceDirectory>${project.build.testSourceDirectory}</testSourceDirectory>
<!-- Refaster input and output test files represent
valid Java code, exposed as resources on the test
classpath. -->
<testSourceDirectory>${basedir}/src/test/resources</testSourceDirectory>
</testSourceDirectories>
</configuration>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.3.1</version>
<version>10.3.2</version>
</dependency>
</dependencies>
<executions>
@@ -749,12 +753,64 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<!-- XXX: MCOMPILER-503: The plugin contructs a highly
unintuitive annotation processor classpath, in which
some indirect dependencies take precedence over
explicitly defined dependencies. This can largely be
mitigated through careful ordering of the dependencies,
but this prevents (where relevant) declaring these
dependencies as part of their corresponding Maven
profile. -->
<annotationProcessorPaths>
<path>
<groupId>${groupId.error-prone}</groupId>
<artifactId>error_prone_core</artifactId>
<version>${version.error-prone}</version>
</path>
<path>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>${version.auto-service}</version>
</path>
<path>
<groupId>com.google.guava</groupId>
<artifactId>guava-beta-checker</artifactId>
<version>${version.guava-beta-checker}</version>
</path>
<path>
<groupId>com.jakewharton.nopen</groupId>
<artifactId>nopen-checker</artifactId>
<version>${version.nopen-checker}</version>
</path>
<!-- XXX: Before enabling these plugins we'll
need to resolve some violations. Some of the
checks will need to be disabled.
<path>
<groupId>com.palantir.assertj-automation</groupId>
<artifactId>assertj-error-prone</artifactId>
<version>${version.palantir-assertj-automation}</version>
</path>
<path>
<groupId>com.palantir.baseline</groupId>
<artifactId>baseline-error-prone</artifactId>
<version>${version.palantir-baseline}</version>
</path>
-->
<path>
<groupId>com.uber.nullaway</groupId>
<artifactId>nullaway</artifactId>
<version>${version.nullaway}</version>
</path>
<path>
<groupId>jp.skypencil.errorprone.slf4j</groupId>
<artifactId>errorprone-slf4j</artifactId>
<version>${version.error-prone-slf4j}</version>
</path>
<path>
<groupId>org.mockito</groupId>
<artifactId>mockito-errorprone</artifactId>
<version>${version.mockito}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Xmaxerrs</arg>
@@ -787,7 +843,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<version>3.0.0</version>
<configuration>
<retryFailedDeploymentCount>3</retryFailedDeploymentCount>
</configuration>
@@ -832,7 +888,7 @@
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.5.1</version>
<version>1.6.1</version>
</dependency>
</dependencies>
<executions>
@@ -860,7 +916,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<version>3.0.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -925,7 +981,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<version>3.3.0</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
@@ -1146,7 +1202,7 @@
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.9.0</version>
<version>1.9.3</version>
<configuration>
<!-- Use multiple threads to speed things up. Extend
timeouts to prevent false positives as a result of
@@ -1260,7 +1316,7 @@
`BugChecker` test code and the Refaster test files) does not
exhibit anti-patterns other than those associated with the
check/template under test. Ideally all test cases are realistic. -->
<error-prone.self-check-args>-Xep:MethodReferenceUsage:OFF</error-prone.self-check-args>
<error-prone.self-check-args>-XepAllSuggestionsAsWarnings -Xep:MethodReferenceUsage:OFF</error-prone.self-check-args>
</properties>
<build>
<plugins>
@@ -1410,65 +1466,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths combine.children="append">
<path>
<groupId>${groupId.error-prone}</groupId>
<artifactId>error_prone_annotations</artifactId>
<version>${version.error-prone}</version>
</path>
<path>
<groupId>${groupId.error-prone}</groupId>
<artifactId>error_prone_core</artifactId>
<version>${version.error-prone}</version>
</path>
<!-- This is a dependency of some Error Prone
plugins, but for licensing reasons it is not
packaged with the artifact. -->
<path>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jFormatString</artifactId>
<version>${version.findbugs-format-string}</version>
</path>
<path>
<groupId>com.google.guava</groupId>
<artifactId>guava-beta-checker</artifactId>
<version>${version.guava-beta-checker}</version>
</path>
<path>
<groupId>com.jakewharton.nopen</groupId>
<artifactId>nopen-checker</artifactId>
<version>${version.nopen-checker}</version>
</path>
<!-- XXX: Before enabling these plugins we'll
need to resolve some violations. Some of the
checks will need to be disabled.
<path>
<groupId>com.palantir.assertj-automation</groupId>
<artifactId>assertj-error-prone</artifactId>
<version>${version.palantir-assertj-automation}</version>
</path>
<path>
<groupId>com.palantir.baseline</groupId>
<artifactId>baseline-error-prone</artifactId>
<version>${version.palantir-baseline}</version>
</path>
-->
<path>
<groupId>com.uber.nullaway</groupId>
<artifactId>nullaway</artifactId>
<version>${version.nullaway}</version>
</path>
<path>
<groupId>jp.skypencil.errorprone.slf4j</groupId>
<artifactId>errorprone-slf4j</artifactId>
<version>${version.error-prone-slf4j}</version>
</path>
<path>
<groupId>org.mockito</groupId>
<artifactId>mockito-errorprone</artifactId>
<version>${version.mockito}</version>
</path>
</annotationProcessorPaths>
<compilerArgs combine.children="append">
<!-- Enable and configure Error Prone. -->
<arg>
@@ -1488,18 +1485,28 @@
<!-- XXX: Enable this once we open-source
this library. -->
-Xep:BetaApi:OFF
<!-- XXX: Enable this check. -->
-Xep:BugPatternNaming:OFF
<!-- We don't target JDK 7. -->
-Xep:Java7ApiChecker:OFF
<!-- We don't target JDK 8. -->
-Xep:Java8ApiChecker:OFF
<!-- We don't target Android. -->
-Xep:StaticOrDefaultInterfaceMethod:OFF
<!-- We generally discourage `var` use. -->
-Xep:Varifier:OFF
<!-- XXX: This check flags false positives.
See https://github.com/google/error-prone/issues/2679. -->
-Xep:VoidMissingNullable:OFF
-XepOpt:CheckReturnValue:CheckAllConstructors=true
<!-- XXX: Enable once there are fewer
false-positives.
-XepOpt:CheckReturnValue:CheckAllMethods=true -->
-XepOpt:InlineMe:SkipInliningsWithComments=false
-XepOpt:NullAway:AnnotatedPackages=tech.picnic
-XepOpt:NullAway:AssertsEnabled=true
-XepOpt:NullAway:CheckOptionalEmptiness=true
-XepOpt:Nullness:Conservative=false
<!-- Append additional custom arguments. -->
${error-prone.patch-args}
${error-prone.self-check-args}

View File

@@ -29,6 +29,7 @@ import java.io.UncheckedIOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.StandardLocation;
@@ -91,6 +92,7 @@ final class RefasterRuleCompilerTaskListener implements TaskListener {
ClassTree tree) {
ListMultimap<ClassTree, CodeTransformer> rules = ArrayListMultimap.create();
new TreeScanner<Void, Void>() {
@Nullable
@Override
public Void visitClass(ClassTree node, Void v) {
rules.putAll(node, RefasterRuleBuilderScanner.extractRules(node, context));

View File

@@ -17,7 +17,6 @@ final class IsArrayTest {
CompilationTestHelper.newInstance(TestChecker.class, getClass())
.addSourceLines(
"A.java",
"package test.foo;",
"class A {",
" Object negative1() {",
" return alwaysNull();",