mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 15:49:33 +00:00
Compare commits
156 Commits
rossendrij
...
v0.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
967017eed9 | ||
|
|
b06945b833 | ||
|
|
ef562c1644 | ||
|
|
efbde936dc | ||
|
|
c57653dd5b | ||
|
|
12b03e95b1 | ||
|
|
c2f24ac739 | ||
|
|
4f5ea8beac | ||
|
|
21646ffcb1 | ||
|
|
c58dceb9df | ||
|
|
90ef2f4042 | ||
|
|
459a498d6c | ||
|
|
78035644dc | ||
|
|
ef67d41512 | ||
|
|
4cecff923a | ||
|
|
38a57db994 | ||
|
|
336557cf8e | ||
|
|
9055dfff19 | ||
|
|
3712a15195 | ||
|
|
9d487e4a88 | ||
|
|
b2b086761c | ||
|
|
ff64247b6d | ||
|
|
bc7443c72d | ||
|
|
abf4d68fba | ||
|
|
5c5f7d849e | ||
|
|
65c4694936 | ||
|
|
a45291c7d8 | ||
|
|
71012f31ab | ||
|
|
6e0905c033 | ||
|
|
af5ac85428 | ||
|
|
0329c25f78 | ||
|
|
9e67e2b795 | ||
|
|
4bafea05f4 | ||
|
|
8ce9cab2dd | ||
|
|
ae30625524 | ||
|
|
dc0046ebfc | ||
|
|
ad6d774818 | ||
|
|
405f5874ac | ||
|
|
bf5199ea3d | ||
|
|
c500516bb4 | ||
|
|
85d68a4f34 | ||
|
|
46467951dd | ||
|
|
6f7ce2067f | ||
|
|
f30ba36d18 | ||
|
|
65736ce83f | ||
|
|
17d5805d5a | ||
|
|
ce01b62832 | ||
|
|
4ee555c62b | ||
|
|
a24bbbe99d | ||
|
|
679e83bc48 | ||
|
|
0bdc171613 | ||
|
|
9b05ec62c6 | ||
|
|
72866183f5 | ||
|
|
9d7f569be5 | ||
|
|
f72adca292 | ||
|
|
5148143ae5 | ||
|
|
3d7fbbf7a2 | ||
|
|
8b6864d8a0 | ||
|
|
a03017b5e6 | ||
|
|
a227436f19 | ||
|
|
3f6558b7c0 | ||
|
|
ce06396521 | ||
|
|
268766a32a | ||
|
|
5366effd74 | ||
|
|
0a63361500 | ||
|
|
a074e2fdd6 | ||
|
|
f06d4e41cf | ||
|
|
cf7bb657fa | ||
|
|
8277b43955 | ||
|
|
691f2c8311 | ||
|
|
362518b0f4 | ||
|
|
b9a3840e25 | ||
|
|
14d8bddbec | ||
|
|
6c7a0b81ea | ||
|
|
3a3825f7ba | ||
|
|
31e54cc990 | ||
|
|
775a2688ca | ||
|
|
3d854a0cc5 | ||
|
|
6ee013da58 | ||
|
|
962d18dcb5 | ||
|
|
aab308a190 | ||
|
|
009bd5d0d7 | ||
|
|
8e57f64e31 | ||
|
|
53e81f3611 | ||
|
|
8745105251 | ||
|
|
3eb3c20b1d | ||
|
|
121618f277 | ||
|
|
5cf4194168 | ||
|
|
c434cd318c | ||
|
|
22aa9cb213 | ||
|
|
3edc483e7c | ||
|
|
fff5d7b329 | ||
|
|
4ca80952ab | ||
|
|
8cecb8bf30 | ||
|
|
a937bf0ddf | ||
|
|
0b71c2b576 | ||
|
|
239d38d69f | ||
|
|
ab57aa5eb6 | ||
|
|
49267337cb | ||
|
|
c201fe1fd2 | ||
|
|
fb20b6f93d | ||
|
|
9264c25b57 | ||
|
|
ca628eef6c | ||
|
|
62168dcd4b | ||
|
|
96a82eaf85 | ||
|
|
0c615b4c15 | ||
|
|
6304130ae3 | ||
|
|
1674e99ba4 | ||
|
|
75bbc8e5b5 | ||
|
|
fe3ed2be63 | ||
|
|
f36350f3ba | ||
|
|
4888ad3aaf | ||
|
|
9daf73f148 | ||
|
|
b08ca514c1 | ||
|
|
4eed7dd0e8 | ||
|
|
618c62e7a5 | ||
|
|
b46f075ddf | ||
|
|
64436ff9b6 | ||
|
|
e028077f1e | ||
|
|
5aa386b5ba | ||
|
|
a480fe908d | ||
|
|
b2316c744c | ||
|
|
9334babfe8 | ||
|
|
b6632d393b | ||
|
|
53d191ff4f | ||
|
|
b8ddf3ac20 | ||
|
|
e859c2774f | ||
|
|
1cb4ce97ae | ||
|
|
92fe96286f | ||
|
|
d7531abceb | ||
|
|
cc7074a62f | ||
|
|
91922454b6 | ||
|
|
eaa98c985c | ||
|
|
94908d6a37 | ||
|
|
e8d9221424 | ||
|
|
fea8f5b2c0 | ||
|
|
2199accedc | ||
|
|
83670aeddf | ||
|
|
e8977bea67 | ||
|
|
0d051064bb | ||
|
|
06913b6a5b | ||
|
|
d2bbee3ed9 | ||
|
|
793a70c29b | ||
|
|
63b4fae185 | ||
|
|
73f8f056b4 | ||
|
|
c1638066cd | ||
|
|
08e99fb54e | ||
|
|
00012c6aa8 | ||
|
|
193589d193 | ||
|
|
1a1588d413 | ||
|
|
6656bd8186 | ||
|
|
26a9b46de7 | ||
|
|
17e74f778b | ||
|
|
e1bdb098de | ||
|
|
0be162c837 | ||
|
|
edfb2a70e8 |
37
.github/workflows/build.yaml
vendored
Normal file
37
.github/workflows/build.yaml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Build and verify
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
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 installed project artifacts
|
||||
run: mvn build-helper:remove-project-artifact
|
||||
|
||||
# XXX: Enable Codecov once we "go public".
|
||||
# XXX: Enable SonarCloud once we "go public".
|
||||
@@ -1,3 +1,6 @@
|
||||
-XX:ReservedCodeCacheSize=512m
|
||||
-XX:SoftRefLRUPolicyMSPerMB=10
|
||||
-XX:+UseParallelGC
|
||||
--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
|
||||
|
||||
1
.mvn/maven.config
Normal file
1
.mvn/maven.config
Normal file
@@ -0,0 +1 @@
|
||||
--batch-mode --errors --strict-checksums
|
||||
22
.renovaterc.json
Normal file
22
.renovaterc.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"packageRules": [
|
||||
{
|
||||
"matchPackagePatterns": [
|
||||
"^org\\.springframework:spring-framework-bom$",
|
||||
"^org\\.springframework\\.boot:spring-boot[a-z-]*$"
|
||||
],
|
||||
"separateMinorPatch": true
|
||||
},
|
||||
{
|
||||
"matchPackagePatterns": [
|
||||
"^com\\.palantir\\.baseline:baseline-error-prone$"
|
||||
],
|
||||
"schedule": "* * 1 * *"
|
||||
}
|
||||
],
|
||||
"reviewers": [
|
||||
"rickie",
|
||||
"Stephan202"
|
||||
]
|
||||
}
|
||||
38
.travis.yml
38
.travis.yml
@@ -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)
|
||||
25
apply-error-prone-suggestions.sh
Executable file
25
apply-error-prone-suggestions.sh
Executable 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
|
||||
@@ -276,10 +276,6 @@ Refaster's expressiveness:
|
||||
to be lost. In such a case don't statically import the method, so that the
|
||||
generic type information can be retained. (There may be cases where generic
|
||||
type information should even be _added_. Find an example.)
|
||||
- Upon application of a template Refaster can throw a _No binding for
|
||||
Key{identifier=someAfterTemplateParam}_ exception. When this happens the
|
||||
template is invalid. Instead perform this check at compile time, such that
|
||||
such malformed templates cannot be defined in the first place.
|
||||
- Provide a way to express "match if (not) annotated (with _X_)". See #1 for a
|
||||
motivating example.
|
||||
- Provide a way to place match constraints on compile time constants. For
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>0.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
@@ -41,27 +41,24 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>migration-util</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-resource-compiler</artifactId>
|
||||
<!-- This dependency is declared only as a hint to Maven that
|
||||
compilation depends on it; see the `maven-compiler-plugin`'s
|
||||
`annotationProcessorPaths` configuration below. -->
|
||||
<artifactId>refaster-support</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-support</artifactId>
|
||||
<artifactId>refaster-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto</groupId>
|
||||
<artifactId>auto-common</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service-annotations</artifactId>
|
||||
@@ -77,11 +74,20 @@
|
||||
<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>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.newrelic.agent.java</groupId>
|
||||
<artifactId>newrelic-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
@@ -122,6 +128,11 @@
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
@@ -132,11 +143,6 @@
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
@@ -167,16 +173,6 @@
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
@@ -192,6 +188,11 @@
|
||||
<artifactId>spring-webflux</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
@@ -202,15 +203,6 @@
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.coveo</groupId>
|
||||
<artifactId>fmt-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<additionalSourceDirectories>
|
||||
<additionalSourceDirectory>${basedir}/src/test/resources</additionalSourceDirectory>
|
||||
</additionalSourceDirectories>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
@@ -218,7 +210,7 @@
|
||||
<annotationProcessorPaths combine.children="append">
|
||||
<path>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-resource-compiler</artifactId>
|
||||
<artifactId>refaster-compiler</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
@@ -226,14 +218,9 @@
|
||||
<artifactId>refaster-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>migration-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs combine.children="append">
|
||||
<arg>-Xplugin:RefasterRuleResourceCompiler</arg>
|
||||
<arg>-Xplugin:RefasterRuleCompiler</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher;
|
||||
@@ -25,12 +25,11 @@ import javax.lang.model.element.AnnotationValue;
|
||||
/** A {@link BugChecker} which flags ambiguous {@code @JsonCreator}s in enums. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "AmbiguousJsonCreator",
|
||||
summary = "`JsonCreator.Mode` should be set for single-argument creators",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.WARNING,
|
||||
tags = StandardTags.LIKELY_ERROR)
|
||||
public final class AmbiguousJsonCreatorCheck extends BugChecker implements AnnotationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = LIKELY_ERROR)
|
||||
public final class AmbiguousJsonCreator extends BugChecker implements AnnotationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<AnnotationTree> IS_JSON_CREATOR_ANNOTATION =
|
||||
isType("com.fasterxml.jackson.annotation.JsonCreator");
|
||||
@@ -0,0 +1,57 @@
|
||||
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.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||
import static com.google.errorprone.matchers.Matchers.argument;
|
||||
import static com.google.errorprone.matchers.Matchers.argumentCount;
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.nullLiteral;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
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.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags AssertJ {@code isEqualTo(null)} checks for simplification.
|
||||
*
|
||||
* <p>This bug checker cannot be replaced with a simple Refaster template, as the Refaster approach
|
||||
* would require that all overloads of {@link org.assertj.core.api.Assert#isEqualTo(Object)} (such
|
||||
* as {@link org.assertj.core.api.AbstractStringAssert#isEqualTo(String)}) are explicitly
|
||||
* enumerated. This bug checker generically matches all such current and future overloads.
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Prefer `.isNull()` over `.isEqualTo(null)`",
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class AssertJIsNull extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<MethodInvocationTree> ASSERT_IS_EQUAL_TO_NULL =
|
||||
allOf(
|
||||
instanceMethod().onDescendantOf("org.assertj.core.api.Assert").named("isEqualTo"),
|
||||
argumentCount(1),
|
||||
argument(0, nullLiteral()));
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
if (!ASSERT_IS_EQUAL_TO_NULL.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
SuggestedFix.Builder fix =
|
||||
SuggestedFix.builder().merge(SuggestedFixes.renameMethodInvocation(tree, "isNull", state));
|
||||
tree.getArguments().forEach(arg -> fix.merge(SuggestedFix.delete(arg)));
|
||||
|
||||
return describeMatch(tree, fix.build());
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
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.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
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.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
|
||||
@@ -26,12 +27,11 @@ import java.util.List;
|
||||
/** A {@link BugChecker} which flags redundant {@code @Autowired} constructor annotations. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "AutowiredConstructor",
|
||||
summary = "Omit `@Autowired` on a class' sole constructor, as it is redundant",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class AutowiredConstructorCheck extends BugChecker implements ClassTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class AutowiredConstructor extends BugChecker implements ClassTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final MultiMatcher<Tree, AnnotationTree> AUTOWIRED_ANNOTATION =
|
||||
annotations(AT_LEAST_ONE, isType("org.springframework.beans.factory.annotation.Autowired"));
|
||||
@@ -43,7 +43,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();
|
||||
@@ -1,11 +1,12 @@
|
||||
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.SIMPLIFICATION;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher;
|
||||
@@ -24,25 +25,24 @@ import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} which flags annotations that could be written more concisely. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "CanonicalAnnotationSyntax",
|
||||
summary = "Omit redundant syntax from annotation declarations",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class CanonicalAnnotationSyntaxCheck extends BugChecker
|
||||
implements AnnotationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class CanonicalAnnotationSyntax extends BugChecker implements AnnotationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Pattern TRAILING_ARRAY_COMMA = Pattern.compile(",\\s*}$");
|
||||
private static final ImmutableSet<BiFunction<AnnotationTree, VisitorState, Optional<Fix>>>
|
||||
FIX_FACTORIES =
|
||||
ImmutableSet.of(
|
||||
CanonicalAnnotationSyntaxCheck::dropRedundantParentheses,
|
||||
CanonicalAnnotationSyntaxCheck::dropRedundantValueAttribute,
|
||||
CanonicalAnnotationSyntaxCheck::dropRedundantCurlies);
|
||||
CanonicalAnnotationSyntax::dropRedundantParentheses,
|
||||
CanonicalAnnotationSyntax::dropRedundantValueAttribute,
|
||||
CanonicalAnnotationSyntax::dropRedundantCurlies);
|
||||
|
||||
@Override
|
||||
public Description matchAnnotation(AnnotationTree tree, VisitorState state) {
|
||||
@@ -102,7 +102,8 @@ public final class CanonicalAnnotationSyntaxCheck extends BugChecker
|
||||
return Optional.of(
|
||||
SuggestedFix.replace(
|
||||
arg,
|
||||
simplifyAttributeValue(expr, state).orElseGet(() -> Util.treeToString(expr, state))));
|
||||
simplifyAttributeValue(expr, state)
|
||||
.orElseGet(() -> SourceCode.treeToString(expr, state))));
|
||||
}
|
||||
|
||||
private static Optional<Fix> dropRedundantCurlies(AnnotationTree tree, VisitorState state) {
|
||||
@@ -137,11 +138,11 @@ public final class CanonicalAnnotationSyntaxCheck extends BugChecker
|
||||
private static Optional<String> simplifySingletonArray(NewArrayTree array, VisitorState state) {
|
||||
return Optional.of(array.getInitializers())
|
||||
.filter(initializers -> initializers.size() == 1)
|
||||
.map(initializers -> Util.treeToString(initializers.get(0), state));
|
||||
.map(initializers -> SourceCode.treeToString(initializers.get(0), state));
|
||||
}
|
||||
|
||||
private static Optional<String> dropTrailingComma(NewArrayTree array, VisitorState state) {
|
||||
String src = Util.treeToString(array, state);
|
||||
String src = SourceCode.treeToString(array, state);
|
||||
return Optional.of(TRAILING_ARRAY_COMMA.matcher(src))
|
||||
.filter(Matcher::find)
|
||||
.map(m -> src.substring(0, m.start()) + '}');
|
||||
@@ -0,0 +1,117 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.FRAGILE_CODE;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
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.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import java.util.stream.Collector;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags {@link Collector Collectors} that don't clearly express
|
||||
* (im)mutability.
|
||||
*
|
||||
* <p>Replacing such collectors with alternatives that produce immutable collections is preferred.
|
||||
* Do note that Guava's immutable collections are null-hostile.
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary =
|
||||
"Avoid `Collectors.to{List,Map,Set}` in favour of alternatives that emphasize (im)mutability",
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = FRAGILE_CODE)
|
||||
public final class CollectorMutability extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> COLLECTOR_METHOD =
|
||||
staticMethod().onClass("java.util.stream.Collectors");
|
||||
private static final Matcher<ExpressionTree> LIST_COLLECTOR =
|
||||
staticMethod().anyClass().named("toList");
|
||||
private static final Matcher<ExpressionTree> MAP_COLLECTOR =
|
||||
staticMethod().anyClass().named("toMap");
|
||||
private static final Matcher<ExpressionTree> SET_COLLECTOR =
|
||||
staticMethod().anyClass().named("toSet");
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
if (!COLLECTOR_METHOD.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
if (LIST_COLLECTOR.matches(tree, state)) {
|
||||
return suggestToCollectionAlternatives(
|
||||
tree, "com.google.common.collect.ImmutableList.toImmutableList", "ArrayList", state);
|
||||
}
|
||||
|
||||
if (MAP_COLLECTOR.matches(tree, state)) {
|
||||
return suggestToMapAlternatives(tree, state);
|
||||
}
|
||||
|
||||
if (SET_COLLECTOR.matches(tree, state)) {
|
||||
return suggestToCollectionAlternatives(
|
||||
tree, "com.google.common.collect.ImmutableSet.toImmutableSet", "HashSet", state);
|
||||
}
|
||||
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
private Description suggestToCollectionAlternatives(
|
||||
MethodInvocationTree tree,
|
||||
String fullyQualifiedImmutableReplacement,
|
||||
String mutableReplacement,
|
||||
VisitorState state) {
|
||||
SuggestedFix.Builder mutableFix = SuggestedFix.builder();
|
||||
String toCollectionSelect =
|
||||
SuggestedFixes.qualifyStaticImport(
|
||||
"java.util.stream.Collectors.toCollection", mutableFix, state);
|
||||
|
||||
return buildDescription(tree)
|
||||
.addFix(replaceMethodInvocation(tree, fullyQualifiedImmutableReplacement, state))
|
||||
.addFix(
|
||||
mutableFix
|
||||
.addImport(String.format("java.util.%s", mutableReplacement))
|
||||
.replace(tree, String.format("%s(%s::new)", toCollectionSelect, mutableReplacement))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Description suggestToMapAlternatives(MethodInvocationTree tree, VisitorState state) {
|
||||
int argCount = tree.getArguments().size();
|
||||
if (argCount > 3) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return buildDescription(tree)
|
||||
.addFix(
|
||||
replaceMethodInvocation(
|
||||
tree, "com.google.common.collect.ImmutableMap.toImmutableMap", state))
|
||||
.addFix(
|
||||
SuggestedFix.builder()
|
||||
.addImport("java.util.HashMap")
|
||||
.postfixWith(
|
||||
tree.getArguments().get(argCount - 1),
|
||||
(argCount == 2 ? ", (a, b) -> { throw new IllegalStateException(); }" : "")
|
||||
+ ", HashMap::new")
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static SuggestedFix replaceMethodInvocation(
|
||||
MethodInvocationTree tree, String fullyQualifiedReplacement, VisitorState state) {
|
||||
SuggestedFix.Builder fix = SuggestedFix.builder();
|
||||
String replacement = SuggestedFixes.qualifyStaticImport(fullyQualifiedReplacement, fix, state);
|
||||
fix.merge(SuggestedFix.replace(tree.getMethodSelect(), replacement));
|
||||
return fix.build();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
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.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
@@ -7,9 +10,6 @@ import static com.google.errorprone.matchers.Matchers.isType;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
@@ -26,12 +26,11 @@ import java.util.Optional;
|
||||
/** A {@link BugChecker} which flags empty methods that seemingly can simply be deleted. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "EmptyMethod",
|
||||
summary = "Empty method can likely be deleted",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class EmptyMethodCheck extends BugChecker implements MethodTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class EmptyMethod extends BugChecker implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<Tree> PERMITTED_ANNOTATION =
|
||||
annotations(
|
||||
@@ -0,0 +1,160 @@
|
||||
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(
|
||||
summary = "Test code should follow the Google Java style",
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = STYLE)
|
||||
public final class ErrorProneTestHelperSourceFormat 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());
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@ package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap;
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.FRAGILE_CODE;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
|
||||
import static java.util.stream.Collectors.collectingAndThen;
|
||||
|
||||
@@ -12,9 +15,6 @@ import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
@@ -35,13 +35,11 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "ExplicitEnumOrdering",
|
||||
summary = "Make sure `Ordering#explicit` lists all of an enum's values",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.WARNING,
|
||||
tags = StandardTags.FRAGILE_CODE)
|
||||
public final class ExplicitEnumOrderingCheck extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = FRAGILE_CODE)
|
||||
public final class ExplicitEnumOrdering extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> EXPLICIT_ORDERING =
|
||||
staticMethod().onClass(Ordering.class.getName()).named("explicit");
|
||||
@@ -73,7 +71,7 @@ public final class ExplicitEnumOrderingCheck extends BugChecker
|
||||
.collect(
|
||||
collectingAndThen(
|
||||
toImmutableSetMultimap(Symbol::asType, Symbol::toString),
|
||||
ExplicitEnumOrderingCheck::getMissingEnumValues));
|
||||
ExplicitEnumOrdering::getMissingEnumValues));
|
||||
}
|
||||
|
||||
private static ImmutableSet<String> getMissingEnumValues(
|
||||
@@ -0,0 +1,85 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.instanceMethod;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MemberReferenceTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MemberReferenceTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags usages of {@link Flux#flatMap(Function)} and {@link
|
||||
* Flux#flatMapSequential(Function)}.
|
||||
*
|
||||
* <p>{@link Flux#flatMap(Function)} and {@link Flux#flatMapSequential(Function)} eagerly perform up
|
||||
* to {@link reactor.util.concurrent.Queues#SMALL_BUFFER_SIZE} subscriptions. Additionally, the
|
||||
* former interleaves values as they are emitted, yielding nondeterministic results. In most cases
|
||||
* {@link Flux#concatMap(Function)} should be preferred, as it produces consistent results and
|
||||
* avoids potentially saturating the thread pool on which subscription happens. If {@code
|
||||
* concatMap}'s single-subscription semantics are undesirable one should invoke a {@code flatMap} or
|
||||
* {@code flatMapSequential} overload with an explicit concurrency level.
|
||||
*
|
||||
* <p>NB: The rarely-used overload {@link Flux#flatMap(Function, Function, Supplier)} is not flagged
|
||||
* by this check because there is no clear alternative to point to.
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary =
|
||||
"`Flux#flatMap` and `Flux#flatMapSequential` have subtle semantics; "
|
||||
+ "please use `Flux#concatMap` or explicitly specify the desired amount of concurrency",
|
||||
linkType = NONE,
|
||||
severity = ERROR,
|
||||
tags = LIKELY_ERROR)
|
||||
public final class FluxFlatMapUsage extends BugChecker
|
||||
implements MethodInvocationTreeMatcher, MemberReferenceTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String MAX_CONCURRENCY_ARG_NAME = "MAX_CONCURRENCY";
|
||||
private static final Matcher<ExpressionTree> FLUX_FLATMAP =
|
||||
instanceMethod()
|
||||
.onDescendantOf("reactor.core.publisher.Flux")
|
||||
.namedAnyOf("flatMap", "flatMapSequential")
|
||||
.withParameters(Function.class.getName());
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
if (!FLUX_FLATMAP.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return buildDescription(tree)
|
||||
.addFix(SuggestedFixes.renameMethodInvocation(tree, "concatMap", state))
|
||||
.addFix(
|
||||
SuggestedFix.builder()
|
||||
.postfixWith(
|
||||
Iterables.getOnlyElement(tree.getArguments()), ", " + MAX_CONCURRENCY_ARG_NAME)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description matchMemberReference(MemberReferenceTree tree, VisitorState state) {
|
||||
if (!FLUX_FLATMAP.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
// Method references are expected to occur very infrequently; generating both variants of
|
||||
// suggested fixes is not worth the trouble.
|
||||
return describeMatch(tree);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||
import static com.google.errorprone.matchers.Matchers.anyMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
@@ -10,9 +13,6 @@ import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
@@ -31,6 +31,8 @@ import com.sun.source.util.SimpleTreeVisitor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags string concatenations that produce a format string; in such
|
||||
@@ -48,12 +50,11 @@ import java.util.Optional;
|
||||
// invocations, as necessary.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "FormatStringConcatenation",
|
||||
summary = "Defer string concatenation to the invoked method",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.WARNING,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class FormatStringConcatenationCheck extends BugChecker
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class FormatStringConcatenation extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
@@ -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);
|
||||
@@ -246,7 +250,7 @@ public final class FormatStringConcatenationCheck extends BugChecker
|
||||
return state.getConstantExpression(formatString.toString())
|
||||
+ ", "
|
||||
+ formatArguments.stream()
|
||||
.map(tree -> Util.treeToString(tree, state))
|
||||
.map(tree -> SourceCode.treeToString(tree, state))
|
||||
.collect(joining(", "));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static com.google.errorprone.suppliers.Suppliers.OBJECT_TYPE;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.primitives.Primitives;
|
||||
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.bugpatterns.TypesWithUndefinedEquality;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.google.errorprone.util.ASTHelpers.TargetType;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Types;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} that flags redundant identity conversions. */
|
||||
// XXX: Consider detecting cases where a flagged expression is passed to a method, and where removal
|
||||
// of the identify conversion would cause a different method overload to be selected. Depending on
|
||||
// the target method such a modification may change the code's semantics or performance.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Avoid or clarify identity conversions",
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class IdentityConversion extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> IS_CONVERSION_METHOD =
|
||||
anyOf(
|
||||
staticMethod()
|
||||
.onClassAny(
|
||||
"com.google.common.collect.ImmutableBiMap",
|
||||
"com.google.common.collect.ImmutableList",
|
||||
"com.google.common.collect.ImmutableListMultimap",
|
||||
"com.google.common.collect.ImmutableMap",
|
||||
"com.google.common.collect.ImmutableMultimap",
|
||||
"com.google.common.collect.ImmutableMultiset",
|
||||
"com.google.common.collect.ImmutableRangeMap",
|
||||
"com.google.common.collect.ImmutableRangeSet",
|
||||
"com.google.common.collect.ImmutableSet",
|
||||
"com.google.common.collect.ImmutableSetMultimap",
|
||||
"com.google.common.collect.ImmutableTable")
|
||||
.named("copyOf"),
|
||||
staticMethod()
|
||||
.onClassAny(
|
||||
Primitives.allWrapperTypes().stream()
|
||||
.map(Class::getName)
|
||||
.collect(toImmutableSet()))
|
||||
.named("valueOf"),
|
||||
staticMethod().onClass(String.class.getName()).named("valueOf"),
|
||||
staticMethod().onClass("reactor.adapter.rxjava.RxJava2Adapter"),
|
||||
staticMethod()
|
||||
.onClass("reactor.core.publisher.Flux")
|
||||
.namedAnyOf("concat", "firstWithSignal", "from", "merge"),
|
||||
staticMethod().onClass("reactor.core.publisher.Mono").namedAnyOf("from", "fromDirect"));
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
List<? extends ExpressionTree> arguments = tree.getArguments();
|
||||
if (arguments.size() != 1 || !IS_CONVERSION_METHOD.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
ExpressionTree sourceTree = arguments.get(0);
|
||||
Type sourceType = ASTHelpers.getType(sourceTree);
|
||||
Type resultType = ASTHelpers.getType(tree);
|
||||
TargetType targetType = ASTHelpers.targetType(state);
|
||||
if (sourceType == null || resultType == null || targetType == null) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
if (!state.getTypes().isSameType(sourceType, resultType)
|
||||
&& !isConvertibleWithWellDefinedEquality(sourceType, targetType.type(), state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return buildDescription(tree)
|
||||
.setMessage(
|
||||
"This method invocation appears redundant; remove it or suppress this warning and "
|
||||
+ "add a comment explaining its purpose")
|
||||
.addFix(SuggestedFix.replace(tree, SourceCode.treeToString(sourceTree, state)))
|
||||
.addFix(SuggestedFixes.addSuppressWarnings(state, canonicalName()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static boolean isConvertibleWithWellDefinedEquality(
|
||||
Type sourceType, Type targetType, VisitorState state) {
|
||||
Types types = state.getTypes();
|
||||
return !types.isSameType(targetType, OBJECT_TYPE.get(state))
|
||||
&& types.isConvertible(sourceType, targetType)
|
||||
&& Arrays.stream(TypesWithUndefinedEquality.values())
|
||||
.noneMatch(b -> b.matchesType(sourceType, state) || b.matchesType(targetType, state));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
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.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.enclosingClass;
|
||||
import static com.google.errorprone.matchers.Matchers.hasModifier;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static tech.picnic.errorprone.bugpatterns.util.JavaKeywords.isReservedKeyword;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.matchers.Matchers;
|
||||
import com.google.errorprone.matchers.MultiMatcher;
|
||||
import com.google.errorprone.predicates.TypePredicate;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.ImportTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.Name;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} which flags non-canonical JUnit method declarations. */
|
||||
// XXX: Consider introducing a class-level check which enforces that test classes:
|
||||
// 1. Are named `*Test` or `Abstract*TestCase`.
|
||||
// 2. If not `abstract`, are package-private and don't have public methods and subclasses.
|
||||
// 3. Only have private fields.
|
||||
// XXX: If implemented, the current logic could flag only `private` JUnit methods.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "JUnit method declaration can likely be improved",
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class JUnitMethodDeclaration extends BugChecker implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TEST_PREFIX = "test";
|
||||
private static final ImmutableSet<Modifier> ILLEGAL_MODIFIERS =
|
||||
ImmutableSet.of(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC);
|
||||
private static final Matcher<MethodTree> HAS_UNMODIFIABLE_SIGNATURE =
|
||||
anyOf(
|
||||
annotations(AT_LEAST_ONE, isType("java.lang.Override")),
|
||||
allOf(
|
||||
Matchers.not(hasModifier(Modifier.FINAL)),
|
||||
Matchers.not(hasModifier(Modifier.PRIVATE)),
|
||||
enclosingClass(hasModifier(Modifier.ABSTRACT))));
|
||||
private static final MultiMatcher<MethodTree, AnnotationTree> TEST_METHOD =
|
||||
annotations(
|
||||
AT_LEAST_ONE,
|
||||
anyOf(
|
||||
isType("org.junit.jupiter.api.Test"),
|
||||
hasMetaAnnotation("org.junit.jupiter.api.TestTemplate")));
|
||||
private static final MultiMatcher<MethodTree, AnnotationTree> SETUP_OR_TEARDOWN_METHOD =
|
||||
annotations(
|
||||
AT_LEAST_ONE,
|
||||
anyOf(
|
||||
isType("org.junit.jupiter.api.AfterAll"),
|
||||
isType("org.junit.jupiter.api.AfterEach"),
|
||||
isType("org.junit.jupiter.api.BeforeAll"),
|
||||
isType("org.junit.jupiter.api.BeforeEach")));
|
||||
|
||||
@Override
|
||||
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||
if (HAS_UNMODIFIABLE_SIGNATURE.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
boolean isTestMethod = TEST_METHOD.matches(tree, state);
|
||||
if (!isTestMethod && !SETUP_OR_TEARDOWN_METHOD.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
|
||||
SuggestedFixes.removeModifiers(tree.getModifiers(), state, ILLEGAL_MODIFIERS)
|
||||
.ifPresent(fixBuilder::merge);
|
||||
|
||||
if (isTestMethod) {
|
||||
suggestTestMethodRenameIfApplicable(tree, fixBuilder, state);
|
||||
}
|
||||
|
||||
return fixBuilder.isEmpty() ? Description.NO_MATCH : describeMatch(tree, fixBuilder.build());
|
||||
}
|
||||
|
||||
private void suggestTestMethodRenameIfApplicable(
|
||||
MethodTree tree, SuggestedFix.Builder fixBuilder, VisitorState state) {
|
||||
tryCanonicalizeMethodName(tree)
|
||||
.ifPresent(
|
||||
newName ->
|
||||
findMethodRenameBlocker(newName, state)
|
||||
.ifPresentOrElse(
|
||||
blocker -> reportMethodRenameBlocker(tree, blocker, state),
|
||||
() -> fixBuilder.merge(SuggestedFixes.renameMethod(tree, newName, state))));
|
||||
}
|
||||
|
||||
private void reportMethodRenameBlocker(MethodTree tree, String reason, VisitorState state) {
|
||||
state.reportMatch(
|
||||
buildDescription(tree)
|
||||
.setMessage(
|
||||
String.format(
|
||||
"This method's name should not redundantly start with `%s` (but note that %s)",
|
||||
TEST_PREFIX, reason))
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* If applicable, returns a human-readable argument against assigning the given name to an
|
||||
* existing method.
|
||||
*
|
||||
* <p>This method implements imperfect heuristics. Things it currently does not consider include
|
||||
* the following:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Whether the rename would merely introduce a method overload, rather than clashing with an
|
||||
* existing method declaration.
|
||||
* <li>Whether the rename would cause a method in a superclass to be overridden.
|
||||
* <li>Whether the rename would in fact clash with a static import. (It could be that a static
|
||||
* import of the same name is only referenced from lexical scopes in which the method under
|
||||
* consideration cannot be referenced directly.)
|
||||
* </ul>
|
||||
*/
|
||||
private static Optional<String> findMethodRenameBlocker(String methodName, VisitorState state) {
|
||||
if (isMethodInEnclosingClass(methodName, state)) {
|
||||
return Optional.of(
|
||||
String.format("a method named `%s` already exists in this class", methodName));
|
||||
}
|
||||
|
||||
if (isSimpleNameStaticallyImported(methodName, state)) {
|
||||
return Optional.of(String.format("`%s` is already statically imported", methodName));
|
||||
}
|
||||
|
||||
if (isReservedKeyword(methodName)) {
|
||||
return Optional.of(String.format("`%s` is a reserved keyword", methodName));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static boolean isMethodInEnclosingClass(String methodName, VisitorState state) {
|
||||
return state.findEnclosing(ClassTree.class).getMembers().stream()
|
||||
.filter(MethodTree.class::isInstance)
|
||||
.map(MethodTree.class::cast)
|
||||
.map(MethodTree::getName)
|
||||
.map(Name::toString)
|
||||
.anyMatch(methodName::equals);
|
||||
}
|
||||
|
||||
private static boolean isSimpleNameStaticallyImported(String simpleName, VisitorState state) {
|
||||
return state.getPath().getCompilationUnit().getImports().stream()
|
||||
.filter(ImportTree::isStatic)
|
||||
.map(ImportTree::getQualifiedIdentifier)
|
||||
.map(tree -> getStaticImportSimpleName(tree, state))
|
||||
.anyMatch(simpleName::contentEquals);
|
||||
}
|
||||
|
||||
private static CharSequence getStaticImportSimpleName(Tree tree, VisitorState state) {
|
||||
String source = SourceCode.treeToString(tree, state);
|
||||
return source.subSequence(source.lastIndexOf('.') + 1, source.length());
|
||||
}
|
||||
|
||||
private static Optional<String> tryCanonicalizeMethodName(MethodTree tree) {
|
||||
return Optional.ofNullable(ASTHelpers.getSymbol(tree))
|
||||
.map(sym -> sym.getQualifiedName().toString())
|
||||
.filter(name -> name.startsWith(TEST_PREFIX))
|
||||
.map(name -> name.substring(TEST_PREFIX.length()))
|
||||
.filter(not(String::isEmpty))
|
||||
.map(name -> Character.toLowerCase(name.charAt(0)) + name.substring(1))
|
||||
.filter(name -> !Character.isDigit(name.charAt(0)));
|
||||
}
|
||||
|
||||
// XXX: Move to a `MoreMatchers` utility class.
|
||||
private static Matcher<AnnotationTree> hasMetaAnnotation(String annotationClassName) {
|
||||
TypePredicate typePredicate = hasAnnotation(annotationClassName);
|
||||
return (tree, state) -> {
|
||||
Symbol sym = ASTHelpers.getSymbol(tree);
|
||||
return sym != null && typePredicate.apply(sym.type, state);
|
||||
};
|
||||
}
|
||||
|
||||
// XXX: Move to a `MoreTypePredicates` utility class.
|
||||
private static TypePredicate hasAnnotation(String annotationClassName) {
|
||||
return (type, state) -> ASTHelpers.hasAnnotation(type.tsym, annotationClassName, state);
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.matchers.MultiMatcher;
|
||||
import com.google.errorprone.predicates.TypePredicate;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.Modifier;
|
||||
|
||||
/** A {@link BugChecker} which flags non-canonical JUnit method declarations. */
|
||||
// XXX: Consider introducing a class-level check which enforces that test classes:
|
||||
// 1. Are named `*Test` or `Abstract*TestCase`.
|
||||
// 2. If not `abstract`, don't have public methods and subclasses.
|
||||
// 3. Only have private fields.
|
||||
// XXX: If implemented, the current logic could flag only `private` JUnit methods.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "JUnitMethodDeclaration",
|
||||
summary = "JUnit method declaration can likely be improved",
|
||||
linkType = BugPattern.LinkType.NONE,
|
||||
severity = BugPattern.SeverityLevel.SUGGESTION,
|
||||
tags = BugPattern.StandardTags.SIMPLIFICATION)
|
||||
public final class JUnitMethodDeclarationCheck extends BugChecker implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TEST_PREFIX = "test";
|
||||
private static final ImmutableSet<Modifier> ILLEGAL_MODIFIERS =
|
||||
ImmutableSet.of(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC);
|
||||
private static final MultiMatcher<MethodTree, AnnotationTree> OVERRIDE_METHOD =
|
||||
annotations(AT_LEAST_ONE, isType("java.lang.Override"));
|
||||
private static final MultiMatcher<MethodTree, AnnotationTree> TEST_METHOD =
|
||||
annotations(
|
||||
AT_LEAST_ONE,
|
||||
anyOf(
|
||||
isType("org.junit.jupiter.api.Test"),
|
||||
hasMetaAnnotation("org.junit.jupiter.api.TestTemplate")));
|
||||
private static final MultiMatcher<MethodTree, AnnotationTree> SETUP_OR_TEARDOWN_METHOD =
|
||||
annotations(
|
||||
AT_LEAST_ONE,
|
||||
anyOf(
|
||||
isType("org.junit.jupiter.api.AfterAll"),
|
||||
isType("org.junit.jupiter.api.AfterEach"),
|
||||
isType("org.junit.jupiter.api.BeforeAll"),
|
||||
isType("org.junit.jupiter.api.BeforeEach")));
|
||||
|
||||
@Override
|
||||
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||
// XXX: Perhaps we should also skip analysis of non-`private` non-`final` methods in abstract
|
||||
// classes?
|
||||
if (OVERRIDE_METHOD.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
boolean isTestMethod = TEST_METHOD.matches(tree, state);
|
||||
if (!isTestMethod && !SETUP_OR_TEARDOWN_METHOD.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
SuggestedFix.Builder builder = SuggestedFix.builder();
|
||||
SuggestedFixes.removeModifiers(tree.getModifiers(), state, ILLEGAL_MODIFIERS)
|
||||
.ifPresent(builder::merge);
|
||||
|
||||
if (isTestMethod) {
|
||||
// XXX: In theory this rename could clash with an existing method or static import. In that
|
||||
// case we should emit a warning without a suggested replacement.
|
||||
tryCanonicalizeMethodName(tree, state).ifPresent(builder::merge);
|
||||
}
|
||||
|
||||
return builder.isEmpty() ? Description.NO_MATCH : describeMatch(tree, builder.build());
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix> tryCanonicalizeMethodName(
|
||||
MethodTree tree, VisitorState state) {
|
||||
return Optional.ofNullable(ASTHelpers.getSymbol(tree))
|
||||
.map(sym -> sym.getQualifiedName().toString())
|
||||
.filter(name -> name.startsWith(TEST_PREFIX))
|
||||
.map(name -> name.substring(TEST_PREFIX.length()))
|
||||
.filter(not(String::isEmpty))
|
||||
.map(name -> Character.toLowerCase(name.charAt(0)) + name.substring(1))
|
||||
.filter(name -> !Character.isDigit(name.charAt(0)))
|
||||
.map(name -> SuggestedFixes.renameMethod(tree, name, state));
|
||||
}
|
||||
|
||||
// XXX: Move to a `MoreMatchers` utility class.
|
||||
private static Matcher<AnnotationTree> hasMetaAnnotation(String annotationClassName) {
|
||||
TypePredicate typePredicate = hasAnnotation(annotationClassName);
|
||||
return (tree, state) -> {
|
||||
Symbol sym = ASTHelpers.getSymbol(tree);
|
||||
return sym != null && typePredicate.apply(sym.type, state);
|
||||
};
|
||||
}
|
||||
|
||||
// XXX: Move to a `MoreTypePredicates` utility class.
|
||||
private static TypePredicate hasAnnotation(String annotationClassName) {
|
||||
return (type, state) -> ASTHelpers.hasAnnotation(type.tsym, annotationClassName, state);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
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 java.util.Comparator.comparing;
|
||||
import static java.util.Comparator.naturalOrder;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
@@ -9,9 +12,6 @@ import com.google.common.collect.Comparators;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.ErrorProneFlags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
@@ -37,6 +37,9 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
import tech.picnic.errorprone.bugpatterns.util.AnnotationAttributeMatcher;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags annotation array listings which aren't sorted lexicographically.
|
||||
@@ -46,12 +49,11 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "LexicographicalAnnotationAttributeListing",
|
||||
summary = "Where possible, sort annotation array attributes lexicographically",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.STYLE)
|
||||
public final class LexicographicalAnnotationAttributeListingCheck extends BugChecker
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = STYLE)
|
||||
public final class LexicographicalAnnotationAttributeListing extends BugChecker
|
||||
implements AnnotationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final ImmutableSet<String> BLACKLISTED_ANNOTATIONS =
|
||||
@@ -67,17 +69,17 @@ public final class LexicographicalAnnotationAttributeListingCheck extends BugChe
|
||||
|
||||
private final AnnotationAttributeMatcher matcher;
|
||||
|
||||
/** Instantiates the default {@link LexicographicalAnnotationAttributeListingCheck}. */
|
||||
public LexicographicalAnnotationAttributeListingCheck() {
|
||||
/** Instantiates the default {@link LexicographicalAnnotationAttributeListing}. */
|
||||
public LexicographicalAnnotationAttributeListing() {
|
||||
this(ErrorProneFlags.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a customized {@link LexicographicalAnnotationAttributeListingCheck}.
|
||||
* Instantiates a customized {@link LexicographicalAnnotationAttributeListing}.
|
||||
*
|
||||
* @param flags Any provided command line flags.
|
||||
*/
|
||||
public LexicographicalAnnotationAttributeListingCheck(ErrorProneFlags flags) {
|
||||
public LexicographicalAnnotationAttributeListing(ErrorProneFlags flags) {
|
||||
matcher = createAnnotationAttributeMatcher(flags);
|
||||
}
|
||||
|
||||
@@ -128,7 +130,7 @@ public final class LexicographicalAnnotationAttributeListingCheck extends BugChe
|
||||
/* The elements aren't sorted. Suggest the sorted alternative. */
|
||||
String suggestion =
|
||||
desiredOrdering.stream()
|
||||
.map(expr -> Util.treeToString(expr, state))
|
||||
.map(expr -> SourceCode.treeToString(expr, state))
|
||||
.collect(joining(", ", "{", "}"));
|
||||
return Optional.of(SuggestedFix.builder().replace(array, suggestion));
|
||||
}
|
||||
@@ -171,18 +173,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));
|
||||
@@ -194,7 +199,7 @@ public final class LexicographicalAnnotationAttributeListingCheck extends BugChe
|
||||
* Tokens are split on `=` so that e.g. inline Spring property declarations are properly
|
||||
* sorted by key, then value.
|
||||
*/
|
||||
return ImmutableList.copyOf(Util.treeToString(node, state).split("=", -1));
|
||||
return ImmutableList.copyOf(SourceCode.treeToString(node, state).split("=", -1));
|
||||
}
|
||||
}.scan(array, null);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
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 java.util.Comparator.comparing;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
@@ -20,6 +20,7 @@ import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags annotations that are not lexicographically sorted.
|
||||
@@ -29,12 +30,11 @@ import java.util.Optional;
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "LexicographicalAnnotationListing",
|
||||
summary = "Sort annotations lexicographically where possible",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.STYLE)
|
||||
public final class LexicographicalAnnotationListingCheck extends BugChecker
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = STYLE)
|
||||
public final class LexicographicalAnnotationListing extends BugChecker
|
||||
implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public final class LexicographicalAnnotationListingCheck extends BugChecker
|
||||
private static ImmutableList<? extends AnnotationTree> sort(
|
||||
List<? extends AnnotationTree> annotations, VisitorState state) {
|
||||
return annotations.stream()
|
||||
.sorted(comparing(annotation -> Util.treeToString(annotation, state)))
|
||||
.sorted(comparing(annotation -> SourceCode.treeToString(annotation, state)))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
@@ -72,7 +72,8 @@ public final class LexicographicalAnnotationListingCheck extends BugChecker
|
||||
originalAnnotations.stream(),
|
||||
sortedAnnotations.stream(),
|
||||
(original, replacement) ->
|
||||
SuggestedFix.builder().replace(original, Util.treeToString(replacement, state)))
|
||||
SuggestedFix.builder()
|
||||
.replace(original, SourceCode.treeToString(replacement, state)))
|
||||
.reduce(SuggestedFix.Builder::merge)
|
||||
.map(SuggestedFix.Builder::build);
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
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 com.google.auto.service.AutoService;
|
||||
import com.google.common.base.VerifyException;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.LambdaExpressionTreeMatcher;
|
||||
@@ -51,13 +51,11 @@ import javax.lang.model.element.Name;
|
||||
// Palantir's `LambdaMethodReference` check seems to suffer a similar issue at this time.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "MethodReferenceUsage",
|
||||
summary = "Prefer method references over lambda expressions",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.STYLE)
|
||||
public final class MethodReferenceUsageCheck extends BugChecker
|
||||
implements LambdaExpressionTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = STYLE)
|
||||
public final class MethodReferenceUsage extends BugChecker implements LambdaExpressionTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
@@ -1,5 +1,8 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
@@ -7,9 +10,6 @@ import static com.google.errorprone.matchers.Matchers.isType;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
|
||||
@@ -24,12 +24,11 @@ import com.sun.source.tree.Tree;
|
||||
/** A {@link BugChecker} that flags likely missing Refaster annotations. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "MissingRefasterAnnotation",
|
||||
summary = "The Refaster template contains a method without any Refaster annotations",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.WARNING,
|
||||
tags = StandardTags.LIKELY_ERROR)
|
||||
public final class MissingRefasterAnnotationCheck extends BugChecker implements ClassTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = LIKELY_ERROR)
|
||||
public final class MissingRefasterAnnotation extends BugChecker implements ClassTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final MultiMatcher<Tree, AnnotationTree> REFASTER_ANNOTATION =
|
||||
annotations(
|
||||
@@ -1,13 +1,13 @@
|
||||
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.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
@@ -17,6 +17,7 @@ import com.google.errorprone.matchers.Matcher;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import java.util.List;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags method invocations for which all arguments are wrapped using
|
||||
@@ -24,12 +25,11 @@ import java.util.List;
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "MockitoStubbing",
|
||||
summary = "Don't unnecessarily use Mockito's `eq(...)`",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class MockitoStubbingCheck extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class MockitoStubbing extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> MOCKITO_EQ_METHOD =
|
||||
staticMethod().onClass("org.mockito.ArgumentMatchers").named("eq");
|
||||
@@ -45,7 +45,7 @@ public final class MockitoStubbingCheck extends BugChecker implements MethodInvo
|
||||
for (ExpressionTree arg : arguments) {
|
||||
suggestedFix.replace(
|
||||
arg,
|
||||
Util.treeToString(
|
||||
SourceCode.treeToString(
|
||||
Iterables.getOnlyElement(((MethodInvocationTree) arg).getArguments()), state));
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.PERFORMANCE;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.instanceMethod;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.base.VerifyException;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
@@ -30,6 +31,8 @@ import com.sun.tools.javac.tree.JCTree.JCMemberReference;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags {@code Comparator#comparing*} invocations that can be replaced
|
||||
@@ -37,18 +40,15 @@ import java.util.function.Function;
|
||||
*/
|
||||
// XXX: Add more documentation. Explain how this is useful in the face of refactoring to more
|
||||
// specific types.
|
||||
// XXX: Change this checker's name?
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "PrimitiveComparison",
|
||||
summary =
|
||||
"Ensure invocations of `Comparator#comparing{,Double,Int,Long}` match the return type"
|
||||
+ " of the provided function",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.WARNING,
|
||||
tags = StandardTags.PERFORMANCE)
|
||||
public final class PrimitiveComparisonCheck extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = PERFORMANCE)
|
||||
public final class PrimitiveComparison extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> STATIC_COMPARISON_METHOD =
|
||||
anyOf(
|
||||
@@ -77,23 +77,53 @@ public final class PrimitiveComparisonCheck extends BugChecker
|
||||
}
|
||||
|
||||
return getPotentiallyBoxedReturnType(tree.getArguments().get(0))
|
||||
.flatMap(cmpType -> tryFix(tree, state, cmpType, isStatic))
|
||||
.flatMap(cmpType -> attemptMethodInvocationReplacement(tree, cmpType, isStatic, state))
|
||||
.map(fix -> describeMatch(tree, fix))
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
|
||||
private static Optional<Fix> tryFix(
|
||||
MethodInvocationTree tree, VisitorState state, Type cmpType, boolean isStatic) {
|
||||
private static Optional<Fix> attemptMethodInvocationReplacement(
|
||||
MethodInvocationTree tree, Type cmpType, boolean isStatic, VisitorState state) {
|
||||
return Optional.ofNullable(ASTHelpers.getSymbol(tree))
|
||||
.map(methodSymbol -> methodSymbol.getSimpleName().toString())
|
||||
.flatMap(
|
||||
actualMethodName ->
|
||||
Optional.of(getPreferredMethod(state, cmpType, isStatic))
|
||||
Optional.of(getPreferredMethod(cmpType, isStatic, state))
|
||||
.filter(not(actualMethodName::equals)))
|
||||
.map(
|
||||
preferredMethodName ->
|
||||
prefixTypeArgumentsIfRelevant(preferredMethodName, tree, cmpType, state))
|
||||
.map(preferredMethodName -> suggestFix(tree, preferredMethodName, state));
|
||||
}
|
||||
|
||||
private static String getPreferredMethod(VisitorState state, Type cmpType, boolean isStatic) {
|
||||
/**
|
||||
* Prefixes the given method name with generic type parameters if it replaces a {@code
|
||||
* Comparator#comparing{,Double,Long,Int}} method which also has generic type parameters.
|
||||
*
|
||||
* <p>Such type parameters are retained as they are likely required.
|
||||
*
|
||||
* <p>Note that any type parameter to {@code Comparator#thenComparing} is likely redundant, and in
|
||||
* any case becomes obsolete once that method is replaced with {@code
|
||||
* Comparator#thenComparing{Double,Long,Int}}. Conversion in the opposite direction does not
|
||||
* require the introduction of a generic type parameter.
|
||||
*/
|
||||
private static String prefixTypeArgumentsIfRelevant(
|
||||
String preferredMethodName, MethodInvocationTree tree, Type cmpType, VisitorState state) {
|
||||
if (tree.getTypeArguments().isEmpty() || preferredMethodName.startsWith("then")) {
|
||||
return preferredMethodName;
|
||||
}
|
||||
|
||||
String typeArguments =
|
||||
Stream.concat(
|
||||
Stream.of(SourceCode.treeToString(tree.getTypeArguments().get(0), state)),
|
||||
Stream.of(cmpType.tsym.getSimpleName())
|
||||
.filter(u -> "comparing".equals(preferredMethodName)))
|
||||
.collect(joining(", ", "<", ">"));
|
||||
|
||||
return typeArguments + preferredMethodName;
|
||||
}
|
||||
|
||||
private static String getPreferredMethod(Type cmpType, boolean isStatic, VisitorState state) {
|
||||
Types types = state.getTypes();
|
||||
Symtab symtab = state.getSymtab();
|
||||
|
||||
@@ -128,9 +158,6 @@ public final class PrimitiveComparisonCheck extends BugChecker
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: We drop explicitly specified generic type information. In case the number of type
|
||||
// arguments before and after doesn't match, that's for the better. But if we e.g. replace
|
||||
// `comparingLong` with `comparingInt`, then we should retain it.
|
||||
private static Fix suggestFix(
|
||||
MethodInvocationTree tree, String preferredMethodName, VisitorState state) {
|
||||
ExpressionTree expr = tree.getMethodSelect();
|
||||
@@ -143,7 +170,7 @@ public final class PrimitiveComparisonCheck extends BugChecker
|
||||
case MEMBER_SELECT:
|
||||
MemberSelectTree ms = (MemberSelectTree) tree.getMethodSelect();
|
||||
return SuggestedFix.replace(
|
||||
ms, Util.treeToString(ms.getExpression(), state) + '.' + preferredMethodName);
|
||||
ms, SourceCode.treeToString(ms.getExpression(), state) + '.' + preferredMethodName);
|
||||
default:
|
||||
throw new VerifyException("Unexpected type of expression: " + expr.getKind());
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
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.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isNonNullUsingDataflow;
|
||||
@@ -12,9 +15,6 @@ import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.ErrorProneFlags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
@@ -41,16 +41,17 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import tech.picnic.errorprone.bugpatterns.util.MethodMatcherFactory;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} which flags redundant explicit string conversions. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "RedundantStringConversion",
|
||||
summary = "Avoid redundant string conversions when possible",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class RedundantStringConversionCheck extends BugChecker
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class RedundantStringConversion extends BugChecker
|
||||
implements BinaryTreeMatcher, CompoundAssignmentTreeMatcher, MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String FLAG_PREFIX = "RedundantStringConversion:";
|
||||
@@ -157,17 +158,17 @@ public final class RedundantStringConversionCheck extends BugChecker
|
||||
|
||||
private final Matcher<ExpressionTree> conversionMethodMatcher;
|
||||
|
||||
/** Instantiates the default {@link RedundantStringConversionCheck}. */
|
||||
public RedundantStringConversionCheck() {
|
||||
/** Instantiates the default {@link RedundantStringConversion}. */
|
||||
public RedundantStringConversion() {
|
||||
this(ErrorProneFlags.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a customized {@link RedundantStringConversionCheck}.
|
||||
* Instantiates a customized {@link RedundantStringConversion}.
|
||||
*
|
||||
* @param flags Any provided command line flags.
|
||||
*/
|
||||
public RedundantStringConversionCheck(ErrorProneFlags flags) {
|
||||
public RedundantStringConversion(ErrorProneFlags flags) {
|
||||
conversionMethodMatcher = createConversionMethodMatcher(flags);
|
||||
}
|
||||
|
||||
@@ -326,7 +327,7 @@ public final class RedundantStringConversionCheck extends BugChecker
|
||||
return trySimplify(tree, state, filter)
|
||||
.map(
|
||||
replacement ->
|
||||
SuggestedFix.builder().replace(tree, Util.treeToString(replacement, state)));
|
||||
SuggestedFix.builder().replace(tree, SourceCode.treeToString(replacement, state)));
|
||||
}
|
||||
|
||||
private Optional<ExpressionTree> trySimplify(
|
||||
@@ -350,7 +351,7 @@ public final class RedundantStringConversionCheck extends BugChecker
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"Cannot simplify method call with two or more arguments: "
|
||||
+ Util.treeToString(tree, state));
|
||||
+ SourceCode.treeToString(tree, state));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,7 +364,7 @@ public final class RedundantStringConversionCheck extends BugChecker
|
||||
return Optional.of(methodInvocation.getMethodSelect())
|
||||
.filter(methodSelect -> methodSelect.getKind() == Kind.MEMBER_SELECT)
|
||||
.map(methodSelect -> ((MemberSelectTree) methodSelect).getExpression())
|
||||
.filter(expr -> !"super".equals(Util.treeToString(expr, state)));
|
||||
.filter(expr -> !"super".equals(SourceCode.treeToString(expr, state)));
|
||||
}
|
||||
|
||||
private static Optional<ExpressionTree> trySimplifyUnaryMethod(
|
||||
@@ -1,12 +1,12 @@
|
||||
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.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
@@ -16,6 +16,7 @@ import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags unnecessary {@link Refaster#anyOf(Object[])} usages.
|
||||
@@ -25,13 +26,11 @@ import com.sun.source.tree.MethodInvocationTree;
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "RefasterAnyOfUsage",
|
||||
summary = "`Refaster#anyOf` should be passed at least two parameters",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class RefasterAnyOfUsageCheck extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class RefasterAnyOfUsage extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> REFASTER_ANY_OF =
|
||||
staticMethod().onClass(Refaster.class.getName()).named("anyOf");
|
||||
@@ -46,7 +45,8 @@ public final class RefasterAnyOfUsageCheck extends BugChecker
|
||||
case 1:
|
||||
return describeMatch(
|
||||
tree,
|
||||
SuggestedFix.replace(tree, Util.treeToString(tree.getArguments().get(0), state)));
|
||||
SuggestedFix.replace(
|
||||
tree, SourceCode.treeToString(tree.getArguments().get(0), state)));
|
||||
default:
|
||||
/* Handled below. */
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.ALL;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isSameType;
|
||||
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
import static com.google.errorprone.matchers.Matchers.methodHasParameters;
|
||||
import static com.google.errorprone.matchers.Matchers.not;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
@@ -31,12 +30,11 @@ import com.sun.source.tree.Tree;
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "RequestMappingAnnotation",
|
||||
summary = "Make sure all `@RequestMapping` method parameters are annotated",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.WARNING,
|
||||
tags = StandardTags.LIKELY_ERROR)
|
||||
public final class RequestMappingAnnotationCheck extends BugChecker implements MethodTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = LIKELY_ERROR)
|
||||
public final class RequestMappingAnnotation extends BugChecker implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String ANN_PACKAGE_PREFIX = "org.springframework.web.bind.annotation.";
|
||||
// XXX: Generalize this logic to fully support Spring meta-annotations, then update the class
|
||||
@@ -51,8 +49,11 @@ public final class RequestMappingAnnotationCheck extends BugChecker implements M
|
||||
isType(ANN_PACKAGE_PREFIX + "PostMapping"),
|
||||
isType(ANN_PACKAGE_PREFIX + "PutMapping"),
|
||||
isType(ANN_PACKAGE_PREFIX + "RequestMapping")));
|
||||
// XXX: Add other parameters as necessary. See
|
||||
// https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-arguments.
|
||||
// XXX: Add other parameters as necessary. Also consider whether it makes sense to have WebMVC-
|
||||
// and WebFlux-specific logic. See
|
||||
// https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-arguments
|
||||
// and
|
||||
// https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-ann-arguments.
|
||||
private static final Matcher<MethodTree> LACKS_PARAMETER_ANNOTATION =
|
||||
not(
|
||||
methodHasParameters(
|
||||
@@ -66,10 +67,17 @@ public final class RequestMappingAnnotationCheck extends BugChecker implements M
|
||||
isType(ANN_PACKAGE_PREFIX + "RequestHeader"),
|
||||
isType(ANN_PACKAGE_PREFIX + "RequestParam"))),
|
||||
isSameType("java.io.InputStream"),
|
||||
isSameType("java.time.ZoneId"),
|
||||
isSameType("java.util.Locale"),
|
||||
isSameType("java.util.TimeZone"),
|
||||
isSameType("javax.servlet.http.HttpServletRequest"),
|
||||
isSameType("javax.servlet.http.HttpServletResponse"),
|
||||
isSameType("org.springframework.http.HttpMethod"),
|
||||
isSubtypeOf("org.springframework.web.context.request.WebRequest"))));
|
||||
isSameType("org.springframework.web.context.request.NativeWebRequest"),
|
||||
isSameType("org.springframework.web.context.request.WebRequest"),
|
||||
isSameType("org.springframework.web.server.ServerWebExchange"),
|
||||
isSameType("org.springframework.web.util.UriBuilder"),
|
||||
isSameType("org.springframework.web.util.UriComponentsBuilder"))));
|
||||
|
||||
@Override
|
||||
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||
@@ -0,0 +1,44 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
|
||||
/** A {@link BugChecker} which flags {@code @RequestParam} parameters with an unsupported type. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "`@RequestParam` does not support `ImmutableCollection` and `ImmutableMap` subtypes",
|
||||
linkType = NONE,
|
||||
severity = ERROR,
|
||||
tags = LIKELY_ERROR)
|
||||
public final class RequestParamType extends BugChecker implements VariableTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<VariableTree> HAS_UNSUPPORTED_REQUEST_PARAM =
|
||||
allOf(
|
||||
annotations(AT_LEAST_ONE, isType("org.springframework.web.bind.annotation.RequestParam")),
|
||||
anyOf(isSubtypeOf(ImmutableCollection.class), isSubtypeOf(ImmutableMap.class)));
|
||||
|
||||
@Override
|
||||
public Description matchVariable(VariableTree tree, VisitorState state) {
|
||||
return HAS_UNSUPPORTED_REQUEST_PARAM.matches(tree, state)
|
||||
? describeMatch(tree)
|
||||
: Description.NO_MATCH;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.hasAnnotation;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
|
||||
import com.google.auto.common.AnnotationMirrors;
|
||||
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;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.matchers.MultiMatcher;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags methods with Spring's {@code @Scheduled} annotation that lack
|
||||
* New Relic Agent's {@code @Trace(dispatcher = true)}.
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Scheduled operation must start a new New Relic transaction",
|
||||
linkType = NONE,
|
||||
severity = ERROR,
|
||||
tags = LIKELY_ERROR)
|
||||
public final class ScheduledTransactionTrace extends BugChecker implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TRACE_ANNOTATION_FQCN = "com.newrelic.api.agent.Trace";
|
||||
private static final Matcher<Tree> IS_SCHEDULED =
|
||||
hasAnnotation("org.springframework.scheduling.annotation.Scheduled");
|
||||
private static final MultiMatcher<Tree, AnnotationTree> TRACE_ANNOTATION =
|
||||
annotations(AT_LEAST_ONE, isType(TRACE_ANNOTATION_FQCN));
|
||||
|
||||
@Override
|
||||
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||
if (!IS_SCHEDULED.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
ImmutableList<AnnotationTree> traceAnnotations =
|
||||
TRACE_ANNOTATION.multiMatchResult(tree, state).matchingNodes();
|
||||
if (traceAnnotations.isEmpty()) {
|
||||
/* This method completely lacks the `@Trace` annotation; add it. */
|
||||
return describeMatch(
|
||||
tree,
|
||||
SuggestedFix.builder()
|
||||
.addImport(TRACE_ANNOTATION_FQCN)
|
||||
.prefixWith(tree, "@Trace(dispatcher = true)")
|
||||
.build());
|
||||
}
|
||||
|
||||
AnnotationTree traceAnnotation = Iterables.getOnlyElement(traceAnnotations);
|
||||
if (isCorrectAnnotation(traceAnnotation)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
/*
|
||||
* The `@Trace` annotation is present but does not specify `dispatcher = true`. Add or update
|
||||
* the `dispatcher` annotation element.
|
||||
*/
|
||||
return describeMatch(
|
||||
traceAnnotation,
|
||||
SuggestedFixes.updateAnnotationArgumentValues(
|
||||
traceAnnotation, state, "dispatcher", ImmutableList.of("true"))
|
||||
.build());
|
||||
}
|
||||
|
||||
private static boolean isCorrectAnnotation(AnnotationTree traceAnnotation) {
|
||||
return Boolean.TRUE.equals(
|
||||
AnnotationMirrors.getAnnotationValue(
|
||||
ASTHelpers.getAnnotationMirror(traceAnnotation), "dispatcher")
|
||||
.getValue());
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
|
||||
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.instanceMethod;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
@@ -22,6 +22,7 @@ import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} which flags SLF4J usages that are likely to be in error. */
|
||||
// XXX: The special-casing of Throwable applies only to SLF4J 1.6.0+; see
|
||||
@@ -31,13 +32,11 @@ import java.util.Optional;
|
||||
// preconditions, ...
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "Slf4jLogStatement",
|
||||
summary = "Make sure SLF4J log statements contain proper placeholders with matching arguments",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.WARNING,
|
||||
tags = StandardTags.LIKELY_ERROR)
|
||||
public final class Slf4jLogStatementCheck extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = LIKELY_ERROR)
|
||||
public final class Slf4jLogStatement extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> MARKER = isSubtypeOf("org.slf4j.Marker");
|
||||
private static final Matcher<ExpressionTree> THROWABLE = isSubtypeOf(Throwable.class);
|
||||
@@ -114,7 +113,7 @@ public final class Slf4jLogStatementCheck extends BugChecker
|
||||
* replaced at this usage site.
|
||||
*/
|
||||
description.addFix(
|
||||
SuggestedFix.replace(tree, Util.treeToString(tree, state).replace("%s", "{}")));
|
||||
SuggestedFix.replace(tree, SourceCode.treeToString(tree, state).replace("%s", "{}")));
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1,6 +1,9 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.base.Verify.verify;
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
@@ -9,9 +12,6 @@ import com.google.common.base.VerifyException;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher;
|
||||
@@ -25,6 +25,8 @@ import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.NewArrayTree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import java.util.Optional;
|
||||
import tech.picnic.errorprone.bugpatterns.util.AnnotationAttributeMatcher;
|
||||
import tech.picnic.errorprone.bugpatterns.util.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} which flags {@code @RequestMapping} annotations that can be written more
|
||||
@@ -32,13 +34,12 @@ import java.util.Optional;
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "SpringMvcAnnotation",
|
||||
summary =
|
||||
"Prefer the conciseness of `@{Get,Put,Post,Delete,Patch}Mapping` over `@RequestMapping`",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class SpringMvcAnnotationCheck extends BugChecker implements AnnotationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class SpringMvcAnnotation extends BugChecker implements AnnotationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String ANN_PACKAGE_PREFIX = "org.springframework.web.bind.annotation.";
|
||||
private static final AnnotationAttributeMatcher ARGUMENT_SELECTOR =
|
||||
@@ -92,7 +93,7 @@ public final class SpringMvcAnnotationCheck extends BugChecker implements Annota
|
||||
private static String extractMethod(ExpressionTree expr, VisitorState state) {
|
||||
switch (expr.getKind()) {
|
||||
case IDENTIFIER:
|
||||
return Util.treeToString(expr, state);
|
||||
return SourceCode.treeToString(expr, state);
|
||||
case MEMBER_SELECT:
|
||||
return ((MemberSelectTree) expr).getIdentifier().toString();
|
||||
default:
|
||||
@@ -105,7 +106,7 @@ public final class SpringMvcAnnotationCheck extends BugChecker implements Annota
|
||||
String newArguments =
|
||||
tree.getArguments().stream()
|
||||
.filter(not(argToRemove::equals))
|
||||
.map(arg -> Util.treeToString(arg, state))
|
||||
.map(arg -> SourceCode.treeToString(arg, state))
|
||||
.collect(joining(", "));
|
||||
|
||||
return SuggestedFix.builder()
|
||||
@@ -1,5 +1,8 @@
|
||||
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.SIMPLIFICATION;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
@@ -7,9 +10,6 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MemberSelectTreeMatcher;
|
||||
@@ -19,14 +19,18 @@ import com.google.errorprone.fixes.Fix;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.util.Optional;
|
||||
|
||||
/** A {@link BugChecker} which flags methods that can and should be statically imported. */
|
||||
/**
|
||||
* A {@link BugChecker} which flags methods and constants that can and should be statically
|
||||
* imported.
|
||||
*/
|
||||
// XXX: Tricky cases:
|
||||
// - `org.springframework.http.MediaType` (do except for `ALL`?)
|
||||
// - `org.springframework.http.HttpStatus` (not always an improvement, and `valueOf` must
|
||||
// certainly be excluded)
|
||||
// - `com.google.common.collect.Tables`
|
||||
@@ -41,21 +45,28 @@ import java.util.Optional;
|
||||
// - Likely any of `*.{ZERO, ONE, MIX, MAX, MIN_VALUE, MAX_VALUE}`.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "StaticImport",
|
||||
summary = "Method should be statically imported",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.SIMPLIFICATION)
|
||||
public final class StaticImportCheck extends BugChecker implements MemberSelectTreeMatcher {
|
||||
summary = "Identifier should be statically imported",
|
||||
linkType = NONE,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class StaticImport extends BugChecker implements MemberSelectTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Types whose members should be statically imported, unless exempted by {@link
|
||||
* #STATIC_IMPORT_EXEMPTED_MEMBERS} or {@link #STATIC_IMPORT_EXEMPTED_IDENTIFIERS}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static final ImmutableSet<String> STATIC_IMPORT_CANDIDATE_CLASSES =
|
||||
static final ImmutableSet<String> STATIC_IMPORT_CANDIDATE_TYPES =
|
||||
ImmutableSet.of(
|
||||
"com.google.common.base.Preconditions",
|
||||
"com.google.common.base.Predicates",
|
||||
"com.google.common.base.Verify",
|
||||
"com.google.common.collect.MoreCollectors",
|
||||
"com.google.errorprone.BugPattern.LinkType",
|
||||
"com.google.errorprone.BugPattern.SeverityLevel",
|
||||
"com.google.errorprone.BugPattern.StandardTags",
|
||||
"com.google.errorprone.refaster.ImportPolicy",
|
||||
"com.mongodb.client.model.Accumulators",
|
||||
"com.mongodb.client.model.Aggregates",
|
||||
"com.mongodb.client.model.Filters",
|
||||
@@ -64,8 +75,10 @@ public final class StaticImportCheck extends BugChecker implements MemberSelectT
|
||||
"com.mongodb.client.model.Sorts",
|
||||
"com.mongodb.client.model.Updates",
|
||||
"java.nio.charset.StandardCharsets",
|
||||
"java.util.Collections",
|
||||
"java.util.Comparator",
|
||||
"java.util.Map.Entry",
|
||||
"java.util.regex.Pattern",
|
||||
"java.util.stream.Collectors",
|
||||
"org.assertj.core.api.Assertions",
|
||||
"org.assertj.core.api.InstanceOfAssertFactories",
|
||||
@@ -80,14 +93,17 @@ public final class StaticImportCheck extends BugChecker implements MemberSelectT
|
||||
"org.mockito.Answers",
|
||||
"org.mockito.ArgumentMatchers",
|
||||
"org.mockito.Mockito",
|
||||
"org.springframework.boot.test.context.SpringBootTest.WebEnvironment",
|
||||
"org.springframework.format.annotation.DateTimeFormat.ISO",
|
||||
"org.springframework.http.HttpHeaders",
|
||||
"org.springframework.http.HttpMethod",
|
||||
"org.springframework.http.MediaType",
|
||||
"org.testng.Assert",
|
||||
"reactor.function.TupleUtils");
|
||||
|
||||
/** Type members that should be statically imported. */
|
||||
@VisibleForTesting
|
||||
static final ImmutableSetMultimap<String, String> STATIC_IMPORT_CANDIDATE_METHODS =
|
||||
static final ImmutableSetMultimap<String, String> STATIC_IMPORT_CANDIDATE_MEMBERS =
|
||||
ImmutableSetMultimap.<String, String>builder()
|
||||
.putAll(
|
||||
"com.google.common.collect.ImmutableListMultimap",
|
||||
@@ -108,8 +124,10 @@ public final class StaticImportCheck extends BugChecker implements MemberSelectT
|
||||
.put("com.google.common.collect.ImmutableTable", "toImmutableTable")
|
||||
.put("com.google.common.collect.Sets", "toImmutableEnumSet")
|
||||
.put("com.google.common.base.Functions", "identity")
|
||||
.put("java.time.ZoneOffset", "UTC")
|
||||
.put("java.util.function.Function", "identity")
|
||||
.put("java.util.function.Predicate", "not")
|
||||
.put("java.util.UUID", "randomUUID")
|
||||
.put("org.junit.jupiter.params.provider.Arguments", "arguments")
|
||||
.putAll(
|
||||
"java.util.Objects",
|
||||
@@ -122,9 +140,57 @@ public final class StaticImportCheck extends BugChecker implements MemberSelectT
|
||||
.putAll("com.google.common.collect.Comparators", "emptiesFirst", "emptiesLast")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Type members that should never be statically imported.
|
||||
*
|
||||
* <p>Identifiers listed by {@link #STATIC_IMPORT_EXEMPTED_IDENTIFIERS} should be omitted from
|
||||
* this collection.
|
||||
*/
|
||||
// XXX: Perhaps the set of exempted `java.util.Collections` methods is too strict. For now any
|
||||
// method name that could be considered "too vague" or could conceivably mean something else in a
|
||||
// specific context is left out.
|
||||
@VisibleForTesting
|
||||
static final ImmutableSetMultimap<String, String> STATIC_IMPORT_EXEMPTED_MEMBERS =
|
||||
ImmutableSetMultimap.<String, String>builder()
|
||||
.put("com.mongodb.client.model.Filters", "empty")
|
||||
.putAll(
|
||||
"java.util.Collections",
|
||||
"addAll",
|
||||
"copy",
|
||||
"fill",
|
||||
"list",
|
||||
"max",
|
||||
"min",
|
||||
"nCopies",
|
||||
"rotate",
|
||||
"sort",
|
||||
"swap")
|
||||
.putAll("java.util.regex.Pattern", "compile", "matches", "quote")
|
||||
.put("org.springframework.http.MediaType", "ALL")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Identifiers that should never be statically imported.
|
||||
*
|
||||
* <p>This should be a superset of the identifiers flagged by {@link
|
||||
* com.google.errorprone.bugpatterns.BadImport}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static final ImmutableSet<String> STATIC_IMPORT_EXEMPTED_IDENTIFIERS =
|
||||
ImmutableSet.of(
|
||||
"builder",
|
||||
"create",
|
||||
"copyOf",
|
||||
"from",
|
||||
"getDefaultInstance",
|
||||
"INSTANCE",
|
||||
"newBuilder",
|
||||
"of",
|
||||
"valueOf");
|
||||
|
||||
@Override
|
||||
public Description matchMemberSelect(MemberSelectTree tree, VisitorState state) {
|
||||
if (!isCandidate(state)) {
|
||||
if (!isCandidateContext(state) || !isCandidate(tree)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
@@ -139,7 +205,7 @@ public final class StaticImportCheck extends BugChecker implements MemberSelectT
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
|
||||
private static boolean isCandidate(VisitorState state) {
|
||||
private static boolean isCandidateContext(VisitorState state) {
|
||||
Tree parentTree =
|
||||
requireNonNull(state.getPath().getParentPath(), "MemberSelectTree lacks enclosing node")
|
||||
.getLeaf();
|
||||
@@ -154,6 +220,17 @@ public final class StaticImportCheck extends BugChecker implements MemberSelectT
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCandidate(MemberSelectTree tree) {
|
||||
String identifier = tree.getIdentifier().toString();
|
||||
if (STATIC_IMPORT_EXEMPTED_IDENTIFIERS.contains(identifier)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Type type = ASTHelpers.getType(tree.getExpression());
|
||||
return type != null
|
||||
&& !STATIC_IMPORT_EXEMPTED_MEMBERS.containsEntry(type.toString(), identifier);
|
||||
}
|
||||
|
||||
private static Optional<String> getCandidateSimpleName(StaticImportInfo importInfo) {
|
||||
String canonicalName = importInfo.canonicalName();
|
||||
return importInfo
|
||||
@@ -161,8 +238,8 @@ public final class StaticImportCheck extends BugChecker implements MemberSelectT
|
||||
.toJavaUtil()
|
||||
.filter(
|
||||
name ->
|
||||
STATIC_IMPORT_CANDIDATE_CLASSES.contains(canonicalName)
|
||||
|| STATIC_IMPORT_CANDIDATE_METHODS.containsEntry(canonicalName, name));
|
||||
STATIC_IMPORT_CANDIDATE_TYPES.contains(canonicalName)
|
||||
|| STATIC_IMPORT_CANDIDATE_MEMBERS.containsEntry(canonicalName, name));
|
||||
}
|
||||
|
||||
private static Optional<Fix> tryStaticImport(
|
||||
@@ -1,42 +0,0 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import static com.google.errorprone.BugPattern.StandardTags;
|
||||
import static com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.instanceMethod;
|
||||
import static com.sun.source.tree.Tree.Kind;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
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.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.LiteralTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "StringIsEmpty",
|
||||
summary = "Prefer `String#isEmpty` over `String#equals`",
|
||||
severity = SeverityLevel.SUGGESTION,
|
||||
tags = StandardTags.STYLE)
|
||||
public final class StringIsEmptyCheck extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final Matcher<ExpressionTree> STRING_EQUALS_INVOCATION =
|
||||
instanceMethod().onDescendantOf("java.lang.String").named("equals");
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
if (STRING_EQUALS_INVOCATION.matches(tree, state)
|
||||
&& tree.getArguments().get(0).getKind() == Kind.STRING_LITERAL
|
||||
&& ((LiteralTree) tree.getArguments().get(0)).getValue().equals("")) {
|
||||
return describeMatch(
|
||||
tree, SuggestedFix.replace(tree, ASTHelpers.getReceiver(tree) + ".isEmpty()"));
|
||||
}
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.FRAGILE_CODE;
|
||||
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.enclosingClass;
|
||||
@@ -10,9 +13,6 @@ import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.LinkType;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.BugPattern.StandardTags;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
@@ -29,13 +29,12 @@ import java.time.LocalTime;
|
||||
/** A {@link BugChecker} which flags illegal time-zone related operations. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
name = "TimeZoneUsage",
|
||||
summary =
|
||||
"Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone",
|
||||
linkType = LinkType.NONE,
|
||||
severity = SeverityLevel.WARNING,
|
||||
tags = StandardTags.FRAGILE_CODE)
|
||||
public final class TimeZoneUsageCheck extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
linkType = NONE,
|
||||
severity = WARNING,
|
||||
tags = FRAGILE_CODE)
|
||||
public final class TimeZoneUsage extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> BANNED_TIME_METHOD =
|
||||
anyOf(
|
||||
@@ -59,7 +58,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) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
@@ -28,7 +28,7 @@ import java.util.stream.Stream;
|
||||
* <p>This class allows one to define a whitelist or blacklist of annotations or their attributes.
|
||||
* Annotations are identified by their fully qualified name.
|
||||
*/
|
||||
final class AnnotationAttributeMatcher implements Serializable {
|
||||
public final class AnnotationAttributeMatcher implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final boolean complement;
|
||||
@@ -59,7 +59,7 @@ final class AnnotationAttributeMatcher implements Serializable {
|
||||
* @param exclusions The listed annotations or annotation attributes are not matched.
|
||||
* @return A non-{@code null} {@link AnnotationAttributeMatcher}.
|
||||
*/
|
||||
static AnnotationAttributeMatcher create(
|
||||
public static AnnotationAttributeMatcher create(
|
||||
Optional<? extends List<String>> inclusions, Iterable<String> exclusions) {
|
||||
Set<String> includedWholeTypes = new HashSet<>();
|
||||
Set<String> excludedWholeTypes = new HashSet<>();
|
||||
@@ -97,7 +97,13 @@ final class AnnotationAttributeMatcher implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
Stream<? extends ExpressionTree> extractMatchingArguments(AnnotationTree tree) {
|
||||
/**
|
||||
* Returns the subset of arguments of the given {@link AnnotationTree} matched by this instance.
|
||||
*
|
||||
* @param tree The annotation AST node to be inspected.
|
||||
* @return Any matching annotation arguments.
|
||||
*/
|
||||
public Stream<? extends ExpressionTree> extractMatchingArguments(AnnotationTree tree) {
|
||||
Type type = ASTHelpers.getType(tree.getAnnotationType());
|
||||
if (type == null) {
|
||||
return Stream.empty();
|
||||
@@ -0,0 +1,129 @@
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/** Utility class that can be used to identify reserved keywords of the Java language. */
|
||||
public final class JavaKeywords {
|
||||
/**
|
||||
* List of all reserved keywords in the Java language.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.9">JDK 17 JLS
|
||||
* section 3.9: Keywords</a>
|
||||
*/
|
||||
private static final ImmutableSet<String> RESERVED_KEYWORDS =
|
||||
ImmutableSet.of(
|
||||
"_",
|
||||
"abstract",
|
||||
"assert",
|
||||
"boolean",
|
||||
"break",
|
||||
"byte",
|
||||
"case",
|
||||
"catch",
|
||||
"char",
|
||||
"class",
|
||||
"const",
|
||||
"continue",
|
||||
"default",
|
||||
"do",
|
||||
"double",
|
||||
"else",
|
||||
"enum",
|
||||
"extends",
|
||||
"final",
|
||||
"finally",
|
||||
"float",
|
||||
"for",
|
||||
"goto",
|
||||
"if",
|
||||
"implements",
|
||||
"import",
|
||||
"instanceof",
|
||||
"int",
|
||||
"interface",
|
||||
"long",
|
||||
"native",
|
||||
"new",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"return",
|
||||
"short",
|
||||
"static",
|
||||
"strictfp",
|
||||
"super",
|
||||
"switch",
|
||||
"synchronized",
|
||||
"this",
|
||||
"throw",
|
||||
"throws",
|
||||
"transient",
|
||||
"try",
|
||||
"void",
|
||||
"volatile",
|
||||
"while");
|
||||
|
||||
/**
|
||||
* List of all contextual keywords in the Java language.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.9">JDK 17 JLS
|
||||
* section 3.9: Keywords</a>
|
||||
*/
|
||||
private static final ImmutableSet<String> CONTEXTUAL_KEYWORDS =
|
||||
ImmutableSet.of(
|
||||
"exports",
|
||||
"module",
|
||||
"non-sealed",
|
||||
"open",
|
||||
"opens",
|
||||
"permits",
|
||||
"provides",
|
||||
"record",
|
||||
"requires",
|
||||
"sealed",
|
||||
"to",
|
||||
"transitive",
|
||||
"uses",
|
||||
"var",
|
||||
"with",
|
||||
"yield");
|
||||
|
||||
/** List of all keywords in the Java language. */
|
||||
private static final ImmutableSet<String> ALL_KEYWORDS =
|
||||
Sets.union(RESERVED_KEYWORDS, CONTEXTUAL_KEYWORDS).immutableCopy();
|
||||
|
||||
private JavaKeywords() {}
|
||||
|
||||
/**
|
||||
* Tells whether the given string is a reserved keyword in the Java language.
|
||||
*
|
||||
* @param str The string of interest.
|
||||
* @return {@code true} if the given string is a reserved keyword in the Java language.
|
||||
*/
|
||||
public static boolean isReservedKeyword(String str) {
|
||||
return RESERVED_KEYWORDS.contains(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the given string is a contextual keyword in the Java language.
|
||||
*
|
||||
* @param str The string of interest.
|
||||
* @return {@code true} if the given string is a contextual keyword in the Java language.
|
||||
*/
|
||||
public static boolean isContextualKeyword(String str) {
|
||||
return CONTEXTUAL_KEYWORDS.contains(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the given string is a reserved or contextual keyword in the Java language.
|
||||
*
|
||||
* @param str The string of interest.
|
||||
* @return {@code true} if the given string is a reserved or contextual keyword in the Java
|
||||
* language.
|
||||
*/
|
||||
public static boolean isKeyword(String str) {
|
||||
return ALL_KEYWORDS.contains(str);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
@@ -15,13 +15,20 @@ import java.util.regex.Pattern;
|
||||
/** A method invocation expression {@link Matcher} factory. */
|
||||
// XXX: Document better. The expressions accepted here could also be defined using `MethodMatchers`.
|
||||
// So explain why this class is still useful.
|
||||
final class MethodMatcherFactory {
|
||||
public final class MethodMatcherFactory {
|
||||
private static final Splitter ARGUMENT_TYPE_SPLITTER =
|
||||
Splitter.on(',').trimResults().omitEmptyStrings();
|
||||
private static final Pattern METHOD_SIGNATURE =
|
||||
Pattern.compile("([^\\s#(,)]+)#([^\\s#(,)]+)\\(((?:[^\\s#(,)]+(?:,[^\\s#(,)]+)*)?)\\)");
|
||||
|
||||
Matcher<ExpressionTree> create(Collection<String> signatures) {
|
||||
/**
|
||||
* Creates a {@link Matcher} of methods with any of the given signatures.
|
||||
*
|
||||
* @param signatures The method signatures of interest.
|
||||
* @return A new {@link Matcher} which accepts invocation expressions of any method identified by
|
||||
* the given signatures.
|
||||
*/
|
||||
public Matcher<ExpressionTree> create(Collection<String> signatures) {
|
||||
return anyOf(
|
||||
signatures.stream()
|
||||
.map(MethodMatcherFactory::createMethodMatcher)
|
||||
@@ -1,19 +1,26 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.sun.source.tree.Tree;
|
||||
|
||||
/**
|
||||
* A collection of Error Prone utility methods for dealing with the source code representation of
|
||||
* AST nodes.
|
||||
*/
|
||||
// XXX: Can we locate this code in a better place? Maybe contribute it upstream?
|
||||
final class Util {
|
||||
private Util() {}
|
||||
public final class SourceCode {
|
||||
private SourceCode() {}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the given {@link Tree}, preferring the original source code
|
||||
* (if available) over its prettified representation.
|
||||
*
|
||||
* @param tree The AST node of interest.
|
||||
* @param state A {@link VisitorState} describing the context in which the given {@link Tree} is
|
||||
* found.
|
||||
* @return A non-{@code null} string.
|
||||
*/
|
||||
static String treeToString(Tree tree, VisitorState state) {
|
||||
public static String treeToString(Tree tree, VisitorState state) {
|
||||
String src = state.getSourceForNode(tree);
|
||||
return src != null ? src : tree.toString();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/** Auxiliary utilities for use by Error Prone checks. */
|
||||
@com.google.errorprone.annotations.CheckReturnValue
|
||||
@javax.annotation.ParametersAreNonnullByDefault
|
||||
package tech.picnic.errorprone.bugpatterns.util;
|
||||
@@ -8,13 +8,22 @@ import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.math.BigDecimal;
|
||||
import org.assertj.core.api.AbstractBigDecimalAssert;
|
||||
import org.assertj.core.api.BigDecimalAssert;
|
||||
|
||||
// XXX: If we add a rule which drops unnecessary `L` suffixes from literal longs, then the `0L`/`1L`
|
||||
// cases below can go.
|
||||
/**
|
||||
* Refaster templates related to AssertJ assertions over {@link BigDecimal}s.
|
||||
*
|
||||
* <p>Note that, contrary to collections of Refaster templates for other {@link
|
||||
* org.assertj.core.api.NumberAssert} subtypes, these templates do not rewrite to/from {@link
|
||||
* BigDecimalAssert#isEqualTo(Object)} and {@link BigDecimalAssert#isNotEqualTo(Object)}. This is
|
||||
* because {@link BigDecimal#equals(Object)} considers not only the numeric value of compared
|
||||
* instances, but also their scale. As a result various seemingly straightforward transformations
|
||||
* would actually subtly change the assertion's semantics.
|
||||
*/
|
||||
final class AssertJBigDecimalTemplates {
|
||||
private AssertJBigDecimalTemplates() {}
|
||||
|
||||
static final class AbstractBigDecimalAssertIsEqualTo {
|
||||
static final class AbstractBigDecimalAssertIsEqualByComparingTo {
|
||||
@BeforeTemplate
|
||||
AbstractBigDecimalAssert<?> before(AbstractBigDecimalAssert<?> bigDecimalAssert, BigDecimal n) {
|
||||
return Refaster.anyOf(
|
||||
@@ -24,11 +33,11 @@ final class AssertJBigDecimalTemplates {
|
||||
|
||||
@AfterTemplate
|
||||
AbstractBigDecimalAssert<?> after(AbstractBigDecimalAssert<?> bigDecimalAssert, BigDecimal n) {
|
||||
return bigDecimalAssert.isEqualTo(n);
|
||||
return bigDecimalAssert.isEqualByComparingTo(n);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AbstractBigDecimalAssertIsNotEqualTo {
|
||||
static final class AbstractBigDecimalAssertIsNotEqualByComparingTo {
|
||||
@BeforeTemplate
|
||||
AbstractBigDecimalAssert<?> before(AbstractBigDecimalAssert<?> bigDecimalAssert, BigDecimal n) {
|
||||
return Refaster.anyOf(
|
||||
@@ -38,52 +47,7 @@ final class AssertJBigDecimalTemplates {
|
||||
|
||||
@AfterTemplate
|
||||
AbstractBigDecimalAssert<?> after(AbstractBigDecimalAssert<?> bigDecimalAssert, BigDecimal n) {
|
||||
return bigDecimalAssert.isNotEqualTo(n);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AbstractBigDecimalAssertIsZero {
|
||||
@BeforeTemplate
|
||||
AbstractBigDecimalAssert<?> before(AbstractBigDecimalAssert<?> bigDecimalAssert) {
|
||||
return Refaster.anyOf(
|
||||
bigDecimalAssert.isZero(),
|
||||
bigDecimalAssert.isEqualTo(0L),
|
||||
bigDecimalAssert.isEqualTo(BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
AbstractBigDecimalAssert<?> after(AbstractBigDecimalAssert<?> bigDecimalAssert) {
|
||||
return bigDecimalAssert.isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AbstractBigDecimalAssertIsNotZero {
|
||||
@BeforeTemplate
|
||||
AbstractBigDecimalAssert<?> before(AbstractBigDecimalAssert<?> bigDecimalAssert) {
|
||||
return Refaster.anyOf(
|
||||
bigDecimalAssert.isNotZero(),
|
||||
bigDecimalAssert.isNotEqualTo(0L),
|
||||
bigDecimalAssert.isNotEqualTo(BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
AbstractBigDecimalAssert<?> after(AbstractBigDecimalAssert<?> bigDecimalAssert) {
|
||||
return bigDecimalAssert.isNotEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AbstractBigDecimalAssertIsOne {
|
||||
@BeforeTemplate
|
||||
AbstractBigDecimalAssert<?> before(AbstractBigDecimalAssert<?> bigDecimalAssert) {
|
||||
return Refaster.anyOf(
|
||||
bigDecimalAssert.isOne(),
|
||||
bigDecimalAssert.isEqualTo(1L),
|
||||
bigDecimalAssert.isEqualTo(BigDecimal.ONE));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
AbstractBigDecimalAssert<?> after(AbstractBigDecimalAssert<?> bigDecimalAssert) {
|
||||
return bigDecimalAssert.isEqualTo(1);
|
||||
return bigDecimalAssert.isNotEqualByComparingTo(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -59,7 +59,7 @@ final class AssertJBooleanTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractBooleanAssert<?> after(boolean b) {
|
||||
return assertThat(b).isTrue();
|
||||
}
|
||||
@@ -88,7 +88,7 @@ final class AssertJBooleanTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractBooleanAssert<?> after(boolean b) {
|
||||
return assertThat(b).isFalse();
|
||||
}
|
||||
|
||||
@@ -15,11 +15,7 @@ final class AssertJByteTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractByteAssert<?> before(AbstractByteAssert<?> byteAssert, byte n) {
|
||||
return Refaster.anyOf(
|
||||
byteAssert.isCloseTo(n, offset((byte) 0)),
|
||||
byteAssert.isCloseTo(Byte.valueOf(n), offset((byte) 0)),
|
||||
byteAssert.isCloseTo(n, withPercentage(0)),
|
||||
byteAssert.isCloseTo(Byte.valueOf(n), withPercentage(0)),
|
||||
byteAssert.isEqualTo(Byte.valueOf(n)));
|
||||
byteAssert.isCloseTo(n, offset((byte) 0)), byteAssert.isCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -33,10 +29,7 @@ final class AssertJByteTemplates {
|
||||
AbstractByteAssert<?> before(AbstractByteAssert<?> byteAssert, byte n) {
|
||||
return Refaster.anyOf(
|
||||
byteAssert.isNotCloseTo(n, offset((byte) 0)),
|
||||
byteAssert.isNotCloseTo(Byte.valueOf(n), offset((byte) 0)),
|
||||
byteAssert.isNotCloseTo(n, withPercentage(0)),
|
||||
byteAssert.isNotCloseTo(Byte.valueOf(n), withPercentage(0)),
|
||||
byteAssert.isNotEqualTo(Byte.valueOf(n)));
|
||||
byteAssert.isNotCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -21,7 +21,7 @@ final class AssertJCharSequenceTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(CharSequence charSequence) {
|
||||
assertThat(charSequence).isEmpty();
|
||||
}
|
||||
@@ -36,7 +36,7 @@ final class AssertJCharSequenceTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractAssert<?, ?> after(CharSequence charSequence) {
|
||||
return assertThat(charSequence).isNotEmpty();
|
||||
}
|
||||
@@ -49,7 +49,7 @@ final class AssertJCharSequenceTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractAssert<?, ?> after(CharSequence charSequence, int length) {
|
||||
return assertThat(charSequence).hasSize(length);
|
||||
}
|
||||
|
||||
@@ -36,11 +36,7 @@ final class AssertJDoubleTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractDoubleAssert<?> before(AbstractDoubleAssert<?> doubleAssert, double n) {
|
||||
return Refaster.anyOf(
|
||||
doubleAssert.isCloseTo(n, offset(0.0)),
|
||||
doubleAssert.isCloseTo(Double.valueOf(n), offset(0.0)),
|
||||
doubleAssert.isCloseTo(n, withPercentage(0.0)),
|
||||
doubleAssert.isCloseTo(Double.valueOf(n), withPercentage(0.0)),
|
||||
doubleAssert.isEqualTo(Double.valueOf(n)));
|
||||
doubleAssert.isCloseTo(n, offset(0.0)), doubleAssert.isCloseTo(n, withPercentage(0.0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -54,10 +50,7 @@ final class AssertJDoubleTemplates {
|
||||
AbstractDoubleAssert<?> before(AbstractDoubleAssert<?> doubleAssert, double n) {
|
||||
return Refaster.anyOf(
|
||||
doubleAssert.isNotCloseTo(n, offset(0.0)),
|
||||
doubleAssert.isNotCloseTo(Double.valueOf(n), offset(0.0)),
|
||||
doubleAssert.isNotCloseTo(n, withPercentage(0.0)),
|
||||
doubleAssert.isNotCloseTo(Double.valueOf(n), withPercentage(0.0)),
|
||||
doubleAssert.isNotEqualTo(Double.valueOf(n)));
|
||||
doubleAssert.isNotCloseTo(n, withPercentage(0.0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
|
||||
@@ -36,11 +36,7 @@ final class AssertJFloatTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractFloatAssert<?> before(AbstractFloatAssert<?> floatAssert, float n) {
|
||||
return Refaster.anyOf(
|
||||
floatAssert.isCloseTo(n, offset(0F)),
|
||||
floatAssert.isCloseTo(Float.valueOf(n), offset(0F)),
|
||||
floatAssert.isCloseTo(n, withPercentage(0)),
|
||||
floatAssert.isCloseTo(Float.valueOf(n), withPercentage(0)),
|
||||
floatAssert.isEqualTo(Float.valueOf(n)));
|
||||
floatAssert.isCloseTo(n, offset(0F)), floatAssert.isCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -53,11 +49,7 @@ final class AssertJFloatTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractFloatAssert<?> before(AbstractFloatAssert<?> floatAssert, float n) {
|
||||
return Refaster.anyOf(
|
||||
floatAssert.isNotCloseTo(n, offset(0F)),
|
||||
floatAssert.isNotCloseTo(Float.valueOf(n), offset(0F)),
|
||||
floatAssert.isNotCloseTo(n, withPercentage(0)),
|
||||
floatAssert.isNotCloseTo(Float.valueOf(n), withPercentage(0)),
|
||||
floatAssert.isNotEqualTo(Float.valueOf(n)));
|
||||
floatAssert.isNotCloseTo(n, offset(0F)), floatAssert.isNotCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
|
||||
@@ -15,11 +15,7 @@ final class AssertJIntegerTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before(AbstractIntegerAssert<?> intAssert, int n) {
|
||||
return Refaster.anyOf(
|
||||
intAssert.isCloseTo(n, offset(0)),
|
||||
intAssert.isCloseTo(Integer.valueOf(n), offset(0)),
|
||||
intAssert.isCloseTo(n, withPercentage(0)),
|
||||
intAssert.isCloseTo(Integer.valueOf(n), withPercentage(0)),
|
||||
intAssert.isEqualTo(Integer.valueOf(n)));
|
||||
intAssert.isCloseTo(n, offset(0)), intAssert.isCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -32,11 +28,7 @@ final class AssertJIntegerTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before(AbstractIntegerAssert<?> intAssert, int n) {
|
||||
return Refaster.anyOf(
|
||||
intAssert.isNotCloseTo(n, offset(0)),
|
||||
intAssert.isNotCloseTo(Integer.valueOf(n), offset(0)),
|
||||
intAssert.isNotCloseTo(n, withPercentage(0)),
|
||||
intAssert.isNotCloseTo(Integer.valueOf(n), withPercentage(0)),
|
||||
intAssert.isNotEqualTo(Integer.valueOf(n)));
|
||||
intAssert.isNotCloseTo(n, offset(0)), intAssert.isNotCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
|
||||
@@ -15,11 +15,7 @@ final class AssertJLongTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractLongAssert<?> before(AbstractLongAssert<?> longAssert, long n) {
|
||||
return Refaster.anyOf(
|
||||
longAssert.isCloseTo(n, offset(0L)),
|
||||
longAssert.isCloseTo(Long.valueOf(n), offset(0L)),
|
||||
longAssert.isCloseTo(n, withPercentage(0)),
|
||||
longAssert.isCloseTo(Long.valueOf(n), withPercentage(0)),
|
||||
longAssert.isEqualTo(Long.valueOf(n)));
|
||||
longAssert.isCloseTo(n, offset(0L)), longAssert.isCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -32,11 +28,7 @@ final class AssertJLongTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractLongAssert<?> before(AbstractLongAssert<?> longAssert, long n) {
|
||||
return Refaster.anyOf(
|
||||
longAssert.isNotCloseTo(n, offset(0L)),
|
||||
longAssert.isNotCloseTo(Long.valueOf(n), offset(0L)),
|
||||
longAssert.isNotCloseTo(n, withPercentage(0)),
|
||||
longAssert.isNotCloseTo(Long.valueOf(n), withPercentage(0)),
|
||||
longAssert.isNotEqualTo(Long.valueOf(n)));
|
||||
longAssert.isNotCloseTo(n, offset(0L)), longAssert.isNotCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.util.Map;
|
||||
import org.assertj.core.api.AbstractMapAssert;
|
||||
|
||||
final class AssertJMapTemplates {
|
||||
private AssertJMapTemplates() {}
|
||||
|
||||
static final class AbstractMapAssertContainsExactlyInAnyOrderEntriesOf<K, V> {
|
||||
@BeforeTemplate
|
||||
AbstractMapAssert<?, ?, K, V> before(AbstractMapAssert<?, ?, K, V> mapAssert, Map<K, V> map) {
|
||||
return mapAssert.isEqualTo(map);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
AbstractMapAssert<?, ?, K, V> after(AbstractMapAssert<?, ?, K, V> mapAssert, Map<K, V> map) {
|
||||
return mapAssert.containsExactlyInAnyOrderEntriesOf(map);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AbstractMapAssertContainsExactlyEntriesOf<K, V> {
|
||||
@BeforeTemplate
|
||||
AbstractMapAssert<?, ?, K, V> before(AbstractMapAssert<?, ?, K, V> mapAssert, K key, V value) {
|
||||
return mapAssert.containsExactlyInAnyOrderEntriesOf(ImmutableMap.of(key, value));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
AbstractMapAssert<?, ?, K, V> after(AbstractMapAssert<?, ?, K, V> mapAssert, K key, V value) {
|
||||
return mapAssert.containsExactlyEntriesOf(ImmutableMap.of(key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import org.assertj.core.api.AbstractBigDecimalAssert;
|
||||
@@ -18,7 +22,7 @@ import org.assertj.core.api.NumberAssert;
|
||||
final class AssertJNumberTemplates {
|
||||
private AssertJNumberTemplates() {}
|
||||
|
||||
static final class NumberIsPositive {
|
||||
static final class NumberAssertIsPositive {
|
||||
@BeforeTemplate
|
||||
AbstractByteAssert<?> before(AbstractByteAssert<?> numberAssert) {
|
||||
return Refaster.anyOf(
|
||||
@@ -69,7 +73,7 @@ final class AssertJNumberTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
static final class NumberIsNotPositive {
|
||||
static final class NumberAssertIsNotPositive {
|
||||
@BeforeTemplate
|
||||
AbstractByteAssert<?> before(AbstractByteAssert<?> numberAssert) {
|
||||
return Refaster.anyOf(
|
||||
@@ -120,7 +124,7 @@ final class AssertJNumberTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
static final class NumberIsNegative {
|
||||
static final class NumberAssertIsNegative {
|
||||
@BeforeTemplate
|
||||
AbstractByteAssert<?> before(AbstractByteAssert<?> numberAssert) {
|
||||
return Refaster.anyOf(
|
||||
@@ -171,7 +175,7 @@ final class AssertJNumberTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
static final class NumberIsNotNegative {
|
||||
static final class NumberAssertIsNotNegative {
|
||||
@BeforeTemplate
|
||||
AbstractByteAssert<?> before(AbstractByteAssert<?> numberAssert) {
|
||||
return Refaster.anyOf(
|
||||
@@ -221,4 +225,40 @@ final class AssertJNumberTemplates {
|
||||
return numberAssert.isNotNegative();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsOdd {
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before(int number) {
|
||||
return assertThat(number % 2).isEqualTo(1);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
AbstractLongAssert<?> before(long number) {
|
||||
return assertThat(number % 2).isEqualTo(1);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
NumberAssert<?, ?> after(long number) {
|
||||
return assertThat(number).isOdd();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsEven {
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before(int number) {
|
||||
return assertThat(number % 2).isEqualTo(0);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
AbstractLongAssert<?> before(long number) {
|
||||
return assertThat(number % 2).isEqualTo(0);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
NumberAssert<?, ?> after(long number) {
|
||||
return assertThat(number).isEven();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -21,7 +21,7 @@ final class AssertJObjectTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ObjectAssert<S> after(S object) {
|
||||
return assertThat(object).isInstanceOf(Refaster.<T>clazz());
|
||||
}
|
||||
@@ -34,7 +34,7 @@ final class AssertJObjectTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ObjectAssert<S> after(S object) {
|
||||
return assertThat(object).isNotInstanceOf(Refaster.<T>clazz());
|
||||
}
|
||||
@@ -47,7 +47,7 @@ final class AssertJObjectTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ObjectAssert<S> after(S object1, T object2) {
|
||||
return assertThat(object1).isEqualTo(object2);
|
||||
}
|
||||
@@ -60,7 +60,7 @@ final class AssertJObjectTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ObjectAssert<S> after(S object1, T object2) {
|
||||
return assertThat(object1).isNotEqualTo(object2);
|
||||
}
|
||||
@@ -73,7 +73,7 @@ final class AssertJObjectTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ObjectAssert<T> after(T object, String str) {
|
||||
return assertThat(object).hasToString(str);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -26,7 +26,7 @@ final class AssertJOptionalTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, T> after(Optional<T> optional) {
|
||||
return assertThat(optional).get();
|
||||
}
|
||||
@@ -53,7 +53,7 @@ final class AssertJOptionalTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
OptionalAssert<T> after(Optional<T> optional) {
|
||||
return assertThat(optional).isPresent();
|
||||
}
|
||||
@@ -80,7 +80,7 @@ final class AssertJOptionalTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
OptionalAssert<T> after(Optional<T> optional) {
|
||||
return assertThat(optional).isEmpty();
|
||||
}
|
||||
@@ -122,7 +122,7 @@ final class AssertJOptionalTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, T> after(Optional<T> optional, Predicate<? super T> predicate) {
|
||||
return assertThat(optional).get().matches(predicate);
|
||||
}
|
||||
|
||||
@@ -15,11 +15,7 @@ final class AssertJShortTemplates {
|
||||
@BeforeTemplate
|
||||
AbstractShortAssert<?> before(AbstractShortAssert<?> shortAssert, short n) {
|
||||
return Refaster.anyOf(
|
||||
shortAssert.isCloseTo(n, offset((short) 0)),
|
||||
shortAssert.isCloseTo(Short.valueOf(n), offset((short) 0)),
|
||||
shortAssert.isCloseTo(n, withPercentage(0)),
|
||||
shortAssert.isCloseTo(Short.valueOf(n), withPercentage(0)),
|
||||
shortAssert.isEqualTo(Short.valueOf(n)));
|
||||
shortAssert.isCloseTo(n, offset((short) 0)), shortAssert.isCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -33,10 +29,7 @@ final class AssertJShortTemplates {
|
||||
AbstractShortAssert<?> before(AbstractShortAssert<?> shortAssert, short n) {
|
||||
return Refaster.anyOf(
|
||||
shortAssert.isNotCloseTo(n, offset((short) 0)),
|
||||
shortAssert.isNotCloseTo(Short.valueOf(n), offset((short) 0)),
|
||||
shortAssert.isNotCloseTo(n, withPercentage(0)),
|
||||
shortAssert.isNotCloseTo(Short.valueOf(n), withPercentage(0)),
|
||||
shortAssert.isNotEqualTo(Short.valueOf(n)));
|
||||
shortAssert.isNotCloseTo(n, withPercentage(0)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
@@ -31,7 +31,7 @@ final class AssertJStringTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(String string) {
|
||||
assertThat(string).isEmpty();
|
||||
}
|
||||
@@ -56,9 +56,35 @@ final class AssertJStringTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractAssert<?, ?> after(String string) {
|
||||
return assertThat(string).isNotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatMatches {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(String string, String regex) {
|
||||
return assertThat(string.matches(regex)).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractAssert<?, ?> after(String string, String regex) {
|
||||
return assertThat(string).matches(regex);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatDoesNotMatch {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(String string, String regex) {
|
||||
return assertThat(string.matches(regex)).isFalse();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractAssert<?, ?> after(String string, String regex) {
|
||||
return assertThat(string).doesNotMatch(regex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
@@ -12,7 +13,6 @@ import com.google.common.collect.ImmutableSortedMultiset;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -39,6 +39,7 @@ import java.util.stream.Collector;
|
||||
import java.util.stream.Stream;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractBooleanAssert;
|
||||
import org.assertj.core.api.AbstractCollectionAssert;
|
||||
import org.assertj.core.api.AbstractComparableAssert;
|
||||
import org.assertj.core.api.AbstractDoubleAssert;
|
||||
import org.assertj.core.api.AbstractIntegerAssert;
|
||||
@@ -96,7 +97,6 @@ import tech.picnic.errorprone.refaster.util.IsArray;
|
||||
// XXX: Right now we use and import `Offset.offset` and `Percentage.withPercentage`. Use the AssertJ
|
||||
// methods instead. (Also in the TestNG migration.)
|
||||
// ^ Also for `Tuple`!
|
||||
// XXX: Use `assertThatIllegalArgumentException` and variants.
|
||||
// XXX: `assertThatCode(x).isInstanceOf(clazz)` -> `assertThatThrownBy(x).isInstanceOf(clazz)`
|
||||
// (etc.)
|
||||
// XXX: Look into using Assertions#contentOf(URL url, Charset charset) instead of our own test
|
||||
@@ -136,7 +136,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
OptionalDoubleAssert after(OptionalDouble optional, double expected) {
|
||||
return assertThat(optional).hasValue(expected);
|
||||
}
|
||||
@@ -155,7 +155,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
OptionalIntAssert after(OptionalInt optional, int expected) {
|
||||
return assertThat(optional).hasValue(expected);
|
||||
}
|
||||
@@ -174,7 +174,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
OptionalLongAssert after(OptionalLong optional, long expected) {
|
||||
return assertThat(optional).hasValue(expected);
|
||||
}
|
||||
@@ -364,6 +364,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ObjectEnumerableAssert<?, S> after(Set<S> set, T element) {
|
||||
return assertThat(set).containsExactly(element);
|
||||
}
|
||||
@@ -428,7 +429,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Collection<E> iterable) {
|
||||
assertThat(iterable).isEmpty();
|
||||
}
|
||||
@@ -452,7 +453,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<E> after(Iterable<E> iterable) {
|
||||
return assertThat(iterable).isNotEmpty();
|
||||
}
|
||||
@@ -470,7 +471,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<E> after(Iterable<E> iterable, int length) {
|
||||
return assertThat(iterable).hasSize(length);
|
||||
}
|
||||
@@ -483,7 +484,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<S> after(Iterable<S> iterable, T element) {
|
||||
return assertThat(iterable).containsExactly(element);
|
||||
}
|
||||
@@ -500,7 +501,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<S> after(Iterable<S> iterable, T element) {
|
||||
return assertThat(iterable).containsExactly(element);
|
||||
}
|
||||
@@ -517,7 +518,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(List<S> list1, List<T> list2) {
|
||||
return assertThat(list1).containsExactlyElementsOf(list2);
|
||||
}
|
||||
@@ -529,15 +530,15 @@ final class AssertJTemplates {
|
||||
|
||||
static final class AssertThatSetsAreEqual<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
IterableAssert<S> before(Set<S> set1, Set<T> set2) {
|
||||
AbstractCollectionAssert<?, ?, S, ?> before(Set<S> set1, Set<T> set2) {
|
||||
return Refaster.anyOf(
|
||||
assertThat(set1).isEqualTo(set2),
|
||||
assertThat(set1).containsExactlyInAnyOrderElementsOf(set2));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<S> after(Set<S> set1, Set<T> set2) {
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractCollectionAssert<?, ?, S, ?> after(Set<S> set1, Set<T> set2) {
|
||||
return assertThat(set1).hasSameElementsAs(set2);
|
||||
}
|
||||
}
|
||||
@@ -548,13 +549,13 @@ final class AssertJTemplates {
|
||||
|
||||
static final class AssertThatMultisetsAreEqual<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
IterableAssert<S> before(Multiset<S> multiset1, Multiset<T> multiset2) {
|
||||
AbstractCollectionAssert<?, ?, S, ?> before(Multiset<S> multiset1, Multiset<T> multiset2) {
|
||||
return assertThat(multiset1).isEqualTo(multiset2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<S> after(Multiset<S> multiset1, Multiset<T> multiset2) {
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractCollectionAssert<?, ?, S, ?> after(Multiset<S> multiset1, Multiset<T> multiset2) {
|
||||
return assertThat(multiset1).containsExactlyInAnyOrderElementsOf(multiset2);
|
||||
}
|
||||
}
|
||||
@@ -631,7 +632,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Map<K, V> map) {
|
||||
assertThat(map).isEmpty();
|
||||
}
|
||||
@@ -668,7 +669,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
MapAssert<K, V> after(Map<K, V> map) {
|
||||
return assertThat(map).isNotEmpty();
|
||||
}
|
||||
@@ -683,7 +684,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
MapAssert<K, V> after(Map<K, V> map, int length) {
|
||||
return assertThat(map).hasSize(length);
|
||||
}
|
||||
@@ -697,7 +698,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
MapAssert<K, V> after(Map<K, V> map1, Map<K, V> map2) {
|
||||
return assertThat(map1).hasSameSizeAs(map2);
|
||||
}
|
||||
@@ -711,7 +712,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
MapAssert<K, V> after(Map<K, V> map, K key) {
|
||||
return assertThat(map).containsKey(key);
|
||||
}
|
||||
@@ -724,7 +725,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
MapAssert<K, V> after(Map<K, V> map, K key) {
|
||||
return assertThat(map).doesNotContainKey(key);
|
||||
}
|
||||
@@ -737,7 +738,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
MapAssert<K, V> after(Map<K, V> map, K key, V value) {
|
||||
return assertThat(map).containsEntry(key, value);
|
||||
}
|
||||
@@ -762,7 +763,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).containsAnyElementsOf(iterable);
|
||||
}
|
||||
@@ -783,7 +784,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, U[] array) {
|
||||
return assertThat(stream).containsAnyOf(array);
|
||||
}
|
||||
@@ -807,7 +808,7 @@ final class AssertJTemplates {
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("ObjectEnumerableContainsOneElement" /* Not a true singleton. */)
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).containsAnyOf(elements);
|
||||
}
|
||||
@@ -828,7 +829,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).containsAll(iterable);
|
||||
}
|
||||
@@ -849,7 +850,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, U[] array) {
|
||||
return assertThat(stream).contains(array);
|
||||
}
|
||||
@@ -872,7 +873,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).contains(elements);
|
||||
}
|
||||
@@ -887,7 +888,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).containsExactlyElementsOf(iterable);
|
||||
}
|
||||
@@ -902,7 +903,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, U[] array) {
|
||||
return assertThat(stream).containsExactly(array);
|
||||
}
|
||||
@@ -918,7 +919,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).containsExactly(elements);
|
||||
}
|
||||
@@ -934,13 +935,13 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
IterableAssert<T> before2(
|
||||
AbstractCollectionAssert<?, ?, T, ?> before2(
|
||||
Stream<S> stream, Collector<S, ?, ? extends Multiset<T>> collector, Iterable<U> iterable) {
|
||||
return assertThat(stream.collect(collector)).containsExactlyInAnyOrderElementsOf(iterable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).containsExactlyInAnyOrderElementsOf(iterable);
|
||||
}
|
||||
@@ -955,13 +956,13 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
IterableAssert<T> before2(
|
||||
AbstractCollectionAssert<?, ?, T, ?> before2(
|
||||
Stream<S> stream, Collector<S, ?, ? extends Multiset<T>> collector, U[] array) {
|
||||
return assertThat(stream.collect(collector)).containsExactlyInAnyOrder(array);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, U[] array) {
|
||||
return assertThat(stream).containsExactlyInAnyOrder(array);
|
||||
}
|
||||
@@ -979,7 +980,7 @@ final class AssertJTemplates {
|
||||
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatStreamContainsExactlyInAnyOrder" /* Varargs converted to array. */)
|
||||
IterableAssert<T> before2(
|
||||
AbstractCollectionAssert<?, ?, T, ?> before2(
|
||||
Stream<S> stream, Collector<S, ?, ? extends Multiset<T>> collector, @Repeated U elements) {
|
||||
return assertThat(stream.collect(collector))
|
||||
.containsExactlyInAnyOrder(Refaster.asVarargs(elements));
|
||||
@@ -987,7 +988,7 @@ final class AssertJTemplates {
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("ObjectEnumerableContainsExactlyOneElement" /* Not a true singleton. */)
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).containsExactlyInAnyOrder(elements);
|
||||
}
|
||||
@@ -1008,7 +1009,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).containsSequence(iterable);
|
||||
}
|
||||
@@ -1025,7 +1026,7 @@ final class AssertJTemplates {
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("ObjectEnumerableContainsOneElement" /* Not a true singleton. */)
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).containsSequence(elements);
|
||||
}
|
||||
@@ -1046,7 +1047,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).containsSubsequence(iterable);
|
||||
}
|
||||
@@ -1064,7 +1065,7 @@ final class AssertJTemplates {
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("ObjectEnumerableContainsOneElement" /* Not a true singleton. */)
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).containsSubsequence(elements);
|
||||
}
|
||||
@@ -1085,7 +1086,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).doesNotContainAnyElementsOf(iterable);
|
||||
}
|
||||
@@ -1106,7 +1107,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, U[] array) {
|
||||
return assertThat(stream).doesNotContain(array);
|
||||
}
|
||||
@@ -1129,7 +1130,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).doesNotContain(elements);
|
||||
}
|
||||
@@ -1150,7 +1151,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).doesNotContainSequence(iterable);
|
||||
}
|
||||
@@ -1168,7 +1169,7 @@ final class AssertJTemplates {
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("ObjectEnumerableDoesNotContainOneElement" /* Not a true singleton. */)
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).doesNotContainSequence(elements);
|
||||
}
|
||||
@@ -1189,7 +1190,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, Iterable<U> iterable) {
|
||||
return assertThat(stream).hasSameElementsAs(iterable);
|
||||
}
|
||||
@@ -1210,7 +1211,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, U[] array) {
|
||||
return assertThat(stream).containsOnly(array);
|
||||
}
|
||||
@@ -1233,7 +1234,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).containsOnly(elements);
|
||||
}
|
||||
@@ -1266,7 +1267,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, U[] iterable) {
|
||||
return assertThat(stream).isSubsetOf(iterable);
|
||||
}
|
||||
@@ -1289,7 +1290,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
|
||||
return assertThat(stream).isSubsetOf(elements);
|
||||
}
|
||||
@@ -1308,7 +1309,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Stream<S> stream) {
|
||||
assertThat(stream).isEmpty();
|
||||
}
|
||||
@@ -1327,7 +1328,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Stream<S> stream) {
|
||||
assertThat(stream).isNotEmpty();
|
||||
}
|
||||
@@ -1340,7 +1341,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Stream<T> stream, int size) {
|
||||
assertThat(stream).hasSize(size);
|
||||
}
|
||||
@@ -1357,7 +1358,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Predicate<T> predicate, T object) {
|
||||
assertThat(predicate).accepts(object);
|
||||
}
|
||||
@@ -1370,7 +1371,7 @@ final class AssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Predicate<T> predicate, T object) {
|
||||
assertThat(predicate).rejects(object);
|
||||
}
|
||||
@@ -2211,7 +2212,7 @@ final class AssertJTemplates {
|
||||
// }
|
||||
//
|
||||
// @AfterTemplate
|
||||
// @UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
// @UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
// IterableAssert<E> after(Iterable<E> iterable, E expected) {
|
||||
// return assertThat(iterable).containsExactly(expected);
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,445 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIOException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.io.IOException;
|
||||
import org.assertj.core.api.AbstractObjectAssert;
|
||||
import org.assertj.core.api.AbstractThrowableAssert;
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
|
||||
/**
|
||||
* Refaster templates related to AssertJ assertions over expressions that may throw a {@link
|
||||
* Throwable} subtype.
|
||||
*
|
||||
* <p>For reasons of consistency we prefer {@link
|
||||
* org.assertj.core.api.Assertions#assertThatThrownBy} over static methods for specific exception
|
||||
* types. Note that only the most common assertion expressions are rewritten here; covering all
|
||||
* cases would require the implementation of an Error Prone check instead.
|
||||
*/
|
||||
final class AssertJThrowingCallableTemplates {
|
||||
private AssertJThrowingCallableTemplates() {}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentException {
|
||||
@BeforeTemplate
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable) {
|
||||
return assertThatIllegalArgumentException().isThrownBy(throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable) {
|
||||
return assertThatThrownBy(throwingCallable).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentExceptionHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalArgumentException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalArgumentException().isThrownBy(throwingCallable).withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentExceptionHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalArgumentException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable, String message, @Repeated Object parameters) {
|
||||
return assertThatIllegalArgumentException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessage(message, parameters);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
ThrowingCallable throwingCallable, String message, @Repeated Object parameters) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage(message, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentExceptionHasMessageStartingWith {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalArgumentException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalArgumentException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessageStartingWith(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageStartingWith(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentExceptionHasMessageContaining {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalArgumentException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalArgumentException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessageContaining(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentExceptionHasMessageNotContainingAny {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalArgumentException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable, @Repeated CharSequence values) {
|
||||
return assertThatIllegalArgumentException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessageNotContainingAny(values);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
ThrowingCallable throwingCallable, @Repeated CharSequence values) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageNotContainingAny(values);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalStateException {
|
||||
@BeforeTemplate
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable) {
|
||||
return assertThatIllegalStateException().isThrownBy(throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable) {
|
||||
return assertThatThrownBy(throwingCallable).isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalStateExceptionHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalStateException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalStateException().isThrownBy(throwingCallable).withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalStateExceptionHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalStateException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable, String message, @Repeated Object parameters) {
|
||||
return assertThatIllegalStateException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessage(message, parameters);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
ThrowingCallable throwingCallable, String message, @Repeated Object parameters) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage(message, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalStateExceptionHasMessageStartingWith {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalStateException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalStateException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessageStartingWith(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageStartingWith(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalStateExceptionHasMessageContaining {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalStateException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalStateException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessageContaining(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalStateExceptionHasMessageNotContaining {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalStateException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalStateException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessageNotContaining(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageNotContaining(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByNullPointerException {
|
||||
@BeforeTemplate
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable) {
|
||||
return assertThatNullPointerException().isThrownBy(throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable) {
|
||||
return assertThatThrownBy(throwingCallable).isInstanceOf(NullPointerException.class);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByNullPointerExceptionHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByNullPointerException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatNullPointerException().isThrownBy(throwingCallable).withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByNullPointerExceptionHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByNullPointerException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable, String message, @Repeated Object parameters) {
|
||||
return assertThatNullPointerException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessage(message, parameters);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
ThrowingCallable throwingCallable, String message, @Repeated Object parameters) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
.hasMessage(message, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByNullPointerExceptionHasMessageStartingWith {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByNullPointerException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatNullPointerException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessageStartingWith(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
.hasMessageStartingWith(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIOException {
|
||||
@BeforeTemplate
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable) {
|
||||
return assertThatIOException().isThrownBy(throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable) {
|
||||
return assertThatThrownBy(throwingCallable).isInstanceOf(IOException.class);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIOExceptionHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIOException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIOException().isThrownBy(throwingCallable).withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IOException.class)
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIOExceptionHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIOException" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable, String message, @Repeated Object parameters) {
|
||||
return assertThatIOException().isThrownBy(throwingCallable).withMessage(message, parameters);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
ThrowingCallable throwingCallable, String message, @Repeated Object parameters) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IOException.class)
|
||||
.hasMessage(message, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownBy {
|
||||
@BeforeTemplate
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
Class<? extends Throwable> exceptionType, ThrowingCallable throwingCallable) {
|
||||
return assertThatExceptionOfType(exceptionType).isThrownBy(throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
Class<? extends Throwable> exceptionType, ThrowingCallable throwingCallable) {
|
||||
return assertThatThrownBy(throwingCallable).isInstanceOf(exceptionType);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatThrownBy" /* Matches strictly more specific expressions. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
Class<? extends Throwable> exceptionType,
|
||||
ThrowingCallable throwingCallable,
|
||||
String message) {
|
||||
return assertThatExceptionOfType(exceptionType)
|
||||
.isThrownBy(throwingCallable)
|
||||
.withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
Class<? extends Throwable> exceptionType,
|
||||
ThrowingCallable throwingCallable,
|
||||
String message) {
|
||||
return assertThatThrownBy(throwingCallable).isInstanceOf(exceptionType).hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Drop this template in favour of a generic Error Prone check which flags
|
||||
// `String.format(...)` arguments to a wide range of format methods.
|
||||
static final class AbstractThrowableAssertHasMessage {
|
||||
@BeforeTemplate
|
||||
AbstractThrowableAssert<?, ? extends Throwable> before(
|
||||
AbstractThrowableAssert<?, ? extends Throwable> abstractThrowableAssert,
|
||||
String message,
|
||||
@Repeated Object parameters) {
|
||||
return abstractThrowableAssert.hasMessage(String.format(message, parameters));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
AbstractThrowableAssert<?, ? extends Throwable> after(
|
||||
AbstractThrowableAssert<?, ? extends Throwable> abstractThrowableAssert,
|
||||
String message,
|
||||
@Repeated Object parameters) {
|
||||
return abstractThrowableAssert.hasMessage(message, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Drop this template in favour of a generic Error Prone check which flags
|
||||
// `String.format(...)` arguments to a wide range of format methods.
|
||||
static final class AbstractThrowableAssertWithFailMessage {
|
||||
@BeforeTemplate
|
||||
AbstractThrowableAssert<?, ? extends Throwable> before(
|
||||
AbstractThrowableAssert<?, ? extends Throwable> abstractThrowableAssert,
|
||||
String message,
|
||||
@Repeated Object args) {
|
||||
return abstractThrowableAssert.withFailMessage(String.format(message, args));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
AbstractThrowableAssert<?, ? extends Throwable> after(
|
||||
AbstractThrowableAssert<?, ? extends Throwable> abstractThrowableAssert,
|
||||
String message,
|
||||
@Repeated Object args) {
|
||||
return abstractThrowableAssert.withFailMessage(message, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package tech.picnic.errorprone.refastertemplates;
|
||||
import static com.google.common.base.Preconditions.checkElementIndex;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Sets.toImmutableEnumSet;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Collections.disjoint;
|
||||
import static java.util.Objects.checkIndex;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
@@ -11,7 +13,6 @@ import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -92,7 +93,7 @@ final class AssortedTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableSet<T> after(Stream<T> stream) {
|
||||
return stream.collect(toImmutableEnumSet());
|
||||
}
|
||||
@@ -162,7 +163,7 @@ final class AssortedTemplates {
|
||||
|
||||
@AfterTemplate
|
||||
boolean after(Set<T> set1, Set<T> set2) {
|
||||
return Collections.disjoint(set1, set2);
|
||||
return disjoint(set1, set2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,15 +178,15 @@ final class AssortedTemplates {
|
||||
@BeforeTemplate
|
||||
boolean before(Collection<T> collection1, Collection<T> collection2) {
|
||||
return Refaster.anyOf(
|
||||
Collections.disjoint(ImmutableSet.copyOf(collection1), collection2),
|
||||
Collections.disjoint(new HashSet<>(collection1), collection2),
|
||||
Collections.disjoint(collection1, ImmutableSet.copyOf(collection2)),
|
||||
Collections.disjoint(collection1, new HashSet<>(collection2)));
|
||||
disjoint(ImmutableSet.copyOf(collection1), collection2),
|
||||
disjoint(new HashSet<>(collection1), collection2),
|
||||
disjoint(collection1, ImmutableSet.copyOf(collection2)),
|
||||
disjoint(collection1, new HashSet<>(collection2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
boolean after(Collection<T> collection1, Collection<T> collection2) {
|
||||
return Collections.disjoint(collection1, collection2);
|
||||
return disjoint(collection1, collection2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.stream.Stream;
|
||||
@@ -129,31 +130,32 @@ final class CollectionTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
static final class CollectionRemoveAllFromCollectionBlock<T, S extends T> {
|
||||
static final class SetRemoveAllCollection<T, S extends T> {
|
||||
@BeforeTemplate
|
||||
void before(Collection<T> removeTo, Collection<S> elementsToRemove) {
|
||||
elementsToRemove.forEach(removeTo::remove);
|
||||
void before(Set<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
elementsToRemove.forEach(removeFrom::remove);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before2(Collection<T> removeTo, Collection<S> elementsToRemove) {
|
||||
void before2(Set<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
for (T element : elementsToRemove) {
|
||||
removeTo.remove(element);
|
||||
removeFrom.remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: This method is identical to `before2` except for the loop type. Make Refaster smarter so
|
||||
// that this is supported out of the box.
|
||||
// that this is supported out of the box. After doing so, also drop the `S extends T` type
|
||||
// constraint; ideally this check applies to any `S`.
|
||||
@BeforeTemplate
|
||||
void before3(Collection<T> removeTo, Collection<S> elementsToRemove) {
|
||||
void before3(Set<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
for (S element : elementsToRemove) {
|
||||
removeTo.remove(element);
|
||||
removeFrom.remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Collection<T> removeTo, Collection<S> elementsToRemove) {
|
||||
removeTo.removeAll(elementsToRemove);
|
||||
void after(Set<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
removeFrom.removeAll(elementsToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +189,7 @@ final class CollectionTemplates {
|
||||
* Don't call {@link ImmutableCollection#asList()} if the result is going to be streamed; stream
|
||||
* directly.
|
||||
*/
|
||||
static final class ImmutableCollectionAsListToStream<T> {
|
||||
static final class ImmutableCollectionStream<T> {
|
||||
@BeforeTemplate
|
||||
Stream<T> before(ImmutableCollection<T> collection) {
|
||||
return collection.asList().stream();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Comparator.comparing;
|
||||
import static java.util.Comparator.comparingDouble;
|
||||
import static java.util.Comparator.comparingInt;
|
||||
@@ -11,7 +12,6 @@ import static java.util.function.Function.identity;
|
||||
import com.google.common.collect.Comparators;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -38,7 +38,7 @@ final class ComparatorTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<T> after() {
|
||||
return naturalOrder();
|
||||
}
|
||||
@@ -52,7 +52,7 @@ final class ComparatorTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<T> after() {
|
||||
return reverseOrder();
|
||||
}
|
||||
@@ -66,7 +66,7 @@ final class ComparatorTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<T> after(Comparator<T> cmp) {
|
||||
return cmp;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ final class ComparatorTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<S> after(Comparator<S> cmp, Function<? super S, ? extends T> function) {
|
||||
return cmp.thenComparing(function, reverseOrder());
|
||||
}
|
||||
@@ -180,7 +180,7 @@ final class ComparatorTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<T> after(Comparator<T> cmp) {
|
||||
return cmp.thenComparing(naturalOrder());
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ final class EqualityTemplates {
|
||||
* remaining reference-based equality checks.
|
||||
*/
|
||||
// XXX: This Refaster rule is the topic of https://github.com/google/error-prone/issues/559. We
|
||||
// work around the issue by selecting the "largest replacements". See RefasterCheck.
|
||||
// work around the issue by selecting the "largest replacements". See the `Refaster` check.
|
||||
@BeforeTemplate
|
||||
boolean before(T a, T b) {
|
||||
return Refaster.anyOf(a.equals(b), Objects.equals(a, b));
|
||||
@@ -34,9 +34,8 @@ final class EqualityTemplates {
|
||||
}
|
||||
|
||||
/** Prefer {@link Object#equals(Object)} over the equivalent lambda function. */
|
||||
// XXX: As it stands, this rule is a special case of what `MethodReferenceUsageCheck` tries to
|
||||
// achieve. If/when `MethodReferenceUsageCheck` becomes production ready, we should simply drop
|
||||
// this check.
|
||||
// XXX: As it stands, this rule is a special case of what `MethodReferenceUsage` tries to achieve.
|
||||
// If/when `MethodReferenceUsage` becomes production ready, we should simply drop this check.
|
||||
// XXX: Alternatively, the rule should be replaced with a plugin which also identifies cases where
|
||||
// the arguments are swapped but simplification is possible anyway, by virtue of `v` being
|
||||
// non-null.
|
||||
|
||||
@@ -2,6 +2,7 @@ package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableListMultimap.flatteningToImmutableListMultimap;
|
||||
import static com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.function.Function.identity;
|
||||
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
@@ -12,7 +13,6 @@ import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import com.google.common.collect.SortedSetMultimap;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -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)
|
||||
@@ -161,7 +161,7 @@ final class ImmutableListMultimapTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableListMultimap<K, V> after(Stream<E> stream) {
|
||||
return stream.collect(toImmutableListMultimap(e -> keyFunction(e), e -> valueFunction(e)));
|
||||
}
|
||||
@@ -272,17 +272,4 @@ final class ImmutableListMultimapTemplates {
|
||||
return ImmutableListMultimap.copyOf(Multimaps.transformValues(multimap, transformation));
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily copy an {@link ImmutableListMultimap}. */
|
||||
static final class ImmutableListMultimapCopyOfImmutableListMultimap<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableListMultimap<K, V> before(ImmutableListMultimap<K, V> multimap) {
|
||||
return ImmutableListMultimap.copyOf(multimap);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableListMultimap<K, V> after(ImmutableListMultimap<K, V> multimap) {
|
||||
return multimap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,20 @@ package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Comparator.naturalOrder;
|
||||
import static java.util.stream.Collectors.collectingAndThen;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -41,37 +40,6 @@ final class ImmutableListTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableList#of()} over more contrived alternatives. */
|
||||
static final class EmptyImmutableList<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableList<T> before() {
|
||||
return Refaster.anyOf(
|
||||
ImmutableList.<T>builder().build(), Stream.<T>empty().collect(toImmutableList()));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after() {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableList#of(Object)} over alternatives that don't communicate the
|
||||
* immutability of the resulting list at the type level.
|
||||
*/
|
||||
// XXX: Note that this rewrite rule is incorrect for nullable elements.
|
||||
static final class SingletonImmutableList<T> {
|
||||
@BeforeTemplate
|
||||
List<T> before(T element) {
|
||||
return Collections.singletonList(element);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after(T element) {
|
||||
return ImmutableList.of(element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableList#copyOf(Iterable)} and variants over more contrived alternatives.
|
||||
*/
|
||||
@@ -108,39 +76,20 @@ final class ImmutableListTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableList#toImmutableList()} over the more verbose alternative. */
|
||||
// XXX: Once the code base has been sufficiently cleaned up, we might want to also rewrite
|
||||
// `Collectors.toList(`), with the caveat that it allows mutation (though this cannot be relied
|
||||
// upon) as well as nulls. Another option is to explicitly rewrite those variants to
|
||||
// `Collectors.toSet(ArrayList::new)`.
|
||||
/** Prefer {@link ImmutableList#toImmutableList()} over less idiomatic alternatives. */
|
||||
static final class StreamToImmutableList<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableList<T> before(Stream<T> stream) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableList.copyOf(stream.iterator()),
|
||||
stream.collect(collectingAndThen(toList(), ImmutableList::copyOf)));
|
||||
return ImmutableList.copyOf(stream.iterator());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableList<T> after(Stream<T> stream) {
|
||||
return stream.collect(toImmutableList());
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't call {@link ImmutableList#asList()}; it is a no-op. */
|
||||
static final class ImmutableListAsList<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableList<T> before(ImmutableList<T> list) {
|
||||
return list.asList();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after(ImmutableList<T> list) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableList#sortedCopyOf(Iterable)} over more contrived alternatives. */
|
||||
static final class ImmutableListSortedCopyOf<T extends Comparable<? super T>> {
|
||||
@BeforeTemplate
|
||||
@@ -194,9 +143,122 @@ final class ImmutableListTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableList<T> after(Stream<T> stream) {
|
||||
return stream.collect(toImmutableSet()).asList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableList#of()} over more contrived alternatives or alternatives that don't
|
||||
* communicate the immutability of the resulting list at the type level.
|
||||
*/
|
||||
// XXX: The `Stream` variant may be too contrived to warrant inclusion. Review its usage if/when
|
||||
// this and similar Refaster templates are replaced with an Error Prone check.
|
||||
static final class ImmutableListOf<T> {
|
||||
@BeforeTemplate
|
||||
List<T> before() {
|
||||
return Refaster.anyOf(
|
||||
ImmutableList.<T>builder().build(),
|
||||
Stream.<T>empty().collect(toImmutableList()),
|
||||
emptyList(),
|
||||
List.of());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after() {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableList#of(Object)} over more contrived alternatives or alternatives that
|
||||
* don't communicate the immutability of the resulting list at the type level.
|
||||
*/
|
||||
// XXX: Note that the replacement of `Collections#singletonList` is incorrect for nullable
|
||||
// elements.
|
||||
static final class ImmutableListOf1<T> {
|
||||
@BeforeTemplate
|
||||
List<T> before(T e1) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableList.<T>builder().add(e1).build(), singletonList(e1), List.of(e1));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after(T e1) {
|
||||
return ImmutableList.of(e1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableList#of(Object, Object)} over alternatives that don't communicate the
|
||||
* immutability of the resulting list at the type level.
|
||||
*/
|
||||
// XXX: Consider writing an Error Prone check which also flags straightforward
|
||||
// `ImmutableList.builder()` usages.
|
||||
static final class ImmutableListOf2<T> {
|
||||
@BeforeTemplate
|
||||
List<T> before(T e1, T e2) {
|
||||
return List.of(e1, e2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after(T e1, T e2) {
|
||||
return ImmutableList.of(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableList#of(Object, Object, Object)} over alternatives that don't
|
||||
* communicate the immutability of the resulting list at the type level.
|
||||
*/
|
||||
// XXX: Consider writing an Error Prone check which also flags straightforward
|
||||
// `ImmutableList.builder()` usages.
|
||||
static final class ImmutableListOf3<T> {
|
||||
@BeforeTemplate
|
||||
List<T> before(T e1, T e2, T e3) {
|
||||
return List.of(e1, e2, e3);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after(T e1, T e2, T e3) {
|
||||
return ImmutableList.of(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableList#of(Object, Object, Object, Object)} over alternatives that don't
|
||||
* communicate the immutability of the resulting list at the type level.
|
||||
*/
|
||||
// XXX: Consider writing an Error Prone check which also flags straightforward
|
||||
// `ImmutableList.builder()` usages.
|
||||
static final class ImmutableListOf4<T> {
|
||||
@BeforeTemplate
|
||||
List<T> before(T e1, T e2, T e3, T e4) {
|
||||
return List.of(e1, e2, e3, e4);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after(T e1, T e2, T e3, T e4) {
|
||||
return ImmutableList.of(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableList#of(Object, Object, Object, Object, Object)} over alternatives that
|
||||
* don't communicate the immutability of the resulting list at the type level.
|
||||
*/
|
||||
// XXX: Consider writing an Error Prone check which also flags straightforward
|
||||
// `ImmutableList.builder()` usages.
|
||||
static final class ImmutableListOf5<T> {
|
||||
@BeforeTemplate
|
||||
List<T> before(T e1, T e2, T e3, T e4, T e5) {
|
||||
return List.of(e1, e2, e3, e4, e5);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableList<T> after(T e1, T e2, T e3, T e4, T e5) {
|
||||
return ImmutableList.of(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static java.util.function.Function.identity;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -14,7 +16,6 @@ import com.google.errorprone.refaster.annotation.MayOptionallyUse;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -40,41 +41,6 @@ final class ImmutableMapTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableMap#of()} over more contrived alternatives. */
|
||||
static final class EmptyImmutableMap<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before() {
|
||||
return ImmutableMap.<K, V>builder().build();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after() {
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableMap#of(Object, Object)} over more contrived alternatives and
|
||||
* alternatives that don't communicate the immutability of the resulting map at the type level..
|
||||
*/
|
||||
// XXX: One can define variants for more than one key-value pair, but at some point the builder
|
||||
// actually produces nicer code. So it's not clear we should add Refaster templates for those
|
||||
// variants.
|
||||
// XXX: Note that the `singletonMap` rewrite rule is incorrect for nullable elements.
|
||||
static final class PairToImmutableMap<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K key, V value) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.<K, V>builder().put(key, value).build(),
|
||||
Collections.singletonMap(key, value));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(K key, V value) {
|
||||
return ImmutableMap.of(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableMap#of(Object, Object)} over more contrived alternatives. */
|
||||
static final class EntryToImmutableMap<K, V> {
|
||||
@BeforeTemplate
|
||||
@@ -178,7 +144,7 @@ final class ImmutableMapTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableMap<K, V> after(Stream<E> stream) {
|
||||
return stream.collect(toImmutableMap(e -> keyFunction(e), e -> valueFunction(e)));
|
||||
}
|
||||
@@ -226,7 +192,7 @@ final class ImmutableMapTemplates {
|
||||
|
||||
// XXX: Instead of `Map.Entry::getKey` we could also match `e -> e.getKey()`. But for some
|
||||
// reason Refaster doesn't handle that case. This doesn't matter if we roll out use of
|
||||
// `MethodReferenceUsageCheck`. Same observation applies to a lot of other Refaster checks.
|
||||
// `MethodReferenceUsage`. Same observation applies to a lot of other Refaster checks.
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("NullAway")
|
||||
ImmutableMap<K, V2> before(Map<K, V1> map) {
|
||||
@@ -242,16 +208,108 @@ final class ImmutableMapTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily copy an {@link ImmutableMap}. */
|
||||
static final class ImmutableMapCopyOfImmutableMap<K, V> {
|
||||
/**
|
||||
* Prefer {@link ImmutableMap#of()} over more contrived alternatives or alternatives that don't
|
||||
* communicate the immutability of the resulting map at the type level.
|
||||
*/
|
||||
static final class ImmutableMapOf<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before(ImmutableMap<K, V> map) {
|
||||
return ImmutableMap.copyOf(map);
|
||||
Map<K, V> before() {
|
||||
return Refaster.anyOf(ImmutableMap.<K, V>builder().build(), emptyMap(), Map.of());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(ImmutableMap<K, V> map) {
|
||||
return map;
|
||||
ImmutableMap<K, V> after() {
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableMap#of(Object, Object)} over more contrived alternatives or alternatives
|
||||
* that don't communicate the immutability of the resulting map at the type level.
|
||||
*/
|
||||
// XXX: Note that the replacement of `Collections#singletonMap` is incorrect for nullable
|
||||
// elements.
|
||||
static final class ImmutableMapOf1<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.<K, V>builder().put(k1, v1).build(), singletonMap(k1, v1), Map.of(k1, v1));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(K k1, V v1) {
|
||||
return ImmutableMap.of(k1, v1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableMap#of(Object, Object, Object, Object)} over alternatives that don't
|
||||
* communicate the immutability of the resulting map at the type level.
|
||||
*/
|
||||
// XXX: Also rewrite the `ImmutableMap.builder()` variant?
|
||||
static final class ImmutableMapOf2<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1, K k2, V v2) {
|
||||
return Map.of(k1, v1, k2, v2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(K k1, V v1, K k2, V v2) {
|
||||
return ImmutableMap.of(k1, v1, k2, v2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableMap#of(Object, Object, Object, Object, Object, Object)} over
|
||||
* alternatives that don't communicate the immutability of the resulting map at the type level.
|
||||
*/
|
||||
// XXX: Also rewrite the `ImmutableMap.builder()` variant?
|
||||
static final class ImmutableMapOf3<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1, K k2, V v2, K k3, V v3) {
|
||||
return Map.of(k1, v1, k2, v2, k3, v3);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(K k1, V v1, K k2, V v2, K k3, V v3) {
|
||||
return ImmutableMap.of(k1, v1, k2, v2, k3, v3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableMap#of(Object, Object, Object, Object, Object, Object, Object, Object)}
|
||||
* over alternatives that don't communicate the immutability of the resulting map at the type
|
||||
* level.
|
||||
*/
|
||||
// XXX: Also rewrite the `ImmutableMap.builder()` variant?
|
||||
static final class ImmutableMapOf4<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
|
||||
return Map.of(k1, v1, k2, v2, k3, v3, k4, v4);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
|
||||
return ImmutableMap.of(k1, v1, k2, v2, k3, v3, k4, v4);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableMap#of(Object, Object, Object, Object, Object, Object, Object, Object,
|
||||
* Object, Object)} over alternatives that don't communicate the immutability of the resulting map
|
||||
* at the type level.
|
||||
*/
|
||||
// XXX: Also rewrite the `ImmutableMap.builder()` variant?
|
||||
static final class ImmutableMapOf5<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
|
||||
return Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
|
||||
return ImmutableMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableMultiset.toImmutableMultiset;
|
||||
import static java.util.stream.Collectors.collectingAndThen;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -90,28 +88,13 @@ final class ImmutableMultisetTemplates {
|
||||
static final class StreamToImmutableMultiset<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableMultiset<T> before(Stream<T> stream) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableMultiset.copyOf(stream.iterator()),
|
||||
stream.collect(collectingAndThen(toList(), ImmutableMultiset::copyOf)));
|
||||
return ImmutableMultiset.copyOf(stream.iterator());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableMultiset<T> after(Stream<T> stream) {
|
||||
return stream.collect(toImmutableMultiset());
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily copy an {@link ImmutableMultiset}. */
|
||||
static final class ImmutableMultisetCopyOfImmutableMultiset<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableMultiset<T> before(ImmutableMultiset<T> multiset) {
|
||||
return ImmutableMultiset.copyOf(multiset);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMultiset<T> after(ImmutableMultiset<T> multiset) {
|
||||
return multiset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableSetMultimap.flatteningToImmutableSetMultimap;
|
||||
import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
@@ -10,7 +11,6 @@ import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import com.google.common.collect.SortedSetMultimap;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -138,7 +138,7 @@ final class ImmutableSetMultimapTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableSetMultimap<K, V> after(Stream<E> stream) {
|
||||
return stream.collect(toImmutableSetMultimap(e -> keyFunction(e), e -> valueFunction(e)));
|
||||
}
|
||||
@@ -162,7 +162,7 @@ final class ImmutableSetMultimapTemplates {
|
||||
@AfterTemplate
|
||||
ImmutableSetMultimap<K, V2> after(Multimap<K, V1> multimap) {
|
||||
return ImmutableSetMultimap.copyOf(
|
||||
Multimaps.transformValues(multimap, v -> valueTransformation(v)));
|
||||
Multimaps.transformValues(multimap, e -> valueTransformation(e)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,17 +215,4 @@ final class ImmutableSetMultimapTemplates {
|
||||
return ImmutableSetMultimap.copyOf(Multimaps.transformValues(multimap, transformation));
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily copy an {@link ImmutableSetMultimap}. */
|
||||
static final class ImmutableSetMultimapCopyOfImmutableSetMultimap<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableSetMultimap<K, V> before(ImmutableSetMultimap<K, V> multimap) {
|
||||
return ImmutableSetMultimap.copyOf(multimap);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSetMultimap<K, V> after(ImmutableSetMultimap<K, V> multimap) {
|
||||
return multimap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static java.util.stream.Collectors.collectingAndThen;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets.SetView;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
@@ -39,37 +37,6 @@ final class ImmutableSetTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableSet#of()} over more contrived alternatives. */
|
||||
static final class EmptyImmutableSet<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableSet<T> before() {
|
||||
return Refaster.anyOf(
|
||||
ImmutableSet.<T>builder().build(), Stream.<T>empty().collect(toImmutableSet()));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after() {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableSet#of(Object)} over alternatives that don't communicate the
|
||||
* immutability of the resulting set at the type level.
|
||||
*/
|
||||
// XXX: Note that this rewrite rule is incorrect for nullable elements.
|
||||
static final class SingletonImmutableSet<T> {
|
||||
@BeforeTemplate
|
||||
Set<T> before(T element) {
|
||||
return Collections.singleton(element);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after(T element) {
|
||||
return ImmutableSet.of(element);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableSet#copyOf(Iterable)} and variants over more contrived alternatives. */
|
||||
static final class IterableToImmutableSet<T> {
|
||||
@BeforeTemplate
|
||||
@@ -105,40 +72,20 @@ final class ImmutableSetTemplates {
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableSet#toImmutableSet()} over less idiomatic alternatives. */
|
||||
// XXX: Once the code base has been sufficiently cleaned up, we might want to also rewrite
|
||||
// `Collectors.toSet(`), with the caveat that it allows mutation (though this cannot be relied
|
||||
// upon) as well as nulls. Another option is to explicitly rewrite those variants to
|
||||
// `Collectors.toSet(HashSet::new)`.
|
||||
static final class StreamToImmutableSet<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableSet<T> before(Stream<T> stream) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableSet.copyOf(stream.iterator()),
|
||||
stream.distinct().collect(toImmutableSet()),
|
||||
stream.collect(collectingAndThen(toList(), ImmutableSet::copyOf)),
|
||||
stream.collect(collectingAndThen(toSet(), ImmutableSet::copyOf)));
|
||||
ImmutableSet.copyOf(stream.iterator()), stream.distinct().collect(toImmutableSet()));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableSet<T> after(Stream<T> stream) {
|
||||
return stream.collect(toImmutableSet());
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily copy an {@link ImmutableSet}. */
|
||||
static final class ImmutableSetCopyOfImmutableSet<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableSet<T> before(ImmutableSet<T> set) {
|
||||
return ImmutableSet.copyOf(set);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after(ImmutableSet<T> set) {
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link SetView#immutableCopy()} over the more verbose alternative. */
|
||||
static final class ImmutableSetCopyOfSetView<T> {
|
||||
@BeforeTemplate
|
||||
@@ -151,4 +98,115 @@ final class ImmutableSetTemplates {
|
||||
return set.immutableCopy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableSet#of()} over more contrived alternatives or alternatives that don't
|
||||
* communicate the immutability of the resulting set at the type level.
|
||||
*/
|
||||
// XXX: The `Stream` variant may be too contrived to warrant inclusion. Review its usage if/when
|
||||
// this and similar Refaster templates are replaced with an Error Prone check.
|
||||
static final class ImmutableSetOf<T> {
|
||||
@BeforeTemplate
|
||||
Set<T> before() {
|
||||
return Refaster.anyOf(
|
||||
ImmutableSet.<T>builder().build(),
|
||||
Stream.<T>empty().collect(toImmutableSet()),
|
||||
emptySet(),
|
||||
Set.of());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after() {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableSet#of(Object)} over more contrived alternatives or alternatives that
|
||||
* don't communicate the immutability of the resulting set at the type level.
|
||||
*/
|
||||
// XXX: Note that the replacement of `Collections#singleton` is incorrect for nullable elements.
|
||||
static final class ImmutableSetOf1<T> {
|
||||
@BeforeTemplate
|
||||
Set<T> before(T e1) {
|
||||
return Refaster.anyOf(ImmutableSet.<T>builder().add(e1).build(), singleton(e1), Set.of(e1));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after(T e1) {
|
||||
return ImmutableSet.of(e1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableSet#of(Object, Object)} over alternatives that don't communicate the
|
||||
* immutability of the resulting set at the type level.
|
||||
*/
|
||||
// XXX: Consider writing an Error Prone check which also flags straightforward
|
||||
// `ImmutableSet.builder()` usages.
|
||||
static final class ImmutableSetOf2<T> {
|
||||
@BeforeTemplate
|
||||
Set<T> before(T e1, T e2) {
|
||||
return Set.of(e1, e2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after(T e1, T e2) {
|
||||
return ImmutableSet.of(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableSet#of(Object, Object, Object)} over alternatives that don't communicate
|
||||
* the immutability of the resulting set at the type level.
|
||||
*/
|
||||
// XXX: Consider writing an Error Prone check which also flags straightforward
|
||||
// `ImmutableSet.builder()` usages.
|
||||
static final class ImmutableSetOf3<T> {
|
||||
@BeforeTemplate
|
||||
Set<T> before(T e1, T e2, T e3) {
|
||||
return Set.of(e1, e2, e3);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after(T e1, T e2, T e3) {
|
||||
return ImmutableSet.of(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableSet#of(Object, Object, Object, Object)} over alternatives that don't
|
||||
* communicate the immutability of the resulting set at the type level.
|
||||
*/
|
||||
// XXX: Consider writing an Error Prone check which also flags straightforward
|
||||
// `ImmutableSet.builder()` usages.
|
||||
static final class ImmutableSetOf4<T> {
|
||||
@BeforeTemplate
|
||||
Set<T> before(T e1, T e2, T e3, T e4) {
|
||||
return Set.of(e1, e2, e3, e4);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after(T e1, T e2, T e3, T e4) {
|
||||
return ImmutableSet.of(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableSet#of(Object, Object, Object, Object, Object)} over alternatives that
|
||||
* don't communicate the immutability of the resulting set at the type level.
|
||||
*/
|
||||
// XXX: Consider writing an Error Prone check which also flags straightforward
|
||||
// `ImmutableSet.builder()` usages.
|
||||
static final class ImmutableSetOf5<T> {
|
||||
@BeforeTemplate
|
||||
Set<T> before(T e1, T e2, T e3, T e4, T e5) {
|
||||
return Set.of(e1, e2, e3, e4, e5);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableSet<T> after(T e1, T e2, T e3, T e4, T e5) {
|
||||
return ImmutableSet.of(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableSortedMultiset.toImmutableSortedMultiset;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Comparator.naturalOrder;
|
||||
import static java.util.stream.Collectors.collectingAndThen;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSortedMultiset;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -93,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(),
|
||||
@@ -108,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(),
|
||||
@@ -134,13 +131,11 @@ final class ImmutableSortedMultisetTemplates {
|
||||
static final class StreamToImmutableSortedMultiset<T extends Comparable<? super T>> {
|
||||
@BeforeTemplate
|
||||
ImmutableSortedMultiset<T> before(Stream<T> stream) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableSortedMultiset.copyOf(stream.iterator()),
|
||||
stream.collect(collectingAndThen(toList(), ImmutableSortedMultiset::copyOf)));
|
||||
return ImmutableSortedMultiset.copyOf(stream.iterator());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableSortedMultiset<T> after(Stream<T> stream) {
|
||||
return stream.collect(toImmutableSortedMultiset(naturalOrder()));
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
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 static java.util.stream.Collectors.collectingAndThen;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -91,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(),
|
||||
@@ -106,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(),
|
||||
@@ -134,13 +131,11 @@ final class ImmutableSortedSetTemplates {
|
||||
static final class StreamToImmutableSortedSet<T extends Comparable<? super T>> {
|
||||
@BeforeTemplate
|
||||
ImmutableSortedSet<T> before(Stream<T> stream) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableSortedSet.copyOf(stream.iterator()),
|
||||
stream.collect(collectingAndThen(toList(), ImmutableSortedSet::copyOf)));
|
||||
return ImmutableSortedSet.copyOf(stream.iterator());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableSortedSet<T> after(Stream<T> stream) {
|
||||
return stream.collect(toImmutableSortedSet(naturalOrder()));
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
@@ -21,7 +21,7 @@ final class JUnitTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Arguments after(@Repeated T objects) {
|
||||
return arguments(objects);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Comparator.comparing;
|
||||
import static java.util.Comparator.naturalOrder;
|
||||
import static java.util.Map.Entry.comparingByKey;
|
||||
import static java.util.Map.Entry.comparingByValue;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -51,7 +51,7 @@ final class MapEntryTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<Map.Entry<K, V>> after() {
|
||||
return comparingByKey();
|
||||
}
|
||||
@@ -65,7 +65,7 @@ final class MapEntryTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<Map.Entry<K, V>> after(Comparator<? super K> cmp) {
|
||||
return comparingByKey(cmp);
|
||||
}
|
||||
@@ -80,7 +80,7 @@ final class MapEntryTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<Map.Entry<K, V>> after() {
|
||||
return comparingByValue();
|
||||
}
|
||||
@@ -94,7 +94,7 @@ final class MapEntryTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Comparator<Map.Entry<K, V>> after(Comparator<? super V> cmp) {
|
||||
return comparingByValue(cmp);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
@@ -26,7 +26,7 @@ final class MockitoTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
VerificationMode after() {
|
||||
return never();
|
||||
}
|
||||
@@ -43,7 +43,7 @@ final class MockitoTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
T after(T mock) {
|
||||
return verify(mock);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
@@ -24,7 +24,7 @@ final class NullTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
T after(T first, T second) {
|
||||
return requireNonNullElse(first, second);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -14,6 +15,7 @@ import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Refaster templates related to expressions dealing with {@link Optional}s. */
|
||||
final class OptionalTemplates {
|
||||
@@ -24,7 +26,7 @@ final class OptionalTemplates {
|
||||
// parentheses around the null check, but that's currently not the case. Try to fix that.
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("TernaryOperatorOptionalNegativeFiltering" /* Special case. */)
|
||||
Optional<T> before(T object) {
|
||||
Optional<T> before(@Nullable T object) {
|
||||
return object == null ? Optional.empty() : Optional.of(object);
|
||||
}
|
||||
|
||||
@@ -91,19 +93,6 @@ final class OptionalTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Optional#stream()} over the Guava alternative. */
|
||||
static final class OptionalToStream<T> {
|
||||
@BeforeTemplate
|
||||
Stream<T> before(Optional<T> optional) {
|
||||
return Streams.stream(optional);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Stream<T> after(Optional<T> optional) {
|
||||
return optional.stream();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't use the ternary operator to extract the first element of a possibly-empty {@link
|
||||
* Iterator} as an {@link Optional}.
|
||||
@@ -115,7 +104,7 @@ final class OptionalTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Optional<T> after(Iterator<T> it) {
|
||||
return Streams.stream(it).findFirst();
|
||||
}
|
||||
@@ -124,7 +113,7 @@ final class OptionalTemplates {
|
||||
/** Prefer {@link Optional#filter(Predicate)} over usage of the ternary operator. */
|
||||
// XXX: This rule may introduce a compilation error: the `test` expression may reference a
|
||||
// non-effectively final variable, which is not allowed in the replacement lambda expression.
|
||||
// Maybe our RefasterCheck should test `compilesWithFix`?
|
||||
// Maybe our `Refaster` checker should test `compilesWithFix`?
|
||||
abstract static class TernaryOperatorOptionalPositiveFiltering<T> {
|
||||
@Placeholder
|
||||
abstract boolean test(T value);
|
||||
@@ -144,7 +133,7 @@ final class OptionalTemplates {
|
||||
/** Prefer {@link Optional#filter(Predicate)} over usage of the ternary operator. */
|
||||
// XXX: This rule may introduce a compilation error: the `test` expression may reference a
|
||||
// non-effectively final variable, which is not allowed in the replacement lambda expression.
|
||||
// Maybe our RefasterCheck should test `compilesWithFix`?
|
||||
// Maybe our `Refaster` checker should test `compilesWithFix`?
|
||||
abstract static class TernaryOperatorOptionalNegativeFiltering<T> {
|
||||
@Placeholder
|
||||
abstract boolean test(T value);
|
||||
@@ -177,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);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.MoreCollectors.toOptional;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.MoreCollectors;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -142,6 +143,35 @@ final class ReactorTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Flux#concatMap(Function)} over more contrived alternatives. */
|
||||
static final class FluxConcatMap<T, S> {
|
||||
@BeforeTemplate
|
||||
Flux<S> before(Flux<T> flux, Function<? super T, ? extends Publisher<? extends S>> function) {
|
||||
return Refaster.anyOf(flux.flatMap(function, 1), flux.flatMapSequential(function, 1));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<S> after(Flux<T> flux, Function<? super T, ? extends Publisher<? extends S>> function) {
|
||||
return flux.concatMap(function);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link Flux#concatMapIterable(Function)} over {@link Flux#flatMapIterable(Function)}, as
|
||||
* the former has equivalent semantics but a clearer name.
|
||||
*/
|
||||
static final class FluxConcatMapIterable<T, S> {
|
||||
@BeforeTemplate
|
||||
Flux<S> before(Flux<T> flux, Function<? super T, ? extends Iterable<? extends S>> function) {
|
||||
return flux.flatMapIterable(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<S> after(Flux<T> flux, Function<? super T, ? extends Iterable<? extends S>> function) {
|
||||
return flux.concatMapIterable(function);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't use {@link Mono#flatMapMany(Function)} to implicitly convert a {@link Mono} to a {@link
|
||||
* Flux}.
|
||||
@@ -161,6 +191,19 @@ final class ReactorTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Mono#flux()}} over more contrived alternatives. */
|
||||
static final class MonoFlux<T> {
|
||||
@BeforeTemplate
|
||||
Flux<T> before(Mono<T> mono) {
|
||||
return Flux.concat(mono);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<T> after(Mono<T> mono) {
|
||||
return mono.flux();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer a collection using {@link MoreCollectors#toOptional()} over more contrived alternatives.
|
||||
*/
|
||||
@@ -175,12 +218,38 @@ final class ReactorTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Mono<Optional<T>> after(Mono<T> mono) {
|
||||
return mono.flux().collect(toOptional());
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Mono#cast(Class)} over {@link Mono#map(Function)} with a cast. */
|
||||
static final class MonoCast<T, S> {
|
||||
@BeforeTemplate
|
||||
Mono<S> before(Mono<T> mono) {
|
||||
return mono.map(Refaster.<S>clazz()::cast);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<S> after(Mono<T> mono) {
|
||||
return mono.cast(Refaster.<S>clazz());
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Flux#cast(Class)} over {@link Flux#map(Function)} with a cast. */
|
||||
static final class FluxCast<T, S> {
|
||||
@BeforeTemplate
|
||||
Flux<S> before(Flux<T> flux) {
|
||||
return flux.map(Refaster.<S>clazz()::cast);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<S> after(Flux<T> flux) {
|
||||
return flux.cast(Refaster.<S>clazz());
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link PublisherProbe#empty()}} over more verbose alternatives. */
|
||||
static final class PublisherProbeEmpty<T> {
|
||||
@BeforeTemplate
|
||||
@@ -194,6 +263,32 @@ final class ReactorTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Mono#as(Function)} when creating a {@link StepVerifier}. */
|
||||
static final class StepVerifierFromMono<T> {
|
||||
@BeforeTemplate
|
||||
StepVerifier.FirstStep<? extends T> before(Mono<T> mono) {
|
||||
return StepVerifier.create(mono);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
StepVerifier.FirstStep<? extends T> after(Mono<T> mono) {
|
||||
return mono.as(StepVerifier::create);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Flux#as(Function)} when creating a {@link StepVerifier}. */
|
||||
static final class StepVerifierFromFlux<T> {
|
||||
@BeforeTemplate
|
||||
StepVerifier.FirstStep<? extends T> before(Flux<T> flux) {
|
||||
return StepVerifier.create(flux);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
StepVerifier.FirstStep<? extends T> after(Flux<T> flux) {
|
||||
return flux.as(StepVerifier::create);
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily call {@link StepVerifier.Step#expectNext(Object[])}. */
|
||||
static final class StepVerifierStepExpectNextEmpty<T> {
|
||||
@BeforeTemplate
|
||||
@@ -252,7 +347,9 @@ final class ReactorTemplates {
|
||||
static final class StepVerifierLastStepVerifyErrorClass<T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
Duration before(StepVerifier.LastStep step, Class<T> clazz) {
|
||||
return step.expectError(clazz).verify();
|
||||
return Refaster.anyOf(
|
||||
step.expectError(clazz).verify(),
|
||||
step.verifyErrorSatisfies(t -> assertThat(t).isInstanceOf(clazz)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
|
||||
@@ -18,19 +18,6 @@ import reactor.core.publisher.Mono;
|
||||
final class RxJava2AdapterTemplates {
|
||||
private RxJava2AdapterTemplates() {}
|
||||
|
||||
/** Remove double conversion of ... */
|
||||
static final class FluxToFlowableToFlux<T> {
|
||||
@BeforeTemplate
|
||||
Flux<T> before(Flux<T> flux) {
|
||||
return RxJava2Adapter.flowableToFlux(RxJava2Adapter.fluxToFlowable(flux));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<T> after(Flux<T> flux) {
|
||||
return flux;
|
||||
}
|
||||
}
|
||||
|
||||
/** Use the fluent API style when using {@link RxJava2Adapter#completableToMono}. */
|
||||
static final class CompletableToMono {
|
||||
@BeforeTemplate
|
||||
@@ -54,11 +41,9 @@ final class RxJava2AdapterTemplates {
|
||||
@BeforeTemplate
|
||||
Publisher<T> before(Flowable<T> flowable) {
|
||||
return Refaster.anyOf(
|
||||
Flux.from(flowable),
|
||||
flowable.compose(Flux::from),
|
||||
flowable.to(Flux::from),
|
||||
flowable.as(Flux::from),
|
||||
RxJava2Adapter.flowableToFlux(flowable),
|
||||
flowable.compose(RxJava2Adapter::flowableToFlux),
|
||||
flowable.to(RxJava2Adapter::flowableToFlux));
|
||||
}
|
||||
@@ -80,7 +65,6 @@ final class RxJava2AdapterTemplates {
|
||||
Flowable.fromPublisher(flux),
|
||||
flux.transform(Flowable::fromPublisher),
|
||||
flux.as(Flowable::fromPublisher),
|
||||
RxJava2Adapter.fluxToFlowable(flux),
|
||||
flux.transform(RxJava2Adapter::fluxToFlowable));
|
||||
}
|
||||
|
||||
@@ -153,7 +137,6 @@ final class RxJava2AdapterTemplates {
|
||||
Flowable.fromPublisher(mono),
|
||||
mono.transform(Flowable::fromPublisher),
|
||||
mono.as(Flowable::fromPublisher),
|
||||
RxJava2Adapter.monoToFlowable(mono),
|
||||
mono.transform(RxJava2Adapter::monoToFlowable));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,506 +0,0 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.CompletableSource;
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.MaybeSource;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleSource;
|
||||
import io.reactivex.functions.Action;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.functions.Predicate;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Supplier;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
|
||||
|
||||
/** The Refaster templates for the migration of the RxJava Completable type to Reactor */
|
||||
final class RxJavaCompletableToReactorTemplates {
|
||||
|
||||
private RxJavaCompletableToReactorTemplates() {}
|
||||
|
||||
static final class CompletableAmb {
|
||||
@BeforeTemplate
|
||||
Completable before(Iterable<? extends Completable> sources) {
|
||||
return Completable.amb(sources);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
|
||||
Completable after(Iterable<? extends Completable> sources) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
Mono.firstWithSignal(
|
||||
Streams.stream(sources)
|
||||
.map(RxJava2Adapter::completableToMono)
|
||||
.collect(toImmutableList())));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Completable ambArray(CompletableSource[])
|
||||
|
||||
static final class CompletableComplete {
|
||||
@BeforeTemplate
|
||||
Completable before() {
|
||||
return Completable.complete();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after() {
|
||||
return RxJava2Adapter.monoToCompletable(Mono.empty());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Completable concat(Iterable)
|
||||
// XXX: public static Completable concat(Publisher)
|
||||
// XXX: public static Completable concat(Publisher,int)
|
||||
// XXX: public static Completable concatArray(CompletableSource[])
|
||||
// XXX: public static Completable create(CompletableOnSubscribe)
|
||||
|
||||
// XXX: The types of the @Before and @After are not matching
|
||||
static final class CompletableDefer {
|
||||
@BeforeTemplate
|
||||
Completable before(Callable<? extends CompletableSource> supplier) {
|
||||
return Completable.defer(supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Callable<? extends Completable> supplier) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
Mono.defer(
|
||||
() ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
RxJavaReactorMigrationUtil.callableAsSupplier(supplier).get())));
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableErrorCallable {
|
||||
@BeforeTemplate
|
||||
Completable before(Callable<? extends Throwable> throwable) {
|
||||
return Completable.error(throwable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Supplier<? extends Throwable> throwable) {
|
||||
return RxJava2Adapter.monoToCompletable(Mono.error(throwable));
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableErrorThrowable {
|
||||
@BeforeTemplate
|
||||
Completable before(Throwable throwable) {
|
||||
return Completable.error(throwable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Throwable throwable) {
|
||||
return RxJava2Adapter.monoToCompletable(Mono.error(throwable));
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableFromAction {
|
||||
@BeforeTemplate
|
||||
Completable before(Action action) {
|
||||
return Completable.fromAction(action);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Action action) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
Mono.fromRunnable(RxJavaReactorMigrationUtil.toRunnable(action)));
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableFromCallable {
|
||||
@BeforeTemplate
|
||||
Completable before(Callable<?> supplier) {
|
||||
return Completable.fromCallable(supplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Callable<?> supplier) {
|
||||
return RxJava2Adapter.monoToCompletable(Mono.fromCallable(supplier));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Completable fromFuture(Future)
|
||||
// XXX: public static Completable fromMaybe(MaybeSource)
|
||||
// XXX: public static Completable fromObservable(ObservableSource)
|
||||
|
||||
static final class CompletableFromPublisher<T> {
|
||||
@BeforeTemplate
|
||||
Completable before(Publisher<T> source) {
|
||||
return Completable.fromPublisher(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Publisher<T> source) {
|
||||
return RxJava2Adapter.monoToCompletable(Mono.from(source));
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableFromRunnable {
|
||||
@BeforeTemplate
|
||||
Completable before(Runnable runnable) {
|
||||
return Completable.fromRunnable(runnable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Runnable runnable) {
|
||||
return RxJava2Adapter.monoToCompletable(Mono.fromRunnable(runnable));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Completable fromSingle(SingleSource)
|
||||
// XXX: public static Completable merge(Iterable)
|
||||
// XXX: public static Completable merge(Publisher)
|
||||
// XXX: public static Completable merge(Publisher,int)
|
||||
// XXX: public static Completable mergeArray(CompletableSource[])
|
||||
// XXX: public static Completable mergeArrayDelayError(CompletableSource[])
|
||||
// XXX: public static Completable mergeDelayError(Iterable)
|
||||
// XXX: public static Completable mergeDelayError(Publisher)
|
||||
// XXX: public static Completable mergeDelayError(Publisher,int)
|
||||
// XXX: public static Completable never()
|
||||
// XXX: public static Completable timer(long,TimeUnit)
|
||||
// XXX: public static Completable timer(long,TimeUnit,Scheduler)
|
||||
// XXX: public static Completable unsafeCreate(CompletableSource)
|
||||
// XXX: public static Completable using(Callable,Function,Consumer)
|
||||
// XXX: public static Completable using(Callable,Function,Consumer,boolean)
|
||||
|
||||
static final class CompletableWrap {
|
||||
@BeforeTemplate
|
||||
Completable before(Completable source) {
|
||||
return Completable.wrap(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Completable source) {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Completable ambWith(CompletableSource)
|
||||
|
||||
static final class CompletableAndThenCompletable {
|
||||
@BeforeTemplate
|
||||
Completable before(Completable completable, CompletableSource source) {
|
||||
return completable.andThen(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Completable completable, CompletableSource source) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
RxJava2Adapter.completableToMono(completable)
|
||||
.then(RxJava2Adapter.completableToMono(Completable.wrap(source))));
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableAndThenMaybe<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Completable completable, MaybeSource<T> source) {
|
||||
return completable.andThen(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Completable completable, MaybeSource<T> source) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.completableToMono(completable)
|
||||
.then(RxJava2Adapter.maybeToMono(Maybe.wrap(source))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Observable andThen(ObservableSource)
|
||||
|
||||
static final class CompletableAndThenPublisher<T> {
|
||||
@BeforeTemplate
|
||||
Flowable<T> before(Completable completable, Publisher<T> source) {
|
||||
return completable.andThen(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<T> after(Completable completable, Publisher<T> source) {
|
||||
return RxJava2Adapter.fluxToFlowable(
|
||||
RxJava2Adapter.completableToMono(completable).thenMany(source));
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableAndThenSingle<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Completable completable, SingleSource<T> source) {
|
||||
return completable.andThen(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Completable completable, SingleSource<T> source) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.completableToMono(completable)
|
||||
.then(RxJava2Adapter.singleToMono(Single.wrap(source))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Object as(CompletableConverter)
|
||||
|
||||
static final class CompletableBlockingAwait {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable) {
|
||||
completable.blockingAwait();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable) {
|
||||
RxJava2Adapter.completableToMono(completable).block();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final boolean blockingAwait(long,TimeUnit)
|
||||
// XXX: public final Throwable blockingGet()
|
||||
// XXX: public final Throwable blockingGet(long,TimeUnit)
|
||||
// XXX: public final Completable cache()
|
||||
// XXX: public final Completable compose(CompletableTransformer)
|
||||
// XXX: public final Completable concatWith(CompletableSource)
|
||||
// XXX: public final Completable delay(long,TimeUnit)
|
||||
// XXX: public final Completable delay(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Completable delay(long,TimeUnit,Scheduler,boolean)
|
||||
// XXX: public final Completable delaySubscription(long,TimeUnit)
|
||||
// XXX: public final Completable delaySubscription(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Completable doAfterTerminate(Action)
|
||||
// XXX: public final Completable doFinally(Action)
|
||||
// XXX: public final Completable doOnComplete(Action)
|
||||
// XXX: public final Completable doOnDispose(Action)
|
||||
// XXX: public final Completable doOnError(Consumer)
|
||||
// XXX: public final Completable doOnEvent(Consumer)
|
||||
// XXX: public final Completable doOnSubscribe(Consumer)
|
||||
|
||||
static final class CompletableDoOnError {
|
||||
@BeforeTemplate
|
||||
Completable before(Completable completable, Consumer<? super Throwable> consumer) {
|
||||
return completable.doOnError(consumer);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Completable completable, Consumer<? super Throwable> consumer) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
RxJava2Adapter.completableToMono(completable)
|
||||
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Completable doOnTerminate(Action)
|
||||
// XXX: public final Completable hide()
|
||||
// XXX: public final Completable lift(CompletableOperator)
|
||||
// XXX: public final Single materialize()
|
||||
// XXX: public final Completable mergeWith(CompletableSource)
|
||||
// XXX: public final Completable observeOn(Scheduler)
|
||||
|
||||
// XXX: Verify whether this is the correct equivalent.
|
||||
static final class CompletableOnErrorComplete {
|
||||
Completable before(Completable completable) {
|
||||
return completable.onErrorComplete();
|
||||
}
|
||||
|
||||
Completable after(Completable completable) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
RxJava2Adapter.completableToMono(completable).onErrorStop());
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableOnErrorCompletePredicate {
|
||||
Completable before(Completable completable, Predicate<? super Throwable> predicate) {
|
||||
return completable.onErrorComplete(predicate);
|
||||
}
|
||||
|
||||
Completable after(Completable completable, Predicate<? super Throwable> predicate) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
RxJava2Adapter.completableToMono(completable)
|
||||
.onErrorResume(
|
||||
RxJavaReactorMigrationUtil.toJdkPredicate(predicate), t -> Mono.empty()));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Completable onErrorComplete(Predicate)
|
||||
// XXX: public final Completable onErrorResumeNext(Function)
|
||||
// XXX: public final Completable onTerminateDetach()
|
||||
// XXX: public final Completable repeat()
|
||||
// XXX: public final Completable repeat(long)
|
||||
// XXX: public final Completable repeatUntil(BooleanSupplier)
|
||||
// XXX: public final Completable repeatWhen(Function)
|
||||
// XXX: public final Completable retry()
|
||||
// XXX: public final Completable retry(BiPredicate)
|
||||
// XXX: public final Completable retry(long)
|
||||
// XXX: public final Completable retry(long,Predicate)
|
||||
// XXX: public final Completable retry(Predicate)
|
||||
// XXX: public final Completable retryWhen(Function)
|
||||
// XXX: public final Completable startWith(CompletableSource)
|
||||
// XXX: public final Observable startWith(Observable)
|
||||
// XXX: public final Flowable startWith(Publisher)
|
||||
// XXX: public final Disposable subscribe()
|
||||
// XXX: public final Disposable subscribe(Action)
|
||||
// XXX: public final Disposable subscribe(Action,Consumer)
|
||||
// XXX: public final void subscribe(CompletableObserver)
|
||||
// XXX: public final Completable subscribeOn(Scheduler)
|
||||
// XXX: public final CompletableObserver subscribeWith(CompletableObserver)
|
||||
// XXX: public final Completable takeUntil(CompletableSource)
|
||||
// XXX: public final Completable timeout(long,TimeUnit)
|
||||
// XXX: public final Completable timeout(long,TimeUnit,CompletableSource)
|
||||
// XXX: public final Completable timeout(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Completable timeout(long,TimeUnit,Scheduler,CompletableSource)
|
||||
// XXX: public final Object to(Function)
|
||||
|
||||
static final class CompletableToFlowable {
|
||||
@BeforeTemplate
|
||||
Flowable<Void> before(Completable completable) {
|
||||
return completable.toFlowable();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<Void> after(Completable completable) {
|
||||
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.completableToMono(completable).flux());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Requires investigation. Should not be Void...
|
||||
static final class CompletableToMaybe {
|
||||
@BeforeTemplate
|
||||
Maybe<Void> before(Completable completable) {
|
||||
return completable.toMaybe();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<Void> after(Completable completable) {
|
||||
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.completableToMono(completable));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Observable toObservable()
|
||||
// XXX: public final Single toSingle(Callable)
|
||||
// XXX: public final Single toSingleDefault(Object)
|
||||
// XXX: public final Completable unsubscribeOn(Scheduler)
|
||||
|
||||
static final class CompletableTestAssertResult {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
completable.test().await().assertResult(),
|
||||
completable.test().assertResult(),
|
||||
completable.test().await());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable) {
|
||||
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableTestAssertComplete {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
completable.test().await().assertComplete(), completable.test().assertComplete());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable) {
|
||||
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableTestAssertErrorClass {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable, Class<? extends Throwable> errorClass)
|
||||
throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
completable.test().await().assertError(errorClass),
|
||||
completable.test().assertError(errorClass));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable, Class<? extends Throwable> errorClass) {
|
||||
RxJava2Adapter.completableToMono(completable)
|
||||
.as(StepVerifier::create)
|
||||
.verifyError(errorClass);
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableTestAssertNoErrors {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable) throws InterruptedException {
|
||||
completable.test().await().assertNoErrors();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable) {
|
||||
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableTestAssertValueCount {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable, int count) throws InterruptedException {
|
||||
completable.test().await().assertValueCount(count);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable, int count) {
|
||||
RxJava2Adapter.completableToMono(completable)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextCount(count)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableTestAssertFailure {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable, Class<? extends Throwable> error)
|
||||
throws InterruptedException {
|
||||
completable.test().await().assertFailure(error);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable, Class<? extends Throwable> error) {
|
||||
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyError(error);
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableTestAssertNoValues {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable) throws InterruptedException {
|
||||
completable.test().await().assertNoValues();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable) {
|
||||
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class CompletableTestAssertFailureAndMessage {
|
||||
@BeforeTemplate
|
||||
void before(Completable completable, Class<? extends Throwable> error, String message)
|
||||
throws InterruptedException {
|
||||
completable.test().await().assertFailureAndMessage(error, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Completable completable, Class<? extends Throwable> error, String message) {
|
||||
RxJava2Adapter.completableToMono(completable)
|
||||
.as(StepVerifier::create)
|
||||
.expectErrorSatisfies(
|
||||
t -> assertThat(t).isInstanceOf(error).hasMessageContaining(message))
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final TestObserver test(boolean)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,959 +0,0 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.CompletableSource;
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.MaybeSource;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleSource;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Action;
|
||||
import io.reactivex.functions.BiFunction;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.functions.Function;
|
||||
import io.reactivex.functions.Predicate;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
|
||||
|
||||
/** The Refaster templates for the migration of the RxJava Maybe type to Reactor */
|
||||
final class RxJavaMaybeToReactorTemplates {
|
||||
private RxJavaMaybeToReactorTemplates() {}
|
||||
|
||||
static final class MaybeAmb<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Iterable<? extends Maybe<? extends T>> iterable) {
|
||||
return Maybe.amb(iterable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Iterable<? extends Maybe<? extends T>> iterable) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
Mono.firstWithSignal(
|
||||
Streams.stream(iterable)
|
||||
.map(RxJava2Adapter::maybeToMono)
|
||||
.collect(toImmutableList())));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Maybe ambArray(MaybeSource... sources)
|
||||
// XXX: public static Flowable concat(Iterable)
|
||||
// XXX: public static Flowable concat(MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable concat(MaybeSource,MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable concat(MaybeSource,MaybeSource,MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable concat(Publisher)
|
||||
// XXX: public static Flowable concat(Publisher,int)
|
||||
|
||||
// XXX: How to make this conversion correct? Turned off test for now.
|
||||
static final class MaybeConcatArray<T> {
|
||||
@BeforeTemplate
|
||||
Flowable<T> before(@Repeated Maybe<T> sources) {
|
||||
return Maybe.concatArray(Refaster.asVarargs(sources));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<T> after(@Repeated Maybe<T> sources) {
|
||||
return RxJava2Adapter.fluxToFlowable(
|
||||
Flux.concat(
|
||||
Arrays.stream(Refaster.asVarargs(sources))
|
||||
.map(RxJava2Adapter::maybeToMono)
|
||||
.collect(toImmutableList())));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Flowable concatArrayDelayError(MaybeSource[])
|
||||
// XXX: public static Flowable concatArrayEager(MaybeSource[])
|
||||
// XXX: public static Flowable concatDelayError(Iterable)
|
||||
// XXX: public static Flowable concatDelayError(Publisher)
|
||||
// XXX: public static Flowable concatEager(Iterable)
|
||||
// XXX: public static Flowable concatEager(Publisher)
|
||||
// XXX: public static Maybe create(MaybeOnSubscribe)
|
||||
|
||||
/// XXX: Add test
|
||||
abstract static class MaybeDeferFirst<T> {
|
||||
@Placeholder
|
||||
abstract Maybe<T> maybeProducer();
|
||||
|
||||
@BeforeTemplate
|
||||
Maybe<T> before() {
|
||||
return Maybe.defer(() -> maybeProducer());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after() {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
Mono.defer(() -> RxJava2Adapter.maybeToMono(maybeProducer())));
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class MaybeDefer<T> {
|
||||
@Placeholder
|
||||
abstract Maybe<T> maybeProducer();
|
||||
|
||||
@BeforeTemplate
|
||||
Mono<T> before() {
|
||||
return Maybe.defer(() -> maybeProducer()).as(RxJava2Adapter::maybeToMono);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<T> after() {
|
||||
return Mono.defer(() -> RxJava2Adapter.maybeToMono(maybeProducer()));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeEmpty<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before() {
|
||||
return Maybe.empty();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after() {
|
||||
return RxJava2Adapter.monoToMaybe(Mono.empty());
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeErrorCallable<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Callable<? extends Throwable> throwable) {
|
||||
return Maybe.error(throwable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Callable<? extends Throwable> throwable) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
Mono.error(RxJavaReactorMigrationUtil.callableAsSupplier(throwable)));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeErrorThrowable<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Throwable throwable) {
|
||||
return Maybe.error(throwable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Throwable throwable) {
|
||||
return RxJava2Adapter.monoToMaybe(Mono.error(throwable));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeFromAction<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Action action) {
|
||||
return Maybe.fromAction(action);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Action action) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
Mono.fromRunnable(RxJavaReactorMigrationUtil.toRunnable(action)));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeFromCallable<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Callable<? extends T> callable) {
|
||||
return Maybe.fromCallable(callable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Callable<? extends T> callable) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
Mono.fromSupplier(RxJavaReactorMigrationUtil.callableAsSupplier(callable)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Maybe fromCompletable(CompletableSource)
|
||||
|
||||
// XXX: Also handle `Future`s that don't extend `CompletableFuture`.
|
||||
static final class MaybeFromFuture<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(CompletableFuture<? extends T> future) {
|
||||
return Maybe.fromFuture(future);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(CompletableFuture<? extends T> future) {
|
||||
return RxJava2Adapter.monoToMaybe(Mono.fromFuture(future));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Maybe fromFuture(Future,long,TimeUnit)
|
||||
|
||||
static final class MaybeFromRunnable<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Runnable runnable) {
|
||||
return Maybe.fromRunnable(runnable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Runnable runnable) {
|
||||
return RxJava2Adapter.monoToMaybe(Mono.fromRunnable(runnable));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeFromSingle<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(SingleSource<T> source) {
|
||||
return Maybe.fromSingle(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(SingleSource<T> source) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
Mono.from(RxJava2Adapter.singleToMono(Single.wrap(source))));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeJust<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(T item) {
|
||||
return Maybe.just(item);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(T item) {
|
||||
return RxJava2Adapter.monoToMaybe(Mono.just(item));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Flowable merge(Iterable)
|
||||
// XXX: public static Maybe merge(MaybeSource)
|
||||
// XXX: public static Flowable merge(MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable merge(MaybeSource,MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable merge(MaybeSource,MaybeSource,MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable merge(Publisher)
|
||||
// XXX: public static Flowable merge(Publisher,int)
|
||||
// XXX: public static Flowable mergeArray(MaybeSource[])
|
||||
// XXX: public static Flowable mergeArrayDelayError(MaybeSource[])
|
||||
// XXX: public static Flowable mergeDelayError(Iterable)
|
||||
// XXX: public static Flowable mergeDelayError(MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable mergeDelayError(MaybeSource,MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable mergeDelayError(MaybeSource,MaybeSource,MaybeSource,MaybeSource)
|
||||
// XXX: public static Flowable mergeDelayError(Publisher)
|
||||
// XXX: public static Flowable mergeDelayError(Publisher,int)
|
||||
// XXX: public static Maybe never()
|
||||
// XXX: public static Single sequenceEqual(MaybeSource,MaybeSource)
|
||||
// XXX: public static Single sequenceEqual(MaybeSource,MaybeSource,BiPredicate)
|
||||
// XXX: public static Maybe timer(long,TimeUnit)
|
||||
// XXX: public static Maybe timer(long,TimeUnit,Scheduler)
|
||||
// XXX: public static Maybe unsafeCreate(MaybeSource)
|
||||
// XXX: public static Maybe using(Callable,Function,Consumer)
|
||||
// XXX: public static Maybe using(Callable,Function,Consumer,boolean)
|
||||
|
||||
static final class MaybeWrap<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<T> maybe) {
|
||||
return Maybe.wrap(maybe);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<T> maybe) {
|
||||
return maybe;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Maybe zip(Iterable,Function)
|
||||
// XXX: public static Maybe zip(MaybeSource,MaybeSource,BiFunction)
|
||||
// XXX: public static Maybe zip(MaybeSource,MaybeSource,MaybeSource,Function3)
|
||||
// XXX: public static Maybe zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function4)
|
||||
// XXX: public static Maybe
|
||||
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function5)
|
||||
// XXX: public static Maybe
|
||||
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function6)
|
||||
// XXX: public static Maybe
|
||||
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function7)
|
||||
// XXX: public static Maybe
|
||||
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function8)
|
||||
// XXX: public static Maybe
|
||||
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function9)
|
||||
// XXX: public static Maybe zipArray(Function,MaybeSource[])
|
||||
|
||||
static final class MaybeAmbWith<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<T> maybe, Maybe<? extends T> otherMaybe) {
|
||||
return maybe.ambWith(otherMaybe);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<T> maybe, Maybe<? extends T> otherMaybe) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe).or(RxJava2Adapter.maybeToMono(otherMaybe)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Object as(MaybeConverter)
|
||||
|
||||
static final class MaybeBlockingGet<T> {
|
||||
@BeforeTemplate
|
||||
Object before(Maybe<T> maybe) {
|
||||
return maybe.blockingGet();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Object after(Maybe<T> maybe) {
|
||||
return RxJava2Adapter.maybeToMono(maybe).block();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Object blockingGet(Object)
|
||||
// XXX: public final Maybe cache()
|
||||
|
||||
static final class MaybeCast<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<T> maybe) {
|
||||
return maybe.cast(Refaster.<T>clazz());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<T> maybe) {
|
||||
return maybe;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Maybe compose(MaybeTransformer)
|
||||
// XXX: public final Maybe concatMap(Function)
|
||||
// XXX: public final Flowable concatWith(MaybeSource)
|
||||
// XXX: public final Single contains(Object)
|
||||
// XXX: public final Single count()
|
||||
|
||||
static final class MaybeDefaultIfEmpty<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<T> maybe, T item) {
|
||||
return maybe.defaultIfEmpty(item);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<T> maybe, T item) {
|
||||
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.maybeToMono(maybe).defaultIfEmpty(item));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Maybe delay(long,TimeUnit)
|
||||
// XXX: public final Maybe delay(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Maybe delay(Publisher)
|
||||
// XXX: public final Maybe delaySubscription(long,TimeUnit)
|
||||
// XXX: public final Maybe delaySubscription(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Maybe delaySubscription(Publisher)
|
||||
// XXX: public final Maybe doAfterSuccess(Consumer)
|
||||
// XXX: public final Maybe doAfterTerminate(Action)
|
||||
// XXX: public final Maybe doFinally(Action)
|
||||
// XXX: public final Maybe doOnComplete(Action)
|
||||
// XXX: public final Maybe doOnDispose(Action)
|
||||
|
||||
static final class MaybeDoOnError<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<T> maybe, Consumer<? super Throwable> consumer) {
|
||||
return maybe.doOnError(consumer);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<T> maybe, Consumer<? super Throwable> consumer) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Maybe doOnEvent(BiConsumer)
|
||||
// XXX: public final Maybe doOnSubscribe(Consumer)
|
||||
|
||||
static final class MaybeDoOnSuccess<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<T> maybe, Consumer<T> consumer) {
|
||||
return maybe.doOnSuccess(consumer);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<T> maybe, Consumer<T> consumer) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.doOnSuccess(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Maybe doOnTerminate(Action)
|
||||
|
||||
static final class MaybeFilter<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<T> maybe, Predicate<T> predicate) {
|
||||
return maybe.filter(predicate);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<T> maybe, Predicate<T> predicate) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate)));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeFlatMapFunction<
|
||||
I, T extends I, O, X extends O, M extends MaybeSource<X>> {
|
||||
@BeforeTemplate
|
||||
Maybe<O> before(
|
||||
Maybe<T> maybe, Function<? super T, ? extends MaybeSource<? extends O>> function) {
|
||||
return maybe.flatMap(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
|
||||
Maybe<O> after(Maybe<T> maybe, Function<I, M> function) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.flatMap(
|
||||
v ->
|
||||
RxJava2Adapter.maybeToMono(
|
||||
Maybe.wrap(
|
||||
RxJavaReactorMigrationUtil.<I, M>toJdkFunction(function).apply(v)))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: There is no link to an original public method for this, but it is important.
|
||||
abstract static class MaybeFlatMapLambda<S, T> {
|
||||
@Placeholder
|
||||
abstract Maybe<T> toMaybeFunction(@MayOptionallyUse S element);
|
||||
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<S> maybe) {
|
||||
return maybe.flatMap(v -> toMaybeFunction(v));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<S> maybe) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.flatMap(z -> toMaybeFunction(z).as(RxJava2Adapter::maybeToMono)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Maybe flatMap(Function,BiFunction)
|
||||
// XXX: public final Maybe flatMap(Function,Function,Callable)
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeFlatMapCompletable<T, R extends CompletableSource> {
|
||||
@BeforeTemplate
|
||||
Completable before(Maybe<T> maybe, Function<T, R> function) {
|
||||
return maybe.flatMapCompletable(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Maybe<T> maybe, Function<T, R> function) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.flatMap(
|
||||
y ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction((Function<T, R>) function)
|
||||
.apply(y))))
|
||||
.then());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Observable flatMapObservable(Function)
|
||||
|
||||
static final class MaybeFlatMapPublisher<T, O extends T, R extends Publisher<O>> {
|
||||
@BeforeTemplate
|
||||
Flowable<O> before(
|
||||
Maybe<T> maybe, Function<? super T, ? extends Publisher<? extends O>> function) {
|
||||
return maybe.flatMapPublisher(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<O> after(Maybe<T> maybe, Function<T, R> function) {
|
||||
return RxJava2Adapter.monoToFlowable(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.flatMap(
|
||||
y ->
|
||||
Mono.from(
|
||||
RxJavaReactorMigrationUtil.<T, R>toJdkFunction(function).apply(y))));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeFlatMapSingle<T, O extends T, R extends SingleSource<O>> {
|
||||
@BeforeTemplate
|
||||
Single<O> before(
|
||||
Maybe<T> maybe, Function<? super T, ? extends SingleSource<? extends O>> function) {
|
||||
return maybe.flatMapSingle(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<O> after(Maybe<T> maybe, Function<T, R> function) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.flatMap(
|
||||
y ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
Single.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, R>toJdkFunction(function).apply(y)))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Improve the @AfterTemplate to not have a cast
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class MaybeFlatMapSingleElement<T, O> {
|
||||
@BeforeTemplate
|
||||
Maybe<O> before(
|
||||
Maybe<T> maybe, Function<? super T, ? extends SingleSource<? extends O>> function) {
|
||||
return maybe.flatMapSingleElement(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<O> after(
|
||||
Maybe<T> maybe, Function<? super T, ? extends SingleSource<? extends O>> function) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.flatMap(
|
||||
e ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
Single.wrap(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(Function<T, SingleSource<O>>) function)
|
||||
.apply(e)))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Flowable flattenAsFlowable(Function)
|
||||
// XXX: public final Observable flattenAsObservable(Function)
|
||||
// XXX: public final Maybe hide()
|
||||
|
||||
static final class MaybeIgnoreElement<T> {
|
||||
@BeforeTemplate
|
||||
Completable before(Maybe<T> maybe) {
|
||||
return maybe.ignoreElement();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Maybe<T> maybe) {
|
||||
return RxJava2Adapter.monoToCompletable(RxJava2Adapter.maybeToMono(maybe).then());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeIsEmpty<T> {
|
||||
@BeforeTemplate
|
||||
Single<Boolean> before(Maybe<T> maybe) {
|
||||
return maybe.isEmpty();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<Boolean> after(Maybe<T> maybe) {
|
||||
return RxJava2Adapter.monoToSingle(RxJava2Adapter.maybeToMono(maybe).hasElement());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Maybe lift(MaybeOperator)
|
||||
// XXX: public final Maybe map(Function)
|
||||
|
||||
static final class MaybeMap<T, R> {
|
||||
@BeforeTemplate
|
||||
Maybe<R> before(Maybe<T> maybe, Function<T, R> mapper) {
|
||||
return maybe.map(mapper);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<R> after(Maybe<T> maybe, Function<T, R> mapper) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe).map(RxJavaReactorMigrationUtil.toJdkFunction(mapper)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single materialize()
|
||||
// XXX: public final Flowable mergeWith(MaybeSource)
|
||||
// XXX: public final Maybe observeOn(Scheduler)
|
||||
// XXX: public final Maybe ofType(Class)
|
||||
// XXX: public final Maybe onErrorComplete()
|
||||
// XXX: public final Maybe onErrorComplete(Predicate)
|
||||
// XXX: public final Maybe onErrorResumeNext(Function)
|
||||
// XXX: public final Maybe onErrorResumeNext(MaybeSource)
|
||||
// XXX: public final Maybe onErrorReturn(Function)
|
||||
|
||||
abstract static class MaybeOnErrorReturn<T, R> {
|
||||
@Placeholder
|
||||
abstract T placeholder(@MayOptionallyUse Throwable throwable);
|
||||
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Maybe<T> maybe) {
|
||||
return maybe.onErrorReturn(t -> placeholder(t));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Maybe<T> maybe) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe).onErrorResume(t -> Mono.just(placeholder(t))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Maybe onErrorReturnItem(Object)
|
||||
// XXX: public final Maybe onExceptionResumeNext(MaybeSource)
|
||||
// XXX: public final Maybe onTerminateDetach()
|
||||
// XXX: public final Flowable repeat()
|
||||
// XXX: public final Flowable repeat(long)
|
||||
// XXX: public final Flowable repeatUntil(BooleanSupplier)
|
||||
// XXX: public final Flowable repeatWhen(Function)
|
||||
// XXX: public final Maybe retry()
|
||||
// XXX: public final Maybe retry(BiPredicate)
|
||||
// XXX: public final Maybe retry(long)
|
||||
// XXX: public final Maybe retry(long,Predicate)
|
||||
// XXX: public final Maybe retry(Predicate)
|
||||
// XXX: public final Maybe retryUntil(BooleanSupplier)
|
||||
// XXX: public final Maybe retryWhen(Function)
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeSubscribe<T> {
|
||||
@BeforeTemplate
|
||||
Disposable before(Maybe<T> maybe) {
|
||||
return maybe.subscribe();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
reactor.core.Disposable after(Maybe<T> maybe) {
|
||||
return RxJava2Adapter.maybeToMono(maybe).subscribe();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeSubscribeConsumer<T> {
|
||||
@BeforeTemplate
|
||||
Disposable before(Maybe<T> maybe, Consumer<? super T> consumer) {
|
||||
return maybe.subscribe(consumer);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
reactor.core.Disposable after(Maybe<T> maybe, Consumer<? super T> consumer) {
|
||||
return RxJava2Adapter.maybeToMono(maybe)
|
||||
.subscribe(RxJavaReactorMigrationUtil.toJdkConsumer(consumer));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeSubscribeTwoConsumers<T> {
|
||||
@BeforeTemplate
|
||||
Disposable before(
|
||||
Maybe<T> maybe, Consumer<? super T> consumer1, Consumer<? super Throwable> consumer2) {
|
||||
return maybe.subscribe(consumer1, consumer2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
reactor.core.Disposable after(
|
||||
Maybe<T> maybe, Consumer<? super T> consumer1, Consumer<? super Throwable> consumer2) {
|
||||
return RxJava2Adapter.maybeToMono(maybe)
|
||||
.subscribe(
|
||||
RxJavaReactorMigrationUtil.toJdkConsumer(consumer1),
|
||||
RxJavaReactorMigrationUtil.toJdkConsumer(consumer2));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeSubscribeTwoConsumersWithAction<T> {
|
||||
@BeforeTemplate
|
||||
Disposable before(
|
||||
Maybe<T> maybe,
|
||||
Consumer<? super T> consumer1,
|
||||
Consumer<? super Throwable> consumer2,
|
||||
Action action) {
|
||||
return maybe.subscribe(consumer1, consumer2, action);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
reactor.core.Disposable after(
|
||||
Maybe<T> maybe,
|
||||
Consumer<? super T> consumer1,
|
||||
Consumer<? super Throwable> consumer2,
|
||||
Action action) {
|
||||
return RxJava2Adapter.maybeToMono(maybe)
|
||||
.subscribe(
|
||||
RxJavaReactorMigrationUtil.toJdkConsumer(consumer1),
|
||||
RxJavaReactorMigrationUtil.toJdkConsumer(consumer2),
|
||||
RxJavaReactorMigrationUtil.toRunnable(action));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final void subscribe(MaybeObserver)
|
||||
// XXX: public final Maybe subscribeOn(Scheduler)
|
||||
// XXX: public final MaybeObserver subscribeWith(MaybeObserver)
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeSourceSwitchIfEmpty<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
Maybe<S> before(Maybe<S> maybe, MaybeSource<T> maybeSource) {
|
||||
return maybe.switchIfEmpty(maybeSource);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<S> after(Maybe<S> maybe, MaybeSource<T> maybeSource) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.switchIfEmpty(RxJava2Adapter.maybeToMono(Maybe.wrap(maybeSource))));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeSwitchIfEmpty<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
Single<S> before(Maybe<S> maybe, SingleSource<T> single) {
|
||||
return maybe.switchIfEmpty(single);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<S> after(Maybe<S> maybe, SingleSource<T> single) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.switchIfEmpty(RxJava2Adapter.singleToMono(Single.wrap(single))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Maybe takeUntil(MaybeSource)
|
||||
// XXX: public final Maybe takeUntil(Publisher)
|
||||
// XXX: public final Maybe timeout(long,TimeUnit)
|
||||
// XXX: public final Maybe timeout(long,TimeUnit,MaybeSource)
|
||||
// XXX: public final Maybe timeout(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Maybe timeout(long,TimeUnit,Scheduler,MaybeSource)
|
||||
// XXX: public final Maybe timeout(MaybeSource)
|
||||
// XXX: public final Maybe timeout(MaybeSource,MaybeSource)
|
||||
// XXX: public final Maybe timeout(Publisher)
|
||||
// XXX: public final Maybe timeout(Publisher,MaybeSource)
|
||||
// XXX: public final Object to(Function)
|
||||
|
||||
static final class MaybeToFlowable<T> {
|
||||
@BeforeTemplate
|
||||
Flowable<T> before(Maybe<T> maybe) {
|
||||
return maybe.toFlowable();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<T> after(Maybe<T> maybe) {
|
||||
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.maybeToMono(maybe).flux());
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeToObservable<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before(Maybe<T> maybe) {
|
||||
return maybe.toObservable();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after(Maybe<T> maybe) {
|
||||
return RxJava2Adapter.fluxToObservable(RxJava2Adapter.maybeToMono(maybe).flux());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeToSingle<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Maybe<T> maybe) {
|
||||
return maybe.toSingle();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Maybe<T> maybe) {
|
||||
return RxJava2Adapter.monoToSingle(RxJava2Adapter.maybeToMono(maybe).single());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single toSingle(Object)
|
||||
// XXX: public final Maybe unsubscribeOn(Scheduler)
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeZipWith<T, R, U> {
|
||||
@BeforeTemplate
|
||||
Maybe<R> before(
|
||||
Maybe<T> maybe,
|
||||
MaybeSource<U> source,
|
||||
BiFunction<? super T, ? super U, ? extends R> biFunction) {
|
||||
return maybe.zipWith(source, biFunction);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<R> after(
|
||||
Maybe<T> maybe,
|
||||
MaybeSource<U> source,
|
||||
BiFunction<? super T, ? super U, ? extends R> biFunction) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.zipWith(
|
||||
RxJava2Adapter.maybeToMono(Maybe.wrap(source)),
|
||||
RxJavaReactorMigrationUtil.toJdkBiFunction(biFunction)));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class MaybeTestAssertResultItem<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe, T item) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
maybe.test().await().assertResult(item),
|
||||
maybe.test().await().assertResult(item).assertComplete(),
|
||||
maybe.test().await().assertComplete().assertResult(item),
|
||||
maybe.test().await().assertValue(item),
|
||||
maybe.test().await().assertValue(item).assertComplete(),
|
||||
maybe.test().await().assertComplete().assertValue(item),
|
||||
// XXX: Move this to correct method
|
||||
maybe.test().await().assertValues(item));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe, T item) {
|
||||
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).expectNext(item).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class MaybeTestAssertResult<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe) throws InterruptedException {
|
||||
maybe.test().await().assertResult();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe) {
|
||||
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeTestAssertValue<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe, Predicate<T> predicate) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
maybe.test().await().assertValue(predicate),
|
||||
maybe.test().await().assertValue(predicate).assertComplete(),
|
||||
maybe.test().await().assertValue(predicate).assertNoErrors().assertComplete(),
|
||||
maybe.test().await().assertComplete().assertValue(predicate));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe, Predicate<T> predicate) {
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(predicate))
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeTestAssertComplete<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe) throws InterruptedException {
|
||||
maybe.test().await().assertComplete();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe) {
|
||||
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeTestAssertErrorClass<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe, Class<? extends Throwable> errorClass) throws InterruptedException {
|
||||
maybe.test().await().assertError(errorClass);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe, Class<? extends Throwable> errorClass) {
|
||||
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyError(errorClass);
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeTestAssertNoErrors<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe) throws InterruptedException {
|
||||
maybe.test().await().assertNoErrors();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe) {
|
||||
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class MaybeTestAssertValueCount<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe, int count) throws InterruptedException {
|
||||
maybe.test().await().assertValueCount(count);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe, int count) {
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextCount(count)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class MaybeTestAssertFailure<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe, Class<? extends Throwable> error) throws InterruptedException {
|
||||
maybe.test().await().assertFailure(error);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe, Class<? extends Throwable> error) {
|
||||
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyError(error);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class MaybeTestAssertNoValues<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
maybe.test().await().assertNoValues(),
|
||||
maybe.test().assertNoValues(),
|
||||
maybe.test().assertNoValues().assertComplete(),
|
||||
maybe.test().await().assertNoValues().assertComplete(),
|
||||
maybe.test().await().assertComplete().assertNoValues());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe) {
|
||||
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
// XXX: This introduces AssertJ dependency
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class MaybeTestAssertFailureAndMessage<T> {
|
||||
@BeforeTemplate
|
||||
void before(Maybe<T> maybe, Class<? extends Throwable> error, String message)
|
||||
throws InterruptedException {
|
||||
maybe.test().await().assertFailureAndMessage(error, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Maybe<T> maybe, Class<? extends Throwable> error, String message) {
|
||||
RxJava2Adapter.maybeToMono(maybe)
|
||||
.as(StepVerifier::create)
|
||||
.expectErrorSatisfies(
|
||||
t -> assertThat(t).isInstanceOf(error).hasMessageContaining(message))
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final TestObserver test(boolean)
|
||||
}
|
||||
@@ -1,927 +0,0 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import io.reactivex.BackpressureStrategy;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.MaybeSource;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.ObservableSource;
|
||||
import io.reactivex.functions.Function;
|
||||
import io.reactivex.functions.Predicate;
|
||||
import java.util.concurrent.Callable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
|
||||
|
||||
/** The Refaster templates for the migration of the RxJava Observable type to Reactor */
|
||||
final class RxJavaObservableToReactorTemplates {
|
||||
|
||||
private RxJavaObservableToReactorTemplates() {}
|
||||
|
||||
static final class ObservableAmb<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before(Iterable<? extends Observable<T>> sources) {
|
||||
return Observable.amb(sources);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after(Iterable<? extends Observable<T>> sources) {
|
||||
return RxJava2Adapter.fluxToObservable(
|
||||
Flux.<T>firstWithSignal(
|
||||
Streams.stream(sources)
|
||||
.map(e -> e.toFlowable(BackpressureStrategy.BUFFER))
|
||||
.map(RxJava2Adapter::flowableToFlux)
|
||||
.collect(toImmutableList())));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Observable ambArray(ObservableSource[])
|
||||
// XXX: public static int bufferSize()
|
||||
// XXX: public static Observable combineLatest(Function,int,ObservableSource[])
|
||||
// XXX: public static Observable combineLatest(Iterable,Function)
|
||||
// XXX: public static Observable combineLatest(Iterable,Function,int)
|
||||
// XXX: public static Observable combineLatest(ObservableSource[],Function)
|
||||
// XXX: public static Observable combineLatest(ObservableSource[],Function,int)
|
||||
// XXX: public static Observable combineLatest(ObservableSource,ObservableSource,BiFunction)
|
||||
// XXX: public static Observable
|
||||
// combineLatest(ObservableSource,ObservableSource,ObservableSource,Function3)
|
||||
// XXX: public static Observable
|
||||
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function4)
|
||||
// XXX: public static Observable
|
||||
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function5)
|
||||
// XXX: public static Observable
|
||||
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function6)
|
||||
// XXX: public static Observable
|
||||
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function7)
|
||||
// XXX: public static Observable
|
||||
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function8)
|
||||
// XXX: public static Observable
|
||||
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function9)
|
||||
// XXX: public static Observable combineLatestDelayError(Function,int,ObservableSource[])
|
||||
// XXX: public static Observable combineLatestDelayError(Iterable,Function)
|
||||
// XXX: public static Observable combineLatestDelayError(Iterable,Function,int)
|
||||
// XXX: public static Observable combineLatestDelayError(ObservableSource[],Function)
|
||||
// XXX: public static Observable combineLatestDelayError(ObservableSource[],Function,int)
|
||||
// XXX: public static Observable concat(Iterable)
|
||||
// XXX: public static Observable concat(ObservableSource)
|
||||
// XXX: public static Observable concat(ObservableSource,int)
|
||||
// XXX: public static Observable concat(ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable concat(ObservableSource,ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable
|
||||
// concat(ObservableSource,ObservableSource,ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable concatArray(ObservableSource[])
|
||||
// XXX: public static Observable concatArrayDelayError(ObservableSource[])
|
||||
// XXX: public static Observable concatArrayEager(int,int,ObservableSource[])
|
||||
// XXX: public static Observable concatArrayEager(ObservableSource[])
|
||||
// XXX: public static Observable concatArrayEagerDelayError(int,int,ObservableSource[])
|
||||
// XXX: public static Observable concatArrayEagerDelayError(ObservableSource[])
|
||||
// XXX: public static Observable concatDelayError(Iterable)
|
||||
// XXX: public static Observable concatDelayError(ObservableSource)
|
||||
// XXX: public static Observable concatDelayError(ObservableSource,int,boolean)
|
||||
// XXX: public static Observable concatEager(Iterable)
|
||||
// XXX: public static Observable concatEager(Iterable,int,int)
|
||||
// XXX: public static Observable concatEager(ObservableSource)
|
||||
// XXX: public static Observable concatEager(ObservableSource,int,int)
|
||||
// XXX: public static Observable create(ObservableOnSubscribe)
|
||||
// XXX: public static Observable defer(Callable)
|
||||
|
||||
static final class ObservableEmpty<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before() {
|
||||
return Observable.empty();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after() {
|
||||
return RxJava2Adapter.fluxToObservable(Flux.empty());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Observable error(Callable)
|
||||
// XXX: public static Observable error(Throwable)
|
||||
// XXX: public static Observable fromArray(Object[])
|
||||
|
||||
static final class ObservableFromCallable<T> {
|
||||
@BeforeTemplate
|
||||
Observable<? extends T> before(Callable<? extends T> callable) {
|
||||
return Observable.fromCallable(callable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<? extends T> after(Callable<? extends T> callable) {
|
||||
return RxJava2Adapter.fluxToObservable(
|
||||
Mono.fromSupplier(RxJavaReactorMigrationUtil.callableAsSupplier(callable)).flux());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Observable fromFuture(Future)
|
||||
// XXX: public static Observable fromFuture(Future,long,TimeUnit)
|
||||
// XXX: public static Observable fromFuture(Future,long,TimeUnit,Scheduler)
|
||||
// XXX: public static Observable fromFuture(Future,Scheduler)
|
||||
// XXX: public static Observable fromIterable(Iterable)
|
||||
|
||||
static final class ObservableFromPublisher<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before(Publisher<? extends T> source) {
|
||||
return Observable.fromPublisher(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after(Publisher<? extends T> source) {
|
||||
return RxJava2Adapter.fluxToObservable(Flux.from(source));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Observable generate(Callable,BiConsumer)
|
||||
// XXX: public static Observable generate(Callable,BiConsumer,Consumer)
|
||||
// XXX: public static Observable generate(Callable,BiFunction)
|
||||
// XXX: public static Observable generate(Callable,BiFunction,Consumer)
|
||||
// XXX: public static Observable generate(Consumer)
|
||||
// XXX: public static Observable interval(long,long,TimeUnit)
|
||||
// XXX: public static Observable interval(long,long,TimeUnit,Scheduler)
|
||||
// XXX: public static Observable interval(long,TimeUnit)
|
||||
// XXX: public static Observable interval(long,TimeUnit,Scheduler)
|
||||
// XXX: public static Observable intervalRange(long,long,long,long,TimeUnit)
|
||||
// XXX: public static Observable intervalRange(long,long,long,long,TimeUnit,Scheduler)
|
||||
|
||||
static final class ObservableJust<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before(T t) {
|
||||
return Observable.just(t);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after(T t) {
|
||||
return RxJava2Adapter.fluxToObservable(Flux.just(t));
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObservableJustTwo<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before(T t, T t2) {
|
||||
return Observable.just(t, t2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after(T t, T t2) {
|
||||
return RxJava2Adapter.fluxToObservable(Flux.just(t, t2));
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObservableJustThree<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before(T t, T t2, T t3) {
|
||||
return Observable.just(t, t2, t3);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after(T t, T t2, T t3) {
|
||||
return RxJava2Adapter.fluxToObservable(Flux.just(t, t2, t3));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Observable just(Object,Object,Object,Object)
|
||||
// XXX: public static Observable just(Object,Object,Object,Object,Object)
|
||||
// XXX: public static Observable just(Object,Object,Object,Object,Object,Object)
|
||||
// XXX: public static Observable just(Object,Object,Object,Object,Object,Object,Object)
|
||||
// XXX: public static Observable just(Object,Object,Object,Object,Object,Object,Object,Object)
|
||||
// XXX: public static Observable
|
||||
// just(Object,Object,Object,Object,Object,Object,Object,Object,Object)
|
||||
// XXX: public static Observable
|
||||
// just(Object,Object,Object,Object,Object,Object,Object,Object,Object,Object)
|
||||
// XXX: public static Observable merge(Iterable)
|
||||
// XXX: public static Observable merge(Iterable,int)
|
||||
// XXX: public static Observable merge(Iterable,int,int)
|
||||
// XXX: public static Observable merge(ObservableSource)
|
||||
// XXX: public static Observable merge(ObservableSource,int)
|
||||
// XXX: public static Observable merge(ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable merge(ObservableSource,ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable
|
||||
// merge(ObservableSource,ObservableSource,ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable mergeArray(int,int,ObservableSource[])
|
||||
// XXX: public static Observable mergeArray(ObservableSource[])
|
||||
// XXX: public static Observable mergeArrayDelayError(int,int,ObservableSource[])
|
||||
// XXX: public static Observable mergeArrayDelayError(ObservableSource[])
|
||||
// XXX: public static Observable mergeDelayError(Iterable)
|
||||
// XXX: public static Observable mergeDelayError(Iterable,int)
|
||||
// XXX: public static Observable mergeDelayError(Iterable,int,int)
|
||||
// XXX: public static Observable mergeDelayError(ObservableSource)
|
||||
// XXX: public static Observable mergeDelayError(ObservableSource,int)
|
||||
// XXX: public static Observable mergeDelayError(ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable
|
||||
// mergeDelayError(ObservableSource,ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable
|
||||
// mergeDelayError(ObservableSource,ObservableSource,ObservableSource,ObservableSource)
|
||||
// XXX: public static Observable never()
|
||||
// XXX: public static Observable range(int,int)
|
||||
// XXX: public static Observable rangeLong(long,long)
|
||||
// XXX: public static Single sequenceEqual(ObservableSource,ObservableSource)
|
||||
// XXX: public static Single sequenceEqual(ObservableSource,ObservableSource,BiPredicate)
|
||||
// XXX: public static Single sequenceEqual(ObservableSource,ObservableSource,BiPredicate,int)
|
||||
// XXX: public static Single sequenceEqual(ObservableSource,ObservableSource,int)
|
||||
// XXX: public static Observable switchOnNext(ObservableSource)
|
||||
// XXX: public static Observable switchOnNext(ObservableSource,int)
|
||||
// XXX: public static Observable switchOnNextDelayError(ObservableSource)
|
||||
// XXX: public static Observable switchOnNextDelayError(ObservableSource,int)
|
||||
// XXX: public static Observable timer(long,TimeUnit)
|
||||
// XXX: public static Observable timer(long,TimeUnit,Scheduler)
|
||||
// XXX: public static Observable unsafeCreate(ObservableSource)
|
||||
// XXX: public static Observable using(Callable,Function,Consumer)
|
||||
// XXX: public static Observable using(Callable,Function,Consumer,boolean)
|
||||
// XXX: public static Observable wrap(ObservableSource)
|
||||
// XXX: public static Observable zip(Iterable,Function)
|
||||
// XXX: public static Observable zip(ObservableSource,Function)
|
||||
// XXX: public static Observable zip(ObservableSource,ObservableSource,BiFunction)
|
||||
// XXX: public static Observable zip(ObservableSource,ObservableSource,BiFunction,boolean)
|
||||
// XXX: public static Observable zip(ObservableSource,ObservableSource,BiFunction,boolean,int)
|
||||
// XXX: public static Observable zip(ObservableSource,ObservableSource,ObservableSource,Function3)
|
||||
// XXX: public static Observable
|
||||
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function4)
|
||||
// XXX: public static Observable
|
||||
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function5)
|
||||
// XXX: public static Observable
|
||||
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function6)
|
||||
// XXX: public static Observable
|
||||
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function7)
|
||||
// XXX: public static Observable
|
||||
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function8)
|
||||
// XXX: public static Observable
|
||||
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function9)
|
||||
// XXX: public static Observable zipArray(Function,boolean,int,ObservableSource[])
|
||||
// XXX: public static Observable zipIterable(Iterable,Function,boolean,int)
|
||||
// XXX: public final Single all(Predicate)
|
||||
// XXX: public final Observable ambWith(ObservableSource)
|
||||
// XXX: public final Single any(Predicate)
|
||||
// XXX: public final Object as(ObservableConverter)
|
||||
// XXX: public final Object blockingFirst()
|
||||
// XXX: public final Object blockingFirst(Object)
|
||||
// XXX: public final void blockingForEach(Consumer)
|
||||
// XXX: public final Iterable blockingIterable()
|
||||
// XXX: public final Iterable blockingIterable(int)
|
||||
// XXX: public final Object blockingLast()
|
||||
// XXX: public final Object blockingLast(Object)
|
||||
// XXX: public final Iterable blockingLatest()
|
||||
// XXX: public final Iterable blockingMostRecent(Object)
|
||||
// XXX: public final Iterable blockingNext()
|
||||
// XXX: public final Object blockingSingle()
|
||||
// XXX: public final Object blockingSingle(Object)
|
||||
// XXX: public final void blockingSubscribe()
|
||||
// XXX: public final void blockingSubscribe(Consumer)
|
||||
// XXX: public final void blockingSubscribe(Consumer,Consumer)
|
||||
// XXX: public final void blockingSubscribe(Consumer,Consumer,Action)
|
||||
// XXX: public final void blockingSubscribe(Observer)
|
||||
// XXX: public final Observable buffer(Callable)
|
||||
// XXX: public final Observable buffer(Callable,Callable)
|
||||
// XXX: public final Observable buffer(int)
|
||||
// XXX: public final Observable buffer(int,Callable)
|
||||
// XXX: public final Observable buffer(int,int)
|
||||
// XXX: public final Observable buffer(int,int,Callable)
|
||||
// XXX: public final Observable buffer(long,long,TimeUnit)
|
||||
// XXX: public final Observable buffer(long,long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable buffer(long,long,TimeUnit,Scheduler,Callable)
|
||||
// XXX: public final Observable buffer(long,TimeUnit)
|
||||
// XXX: public final Observable buffer(long,TimeUnit,int)
|
||||
// XXX: public final Observable buffer(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable buffer(long,TimeUnit,Scheduler,int)
|
||||
// XXX: public final Observable buffer(long,TimeUnit,Scheduler,int,Callable,boolean)
|
||||
// XXX: public final Observable buffer(ObservableSource)
|
||||
// XXX: public final Observable buffer(ObservableSource,Callable)
|
||||
// XXX: public final Observable buffer(ObservableSource,Function)
|
||||
// XXX: public final Observable buffer(ObservableSource,Function,Callable)
|
||||
// XXX: public final Observable buffer(ObservableSource,int)
|
||||
// XXX: public final Observable cache()
|
||||
// XXX: public final Observable cacheWithInitialCapacity(int)
|
||||
// XXX: public final Observable cast(Class)
|
||||
// XXX: public final Single collect(Callable,BiConsumer)
|
||||
// XXX: public final Single collectInto(Object,BiConsumer)
|
||||
// XXX: public final Observable compose(ObservableTransformer)
|
||||
// XXX: public final Observable concatMap(Function)
|
||||
// XXX: public final Observable concatMap(Function,int)
|
||||
// XXX: public final Completable concatMapCompletable(Function)
|
||||
// XXX: public final Completable concatMapCompletable(Function,int)
|
||||
// XXX: public final Completable concatMapCompletableDelayError(Function)
|
||||
// XXX: public final Completable concatMapCompletableDelayError(Function,boolean)
|
||||
// XXX: public final Completable concatMapCompletableDelayError(Function,boolean,int)
|
||||
// XXX: public final Observable concatMapDelayError(Function)
|
||||
// XXX: public final Observable concatMapDelayError(Function,int,boolean)
|
||||
// XXX: public final Observable concatMapEager(Function)
|
||||
// XXX: public final Observable concatMapEager(Function,int,int)
|
||||
// XXX: public final Observable concatMapEagerDelayError(Function,boolean)
|
||||
// XXX: public final Observable concatMapEagerDelayError(Function,int,int,boolean)
|
||||
// XXX: public final Observable concatMapIterable(Function)
|
||||
// XXX: public final Observable concatMapIterable(Function,int)
|
||||
// XXX: public final Observable concatMapMaybe(Function)
|
||||
// XXX: public final Observable concatMapMaybe(Function,int)
|
||||
// XXX: public final Observable concatMapMaybeDelayError(Function)
|
||||
// XXX: public final Observable concatMapMaybeDelayError(Function,boolean)
|
||||
// XXX: public final Observable concatMapMaybeDelayError(Function,boolean,int)
|
||||
// XXX: public final Observable concatMapSingle(Function)
|
||||
// XXX: public final Observable concatMapSingle(Function,int)
|
||||
// XXX: public final Observable concatMapSingleDelayError(Function)
|
||||
// XXX: public final Observable concatMapSingleDelayError(Function,boolean)
|
||||
// XXX: public final Observable concatMapSingleDelayError(Function,boolean,int)
|
||||
// XXX: public final Observable concatWith(CompletableSource)
|
||||
// XXX: public final Observable concatWith(MaybeSource)
|
||||
// XXX: public final Observable concatWith(ObservableSource)
|
||||
// XXX: public final Observable concatWith(SingleSource)
|
||||
// XXX: public final Single contains(Object)
|
||||
// XXX: public final Single count()
|
||||
// XXX: public final Observable debounce(Function)
|
||||
// XXX: public final Observable debounce(long,TimeUnit)
|
||||
// XXX: public final Observable debounce(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable defaultIfEmpty(Object)
|
||||
// XXX: public final Observable delay(Function)
|
||||
// XXX: public final Observable delay(long,TimeUnit)
|
||||
// XXX: public final Observable delay(long,TimeUnit,boolean)
|
||||
// XXX: public final Observable delay(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable delay(long,TimeUnit,Scheduler,boolean)
|
||||
// XXX: public final Observable delay(ObservableSource,Function)
|
||||
// XXX: public final Observable delaySubscription(long,TimeUnit)
|
||||
// XXX: public final Observable delaySubscription(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable delaySubscription(ObservableSource)
|
||||
// XXX: public final Observable dematerialize()
|
||||
// XXX: public final Observable dematerialize(Function)
|
||||
// XXX: public final Observable distinct()
|
||||
// XXX: public final Observable distinct(Function)
|
||||
// XXX: public final Observable distinct(Function,Callable)
|
||||
// XXX: public final Observable distinctUntilChanged()
|
||||
// XXX: public final Observable distinctUntilChanged(BiPredicate)
|
||||
// XXX: public final Observable distinctUntilChanged(Function)
|
||||
// XXX: public final Observable doAfterNext(Consumer)
|
||||
// XXX: public final Observable doAfterTerminate(Action)
|
||||
// XXX: public final Observable doFinally(Action)
|
||||
// XXX: public final Observable doOnComplete(Action)
|
||||
// XXX: public final Observable doOnDispose(Action)
|
||||
// XXX: public final Observable doOnEach(Consumer)
|
||||
// XXX: public final Observable doOnEach(Observer)
|
||||
// XXX: public final Observable doOnError(Consumer)
|
||||
// XXX: public final Observable doOnLifecycle(Consumer,Action)
|
||||
// XXX: public final Observable doOnNext(Consumer)
|
||||
// XXX: public final Observable doOnSubscribe(Consumer)
|
||||
// XXX: public final Observable doOnTerminate(Action)
|
||||
// XXX: public final Maybe elementAt(long)
|
||||
// XXX: public final Single elementAt(long,Object)
|
||||
// XXX: public final Single elementAtOrError(long)
|
||||
|
||||
// XXX: Default BackPressureStrategy.BUFFER is set.
|
||||
static final class ObservableFilter<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before(Observable<T> observable, Predicate<T> predicate) {
|
||||
return observable.filter(predicate);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after(Observable<T> observable, Predicate<T> predicate) {
|
||||
return RxJava2Adapter.fluxToObservable(
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single first(Object)
|
||||
|
||||
// XXX: Default BUFFER is chosen here.
|
||||
static final class MaybeFirstElement<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Observable<T> observable) {
|
||||
return observable.firstElement();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Observable<T> observable) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER).next());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single firstOrError()
|
||||
// XXX: public final Observable flatMap(Function)
|
||||
|
||||
// XXX: Add test
|
||||
// XXX: Default BUFFER is set here.
|
||||
static final class ObservableFlatMap<I, T extends I, O, P extends ObservableSource<O>> {
|
||||
@BeforeTemplate
|
||||
Observable<O> before(
|
||||
Observable<T> observable,
|
||||
Function<? super T, ? extends ObservableSource<? extends O>> function) {
|
||||
return observable.flatMap(function);
|
||||
}
|
||||
|
||||
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
|
||||
@AfterTemplate
|
||||
Observable<O> after(Observable<T> observable, Function<I, P> function) {
|
||||
return RxJava2Adapter.fluxToObservable(
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.flatMap(
|
||||
z ->
|
||||
RxJava2Adapter.observableToFlux(
|
||||
Observable.wrap(
|
||||
RxJavaReactorMigrationUtil.<I, P>toJdkFunction(function).apply(z)),
|
||||
BackpressureStrategy.BUFFER)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Observable flatMap(Function,BiFunction)
|
||||
// XXX: public final Observable flatMap(Function,BiFunction,boolean)
|
||||
// XXX: public final Observable flatMap(Function,BiFunction,boolean,int)
|
||||
// XXX: public final Observable flatMap(Function,BiFunction,boolean,int,int)
|
||||
// XXX: public final Observable flatMap(Function,BiFunction,int)
|
||||
// XXX: public final Observable flatMap(Function,boolean)
|
||||
// XXX: public final Observable flatMap(Function,boolean,int)
|
||||
// XXX: public final Observable flatMap(Function,boolean,int,int)
|
||||
// XXX: public final Observable flatMap(Function,Function,Callable)
|
||||
// XXX: public final Observable flatMap(Function,Function,Callable,int)
|
||||
// XXX: public final Observable flatMap(Function,int)
|
||||
// XXX: public final Completable flatMapCompletable(Function)
|
||||
// XXX: public final Completable flatMapCompletable(Function,boolean)
|
||||
|
||||
static final class ObservableFromIterable<T> {
|
||||
@BeforeTemplate
|
||||
Observable<T> before(Iterable<? extends T> iterable) {
|
||||
return Observable.fromIterable(iterable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Observable<T> after(Iterable<? extends T> iterable) {
|
||||
return RxJava2Adapter.fluxToObservable(Flux.fromIterable(iterable));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Observable flatMapIterable(Function,BiFunction)
|
||||
|
||||
static final class ObservableFlatMapMaybe<T, R, O extends R, M extends MaybeSource<O>> {
|
||||
Observable<O> before(
|
||||
Observable<T> observable, Function<? super T, ? extends MaybeSource<? extends O>> mapper) {
|
||||
return observable.flatMapMaybe(mapper);
|
||||
}
|
||||
|
||||
Observable<O> after(Observable<T> observable, Function<T, M> mapper) {
|
||||
return RxJava2Adapter.fluxToObservable(
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.flatMap(
|
||||
t ->
|
||||
RxJava2Adapter.maybeToMono(
|
||||
Maybe.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, M>toJdkFunction(mapper).apply(t)))));
|
||||
}
|
||||
} // XXX: public final Observable flatMapMaybe(Function,boolean)
|
||||
// XXX: public final Observable flatMapSingle(Function)
|
||||
// XXX: public final Observable flatMapSingle(Function,boolean)
|
||||
// XXX: public final Disposable forEach(Consumer)
|
||||
// XXX: public final Disposable forEachWhile(Predicate)
|
||||
// XXX: public final Disposable forEachWhile(Predicate,Consumer)
|
||||
// XXX: public final Disposable forEachWhile(Predicate,Consumer,Action)
|
||||
// XXX: public final Observable groupBy(Function)
|
||||
// XXX: public final Observable groupBy(Function,boolean)
|
||||
// XXX: public final Observable groupBy(Function,Function)
|
||||
// XXX: public final Observable groupBy(Function,Function,boolean)
|
||||
// XXX: public final Observable groupBy(Function,Function,boolean,int)
|
||||
// XXX: public final Observable groupJoin(ObservableSource,Function,Function,BiFunction)
|
||||
// XXX: public final Observable hide()
|
||||
|
||||
static final class ObservableIgnoreElements<T> {
|
||||
@BeforeTemplate
|
||||
Completable before(Observable<T> observable) {
|
||||
return observable.ignoreElements();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Observable<T> observable) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.ignoreElements()
|
||||
.then());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single isEmpty()
|
||||
// XXX: public final Observable join(ObservableSource,Function,Function,BiFunction)
|
||||
// XXX: public final Single last(Object)
|
||||
// XXX: public final Maybe lastElement()
|
||||
// XXX: public final Single lastOrError()
|
||||
// XXX: public final Observable lift(ObservableOperator)
|
||||
// XXX: public final Observable map(Function)
|
||||
// XXX: public final Observable materialize()
|
||||
// XXX: public final Observable mergeWith(CompletableSource)
|
||||
// XXX: public final Observable mergeWith(MaybeSource)
|
||||
// XXX: public final Observable mergeWith(ObservableSource)
|
||||
// XXX: public final Observable mergeWith(SingleSource)
|
||||
// XXX: public final Observable observeOn(Scheduler)
|
||||
// XXX: public final Observable observeOn(Scheduler,boolean)
|
||||
// XXX: public final Observable observeOn(Scheduler,boolean,int)
|
||||
// XXX: public final Observable ofType(Class)
|
||||
// XXX: public final Observable onErrorResumeNext(Function)
|
||||
// XXX: public final Observable onErrorResumeNext(ObservableSource)
|
||||
// XXX: public final Observable onErrorReturn(Function)
|
||||
// XXX: public final Observable onErrorReturnItem(Object)
|
||||
// XXX: public final Observable onExceptionResumeNext(ObservableSource)
|
||||
// XXX: public final Observable onTerminateDetach()
|
||||
// XXX: public final ConnectableObservable publish()
|
||||
// XXX: public final Observable publish(Function)
|
||||
// XXX: public final Maybe reduce(BiFunction)
|
||||
// XXX: public final Single reduce(Object,BiFunction)
|
||||
// XXX: public final Single reduceWith(Callable,BiFunction)
|
||||
// XXX: public final Observable repeat()
|
||||
// XXX: public final Observable repeat(long)
|
||||
// XXX: public final Observable repeatUntil(BooleanSupplier)
|
||||
// XXX: public final Observable repeatWhen(Function)
|
||||
// XXX: public final ConnectableObservable replay()
|
||||
// XXX: public final Observable replay(Function)
|
||||
// XXX: public final Observable replay(Function,int)
|
||||
// XXX: public final Observable replay(Function,int,long,TimeUnit)
|
||||
// XXX: public final Observable replay(Function,int,long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable replay(Function,int,Scheduler)
|
||||
// XXX: public final Observable replay(Function,long,TimeUnit)
|
||||
// XXX: public final Observable replay(Function,long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable replay(Function,Scheduler)
|
||||
// XXX: public final ConnectableObservable replay(int)
|
||||
// XXX: public final ConnectableObservable replay(int,long,TimeUnit)
|
||||
// XXX: public final ConnectableObservable replay(int,long,TimeUnit,Scheduler)
|
||||
// XXX: public final ConnectableObservable replay(int,Scheduler)
|
||||
// XXX: public final ConnectableObservable replay(long,TimeUnit)
|
||||
// XXX: public final ConnectableObservable replay(long,TimeUnit,Scheduler)
|
||||
// XXX: public final ConnectableObservable replay(Scheduler)
|
||||
// XXX: public final Observable retry()
|
||||
// XXX: public final Observable retry(BiPredicate)
|
||||
// XXX: public final Observable retry(long)
|
||||
// XXX: public final Observable retry(long,Predicate)
|
||||
// XXX: public final Observable retry(Predicate)
|
||||
// XXX: public final Observable retryUntil(BooleanSupplier)
|
||||
// XXX: public final Observable retryWhen(Function)
|
||||
// XXX: public final void safeSubscribe(Observer)
|
||||
// XXX: public final Observable sample(long,TimeUnit)
|
||||
// XXX: public final Observable sample(long,TimeUnit,boolean)
|
||||
// XXX: public final Observable sample(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable sample(long,TimeUnit,Scheduler,boolean)
|
||||
// XXX: public final Observable sample(ObservableSource)
|
||||
// XXX: public final Observable sample(ObservableSource,boolean)
|
||||
// XXX: public final Observable scan(BiFunction)
|
||||
// XXX: public final Observable scan(Object,BiFunction)
|
||||
// XXX: public final Observable scanWith(Callable,BiFunction)
|
||||
// XXX: public final Observable serialize()
|
||||
// XXX: public final Observable share()
|
||||
// XXX: public final Single single(Object)
|
||||
// XXX: public final Maybe singleElement()
|
||||
// XXX: public final Single singleOrError()
|
||||
// XXX: public final Observable skip(long)
|
||||
// XXX: public final Observable skip(long,TimeUnit)
|
||||
// XXX: public final Observable skip(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable skipLast(int)
|
||||
// XXX: public final Observable skipLast(long,TimeUnit)
|
||||
// XXX: public final Observable skipLast(long,TimeUnit,boolean)
|
||||
// XXX: public final Observable skipLast(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable skipLast(long,TimeUnit,Scheduler,boolean)
|
||||
// XXX: public final Observable skipLast(long,TimeUnit,Scheduler,boolean,int)
|
||||
// XXX: public final Observable skipUntil(ObservableSource)
|
||||
// XXX: public final Observable skipWhile(Predicate)
|
||||
// XXX: public final Observable sorted()
|
||||
// XXX: public final Observable sorted(Comparator)
|
||||
// XXX: public final Observable startWith(Iterable)
|
||||
// XXX: public final Observable startWith(Object)
|
||||
// XXX: public final Observable startWith(ObservableSource)
|
||||
// XXX: public final Observable startWithArray(Object[])
|
||||
// XXX: public final Disposable subscribe()
|
||||
// XXX: public final Disposable subscribe(Consumer)
|
||||
// XXX: public final Disposable subscribe(Consumer,Consumer)
|
||||
// XXX: public final Disposable subscribe(Consumer,Consumer,Action)
|
||||
// XXX: public final Disposable subscribe(Consumer,Consumer,Action,Consumer)
|
||||
// XXX: public final void subscribe(Observer)
|
||||
// XXX: public final Observable subscribeOn(Scheduler)
|
||||
// XXX: public final Observer subscribeWith(Observer)
|
||||
// XXX: public final Observable switchIfEmpty(ObservableSource)
|
||||
// XXX: public final Observable switchMap(Function)
|
||||
// XXX: public final Observable switchMap(Function,int)
|
||||
// XXX: public final Completable switchMapCompletable(Function)
|
||||
// XXX: public final Completable switchMapCompletableDelayError(Function)
|
||||
// XXX: public final Observable switchMapDelayError(Function)
|
||||
// XXX: public final Observable switchMapDelayError(Function,int)
|
||||
// XXX: public final Observable switchMapMaybe(Function)
|
||||
// XXX: public final Observable switchMapMaybeDelayError(Function)
|
||||
// XXX: public final Observable switchMapSingle(Function)
|
||||
// XXX: public final Observable switchMapSingleDelayError(Function)
|
||||
// XXX: public final Observable take(long)
|
||||
// XXX: public final Observable take(long,TimeUnit)
|
||||
// XXX: public final Observable take(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable takeLast(int)
|
||||
// XXX: public final Observable takeLast(long,long,TimeUnit)
|
||||
// XXX: public final Observable takeLast(long,long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable takeLast(long,long,TimeUnit,Scheduler,boolean,int)
|
||||
// XXX: public final Observable takeLast(long,TimeUnit)
|
||||
// XXX: public final Observable takeLast(long,TimeUnit,boolean)
|
||||
// XXX: public final Observable takeLast(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable takeLast(long,TimeUnit,Scheduler,boolean)
|
||||
// XXX: public final Observable takeLast(long,TimeUnit,Scheduler,boolean,int)
|
||||
// XXX: public final Observable takeUntil(ObservableSource)
|
||||
// XXX: public final Observable takeUntil(Predicate)
|
||||
// XXX: public final Observable takeWhile(Predicate)
|
||||
// XXX: public final Observable throttleFirst(long,TimeUnit)
|
||||
// XXX: public final Observable throttleFirst(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable throttleLast(long,TimeUnit)
|
||||
// XXX: public final Observable throttleLast(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable throttleLatest(long,TimeUnit)
|
||||
// XXX: public final Observable throttleLatest(long,TimeUnit,boolean)
|
||||
// XXX: public final Observable throttleLatest(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable throttleLatest(long,TimeUnit,Scheduler,boolean)
|
||||
// XXX: public final Observable throttleWithTimeout(long,TimeUnit)
|
||||
// XXX: public final Observable throttleWithTimeout(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable timeInterval()
|
||||
// XXX: public final Observable timeInterval(Scheduler)
|
||||
// XXX: public final Observable timeInterval(TimeUnit)
|
||||
// XXX: public final Observable timeInterval(TimeUnit,Scheduler)
|
||||
// XXX: public final Observable timeout(Function)
|
||||
// XXX: public final Observable timeout(Function,ObservableSource)
|
||||
// XXX: public final Observable timeout(long,TimeUnit)
|
||||
// XXX: public final Observable timeout(long,TimeUnit,ObservableSource)
|
||||
// XXX: public final Observable timeout(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable timeout(long,TimeUnit,Scheduler,ObservableSource)
|
||||
// XXX: public final Observable timeout(ObservableSource,Function)
|
||||
// XXX: public final Observable timeout(ObservableSource,Function,ObservableSource)
|
||||
// XXX: public final Observable timestamp()
|
||||
// XXX: public final Observable timestamp(Scheduler)
|
||||
// XXX: public final Observable timestamp(TimeUnit)
|
||||
// XXX: public final Observable timestamp(TimeUnit,Scheduler)
|
||||
// XXX: public final Object to(Function)
|
||||
|
||||
static final class CompletableToFlowable<T> {
|
||||
@BeforeTemplate
|
||||
Flowable<T> before(Observable<T> observable, BackpressureStrategy strategy) {
|
||||
return observable.toFlowable(strategy);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<T> after(Observable<T> observable, BackpressureStrategy strategy) {
|
||||
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.observableToFlux(observable, strategy));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Future toFuture()
|
||||
// XXX: public final Single toList()
|
||||
// XXX: public final Single toList(Callable)
|
||||
// XXX: public final Single toList(int)
|
||||
// XXX: public final Single toMap(Function)
|
||||
// XXX: public final Single toMap(Function,Function)
|
||||
// XXX: public final Single toMap(Function,Function,Callable)
|
||||
// XXX: public final Single toMultimap(Function)
|
||||
// XXX: public final Single toMultimap(Function,Function)
|
||||
// XXX: public final Single toMultimap(Function,Function,Callable)
|
||||
// XXX: public final Single toMultimap(Function,Function,Callable,Function)
|
||||
// XXX: public final Single toSortedList()
|
||||
// XXX: public final Single toSortedList(Comparator)
|
||||
// XXX: public final Single toSortedList(Comparator,int)
|
||||
// XXX: public final Single toSortedList(int)
|
||||
// XXX: public final Observable unsubscribeOn(Scheduler)
|
||||
// XXX: public final Observable window(Callable)
|
||||
// XXX: public final Observable window(Callable,int)
|
||||
// XXX: public final Observable window(long)
|
||||
// XXX: public final Observable window(long,long)
|
||||
// XXX: public final Observable window(long,long,int)
|
||||
// XXX: public final Observable window(long,long,TimeUnit)
|
||||
// XXX: public final Observable window(long,long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable window(long,long,TimeUnit,Scheduler,int)
|
||||
// XXX: public final Observable window(long,TimeUnit)
|
||||
// XXX: public final Observable window(long,TimeUnit,long)
|
||||
// XXX: public final Observable window(long,TimeUnit,long,boolean)
|
||||
// XXX: public final Observable window(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Observable window(long,TimeUnit,Scheduler,long)
|
||||
// XXX: public final Observable window(long,TimeUnit,Scheduler,long,boolean)
|
||||
// XXX: public final Observable window(long,TimeUnit,Scheduler,long,boolean,int)
|
||||
// XXX: public final Observable window(ObservableSource)
|
||||
// XXX: public final Observable window(ObservableSource,Function)
|
||||
// XXX: public final Observable window(ObservableSource,Function,int)
|
||||
// XXX: public final Observable window(ObservableSource,int)
|
||||
// XXX: public final Observable withLatestFrom(Iterable,Function)
|
||||
// XXX: public final Observable withLatestFrom(ObservableSource,BiFunction)
|
||||
// XXX: public final Observable withLatestFrom(ObservableSource[],Function)
|
||||
// XXX: public final Observable withLatestFrom(ObservableSource,ObservableSource,Function3)
|
||||
// XXX: public final Observable
|
||||
// withLatestFrom(ObservableSource,ObservableSource,ObservableSource,Function4)
|
||||
// XXX: public final Observable
|
||||
// withLatestFrom(ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function5)
|
||||
// XXX: public final Observable zipWith(Iterable,BiFunction)
|
||||
// XXX: public final Observable zipWith(ObservableSource,BiFunction)
|
||||
// XXX: public final Observable zipWith(ObservableSource,BiFunction,boolean)
|
||||
// XXX: public final Observable zipWith(ObservableSource,BiFunction,boolean,int)
|
||||
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
static final class ObservableTestAssertResultItem<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable, T item) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
observable.test().await().assertResult(item),
|
||||
observable.test().await().assertValue(item));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable, T item) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.expectNext(item)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class ObservableTestAssertResult<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable) throws InterruptedException {
|
||||
Refaster.anyOf(observable.test().await().assertResult(), observable.test().await());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class ObservableTestAssertResultTwoItems<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable, T t1, T t2) throws InterruptedException {
|
||||
observable.test().await().assertResult(t1, t2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable, T t1, T t2) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.expectNext(t1, t2)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
static final class ObservableTestAssertValue<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable, Predicate<T> predicate) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
observable.test().await().assertValue(predicate),
|
||||
observable.test().await().assertValue(predicate).assertNoErrors().assertComplete(),
|
||||
observable.test().await().assertComplete().assertValue(predicate),
|
||||
observable.test().await().assertValue(predicate).assertComplete());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable, Predicate<T> predicate) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(predicate))
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
static final class ObservableTestAssertResultValues<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable, @Repeated T item) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
observable.test().await().assertResult(Refaster.asVarargs(item)),
|
||||
observable.test().await().assertValues(Refaster.asVarargs(item)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable, @Repeated T item) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.expectNext(item)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
static final class ObservableTestAssertComplete<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable) throws InterruptedException {
|
||||
observable.test().await().assertComplete();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
static final class ObservableTestAssertErrorClass<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable, Class<? extends Throwable> errorClass)
|
||||
throws InterruptedException {
|
||||
observable.test().await().assertError(errorClass);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable, Class<? extends Throwable> errorClass) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.verifyError(errorClass);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
static final class ObservableTestAssertNoErrors<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable) throws InterruptedException {
|
||||
observable.test().await().assertNoErrors();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
static final class ObservableTestAssertValueCount<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable, int count) throws InterruptedException {
|
||||
observable.test().await().assertValueCount(count);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable, int count) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextCount(count)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class ObservableTestAssertFailure<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable, Class<? extends Throwable> error)
|
||||
throws InterruptedException {
|
||||
observable.test().await().assertFailure(error);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable, Class<? extends Throwable> error) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.verifyError(error);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
// XXX: Default BackpressureStrategy.BUFFER is set
|
||||
static final class ObservableTestAssertNoValues<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
observable.test().await().assertNoValues(),
|
||||
observable.test().await().assertNoValues().assertComplete());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Observable<T> observable) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
// XXX: This introduces AssertJ dependency
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class ObservableTestAssertFailureAndMessage<T> {
|
||||
@BeforeTemplate
|
||||
void before(Observable<T> observable, Class<? extends Throwable> error, String message)
|
||||
throws InterruptedException {
|
||||
observable.test().await().assertFailureAndMessage(error, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
|
||||
void after(Observable<T> observable, Class<? extends Throwable> error, String message) {
|
||||
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
|
||||
.as(StepVerifier::create)
|
||||
.expectErrorSatisfies(
|
||||
t -> assertThat(t).isInstanceOf(error).hasMessageContaining(message))
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final TestObserver test(boolean)
|
||||
}
|
||||
@@ -1,764 +0,0 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.CompletableSource;
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.MaybeSource;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleSource;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.BiFunction;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.functions.Function;
|
||||
import io.reactivex.functions.Predicate;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.util.concurrent.Callable;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
|
||||
|
||||
/** The Refaster templates for the migration of the RxJava Single type to Reactor */
|
||||
final class RxJavaSingleToReactorTemplates {
|
||||
|
||||
private RxJavaSingleToReactorTemplates() {}
|
||||
|
||||
// XXX: public static Single amb(Iterable)
|
||||
// XXX: public static Single ambArray(SingleSource[])
|
||||
// XXX: public static Flowable concat(Iterable)
|
||||
// XXX: public static Observable concat(ObservableSource)
|
||||
// XXX: public static Flowable concat(Publisher)
|
||||
// XXX: public static Flowable concat(Publisher,int)
|
||||
// XXX: public static Flowable concat(SingleSource,SingleSource)
|
||||
// XXX: public static Flowable concat(SingleSource,SingleSource,SingleSource)
|
||||
// XXX: public static Flowable concat(SingleSource,SingleSource,SingleSource,SingleSource)
|
||||
// XXX: public static Flowable concatArray(SingleSource[])
|
||||
// XXX: public static Flowable concatArrayEager(SingleSource[])
|
||||
// XXX: public static Flowable concatEager(Iterable)
|
||||
// XXX: public static Flowable concatEager(Publisher)
|
||||
// XXX: public static Single create(SingleOnSubscribe)
|
||||
|
||||
abstract static class SingleDeferFirst<T> {
|
||||
@Placeholder
|
||||
abstract Single<? extends T> singleProducer();
|
||||
|
||||
@BeforeTemplate
|
||||
Single<T> before() {
|
||||
return Single.defer(() -> singleProducer());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<? extends T> after() {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
Mono.defer(() -> RxJava2Adapter.singleToMono(singleProducer())));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Single equals(SingleSource,SingleSource)
|
||||
|
||||
static final class SingleErrorCallable<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Callable<? extends Throwable> throwable) {
|
||||
return Single.error(throwable);
|
||||
}
|
||||
|
||||
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
|
||||
@AfterTemplate
|
||||
Single<T> after(Callable<? extends Throwable> throwable) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
Mono.error(RxJavaReactorMigrationUtil.callableAsSupplier(throwable)));
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleErrorThrowable<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Throwable throwable) {
|
||||
return Single.error(throwable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Throwable throwable) {
|
||||
return RxJava2Adapter.monoToSingle(Mono.error(throwable));
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleFromCallable<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Callable<? extends T> callable) {
|
||||
return Single.fromCallable(callable);
|
||||
}
|
||||
|
||||
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
|
||||
@AfterTemplate
|
||||
Single<T> after(Callable<? extends T> callable) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
Mono.fromSupplier(RxJavaReactorMigrationUtil.callableAsSupplier(callable)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Single fromFuture(Future)
|
||||
// XXX: public static Single fromFuture(Future,long,TimeUnit)
|
||||
// XXX: public static Single fromFuture(Future,long,TimeUnit,Scheduler)
|
||||
// XXX: public static Single fromFuture(Future,Scheduler)
|
||||
// XXX: public static Single fromObservable(ObservableSource)
|
||||
|
||||
static final class SingleFromPublisher<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Publisher<? extends T> source) {
|
||||
return Single.fromPublisher(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Publisher<? extends T> source) {
|
||||
return RxJava2Adapter.monoToSingle(Mono.from(source));
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleJust<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(T item) {
|
||||
return Single.just(item);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(T item) {
|
||||
return RxJava2Adapter.monoToSingle(Mono.just(item));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Flowable merge(Iterable)
|
||||
// XXX: public static Flowable merge(Publisher)
|
||||
// XXX: public static Single merge(SingleSource)
|
||||
// XXX: public static Flowable merge(SingleSource,SingleSource)
|
||||
// XXX: public static Flowable merge(SingleSource,SingleSource,SingleSource)
|
||||
// XXX: public static Flowable merge(SingleSource,SingleSource,SingleSource,SingleSource)
|
||||
// XXX: public static Flowable mergeDelayError(Iterable)
|
||||
// XXX: public static Flowable mergeDelayError(Publisher)
|
||||
// XXX: public static Flowable mergeDelayError(SingleSource,SingleSource)
|
||||
// XXX: public static Flowable mergeDelayError(SingleSource,SingleSource,SingleSource)
|
||||
// XXX: public static Flowable
|
||||
// mergeDelayError(SingleSource,SingleSource,SingleSource,SingleSource)
|
||||
// XXX: public static Single never()
|
||||
static final class SingleNever {
|
||||
@BeforeTemplate
|
||||
<T> Single<T> before() {
|
||||
return Single.never();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
<T> Single<T> after() {
|
||||
return RxJava2Adapter.monoToSingle(Mono.never());
|
||||
}
|
||||
}
|
||||
// XXX: public static Single timer(long,TimeUnit)
|
||||
// XXX: public static Single timer(long,TimeUnit,Scheduler)
|
||||
// XXX: public static Single unsafeCreate(SingleSource)
|
||||
// XXX: public static Single using(Callable,Function,Consumer)
|
||||
// XXX: public static Single using(Callable,Function,Consumer,boolean)
|
||||
|
||||
static final class SingleWrap<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Single<T> single) {
|
||||
return Single.wrap(single);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Single<T> single) {
|
||||
return single;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public static Single zip(Iterable,Function)
|
||||
// XXX: public static Single zip(SingleSource,SingleSource,BiFunction)
|
||||
// XXX: public static Single zip(SingleSource,SingleSource,SingleSource,Function3)
|
||||
// XXX: public static Single zip(SingleSource,SingleSource,SingleSource,SingleSource,Function4)
|
||||
// XXX: public static Single
|
||||
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function5)
|
||||
// XXX: public static Single
|
||||
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function6)
|
||||
// XXX: public static Single
|
||||
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function7)
|
||||
// XXX: public static Single
|
||||
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function8)
|
||||
// XXX: public static Single
|
||||
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function9)
|
||||
// XXX: public static Single zipArray(Function,SingleSource[])
|
||||
// XXX: public final Single ambWith(SingleSource)
|
||||
// XXX: public final Object as(SingleConverter)
|
||||
|
||||
static final class SingleBlockingGet<T> {
|
||||
@BeforeTemplate
|
||||
Object before(Single<T> single) {
|
||||
return single.blockingGet();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Object after(Single<T> single) {
|
||||
return RxJava2Adapter.singleToMono(single).block();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single cache()
|
||||
// XXX: public final Single cast(Class)
|
||||
// XXX: public final Single compose(SingleTransformer)
|
||||
|
||||
static final class SingleConcatWith<T> {
|
||||
@BeforeTemplate
|
||||
Flowable<T> before(Single<T> single, SingleSource<? extends T> source) {
|
||||
return single.concatWith(source);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<T> after(Single<T> single, SingleSource<? extends T> source) {
|
||||
return RxJava2Adapter.fluxToFlowable(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.concatWith(RxJava2Adapter.singleToMono(Single.wrap(source))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single contains(Object)
|
||||
// XXX: public final Single contains(Object,BiPredicate)
|
||||
// XXX: public final Single delay(long,TimeUnit)
|
||||
// XXX: public final Single delay(long,TimeUnit,boolean)
|
||||
// XXX: public final Single delay(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Single delay(long,TimeUnit,Scheduler,boolean)
|
||||
// XXX: public final Single delaySubscription(CompletableSource)
|
||||
// XXX: public final Single delaySubscription(long,TimeUnit)
|
||||
// XXX: public final Single delaySubscription(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Single delaySubscription(ObservableSource)
|
||||
// XXX: public final Single delaySubscription(Publisher)
|
||||
// XXX: public final Single delaySubscription(SingleSource)
|
||||
// XXX: public final Maybe dematerialize(Function)
|
||||
// XXX: public final Single doAfterSuccess(Consumer)
|
||||
// XXX: public final Single doAfterTerminate(Action)
|
||||
// XXX: public final Single doFinally(Action)
|
||||
// XXX: public final Single doOnDispose(Action)
|
||||
|
||||
static final class SingleDoOnError<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Single<T> single, Consumer<? super Throwable> consumer) {
|
||||
return single.doOnError(consumer);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Single<T> single, Consumer<? super Throwable> consumer) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single doOnEvent(BiConsumer)
|
||||
// XXX: public final Single doOnSubscribe(Consumer)
|
||||
|
||||
static final class SingleDoOnSuccess<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Single<T> single, Consumer<T> consumer) {
|
||||
return single.doOnSuccess(consumer);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Single<T> single, Consumer<T> consumer) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.doOnSuccess(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single doOnTerminate(Action)
|
||||
|
||||
static final class SingleFilter<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Single<T> single, Predicate<S> predicate) {
|
||||
return single.filter(predicate);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Single<T> single, Predicate<S> predicate) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class SingleFlatMapFunction<I, T extends I, O, M extends SingleSource<O>> {
|
||||
@BeforeTemplate
|
||||
Single<O> before(
|
||||
Single<T> single, Function<? super I, ? extends SingleSource<? extends O>> function) {
|
||||
return single.flatMap(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
|
||||
Single<O> after(Single<T> single, Function<I, M> function) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.flatMap(
|
||||
v ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
Single.wrap(
|
||||
RxJavaReactorMigrationUtil.<I, M>toJdkFunction(function).apply(v)))));
|
||||
}
|
||||
}
|
||||
|
||||
abstract static class SingleFlatMapLambda<S, T> {
|
||||
@Placeholder
|
||||
abstract Single<T> toSingleFunction(@MayOptionallyUse S element);
|
||||
|
||||
@BeforeTemplate
|
||||
Single<T> before(Single<S> single) {
|
||||
return Refaster.anyOf(
|
||||
single.flatMap(v -> toSingleFunction(v)), single.flatMap((S v) -> toSingleFunction(v)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Single<S> single) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.flatMap(v -> RxJava2Adapter.singleToMono(toSingleFunction(v))));
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleFlatMapCompletable<T, R extends CompletableSource> {
|
||||
@BeforeTemplate
|
||||
Completable before(
|
||||
Single<T> single, Function<? super T, ? extends CompletableSource> function) {
|
||||
return single.flatMapCompletable(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Single<T> single, Function<T, R> function) {
|
||||
return RxJava2Adapter.monoToCompletable(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.flatMap(
|
||||
z ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, R>toJdkFunction(function).apply(z))))
|
||||
.then());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class SingleFlatMapMaybe<T, R, M extends MaybeSource<R>> {
|
||||
@BeforeTemplate
|
||||
Maybe<R> before(
|
||||
Single<T> single, Function<? super T, ? extends MaybeSource<? extends R>> mapper) {
|
||||
return single.flatMapMaybe(mapper);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<R> after(Single<T> single, Function<T, M> mapper) {
|
||||
return RxJava2Adapter.monoToMaybe(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.flatMap(
|
||||
e ->
|
||||
RxJava2Adapter.maybeToMono(
|
||||
Maybe.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, M>toJdkFunction(mapper).apply(e)))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Observable flatMapObservable(Function)
|
||||
|
||||
static final class SingleFlatMapPublisher<T, R> {
|
||||
@BeforeTemplate
|
||||
Flowable<R> before(
|
||||
Single<T> single, Function<? super T, ? extends Publisher<? extends R>> mapper) {
|
||||
return single.flatMapPublisher(mapper);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<R> after(
|
||||
Single<T> single, Function<? super T, ? extends Publisher<? extends R>> mapper) {
|
||||
return RxJava2Adapter.fluxToFlowable(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.flatMapMany(RxJavaReactorMigrationUtil.toJdkFunction(mapper)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Flowable flattenAsFlowable(Function)
|
||||
// XXX: public final Observable flattenAsObservable(Function)
|
||||
// XXX: public final Single hide()
|
||||
|
||||
static final class CompletableIgnoreElement<T> {
|
||||
@BeforeTemplate
|
||||
Completable before(Single<T> single) {
|
||||
return single.ignoreElement();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Completable after(Single<T> single) {
|
||||
return RxJava2Adapter.monoToCompletable(RxJava2Adapter.singleToMono(single).then());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single lift(SingleOperator)
|
||||
|
||||
static final class SingleMap<I, T extends I, O> {
|
||||
@BeforeTemplate
|
||||
Single<O> before(Single<T> single, Function<? super I, ? extends O> function) {
|
||||
return single.map(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<O> after(Single<T> single, Function<I, O> function) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.map(RxJavaReactorMigrationUtil.toJdkFunction(function)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single materialize()
|
||||
// XXX: public final Flowable mergeWith(SingleSource)
|
||||
// XXX: public final Single observeOn(Scheduler)
|
||||
|
||||
static final class SingleOnErrorResumeNext<
|
||||
S, T extends S, R, P extends Throwable, Q extends Single<T>> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(
|
||||
Single<T> single,
|
||||
Function<? super Throwable, ? extends SingleSource<? extends T>> function) {
|
||||
return single.onErrorResumeNext(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Single<T> single, Function<Throwable, Q> function) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.onErrorResume(
|
||||
err ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
RxJavaReactorMigrationUtil.<Throwable, Q>toJdkFunction(function)
|
||||
.apply(err))));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Single onErrorResumeNext(Single)
|
||||
// XXX: public final Single onErrorReturn(Function)
|
||||
// XXX: public final Single onErrorReturnItem(Object)
|
||||
// XXX: public final Single onTerminateDetach()
|
||||
// XXX: public final Flowable repeat()
|
||||
// XXX: public final Flowable repeat(long)
|
||||
// XXX: public final Flowable repeatUntil(BooleanSupplier)
|
||||
// XXX: public final Flowable repeatWhen(Function)
|
||||
// XXX: public final Single retry()
|
||||
// XXX: public final Single retry(BiPredicate)
|
||||
// XXX: public final Single retry(long)
|
||||
// XXX: public final Single retry(long,Predicate)
|
||||
// XXX: public final Single retry(Predicate)
|
||||
// XXX: public final Single retryWhen(Function)
|
||||
|
||||
// XXX: Add test
|
||||
static final class SingleSubscribe<T> {
|
||||
@BeforeTemplate
|
||||
Disposable before(Single<T> single) {
|
||||
return single.subscribe();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
reactor.core.Disposable after(Single<T> single) {
|
||||
return RxJava2Adapter.singleToMono(single).subscribe();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Disposable subscribe(BiConsumer)
|
||||
|
||||
// XXX: Add test
|
||||
static final class SingleSubscribeConsumer<T> {
|
||||
@BeforeTemplate
|
||||
Disposable before(Single<T> single, Consumer<? super T> consumer) {
|
||||
return single.subscribe(consumer);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
reactor.core.Disposable after(Single<T> single, Consumer<? super T> consumer) {
|
||||
return RxJava2Adapter.singleToMono(single)
|
||||
.subscribe(RxJavaReactorMigrationUtil.toJdkConsumer(consumer));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class SingleSubscribeTwoConsumers<T> {
|
||||
@BeforeTemplate
|
||||
Disposable before(
|
||||
Single<T> single, Consumer<? super T> consumer1, Consumer<? super Throwable> consumer2) {
|
||||
return single.subscribe(consumer1, consumer2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
reactor.core.Disposable after(
|
||||
Single<T> single, Consumer<? super T> consumer1, Consumer<? super Throwable> consumer2) {
|
||||
return RxJava2Adapter.singleToMono(single)
|
||||
.subscribe(
|
||||
RxJavaReactorMigrationUtil.toJdkConsumer(consumer1),
|
||||
RxJavaReactorMigrationUtil.toJdkConsumer(consumer2));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final void subscribe(SingleObserver)
|
||||
|
||||
// XXX: We are currently not accounting for the Schedulers.computation()
|
||||
static final class SingleSubscribeOn<T> {
|
||||
@BeforeTemplate
|
||||
Single<T> before(Single<T> single) {
|
||||
return single.subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<T> after(Single<T> single) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.subscribeOn(reactor.core.scheduler.Schedulers.boundedElastic()));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final SingleObserver subscribeWith(SingleObserver)
|
||||
// XXX: public final Single takeUntil(CompletableSource)
|
||||
// XXX: public final Single takeUntil(Publisher)
|
||||
// XXX: public final Single takeUntil(SingleSource)
|
||||
// XXX: public final Single timeout(long,TimeUnit)
|
||||
// XXX: public final Single timeout(long,TimeUnit,Scheduler)
|
||||
// XXX: public final Single timeout(long,TimeUnit,Scheduler,SingleSource)
|
||||
// XXX: public final Single timeout(long,TimeUnit,SingleSource)
|
||||
// XXX: public final Object to(Function)
|
||||
// XXX: public final Completable toCompletable()
|
||||
|
||||
static final class SingleToFlowable<T> {
|
||||
@BeforeTemplate
|
||||
Flowable<T> before(Single<T> single) {
|
||||
return single.toFlowable();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<T> after(Single<T> single) {
|
||||
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.singleToMono(single).flux());
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Future toFuture()
|
||||
|
||||
static final class SingleToMaybe<T> {
|
||||
@BeforeTemplate
|
||||
Maybe<T> before(Single<T> single) {
|
||||
return single.toMaybe();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Maybe<T> after(Single<T> single) {
|
||||
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.singleToMono(single));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final Observable toObservable()
|
||||
// XXX: public final Single unsubscribeOn(Scheduler)
|
||||
|
||||
static final class SingleZipWith<T, R, U> {
|
||||
@BeforeTemplate
|
||||
Single<R> before(
|
||||
Single<T> single,
|
||||
SingleSource<U> source,
|
||||
BiFunction<? super T, ? super U, ? extends R> biFunction) {
|
||||
return single.zipWith(source, biFunction);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Single<R> after(
|
||||
Single<T> single,
|
||||
SingleSource<U> source,
|
||||
BiFunction<? super T, ? super U, ? extends R> biFunction) {
|
||||
return RxJava2Adapter.monoToSingle(
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.zipWith(
|
||||
RxJava2Adapter.singleToMono(Single.wrap(source)),
|
||||
RxJavaReactorMigrationUtil.toJdkBiFunction(biFunction)));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class SingleTestAssertResultItem<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single, T item) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
single.test().assertResult(item),
|
||||
single.test().await().assertResult(item),
|
||||
single.test().await().assertComplete().assertResult(item),
|
||||
single.test().await().assertResult(item).assertComplete(),
|
||||
single.test().await().assertValue(item),
|
||||
single.test().await().assertComplete().assertValue(item),
|
||||
single.test().assertValue(item),
|
||||
single.test().await().assertValue(item).assertComplete());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single, T item) {
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.as(StepVerifier::create)
|
||||
.expectNext(item)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleAssertValueSet<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single, ImmutableSet<? extends T> set) throws InterruptedException {
|
||||
single.test().await().assertNoErrors().assertValueSet(set).assertComplete();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single, ImmutableSet<? extends T> set) {
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.map(ImmutableSet::of)
|
||||
.as(StepVerifier::create)
|
||||
.expectNext(ImmutableSet.copyOf(set))
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class SingleTestAssertResult<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single) throws InterruptedException {
|
||||
single.test().await().assertResult();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single) {
|
||||
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleTestAssertValue<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single, Predicate<T> predicate) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
single.test().await().assertValue(predicate),
|
||||
single.test().await().assertValue(predicate).assertComplete(),
|
||||
single.test().await().assertValue(predicate).assertNoErrors().assertComplete(),
|
||||
single.test().await().assertComplete().assertValue(predicate));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single, Predicate<T> predicate) {
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(predicate))
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleTestAssertComplete<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single) throws InterruptedException {
|
||||
single.test().await().assertComplete();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single) {
|
||||
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleTestAssertErrorClass<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single, Class<? extends Throwable> errorClass)
|
||||
throws InterruptedException {
|
||||
single.test().await().assertError(errorClass);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single, Class<? extends Throwable> errorClass) {
|
||||
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyError(errorClass);
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleTestAssertNoErrors<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single) throws InterruptedException {
|
||||
single.test().await().assertNoErrors();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single) {
|
||||
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
static final class SingleTestAssertValueCount<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single, int count) throws InterruptedException {
|
||||
single.test().await().assertValueCount(count);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single, int count) {
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextCount(count)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("unchecked")
|
||||
static final class SingleTestAssertFailure<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single, Class<? extends Throwable> error) throws InterruptedException {
|
||||
single.test().await().assertFailure(error);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single, Class<? extends Throwable> error) {
|
||||
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyError(error);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
static final class SingleTestAssertNoValues<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single) throws InterruptedException {
|
||||
Refaster.anyOf(
|
||||
single.test().await().assertNoValues(),
|
||||
single.test().await().assertNoValues().assertComplete());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single) {
|
||||
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
// XXX: This introduces AssertJ dependency
|
||||
static final class SingleTestAssertFailureAndMessage<T> {
|
||||
@BeforeTemplate
|
||||
void before(Single<T> single, Class<? extends Throwable> error, String message)
|
||||
throws InterruptedException {
|
||||
single.test().await().assertFailureAndMessage(error, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Single<T> single, Class<? extends Throwable> error, String message) {
|
||||
RxJava2Adapter.singleToMono(single)
|
||||
.as(StepVerifier::create)
|
||||
.expectErrorSatisfies(
|
||||
t -> assertThat(t).isInstanceOf(error).hasMessageContaining(message))
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: public final TestObserver test(boolean)
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.CanTransformToTargetType;
|
||||
import io.reactivex.BackpressureStrategy;
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.functions.Action;
|
||||
import io.reactivex.functions.BiFunction;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.functions.Function;
|
||||
import io.reactivex.functions.Predicate;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Supplier;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
|
||||
|
||||
/** Assorted Refaster templates for the migration of RxJava to Reactor */
|
||||
public final class RxJavaToReactorTemplates {
|
||||
private RxJavaToReactorTemplates() {}
|
||||
|
||||
static final class FluxToFlowableToFlux<T> {
|
||||
@BeforeTemplate
|
||||
Flux<T> before(Flux<T> flux, BackpressureStrategy strategy) {
|
||||
return Refaster.anyOf(
|
||||
RxJava2Adapter.fluxToFlowable(flux).as(RxJava2Adapter::flowableToFlux),
|
||||
RxJava2Adapter.flowableToFlux(RxJava2Adapter.fluxToFlowable(flux)),
|
||||
RxJava2Adapter.flowableToFlux(flux.as(RxJava2Adapter::fluxToFlowable)),
|
||||
RxJava2Adapter.observableToFlux(flux.as(RxJava2Adapter::fluxToObservable), strategy),
|
||||
flux.as(RxJava2Adapter::fluxToObservable)
|
||||
.toFlowable(strategy)
|
||||
.as(RxJava2Adapter::flowableToFlux),
|
||||
RxJava2Adapter.observableToFlux(RxJava2Adapter.fluxToObservable(flux), strategy),
|
||||
flux.as(RxJava2Adapter::fluxToFlowable).as(RxJava2Adapter::flowableToFlux));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<T> after(Flux<T> flux) {
|
||||
return flux;
|
||||
}
|
||||
}
|
||||
|
||||
static final class MonoToFlowableToMono<T> {
|
||||
@BeforeTemplate
|
||||
Mono<Void> before(Mono<Void> mono) {
|
||||
return Refaster.anyOf(
|
||||
RxJava2Adapter.monoToCompletable(mono).as(RxJava2Adapter::completableToMono),
|
||||
mono.as(RxJava2Adapter::monoToCompletable).as(RxJava2Adapter::completableToMono),
|
||||
RxJava2Adapter.completableToMono(RxJava2Adapter.monoToCompletable(mono)),
|
||||
RxJava2Adapter.completableToMono(mono.as(RxJava2Adapter::monoToCompletable)));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
Mono<T> before2(Mono<T> mono) {
|
||||
return Refaster.anyOf(
|
||||
RxJava2Adapter.monoToMaybe(mono).as(RxJava2Adapter::maybeToMono),
|
||||
RxJava2Adapter.maybeToMono(RxJava2Adapter.monoToMaybe(mono)),
|
||||
RxJava2Adapter.maybeToMono(mono.as(RxJava2Adapter::monoToMaybe)),
|
||||
mono.as(RxJava2Adapter::monoToMaybe).as(RxJava2Adapter::maybeToMono),
|
||||
RxJava2Adapter.monoToSingle(mono).as(RxJava2Adapter::singleToMono),
|
||||
RxJava2Adapter.singleToMono(RxJava2Adapter.monoToSingle(mono)),
|
||||
RxJava2Adapter.singleToMono(mono.as(RxJava2Adapter::monoToSingle)),
|
||||
mono.as(RxJava2Adapter::monoToSingle).as(RxJava2Adapter::singleToMono));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
Mono<Void> before3(Mono<T> mono) {
|
||||
return Refaster.anyOf(
|
||||
RxJava2Adapter.completableToMono(RxJava2Adapter.monoToCompletable(mono)),
|
||||
RxJava2Adapter.completableToMono(mono.as(RxJava2Adapter::monoToCompletable)),
|
||||
RxJava2Adapter.monoToCompletable(mono).as(RxJava2Adapter::completableToMono));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<T> after(Mono<T> mono) {
|
||||
return mono;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test cases
|
||||
static final class MonoToFlowableToFlux<T> {
|
||||
@BeforeTemplate
|
||||
Flux<T> before(Mono<T> mono) {
|
||||
return mono.as(RxJava2Adapter::monoToFlowable).as(RxJava2Adapter::flowableToFlux);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<T> after(Mono<T> mono) {
|
||||
return mono.flux();
|
||||
}
|
||||
}
|
||||
|
||||
static final class MonoErrorCallableSupplierUtil<T> {
|
||||
@BeforeTemplate
|
||||
Mono<T> before(@CanTransformToTargetType Callable<? extends Throwable> callable) {
|
||||
return Mono.error(RxJavaReactorMigrationUtil.callableAsSupplier(callable));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<T> after(Supplier<? extends Throwable> callable) {
|
||||
return Mono.error(callable);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"NoFunctionalReturnType", "FunctionalInterfaceClash"})
|
||||
static final class RemoveUtilCallable<T> {
|
||||
@BeforeTemplate
|
||||
Supplier<T> before(@CanTransformToTargetType Callable<T> callable) {
|
||||
return RxJavaReactorMigrationUtil.callableAsSupplier(callable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Supplier<T> before(Supplier<T> callable) {
|
||||
return callable;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
static final class UnnecessaryFunctionConversion<I, O> {
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<I, O> before(@CanTransformToTargetType Function<I, O> function) {
|
||||
return RxJavaReactorMigrationUtil.toJdkFunction(function);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<I, O> after(java.util.function.Function<I, O> function) {
|
||||
return function;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
static final class UnnecessaryBiFunctionConversion<T, U, R> {
|
||||
@BeforeTemplate
|
||||
java.util.function.BiFunction<? super T, ? super U, ? extends R> before(
|
||||
@CanTransformToTargetType BiFunction<? super T, ? super U, ? extends R> zipper) {
|
||||
return RxJavaReactorMigrationUtil.toJdkBiFunction(zipper);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.BiFunction<? super T, ? super U, ? extends R> after(
|
||||
java.util.function.BiFunction<? super T, ? super U, ? extends R> zipper) {
|
||||
return zipper;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
static final class UnnecessaryConsumerConversion<T> {
|
||||
@BeforeTemplate
|
||||
java.util.function.Consumer<? extends T> before(
|
||||
@CanTransformToTargetType Consumer<? extends T> consumer) {
|
||||
return RxJavaReactorMigrationUtil.toJdkConsumer(consumer);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Consumer<? extends T> after(
|
||||
java.util.function.Consumer<? extends T> consumer) {
|
||||
return consumer;
|
||||
}
|
||||
}
|
||||
|
||||
static final class UnnecessaryRunnableConversion {
|
||||
@BeforeTemplate
|
||||
Runnable before(@CanTransformToTargetType Action action) {
|
||||
return RxJavaReactorMigrationUtil.toRunnable(action);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Runnable after(Runnable action) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
static final class UnnecessaryPredicateConversion<T> {
|
||||
@BeforeTemplate
|
||||
java.util.function.Predicate<? extends T> before(
|
||||
@CanTransformToTargetType Predicate<? extends T> predicate) {
|
||||
return RxJavaReactorMigrationUtil.toJdkPredicate(predicate);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Predicate<? extends T> after(
|
||||
java.util.function.Predicate<? extends T> predicate) {
|
||||
return predicate;
|
||||
}
|
||||
}
|
||||
|
||||
static final class FlowableBiFunctionRemoveUtil<T, U, R> {
|
||||
@BeforeTemplate
|
||||
Flowable<R> before(
|
||||
Publisher<? extends T> source1,
|
||||
Publisher<? extends U> source2,
|
||||
@CanTransformToTargetType BiFunction<? super T, ? super U, ? extends R> zipper) {
|
||||
return RxJava2Adapter.fluxToFlowable(
|
||||
Flux.<T, U, R>zip(source1, source2, RxJavaReactorMigrationUtil.toJdkBiFunction(zipper)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flowable<R> after(
|
||||
Publisher<? extends T> source1,
|
||||
Publisher<? extends U> source2,
|
||||
java.util.function.BiFunction<? super T, ? super U, ? extends R> zipper) {
|
||||
return RxJava2Adapter.fluxToFlowable(Flux.<T, U, R>zip(source1, source2, zipper));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
//////////// ASSORTED TEMPLATES ///////////
|
||||
///////////////////////////////////////////
|
||||
|
||||
static final class MonoFromNestedPublisher<T> {
|
||||
@BeforeTemplate
|
||||
Mono<T> before(Flux<T> flux) {
|
||||
return Mono.from(RxJava2Adapter.fluxToFlowable(flux));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<T> after(Flux<T> flux) {
|
||||
return Mono.from(flux);
|
||||
}
|
||||
}
|
||||
|
||||
static final class FlowableToFluxWithFilter<T> {
|
||||
@BeforeTemplate
|
||||
Flux<T> before(Flux<T> flux, Predicate<T> predicate) {
|
||||
return RxJava2Adapter.flowableToFlux(
|
||||
flux.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate))
|
||||
.as(RxJava2Adapter::fluxToFlowable));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<T> after(Flux<T> flux, Predicate<T> predicate) {
|
||||
return flux.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObservableToFlux<T> {
|
||||
@BeforeTemplate
|
||||
Flux<T> before(Flux<T> flux, Predicate<T> predicate, BackpressureStrategy strategy) {
|
||||
return RxJava2Adapter.observableToFlux(
|
||||
RxJava2Adapter.fluxToObservable(flux).filter(predicate), strategy);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<T> after(Flux<T> flux, Predicate<T> predicate, BackpressureStrategy strategy) {
|
||||
return flux.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
static final class MonoFromToFlowableToFlux<T> {
|
||||
@BeforeTemplate
|
||||
Flux<T> before(Mono<T> mono) {
|
||||
return RxJava2Adapter.flowableToFlux(mono.as(RxJava2Adapter::monoToFlowable));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<T> after(Mono<T> mono) {
|
||||
return mono.flux();
|
||||
}
|
||||
}
|
||||
|
||||
static final class MonoThenThen<T> {
|
||||
@BeforeTemplate
|
||||
Mono<T> before(Mono<T> mono, Mono<T> other) {
|
||||
return mono.then().then(other);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<T> after(Mono<T> mono, Mono<T> other) {
|
||||
return mono.then(other);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Find out how we can use this in the future.
|
||||
// static final class RemoveRedundantCast<T> {
|
||||
// @BeforeTemplate
|
||||
// T before(T object) {
|
||||
// return (T) object;
|
||||
// }
|
||||
//
|
||||
// @AfterTemplate
|
||||
// T after(T object) {
|
||||
// return object;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -1,404 +0,0 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.CompletableSource;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.MaybeSource;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleSource;
|
||||
import io.reactivex.functions.Function;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.adapter.rxjava.RxJava2Adapter;
|
||||
import reactor.core.publisher.Mono;
|
||||
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
|
||||
|
||||
public final class RxJavaUnwrapTemplates {
|
||||
private RxJavaUnwrapTemplates() {}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class FlowableConcatMapCompletableUnwrapLambda<T> {
|
||||
@Placeholder
|
||||
abstract Mono<?> placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<? super T, ? extends Publisher<?>> before() {
|
||||
return e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
|
||||
.apply(e));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<T, ? extends Publisher<?>> after() {
|
||||
return v -> placeholder(v);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class MaybeFlatMapUnwrapLambda<I, T extends I, O> {
|
||||
@Placeholder
|
||||
abstract Mono<? extends O> placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
java.util.function.Function<? super T, ? extends Mono<? extends O>> before() {
|
||||
return Refaster.anyOf(
|
||||
v ->
|
||||
RxJava2Adapter.maybeToMono(
|
||||
(Maybe<O>)
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(T ident) -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
|
||||
.apply(v)),
|
||||
v ->
|
||||
RxJava2Adapter.maybeToMono(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(T ident) -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
|
||||
.apply(v)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<? super T, ? extends Mono<? extends O>> after() {
|
||||
return v -> placeholder(v);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class MaybeFlatMapSingleElementUnwrapLambda<T, R> {
|
||||
@Placeholder
|
||||
abstract Mono<R> placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<T, ? extends Mono<? extends R>> before() {
|
||||
return Refaster.anyOf(
|
||||
e ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
Single.wrap(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(Function<T, SingleSource<R>>)
|
||||
(T ident) -> RxJava2Adapter.monoToSingle(placeholder(ident)))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
Single.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, SingleSource<R>>toJdkFunction(
|
||||
(T ident) -> RxJava2Adapter.monoToSingle(placeholder(ident)))
|
||||
.apply(e))));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<T, ? extends Mono<? extends R>> after() {
|
||||
return e -> placeholder(e);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class SingleFlatMapMaybeUnwrapLambda<T, R> {
|
||||
@Placeholder
|
||||
abstract Mono<R> placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<? super T, ? extends Mono<? extends R>> before() {
|
||||
return Refaster.anyOf(
|
||||
e ->
|
||||
RxJava2Adapter.maybeToMono(
|
||||
Maybe.wrap(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(Function<T, MaybeSource<R>>)
|
||||
(T ident) -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.maybeToMono(
|
||||
Maybe.wrap(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(Function<T, MaybeSource<R>>)
|
||||
ident -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.maybeToMono(
|
||||
Maybe.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, MaybeSource<R>>toJdkFunction(
|
||||
ident -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
|
||||
.apply(e))));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<? super T, ? extends Mono<? extends R>> after() {
|
||||
return e -> placeholder(e);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings({"NoFunctionalReturnType", "unchecked"})
|
||||
abstract static class SingleOnResumeUnwrapLambda<T, R> {
|
||||
@Placeholder
|
||||
abstract Mono<? extends R> placeholder(@MayOptionallyUse Throwable input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<? extends Throwable, ? extends Mono<? extends R>> before() {
|
||||
return Refaster.anyOf(
|
||||
e ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
ident -> RxJava2Adapter.monoToSingle(placeholder(e)))
|
||||
.apply(e)),
|
||||
e ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
Single.wrap(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(Function<Throwable, ? extends SingleSource<? extends R>>)
|
||||
placeholder(e))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
Single.wrap(
|
||||
RxJavaReactorMigrationUtil.<Throwable, SingleSource<R>>toJdkFunction(
|
||||
(Function<Throwable, SingleSource<R>>) placeholder(e))
|
||||
.apply(e))));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<Throwable, ? extends Mono<? extends R>> after() {
|
||||
return v -> placeholder(v);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class FlowableConcatMapMaybeDelayErrorUnwrapLambda<T, R> {
|
||||
@Placeholder
|
||||
abstract Mono<R> placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<? super T, ? extends Publisher<? extends R>> after() {
|
||||
return Refaster.anyOf(
|
||||
e ->
|
||||
Maybe.wrap(
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(Function<T, MaybeSource<R>>)
|
||||
ident -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
|
||||
.apply(e))
|
||||
.toFlowable(),
|
||||
e ->
|
||||
Maybe.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, MaybeSource<R>>toJdkFunction(
|
||||
ident -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
|
||||
.apply(e))
|
||||
.toFlowable());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<? super T, ? extends Publisher<? extends R>> before() {
|
||||
return e -> placeholder(e);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class FlowableFlatMapCompletableUnwrapLambda<T> {
|
||||
@Placeholder
|
||||
abstract Mono<?> placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<T, ? extends Publisher<? extends Void>> before() {
|
||||
return Refaster.anyOf(
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
|
||||
(Function<T, Completable>)
|
||||
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
|
||||
(Function<T, Completable>)
|
||||
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
|
||||
.apply(e)),
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
|
||||
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
|
||||
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
|
||||
.apply(e)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<T, Mono<?>> after() {
|
||||
return v -> placeholder(v);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Improve naming and add test case
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class FlowableUnwrapLambda<T> {
|
||||
@Placeholder
|
||||
abstract Completable placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<T, Publisher<? extends Void>> before() {
|
||||
return Refaster.anyOf(
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
|
||||
(Function<T, CompletableSource>) v -> placeholder(v))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
|
||||
v -> placeholder(v))
|
||||
.apply(e))));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<T, Mono<? extends Void>> after() {
|
||||
return v -> RxJava2Adapter.completableToMono(Completable.wrap(placeholder(v)));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class FlowableFlatMapUnwrapLambda<T> {
|
||||
@Placeholder
|
||||
abstract CompletableSource placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<T, ? extends Publisher<? extends Void>> before() {
|
||||
return e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
|
||||
(Function<T, CompletableSource>) v -> placeholder(v))
|
||||
.apply(e)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<T, Mono<? extends Void>> after() {
|
||||
return v -> RxJava2Adapter.completableToMono(Completable.wrap(placeholder(v)));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class SingleFlatMapUnwrapLambda<T, R> {
|
||||
@Placeholder
|
||||
abstract Mono<? extends R> placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<T, ? extends Mono<? extends R>> before() {
|
||||
return v ->
|
||||
RxJava2Adapter.singleToMono(
|
||||
(Single<? extends R>)
|
||||
RxJavaReactorMigrationUtil.toJdkFunction(
|
||||
(T ident) -> RxJava2Adapter.monoToSingle(placeholder(ident)))
|
||||
.apply(v));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<T, ? extends Mono<? extends R>> after() {
|
||||
return v -> placeholder(v);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class SingleRemoveLambdaWithCast<T> {
|
||||
@Placeholder
|
||||
abstract Mono<?> placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<? super T, ? extends Publisher<? extends Void>> before() {
|
||||
return Refaster.anyOf(
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
|
||||
(Function<T, Completable>)
|
||||
v -> placeholder(v).as(RxJava2Adapter::monoToCompletable))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
|
||||
(Function<T, Completable>)
|
||||
v -> RxJava2Adapter.monoToCompletable(placeholder(v)))
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
|
||||
v -> RxJava2Adapter.monoToCompletable(placeholder(v)))
|
||||
.apply(e))));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<? super T, ? extends Mono<?>> after() {
|
||||
return v -> placeholder(v);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add test
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class SingleRemoveLambdaWithCompletable<T> {
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<? super T, ? extends Mono<? extends Void>> before(
|
||||
Completable completable) {
|
||||
return Refaster.anyOf(
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
|
||||
(Function<T, CompletableSource>) v -> completable)
|
||||
.apply(e))),
|
||||
e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
|
||||
v -> completable)
|
||||
.apply(e))));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<? super T, ? extends Mono<? extends Void>> after(
|
||||
Completable completable) {
|
||||
return v -> RxJava2Adapter.completableToMono(completable);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Verify if this template still flags other cases than the one above.
|
||||
@SuppressWarnings("NoFunctionalReturnType")
|
||||
abstract static class SingleRemoveLambdaWithCompletableExtra<T> {
|
||||
@Placeholder
|
||||
abstract Completable placeholder(@MayOptionallyUse T input);
|
||||
|
||||
@BeforeTemplate
|
||||
java.util.function.Function<? super T, ? extends Mono<? extends Void>> before() {
|
||||
return e ->
|
||||
RxJava2Adapter.completableToMono(
|
||||
Completable.wrap(
|
||||
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
|
||||
(Function<T, CompletableSource>) v -> placeholder(v))
|
||||
.apply(e)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
java.util.function.Function<? super T, ? extends Mono<? extends Void>> after() {
|
||||
return v -> RxJava2Adapter.completableToMono(placeholder(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Comparator.naturalOrder;
|
||||
import static java.util.Comparator.reverseOrder;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -18,12 +19,31 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/** Refaster templates related to expressions dealing with {@link Stream}s. */
|
||||
final class StreamTemplates {
|
||||
private StreamTemplates() {}
|
||||
|
||||
/**
|
||||
* Prefer {@link Collectors#joining()} over {@link Collectors#joining(CharSequence)} with an empty
|
||||
* delimiter string.
|
||||
*/
|
||||
static final class Joining {
|
||||
@BeforeTemplate
|
||||
Collector<CharSequence, ?, String> before() {
|
||||
return joining("");
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Collector<CharSequence, ?, String> after() {
|
||||
return joining();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Stream#empty()} over less clear alternatives. */
|
||||
static final class EmptyStream<T> {
|
||||
@BeforeTemplate
|
||||
@@ -216,7 +236,7 @@ final class StreamTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Optional<T> after(Stream<T> stream) {
|
||||
return stream.min(naturalOrder());
|
||||
}
|
||||
@@ -242,7 +262,7 @@ final class StreamTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Optional<T> after(Stream<T> stream) {
|
||||
return stream.max(naturalOrder());
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** Refaster templates related to expressions dealing with {@link String}s. */
|
||||
// XXX: Should we prefer `s -> !s.isEmpty()` or `not(String::isEmpty)`?
|
||||
@@ -37,7 +38,7 @@ final class StringTemplates {
|
||||
/** Prefer {@link Strings#isNullOrEmpty(String)} over the more verbose alternative. */
|
||||
static final class StringIsNullOrEmpty {
|
||||
@BeforeTemplate
|
||||
boolean before(String str) {
|
||||
boolean before(@Nullable String str) {
|
||||
return str == null || str.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
@@ -17,7 +18,6 @@ import static org.testng.Assert.assertTrue;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.DoNotCall;
|
||||
import com.google.errorprone.refaster.ImportPolicy;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
@@ -96,7 +96,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(String message) {
|
||||
fail(message);
|
||||
}
|
||||
@@ -110,7 +110,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(String message, Throwable throwable) {
|
||||
fail(message, throwable);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean condition) {
|
||||
assertThat(condition).isTrue();
|
||||
}
|
||||
@@ -136,7 +136,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean condition, String message) {
|
||||
assertThat(condition).withFailMessage(message).isTrue();
|
||||
}
|
||||
@@ -149,7 +149,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean condition) {
|
||||
assertThat(condition).isFalse();
|
||||
}
|
||||
@@ -162,7 +162,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean condition, String message) {
|
||||
assertThat(condition).withFailMessage(message).isFalse();
|
||||
}
|
||||
@@ -175,7 +175,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object object) {
|
||||
assertThat(object).isNull();
|
||||
}
|
||||
@@ -188,7 +188,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object object, String message) {
|
||||
assertThat(object).withFailMessage(message).isNull();
|
||||
}
|
||||
@@ -201,7 +201,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object object) {
|
||||
assertThat(object).isNotNull();
|
||||
}
|
||||
@@ -214,7 +214,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object object, String message) {
|
||||
assertThat(object).withFailMessage(message).isNotNull();
|
||||
}
|
||||
@@ -227,7 +227,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected) {
|
||||
assertThat(actual).isSameAs(expected);
|
||||
}
|
||||
@@ -240,7 +240,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).isSameAs(expected);
|
||||
}
|
||||
@@ -253,7 +253,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected) {
|
||||
assertThat(actual).isNotSameAs(expected);
|
||||
}
|
||||
@@ -266,7 +266,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).isNotSameAs(expected);
|
||||
}
|
||||
@@ -329,7 +329,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected) {
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
@@ -392,7 +392,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).isEqualTo(expected);
|
||||
}
|
||||
@@ -405,7 +405,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float actual, float expected, float delta) {
|
||||
assertThat(actual).isCloseTo(expected, offset(delta));
|
||||
}
|
||||
@@ -418,7 +418,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float actual, float expected, float delta, String message) {
|
||||
assertThat(actual).withFailMessage(message).isCloseTo(expected, offset(delta));
|
||||
}
|
||||
@@ -431,7 +431,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double actual, double expected, double delta) {
|
||||
assertThat(actual).isCloseTo(expected, offset(delta));
|
||||
}
|
||||
@@ -444,7 +444,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double actual, double expected, double delta, String message) {
|
||||
assertThat(actual).withFailMessage(message).isCloseTo(expected, offset(delta));
|
||||
}
|
||||
@@ -497,7 +497,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object[] actual, Object[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
@@ -550,7 +550,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object[] actual, Object[] expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
@@ -563,7 +563,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object[] actual, Object[] expected) {
|
||||
assertThat(actual).containsExactlyInAnyOrder(expected);
|
||||
}
|
||||
@@ -576,7 +576,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object[] actual, Object[] expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).containsExactlyInAnyOrder(expected);
|
||||
}
|
||||
@@ -589,7 +589,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
<S, T extends S> void after(Iterator<S> actual, Iterator<T> expected) {
|
||||
// XXX: This is not `null`-safe.
|
||||
// XXX: The `ImmutableList.copyOf` should actually *not* be imported statically.
|
||||
@@ -604,7 +604,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
<S, T extends S> void after(Iterator<S> actual, Iterator<T> expected, String message) {
|
||||
// XXX: This is not `null`-safe.
|
||||
// XXX: The `ImmutableList.copyOf` should actually *not* be imported statically.
|
||||
@@ -629,7 +629,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
<S, T extends S> void after(Iterable<S> actual, Iterable<T> expected) {
|
||||
assertThat(actual).containsExactlyElementsOf(expected);
|
||||
}
|
||||
@@ -647,7 +647,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
<S, T extends S> void after(Iterable<S> actual, Iterable<T> expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).containsExactlyElementsOf(expected);
|
||||
}
|
||||
@@ -660,7 +660,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
<S, T extends S> void after(Set<S> actual, Set<T> expected) {
|
||||
assertThat(actual).hasSameElementsAs(expected);
|
||||
}
|
||||
@@ -673,7 +673,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
<S, T extends S> void after(Set<S> actual, Set<T> expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).hasSameElementsAs(expected);
|
||||
}
|
||||
@@ -741,7 +741,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected) {
|
||||
assertThat(actual).isNotEqualTo(expected);
|
||||
}
|
||||
@@ -809,7 +809,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object actual, Object expected, String message) {
|
||||
assertThat(actual).withFailMessage(message).isNotEqualTo(expected);
|
||||
}
|
||||
@@ -822,7 +822,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float actual, float expected, float delta) {
|
||||
assertThat(actual).isNotCloseTo(expected, offset(delta));
|
||||
}
|
||||
@@ -835,7 +835,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float actual, float expected, float delta, String message) {
|
||||
assertThat(actual).withFailMessage(message).isNotCloseTo(expected, offset(delta));
|
||||
}
|
||||
@@ -848,7 +848,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double actual, double expected, double delta) {
|
||||
assertThat(actual).isNotCloseTo(expected, offset(delta));
|
||||
}
|
||||
@@ -861,7 +861,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double actual, double expected, double delta, String message) {
|
||||
assertThat(actual).withFailMessage(message).isNotCloseTo(expected, offset(delta));
|
||||
}
|
||||
@@ -874,7 +874,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable runnable) {
|
||||
assertThatThrownBy(runnable);
|
||||
}
|
||||
@@ -887,7 +887,7 @@ final class TestNGToAssertJTemplates {
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable runnable, Class<T> clazz) {
|
||||
assertThatThrownBy(runnable).isInstanceOf(clazz);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.AlsoNegation;
|
||||
@@ -17,6 +19,7 @@ import java.time.ZoneOffset;
|
||||
import java.time.chrono.ChronoLocalDate;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
import java.time.chrono.ChronoZonedDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
|
||||
/** Refaster templates related to expressions dealing with time. */
|
||||
@@ -49,13 +52,26 @@ final class TimeTemplates {
|
||||
ZoneId.of("UTC"),
|
||||
ZoneId.of("+0"),
|
||||
ZoneId.of("-0"),
|
||||
ZoneOffset.UTC.normalized(),
|
||||
ZoneId.from(ZoneOffset.UTC));
|
||||
UTC.normalized(),
|
||||
ZoneId.from(UTC));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ZoneOffset after() {
|
||||
return ZoneOffset.UTC;
|
||||
return UTC;
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Instant#atOffset(ZoneOffset)} over the more verbose alternative. */
|
||||
static final class InstantAtOffset {
|
||||
@BeforeTemplate
|
||||
OffsetDateTime before(Instant instant, ZoneOffset zoneOffset) {
|
||||
return OffsetDateTime.ofInstant(instant, zoneOffset);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
OffsetDateTime after(Instant instant, ZoneOffset zoneOffset) {
|
||||
return instant.atOffset(zoneOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +80,7 @@ final class TimeTemplates {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("TimeZoneUsage")
|
||||
Clock before() {
|
||||
return Clock.system(ZoneOffset.UTC);
|
||||
return Clock.system(UTC);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -310,8 +326,86 @@ final class TimeTemplates {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Duration#ofDays(long)} over alternative representations. */
|
||||
static final class DurationOfDays {
|
||||
@BeforeTemplate
|
||||
Duration before(long amount) {
|
||||
return Duration.of(amount, ChronoUnit.DAYS);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(long amount) {
|
||||
return Duration.ofDays(amount);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Duration#ofHours(long)} over alternative representations. */
|
||||
static final class DurationOfHours {
|
||||
@BeforeTemplate
|
||||
Duration before(long amount) {
|
||||
return Duration.of(amount, ChronoUnit.HOURS);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(long amount) {
|
||||
return Duration.ofHours(amount);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Duration#ofMillis(long)} over alternative representations. */
|
||||
static final class DurationOfMillis {
|
||||
@BeforeTemplate
|
||||
Duration before(long amount) {
|
||||
return Duration.of(amount, ChronoUnit.MILLIS);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(long amount) {
|
||||
return Duration.ofMillis(amount);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Duration#ofMinutes(long)} over alternative representations. */
|
||||
static final class DurationOfMinutes {
|
||||
@BeforeTemplate
|
||||
Duration before(long amount) {
|
||||
return Duration.of(amount, ChronoUnit.MINUTES);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(long amount) {
|
||||
return Duration.ofMinutes(amount);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Duration#ofNanos(long)} over alternative representations. */
|
||||
static final class DurationOfNanos {
|
||||
@BeforeTemplate
|
||||
Duration before(long amount) {
|
||||
return Duration.of(amount, ChronoUnit.NANOS);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(long amount) {
|
||||
return Duration.ofNanos(amount);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Duration#ofSeconds(long)} over alternative representations. */
|
||||
static final class DurationOfSeconds {
|
||||
@BeforeTemplate
|
||||
Duration before(long amount) {
|
||||
return Duration.of(amount, ChronoUnit.SECONDS);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(long amount) {
|
||||
return Duration.ofSeconds(amount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't unnecessarily convert two and from milliseconds. (This way nanosecond precision is
|
||||
* Don't unnecessarily convert to and from milliseconds. (This way nanosecond precision is
|
||||
* retained.)
|
||||
*
|
||||
* <p><strong>Warning:</strong> this rewrite rule increases precision!
|
||||
@@ -329,7 +423,7 @@ final class TimeTemplates {
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't unnecessarily convert two and from milliseconds. (This way nanosecond precision is
|
||||
* Don't unnecessarily convert to and from milliseconds. (This way nanosecond precision is
|
||||
* retained.)
|
||||
*
|
||||
* <p><strong>Warning:</strong> this rewrite rule increases precision!
|
||||
|
||||
@@ -1,12 +1,25 @@
|
||||
package tech.picnic.errorprone.refastertemplates;
|
||||
|
||||
import static org.springframework.http.HttpMethod.GET;
|
||||
import static org.springframework.http.HttpMethod.HEAD;
|
||||
import static org.springframework.http.HttpMethod.OPTIONS;
|
||||
import static org.springframework.http.HttpMethod.PATCH;
|
||||
import static org.springframework.http.HttpMethod.POST;
|
||||
import static org.springframework.http.HttpMethod.PUT;
|
||||
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import java.util.function.Function;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec;
|
||||
import org.springframework.web.reactive.function.client.WebClient.RequestBodyUriSpec;
|
||||
import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
|
||||
import org.springframework.web.reactive.function.client.WebClient.RequestHeadersUriSpec;
|
||||
|
||||
/**
|
||||
* Refaster templates related to expressions dealing with {@link
|
||||
@@ -23,7 +36,7 @@ final class WebClientTemplates {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
WebTestClient.RequestHeadersSpec<?> before2(
|
||||
WebTestClient.RequestHeadersSpec<?> before(
|
||||
WebTestClient.RequestBodySpec requestBodySpec, T value) {
|
||||
return requestBodySpec.body(fromValue(value));
|
||||
}
|
||||
@@ -33,4 +46,159 @@ final class WebClientTemplates {
|
||||
return requestBodySpec.bodyValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link WebClient#get()} over {@link WebClient#method(HttpMethod)} with {@link
|
||||
* HttpMethod#GET}.
|
||||
*/
|
||||
static final class WebClientGet {
|
||||
@BeforeTemplate
|
||||
RequestHeadersSpec<?> before(WebClient webClient) {
|
||||
return webClient.method(GET);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
WebTestClient.RequestHeadersSpec<?> before(WebTestClient webClient) {
|
||||
return webClient.method(GET);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
RequestHeadersSpec<?> after(WebClient webClient) {
|
||||
return webClient.get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link WebClient#head()} over {@link WebClient#method(HttpMethod)} with {@link
|
||||
* HttpMethod#HEAD}.
|
||||
*/
|
||||
static final class WebClientHead {
|
||||
@BeforeTemplate
|
||||
RequestHeadersSpec<?> before(WebClient webClient) {
|
||||
return webClient.method(HEAD);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
WebTestClient.RequestHeadersSpec<?> before(WebTestClient webClient) {
|
||||
return webClient.method(HEAD);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
RequestHeadersSpec<?> after(WebClient webClient) {
|
||||
return webClient.head();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link WebClient#options()} over {@link WebClient#method(HttpMethod)} with {@link
|
||||
* HttpMethod#OPTIONS}.
|
||||
*/
|
||||
static final class WebClientOptions {
|
||||
@BeforeTemplate
|
||||
RequestHeadersSpec<?> before(WebClient webClient) {
|
||||
return webClient.method(OPTIONS);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
WebTestClient.RequestHeadersSpec<?> before(WebTestClient webClient) {
|
||||
return webClient.method(OPTIONS);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
RequestHeadersSpec<?> after(WebClient webClient) {
|
||||
return webClient.options();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link WebClient#patch()} over {@link WebClient#method(HttpMethod)} with {@link
|
||||
* HttpMethod#PATCH}.
|
||||
*/
|
||||
static final class WebClientPatch {
|
||||
@BeforeTemplate
|
||||
RequestBodyUriSpec before(WebClient webClient) {
|
||||
return webClient.method(PATCH);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
WebTestClient.RequestBodyUriSpec before(WebTestClient webClient) {
|
||||
return webClient.method(PATCH);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
RequestBodyUriSpec after(WebClient webClient) {
|
||||
return webClient.patch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link WebClient#post()} over {@link WebClient#method(HttpMethod)} with {@link
|
||||
* HttpMethod#POST}.
|
||||
*/
|
||||
static final class WebClientPost {
|
||||
@BeforeTemplate
|
||||
RequestBodyUriSpec before(WebClient webClient) {
|
||||
return webClient.method(POST);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
WebTestClient.RequestBodyUriSpec before(WebTestClient webClient) {
|
||||
return webClient.method(POST);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
RequestBodyUriSpec after(WebClient webClient) {
|
||||
return webClient.post();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link WebClient#put()} over {@link WebClient#method(HttpMethod)} with {@link
|
||||
* HttpMethod#PUT}.
|
||||
*/
|
||||
static final class WebClientPut {
|
||||
@BeforeTemplate
|
||||
RequestBodyUriSpec before(WebClient webClient) {
|
||||
return webClient.method(PUT);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
WebTestClient.RequestBodyUriSpec before(WebTestClient webClient) {
|
||||
return webClient.method(PUT);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
RequestBodyUriSpec after(WebClient webClient) {
|
||||
return webClient.put();
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily use {@link RequestHeadersUriSpec#uri(Function)}. */
|
||||
abstract static class RequestHeadersUriSpecUri {
|
||||
@BeforeTemplate
|
||||
RequestHeadersSpec<?> before(
|
||||
RequestHeadersUriSpec<?> requestHeadersUriSpec,
|
||||
String path,
|
||||
@Repeated Object uriVariables) {
|
||||
return requestHeadersUriSpec.uri(
|
||||
uriBuilder -> uriBuilder.path(path).build(Refaster.asVarargs(uriVariables)));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
WebTestClient.RequestHeadersSpec<?> before(
|
||||
WebTestClient.RequestHeadersUriSpec<?> requestHeadersUriSpec,
|
||||
String path,
|
||||
@Repeated Object uriVariables) {
|
||||
return requestHeadersUriSpec.uri(
|
||||
uriBuilder -> uriBuilder.path(path).build(Refaster.asVarargs(uriVariables)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
RequestHeadersSpec<?> after(
|
||||
RequestHeadersUriSpec<?> requestHeadersUriSpec,
|
||||
String path,
|
||||
@Repeated Object uriVariables) {
|
||||
return requestHeadersUriSpec.uri(path, Refaster.asVarargs(uriVariables));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class AmbiguousJsonCreatorCheckTest {
|
||||
final class AmbiguousJsonCreatorTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(AmbiguousJsonCreatorCheck.class, getClass())
|
||||
CompilationTestHelper.newInstance(AmbiguousJsonCreator.class, getClass())
|
||||
.expectErrorMessage(
|
||||
"X",
|
||||
containsPattern("`JsonCreator.Mode` should be set for single-argument creators"));
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(AmbiguousJsonCreatorCheck.class, getClass());
|
||||
BugCheckerRefactoringTestHelper.newInstance(AmbiguousJsonCreator.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
@@ -112,7 +112,6 @@ final class AmbiguousJsonCreatorCheckTest {
|
||||
" return new F(s);",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class AssertJIsNullTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(AssertJIsNull.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(AssertJIsNull.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" assertThat(1).isEqualTo(1);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(1).isEqualTo(null);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" assertThat(\"foo\").isEqualTo(null);",
|
||||
" isEqualTo(null);",
|
||||
" }",
|
||||
"",
|
||||
" private boolean isEqualTo(Object value) {",
|
||||
" return value.equals(\"bar\");",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" assertThat(1).isEqualTo(null);",
|
||||
" assertThat(\"foo\").isEqualTo(null);",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" assertThat(1).isNull();",
|
||||
" assertThat(\"foo\").isNull();",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,11 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public final class AutowiredConstructorCheckTest {
|
||||
final class AutowiredConstructorTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(AutowiredConstructorCheck.class, getClass());
|
||||
CompilationTestHelper.newInstance(AutowiredConstructor.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(AutowiredConstructorCheck.class, getClass());
|
||||
BugCheckerRefactoringTestHelper.newInstance(AutowiredConstructor.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
@@ -27,27 +27,34 @@ public 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 @@ public final class AutowiredConstructorCheckTest {
|
||||
" }",
|
||||
"",
|
||||
" class H {",
|
||||
" @SafeVarargs H(List<String>... lists) {}",
|
||||
" @SafeVarargs",
|
||||
" H(List<String>... lists) {}",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
@@ -70,11 +78,14 @@ public 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 @@ public final class AutowiredConstructorCheckTest {
|
||||
"",
|
||||
"interface Container {",
|
||||
" class A {",
|
||||
" @Deprecated A() {}",
|
||||
"",
|
||||
" @Deprecated",
|
||||
" A() {}",
|
||||
" }",
|
||||
"",
|
||||
" class B {",
|
||||
"",
|
||||
" B(String x) {}",
|
||||
" }",
|
||||
"}")
|
||||
@@ -1,156 +0,0 @@
|
||||
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;
|
||||
|
||||
public final class CanonicalAnnotationSyntaxCheckTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(CanonicalAnnotationSyntaxCheck.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(CanonicalAnnotationSyntaxCheck.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" int[] value() default {};",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo A minimal1();",
|
||||
" @A.Foo A minimal2();",
|
||||
" @Foo A minimal3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo() A functional1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo() A functional2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo() A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(1) A simple1();",
|
||||
" @A.Foo(1) A simple2();",
|
||||
" @Foo(1) A simple3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo({1}) A singleton1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo({1}) A singleton2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({1}) A singleton3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo(value = 1) A verbose1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo(value = 1) A verbose2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(value = 1) A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value2 = 2) A custom1();",
|
||||
" @A.Foo(value2 = 2) A custom2();",
|
||||
" @Foo(value2 = 2) A custom3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo(value2 = {2}) A customSingleton1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo(value2 = {2}) A customSingleton2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(value2 = {2}) A customSingleton3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value2 = {2, 2}) A customPair1();",
|
||||
" @A.Foo(value2 = {2, 2}) A customPair2();",
|
||||
" @Foo(value2 = {2, 2}) A customPair3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = 1, value2 = 2) A extended1();",
|
||||
" @A.Foo(value = 1, value2 = 2) A extended2();",
|
||||
" @Foo(value = 1, value2 = 2) A extended3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo({1, 1,}) A trailingComma1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo({1, 1,}) A trailingComma2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({1, 1,}) A trailingComma3();",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"in/pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo() A functional1();",
|
||||
" @A.Foo() A functional2();",
|
||||
" @Foo() A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = \"foo\") A verbose1();",
|
||||
" @A.Foo(value = \"a'b\") A verbose2();",
|
||||
" @Foo(value = \"a\" + \"\\nb\") A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = {\"foo\"}) A moreVerbose1();",
|
||||
" @A.Foo(value = {\"a'b\"}) A moreVerbose2();",
|
||||
" @Foo(value = {\"a\" + \"\\nb\"}) A moreVerbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = {\"foo\", \"bar\"}, value2 = {2}) A extended1();",
|
||||
" @A.Foo(value = {\"a'b\", \"c'd\"}, value2 = {2}) A extended2();",
|
||||
" @Foo(value = {\"a\" + \"\\nb\", \"c\" + \"\\nd\"}, value2 = {2}) A extended3();",
|
||||
"",
|
||||
" @pkg.A.Foo({\"foo\", \"bar\",}) A trailingComma1();",
|
||||
" @A.Foo({\"a'b\", \"c'd\",}) A trailingComma2();",
|
||||
" @Foo({\"a\" + \"\\nb\", \"c\" + \"\\nd\",}) A trailingComma3();",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"out/pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo A functional1();",
|
||||
" @A.Foo A functional2();",
|
||||
" @Foo A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(\"foo\") A verbose1();",
|
||||
" @A.Foo(\"a'b\") A verbose2();",
|
||||
" @Foo(\"a\" + \"\\nb\") A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(\"foo\") A moreVerbose1();",
|
||||
" @A.Foo(\"a'b\") A moreVerbose2();",
|
||||
" @Foo(\"a\" + \"\\nb\") A moreVerbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = {\"foo\", \"bar\"}, value2 = 2) A extended1();",
|
||||
" @A.Foo(value = {\"a'b\", \"c'd\"}, value2 = 2) A extended2();",
|
||||
" @Foo(value = {\"a\" + \"\\nb\", \"c\" + \"\\nd\"}, value2 = 2) A extended3();",
|
||||
"",
|
||||
" @pkg.A.Foo({\"foo\", \"bar\"}) A trailingComma1();",
|
||||
" @A.Foo({\"a'b\", \"c'd\"}) A trailingComma2();",
|
||||
" @Foo({\"a\" + \"\\nb\", \"c\" + \"\\nd\"}) A trailingComma3();",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
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 CanonicalAnnotationSyntaxTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(CanonicalAnnotationSyntax.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" int[] value() default {};",
|
||||
"",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo",
|
||||
" A minimal1();",
|
||||
"",
|
||||
" @A.Foo",
|
||||
" A minimal2();",
|
||||
"",
|
||||
" @Foo",
|
||||
" A minimal3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo()",
|
||||
" A functional1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo()",
|
||||
" A functional2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo()",
|
||||
" A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(1)",
|
||||
" A simple1();",
|
||||
"",
|
||||
" @A.Foo(1)",
|
||||
" A simple2();",
|
||||
"",
|
||||
" @Foo(1)",
|
||||
" A simple3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo({1})",
|
||||
" A singleton1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo({1})",
|
||||
" A singleton2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({1})",
|
||||
" A singleton3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo(value = 1)",
|
||||
" A verbose1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo(value = 1)",
|
||||
" A verbose2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(value = 1)",
|
||||
" A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value2 = 2)",
|
||||
" A custom1();",
|
||||
"",
|
||||
" @A.Foo(value2 = 2)",
|
||||
" A custom2();",
|
||||
"",
|
||||
" @Foo(value2 = 2)",
|
||||
" A custom3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo(value2 = {2})",
|
||||
" A customSingleton1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo(value2 = {2})",
|
||||
" A customSingleton2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo(value2 = {2})",
|
||||
" A customSingleton3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value2 = {2, 2})",
|
||||
" A customPair1();",
|
||||
"",
|
||||
" @A.Foo(value2 = {2, 2})",
|
||||
" A customPair2();",
|
||||
"",
|
||||
" @Foo(value2 = {2, 2})",
|
||||
" A customPair3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = 1, value2 = 2)",
|
||||
" A extended1();",
|
||||
"",
|
||||
" @A.Foo(value = 1, value2 = 2)",
|
||||
" A extended2();",
|
||||
"",
|
||||
" @Foo(value = 1, value2 = 2)",
|
||||
" A extended3();",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @pkg.A.Foo({",
|
||||
" 1, 1,",
|
||||
" })",
|
||||
" A trailingComma1();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @A.Foo({",
|
||||
" 1, 1,",
|
||||
" })",
|
||||
" A trailingComma2();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" @Foo({",
|
||||
" 1, 1,",
|
||||
" })",
|
||||
" A trailingComma3();",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"in/pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo()",
|
||||
" A functional1();",
|
||||
"",
|
||||
" @A.Foo()",
|
||||
" A functional2();",
|
||||
"",
|
||||
" @Foo()",
|
||||
" A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = \"foo\")",
|
||||
" A verbose1();",
|
||||
"",
|
||||
" @A.Foo(value = \"a'b\")",
|
||||
" A verbose2();",
|
||||
"",
|
||||
" @Foo(value = \"a\" + \"\\nb\")",
|
||||
" A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(value = {\"foo\"})",
|
||||
" A moreVerbose1();",
|
||||
"",
|
||||
" @A.Foo(value = {\"a'b\"})",
|
||||
" A moreVerbose2();",
|
||||
"",
|
||||
" @Foo(value = {\"a\" + \"\\nb\"})",
|
||||
" A moreVerbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(",
|
||||
" value = {\"foo\", \"bar\"},",
|
||||
" value2 = {2})",
|
||||
" A extended1();",
|
||||
"",
|
||||
" @A.Foo(",
|
||||
" value = {\"a'b\", \"c'd\"},",
|
||||
" value2 = {2})",
|
||||
" A extended2();",
|
||||
"",
|
||||
" @Foo(",
|
||||
" value = {\"a\" + \"\\nb\", \"c\" + \"\\nd\"},",
|
||||
" value2 = {2})",
|
||||
" A extended3();",
|
||||
"",
|
||||
" @pkg.A.Foo({",
|
||||
" \"foo\", \"bar\",",
|
||||
" })",
|
||||
" A trailingComma1();",
|
||||
"",
|
||||
" @A.Foo({",
|
||||
" \"a'b\", \"c'd\",",
|
||||
" })",
|
||||
" A trailingComma2();",
|
||||
"",
|
||||
" @Foo({",
|
||||
" \"a\" + \"\\nb\",",
|
||||
" \"c\" + \"\\nd\",",
|
||||
" })",
|
||||
" A trailingComma3();",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"out/pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import pkg.A.Foo;",
|
||||
"",
|
||||
"interface A {",
|
||||
" @interface Foo {",
|
||||
" String[] value() default {};",
|
||||
"",
|
||||
" int[] value2() default {};",
|
||||
" }",
|
||||
"",
|
||||
" @pkg.A.Foo",
|
||||
" A functional1();",
|
||||
"",
|
||||
" @A.Foo",
|
||||
" A functional2();",
|
||||
"",
|
||||
" @Foo",
|
||||
" A functional3();",
|
||||
"",
|
||||
" @pkg.A.Foo(\"foo\")",
|
||||
" A verbose1();",
|
||||
"",
|
||||
" @A.Foo(\"a'b\")",
|
||||
" A verbose2();",
|
||||
"",
|
||||
" @Foo(\"a\" + \"\\nb\")",
|
||||
" A verbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(\"foo\")",
|
||||
" A moreVerbose1();",
|
||||
"",
|
||||
" @A.Foo(\"a'b\")",
|
||||
" A moreVerbose2();",
|
||||
"",
|
||||
" @Foo(\"a\" + \"\\nb\")",
|
||||
" A moreVerbose3();",
|
||||
"",
|
||||
" @pkg.A.Foo(",
|
||||
" value = {\"foo\", \"bar\"},",
|
||||
" value2 = 2)",
|
||||
" A extended1();",
|
||||
"",
|
||||
" @A.Foo(",
|
||||
" value = {\"a'b\", \"c'd\"},",
|
||||
" value2 = 2)",
|
||||
" A extended2();",
|
||||
"",
|
||||
" @Foo(",
|
||||
" value = {\"a\" + \"\\nb\", \"c\" + \"\\nd\"},",
|
||||
" value2 = 2)",
|
||||
" A extended3();",
|
||||
"",
|
||||
" @pkg.A.Foo({\"foo\", \"bar\"})",
|
||||
" A trailingComma1();",
|
||||
"",
|
||||
" @A.Foo({\"a'b\", \"c'd\"})",
|
||||
" A trailingComma2();",
|
||||
"",
|
||||
" @Foo({\"a\" + \"\\nb\", \"c\" + \"\\nd\"})",
|
||||
" A trailingComma3();",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers.SECOND;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class CollectorMutabilityTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(CollectorMutability.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(CollectorMutability.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
"import static com.google.common.collect.ImmutableMap.toImmutableMap;",
|
||||
"import static com.google.common.collect.ImmutableSet.toImmutableSet;",
|
||||
"import static java.util.stream.Collectors.toCollection;",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.HashMap;",
|
||||
"import java.util.HashSet;",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).collect(Collectors.toList());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(2).collect(toList());",
|
||||
" Flux.just(3).collect(toImmutableList());",
|
||||
" Flux.just(4).collect(toCollection(ArrayList::new));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(\"foo\").collect(Collectors.toMap(String::getBytes, String::length));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(\"bar\").collect(toMap(String::getBytes, String::length));",
|
||||
" Flux.just(\"baz\").collect(toImmutableMap(String::getBytes, String::length));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(\"qux\").collect(toMap(String::getBytes, String::length, (a, b) -> a));",
|
||||
" Flux.just(\"quux\").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> a));",
|
||||
" Flux.just(\"quuz\").collect(toMap(String::getBytes, String::length, (a, b) -> a, HashMap::new));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of(1).collect(Collectors.toSet());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of(2).collect(toSet());",
|
||||
" Stream.of(3).collect(toImmutableSet());",
|
||||
" Stream.of(4).collect(toCollection(HashSet::new));",
|
||||
"",
|
||||
" Flux.just(\"foo\").collect(Collectors.joining());",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(Collectors.toList());",
|
||||
" Flux.just(2).collect(toList());",
|
||||
"",
|
||||
" Stream.of(\"foo\").collect(Collectors.toMap(String::getBytes, String::length));",
|
||||
" Stream.of(\"bar\").collect(toMap(String::getBytes, String::length));",
|
||||
" Flux.just(\"baz\").collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
" Flux.just(\"qux\").collect(toMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
"",
|
||||
" Stream.of(1).collect(Collectors.toSet());",
|
||||
" Stream.of(2).collect(toSet());",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.collect.ImmutableList.toImmutableList;",
|
||||
"import static com.google.common.collect.ImmutableMap.toImmutableMap;",
|
||||
"import static com.google.common.collect.ImmutableSet.toImmutableSet;",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(toImmutableList());",
|
||||
" Flux.just(2).collect(toImmutableList());",
|
||||
"",
|
||||
" Stream.of(\"foo\").collect(toImmutableMap(String::getBytes, String::length));",
|
||||
" Stream.of(\"bar\").collect(toImmutableMap(String::getBytes, String::length));",
|
||||
" Flux.just(\"baz\").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
" Flux.just(\"qux\").collect(toImmutableMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
"",
|
||||
" Stream.of(1).collect(toImmutableSet());",
|
||||
" Stream.of(2).collect(toImmutableSet());",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
.setFixChooser(SECOND)
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(Collectors.toList());",
|
||||
" Flux.just(2).collect(toList());",
|
||||
"",
|
||||
" Stream.of(\"foo\").collect(Collectors.toMap(String::getBytes, String::length));",
|
||||
" Stream.of(\"bar\").collect(toMap(String::getBytes, String::length));",
|
||||
" Flux.just(\"baz\").collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
" Flux.just(\"qux\").collect(toMap(String::getBytes, String::length, (a, b) -> b));",
|
||||
"",
|
||||
" Stream.of(1).collect(Collectors.toSet());",
|
||||
" Stream.of(2).collect(toSet());",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static java.util.stream.Collectors.toCollection;",
|
||||
"import static java.util.stream.Collectors.toList;",
|
||||
"import static java.util.stream.Collectors.toMap;",
|
||||
"import static java.util.stream.Collectors.toSet;",
|
||||
"",
|
||||
"import java.util.ArrayList;",
|
||||
"import java.util.HashMap;",
|
||||
"import java.util.HashSet;",
|
||||
"import java.util.stream.Collectors;",
|
||||
"import java.util.stream.Stream;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).collect(toCollection(ArrayList::new));",
|
||||
" Flux.just(2).collect(toCollection(ArrayList::new));",
|
||||
"",
|
||||
" Stream.of(\"foo\")",
|
||||
" .collect(",
|
||||
" Collectors.toMap(",
|
||||
" String::getBytes,",
|
||||
" String::length,",
|
||||
" (a, b) -> {",
|
||||
" throw new IllegalStateException();",
|
||||
" },",
|
||||
" HashMap::new));",
|
||||
" Stream.of(\"bar\")",
|
||||
" .collect(",
|
||||
" toMap(",
|
||||
" String::getBytes,",
|
||||
" String::length,",
|
||||
" (a, b) -> {",
|
||||
" throw new IllegalStateException();",
|
||||
" },",
|
||||
" HashMap::new));",
|
||||
" Flux.just(\"baz\")",
|
||||
" .collect(Collectors.toMap(String::getBytes, String::length, (a, b) -> b, HashMap::new));",
|
||||
" Flux.just(\"qux\").collect(toMap(String::getBytes, String::length, (a, b) -> b, HashMap::new));",
|
||||
"",
|
||||
" Stream.of(1).collect(toCollection(HashSet::new));",
|
||||
" Stream.of(2).collect(toCollection(HashSet::new));",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,11 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public final class EmptyMethodCheckTest {
|
||||
final class EmptyMethodTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(EmptyMethodCheck.class, getClass());
|
||||
CompilationTestHelper.newInstance(EmptyMethod.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethodCheck.class, getClass());
|
||||
BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
@@ -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 ErrorProneTestHelperSourceFormatTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(ErrorProneTestHelperSourceFormat.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
ErrorProneTestHelperSourceFormat.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.EmptyMethod;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final CompilationTestHelper compilationTestHelper =",
|
||||
" CompilationTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
"",
|
||||
" void m() {",
|
||||
" compilationTestHelper",
|
||||
" // BUG: Diagnostic contains: No source code provided",
|
||||
" .addSourceLines(\"A.java\")",
|
||||
" // BUG: Diagnostic contains: Source code is malformed:",
|
||||
" .addSourceLines(\"B.java\", \"class B {\")",
|
||||
" // Well-formed code, so not flagged.",
|
||||
" .addSourceLines(\"C.java\", \"class C {}\")",
|
||||
" // Malformed code, but not compile-time constant, so not flagged.",
|
||||
" .addSourceLines(\"D.java\", \"class D {\" + getClass())",
|
||||
" // BUG: Diagnostic contains: Test code should follow the Google Java style",
|
||||
" .addSourceLines(\"E.java\", \"class E { }\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" refactoringTestHelper",
|
||||
" // BUG: Diagnostic contains: Test code should follow the Google Java style",
|
||||
" .addInputLines(\"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.EmptyMethod;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final CompilationTestHelper compilationTestHelper =",
|
||||
" CompilationTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
"",
|
||||
" void m() {",
|
||||
" compilationTestHelper",
|
||||
" .addSourceLines(",
|
||||
" \"A.java\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"import java.util.Collection;\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A,A> { }\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" refactoringTestHelper",
|
||||
" .addInputLines(",
|
||||
" \"in/A.java\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"import java.util.Collection;\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A,A> { }\")",
|
||||
" .addOutputLines(",
|
||||
" \"out/A.java\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"import java.util.Collection;\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A,A> { }\")",
|
||||
" .doTest(TestMode.TEXT_MATCH);",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"out/A.java",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import tech.picnic.errorprone.bugpatterns.EmptyMethod;",
|
||||
"",
|
||||
"class A {",
|
||||
" private final CompilationTestHelper compilationTestHelper =",
|
||||
" CompilationTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
" private final BugCheckerRefactoringTestHelper refactoringTestHelper =",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(EmptyMethod.class, getClass());",
|
||||
"",
|
||||
" void m() {",
|
||||
" compilationTestHelper",
|
||||
" .addSourceLines(",
|
||||
" \"A.java\",",
|
||||
" \"import java.util.List;\",",
|
||||
" \"import java.util.Map;\",",
|
||||
" \"\",",
|
||||
" \"interface A extends List<A>, Map<A, A> {}\")",
|
||||
" .doTest();",
|
||||
"",
|
||||
" refactoringTestHelper",
|
||||
" .addInputLines(",
|
||||
" \"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);
|
||||
}
|
||||
}
|
||||
@@ -3,23 +3,23 @@ package tech.picnic.errorprone.bugpatterns;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ExplicitEnumOrderingCheckTest {
|
||||
final class ExplicitEnumOrderingTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(ExplicitEnumOrderingCheck.class, getClass());
|
||||
CompilationTestHelper.newInstance(ExplicitEnumOrdering.class, getClass());
|
||||
|
||||
@Test
|
||||
void Identification() {
|
||||
void identification() {
|
||||
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;",
|
||||
"",
|
||||
@@ -0,0 +1,122 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugCheckerRefactoringTestHelper.newInstance;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class FluxFlatMapUsageTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(FluxFlatMapUsage.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
newInstance(FluxFlatMapUsage.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
compilationTestHelper
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.function.BiFunction;",
|
||||
"import java.util.function.Function;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).flatMap(Flux::just);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).<String>flatMap(i -> Flux.just(String.valueOf(i)));",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).flatMapSequential(Flux::just);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Flux.just(1).<String>flatMapSequential(i -> Flux.just(String.valueOf(i)));",
|
||||
"",
|
||||
" Mono.just(1).flatMap(Mono::just);",
|
||||
" Flux.just(1).concatMap(Flux::just);",
|
||||
"",
|
||||
" Flux.just(1).flatMap(Flux::just, 1);",
|
||||
" Flux.just(1).flatMap(Flux::just, 1, 1);",
|
||||
" Flux.just(1).flatMap(Flux::just, throwable -> Flux.empty(), Flux::empty);",
|
||||
"",
|
||||
" Flux.just(1).flatMapSequential(Flux::just, 1);",
|
||||
" Flux.just(1).flatMapSequential(Flux::just, 1, 1);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.<String, Flux<String>>sink(Flux::flatMap);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.<Integer, Flux<Integer>>sink(Flux::<Integer>flatMap);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.<String, Flux<String>>sink(Flux::flatMapSequential);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" this.<Integer, Flux<Integer>>sink(Flux::<Integer>flatMapSequential);",
|
||||
"",
|
||||
" this.<String, Mono<String>>sink(Mono::flatMap);",
|
||||
" }",
|
||||
"",
|
||||
" private <T, P> void sink(BiFunction<P, Function<T, P>, P> fun) {}",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacementFirstSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
.setFixChooser(FixChoosers.FIRST)
|
||||
.addInputLines(
|
||||
"in/A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).flatMap(Flux::just);",
|
||||
" Flux.just(1).flatMapSequential(Flux::just);",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"out/A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" Flux.just(1).concatMap(Flux::just);",
|
||||
" Flux.just(1).concatMap(Flux::just);",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacementSecondSuggestedFix() {
|
||||
refactoringTestHelper
|
||||
.setFixChooser(FixChoosers.SECOND)
|
||||
.addInputLines(
|
||||
"in/A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final int MAX_CONCURRENCY = 8;",
|
||||
"",
|
||||
" void m() {",
|
||||
" Flux.just(1).flatMap(Flux::just);",
|
||||
" Flux.just(1).flatMapSequential(Flux::just);",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"out/A.java",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final int MAX_CONCURRENCY = 8;",
|
||||
"",
|
||||
" void m() {",
|
||||
" Flux.just(1).flatMap(Flux::just, MAX_CONCURRENCY);",
|
||||
" Flux.just(1).flatMapSequential(Flux::just, MAX_CONCURRENCY);",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,11 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public final class FormatStringConcatenationCheckTest {
|
||||
final class FormatStringConcatenationTest {
|
||||
private final CompilationTestHelper compilationTestHelper =
|
||||
CompilationTestHelper.newInstance(FormatStringConcatenationCheck.class, getClass());
|
||||
CompilationTestHelper.newInstance(FormatStringConcatenation.class, getClass());
|
||||
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
|
||||
BugCheckerRefactoringTestHelper.newInstance(FormatStringConcatenationCheck.class, getClass());
|
||||
BugCheckerRefactoringTestHelper.newInstance(FormatStringConcatenation.class, getClass());
|
||||
|
||||
@Test
|
||||
void identification() {
|
||||
@@ -23,8 +23,8 @@ public 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 @@ public 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 @@ public 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 @@ public 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 @@ public 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 @@ public 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 @@ public 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 @@ public 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());",
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user