Compare commits

...

162 Commits

Author SHA1 Message Date
Rick Ossendrijver
db949f852b Remove things for SS 2021-11-18 13:11:49 +01:00
Rick Ossendrijver
0d574016d0 Improve the retrieval of receiver 2021-11-17 13:58:20 +01:00
Rick Ossendrijver
a0b9a7eb64 Introduce first version of StringIsEmpty BugPattern for demo purposes 2021-11-17 13:47:22 +01:00
Rick Ossendrijver
6528175120 Add Single#never() template 2021-11-12 15:03:06 +01:00
Rick Ossendrijver
078aeb431b Cleanup, sorting, moving, tests 2021-11-11 08:38:30 +01:00
Rick Ossendrijver
1343ddf5ac Add templates for Gravitee migration 2021-10-17 15:12:20 +02:00
Rick Ossendrijver
3b5d3604aa Improve template generic types 2021-10-16 13:27:52 +02:00
Rick Ossendrijver
28905107a0 Run textwidth=72 2021-10-15 20:37:05 +02:00
Rick Ossendrijver
8e8d75792a Many rewrites 2021-10-15 13:03:02 +02:00
Stephan Schroevers
d9f1c1aef6 Submit defeat 2021-10-14 18:12:23 +02:00
Rick Ossendrijver
899e3f7d8f Add fix for every occurence but is still problem 2021-10-14 17:21:34 +02:00
Rick Ossendrijver
7a38970c77 Many rewrite from .as() to RxJava2Adapter.() 2021-10-14 17:03:21 +02:00
Stephan Schroevers
dccd031846 Generalize 2021-10-14 15:50:21 +02:00
Rick Ossendrijver
0268418f8d Push 2021-10-14 15:34:53 +02:00
Rick Ossendrijver
4ab1ecafd4 Move some templates and temporarily turn off for start of migration 2021-10-14 12:43:51 +02:00
Rick Ossendrijver
b4ece293ef Add new templates 2021-10-12 14:06:30 +02:00
Rick Ossendrijver
52244dc28f Add assorted templates to improve the migration 2021-10-11 22:07:55 +02:00
Rick Ossendrijver
05e7a064fa Add exttra rule for Flux.array with single element 2021-10-08 18:42:04 +02:00
Rick Ossendrijver
6a55177e08 Add extra cases for test.await.assertXXX 2021-10-07 11:26:32 +02:00
Rick Ossendrijver
d69c442e2d Add extra templates 2021-10-07 09:43:49 +02:00
Rick Ossendrijver
c61851a373 Add extra templates and tests 2021-10-05 15:53:49 +02:00
Rick Ossendrijver
27cade2fc7 Apply suggestions and add templates 2021-10-05 13:32:26 +02:00
Rick Ossendrijver
d218b6f4d8 Fix tests and improve imports of the tests 2021-10-05 09:45:18 +02:00
Rick Ossendrijver
d6c3128940 Add unwrap methods 2021-10-04 19:55:47 +02:00
Rick Ossendrijver
a9c08e0c75 Add RxJavaUnwrapTemplates 2021-10-04 13:27:09 +02:00
Rick Ossendrijver
04e5cf4f03 Format for Stephan ;) 2021-10-02 17:08:40 +02:00
Rick Ossendrijver
8235c0649f Update the templates by removing some flat/concat|maps and adding tests 2021-10-02 17:07:15 +02:00
Rick Ossendrijver
a5ac555a04 Add minor improvements and cleanup 2021-10-01 15:22:55 +02:00
Rick Ossendrijver
cdefaf1b36 Add clean up Refaster templates 2021-09-28 16:32:15 +02:00
Rick Ossendrijver
2a70576662 Improve some templates and add one for every RxJava type for assertNoValues() 2021-09-28 14:07:50 +02:00
Rick Ossendrijver
4531720691 Write templates and fix edge cases 2021-09-28 09:28:07 +02:00
Rick Ossendrijver
e202422f34 Improve templates and cleanup tests 2021-09-27 10:32:32 +02:00
Stephan Schroevers
efea6c0ca9 As discussed 2021-09-25 12:58:35 +02:00
Rick Ossendrijver
796608a777 Improve templates so that they match PRP code 2021-09-24 14:43:58 +02:00
Rick Ossendrijver
5049044579 Add two examples that work for flatMapCompletable single and flowable 2021-09-24 13:01:14 +02:00
Rick Ossendrijver
6c6c21f8fb YESSSS fix the flatmapCompletable for Single and Flowable 2021-09-23 18:41:24 +02:00
Stephan Schroevers
b66d3afc7d Ideation 2021-09-23 16:28:46 +02:00
Rick Ossendrijver
050b85b58a Quick push 2021-09-23 16:11:21 +02:00
Stephan Schroevers
5db4e30140 Pair programming 2021-09-23 11:21:13 +02:00
Rick Ossendrijver
702987e2ca Do more things 2021-09-23 10:06:57 +02:00
Rick Ossendrijver
9995e65f7c Add templates for assertFailure and a MonoNestedPublisher 2021-09-22 21:59:36 +02:00
Rick Ossendrijver
061bc07b2f Many tweaks and improvements 2021-09-22 21:24:15 +02:00
Rick Ossendrijver
445fd26942 Update the templates and format 2021-09-21 13:52:13 +02:00
Rick Ossendrijver
5703608f66 Add extra case of assertValue with assertComplete 2021-09-21 09:46:01 +02:00
Rick Ossendrijver
47a9571035 Add AssertValue for 4 types 2021-09-21 09:33:12 +02:00
Rick Ossendrijver
0d92ae93e9 Add the test conversions to StepVerifier for Completable 2021-09-21 09:09:33 +02:00
Rick Ossendrijver
24d8535f20 Add RxJava test to StepVerifier tests templates 2021-09-21 08:42:01 +02:00
Rick Ossendrijver
0c2715e4e3 Add import to test output file 2021-09-20 11:28:33 +02:00
Rick Ossendrijver
54584a89a0 Add filtering 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
fe3e4bac9c Cleanup code and tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
7ac9650775 Add templates and cleanup todos 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
f96e6ab7cd Fix some todos and remove some annotations sadly enough 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e1d4917772 Solve XXXs and add tests and templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
6a229f86cb Add todos and information 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
224b9cf2a9 Update many templates and move the MigrationUtil to own module 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
84b5f99d23 Fix bug in test 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
5635538013 Some errors in there, but push many new templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e66e2be8ff Add many templates and tiny improvements. Note: tests are broken now because building against picnic-error-prone 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
773eeae53b Make EPS use the HEAD-SNAPSHOT of Error Prone for CanBeTransformedTo 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
0e511e3fde Add templates and tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
d5912cc80a Improve the templates and add many tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
3fd8570831 Turn on extra tests and fix many issues, but leave a few for next time. 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
73810e0676 Small improvements 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
78aeea5242 Add todos and some cases 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
83535739d8 Add templates and tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
af1be5e2e1 Add some templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
ca751c74c9 Add FlowableZipWith 2021-09-20 11:25:51 +02:00
Stephan Schroevers
52f6ff607b Pair programming 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
398f554f34 Add todos and implements some templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e3f9966011 Remove public modifiers from the XXXs and add two templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e6381f6b5f Improve templates with assorted methods 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
4e5624240c Remove old ideation on the CanBeCoercedTo problem and an early version of the MyUtil with conversion of io.reactivex.function to java.util.function 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
b1305814e3 Move every template to their respective class and cleanup RxJavaToReactorTemplates.java 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
8292e50d4f Add test templates to the RefasterCheckTest 2021-09-20 11:25:51 +02:00
Stephan Schroevers
681d59b754 Fix it 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
a57b4d5731 Quick commit 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
704705e47b Add the testFlowableCombineLatest 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
256a4b6cac Add some templates like fromCallable and FromAction and fromFuture 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
23da8ed2c3 Add some templates with Amb and add the RxJavaMaybeToReactor file 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
2b20eb887f Add Templates for the RxJava types that we want to migrate to Reactor 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
8aba6197d3 Update the ordering of the Templates and the tests to be in alphabetical order 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
ce4a1ce411 Remove some warnings 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
8d97ae281d Try to fix the tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
b38f5eaedd Add 1/4 templates for Flowable.concatWith 2021-09-20 11:25:51 +02:00
Stephan Schroevers
e1697db0d1 One more 2021-09-20 11:25:51 +02:00
Stephan Schroevers
9caff73b00 Ideation 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
bcc0b8a5ea Fix typo 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
7b819dce09 Update templates and fix some tests for the new templates and reorder some 2021-09-20 11:25:51 +02:00
Stephan Schroevers
2875a95374 WIP 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
11eaa182e5 Add some examples because im not sure how it works now 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
df6e76befc Add some tests for the new templates 2021-09-20 11:25:51 +02:00
Stephan Schroevers
a4d2f0d6aa Pair programming 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
5ea89ef59c Improve some comments and add an extra template 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e2be932179 Update templates and add a few commented templates to discuss with Stephan 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
6b535aa8fc Add tests for added templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
5a3691740b Change order of functions and add a failing one 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
9d8e21a304 Fix last part of test 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
5b6d0c3738 Do some renaming and improve almost all tests 2021-09-20 11:25:51 +02:00
Stephan Schroevers
31a67b6865 Pair programming 2021-09-20 11:25:51 +02:00
Stephan Schroevers
af1c2380a6 Fix it 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
fbda14828a Improve the templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
85cc0ed073 Update some of the Templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
8e28241c4e Add RxJavaToReactorTemplates class with Input and Output Test files. 2021-09-20 11:25:51 +02:00
Stephan Schroevers
c1e5dc4339 Assorted upgrades 2021-09-19 21:07:40 +02:00
Stephan Schroevers
7218006b3c Assorted upgrades 2021-09-03 07:42:57 +02:00
Rick Ossendrijver
a3f599ba1b Introduce WebClientTemplates (#16) 2021-08-30 21:54:28 +02:00
Stephan Schroevers
f819a3e42f Assorted upgrades 2021-08-20 08:50:15 +02:00
Stephan Schroevers
7fc865c769 Light RefasterRuleResourceCompilerTaskListener cleanup 2021-08-19 22:43:10 +02:00
Stephan Schroevers
0287060d96 Fix and optimize FormatStringConcatenationCheck 2021-08-19 22:42:41 +02:00
Stephan Schroevers
ac4e81f2c7 Support running the build using JDK 16+ 2021-08-14 19:29:55 +02:00
Stephan Schroevers
350f028781 Sync with PSM parent 2021-08-14 19:13:31 +02:00
Stephan Schroevers
299ce7b800 Assorted upgrades 2021-08-14 19:13:31 +02:00
Stephan Schroevers
f3a929a3bb Upgrade fmt-maven-plugin, reformat 2021-08-04 10:59:23 +02:00
Stephan Schroevers
625a55add5 Add extra Refaster rule, document possible FormatStringConcatenation extension 2021-08-04 10:58:16 +02:00
Stephan Schroevers
ef59340987 Assorted upgrades 2021-08-04 10:58:05 +02:00
Stephan Schroevers
f2aea38b17 Introduce AbstractOptionalAssertContainsSame Refaster template 2021-08-03 13:53:44 +02:00
Stephan Schroevers
5cd8863eb5 Slightly optimize MethodReferenceUsage check 2021-08-01 19:10:46 +02:00
Stephan Schroevers
5b57b4720b Introduce MockitoStubbing check 2021-08-01 18:29:54 +02:00
Stephan Schroevers
5224571407 Assorted FormatStringConcatenationCheck improvements 2021-08-01 15:56:32 +02:00
Stephan Schroevers
c8189e9431 Document RefasterCheck follow-up task 2021-08-01 12:41:00 +02:00
Stephan Schroevers
0fe42f1ea6 Introduce FormatStringConcatenation check 2021-08-01 12:32:08 +02:00
Stephan Schroevers
78b29107a3 Upgrade dependencies 2021-07-29 12:09:19 +02:00
Stephan Schroevers
7ae7d5105a Document StreamMapFirst gotcha, courtesy of Nathan 2021-07-29 11:51:11 +02:00
Stephan Schroevers
0976b33d61 Support Refaster templates without an @AfterTemplate method 2021-07-29 11:48:51 +02:00
Stephan Schroevers
4b6f81c4fa imeZoneUsageCheck: dDon't flag likely overrides 2021-07-27 17:44:04 +02:00
Stephan Schroevers
1e879c175e Don't flag empty test (helper) methods 2021-07-27 17:43:08 +02:00
Stephan Schroevers
d014fed400 Deduplicate Refaster templates 2021-07-24 23:20:26 +02:00
Stephan Schroevers
1357f60fbc Introduce refaster-support module
This new module is meant to expose helper logic for use with Refaster
templates. For a start, one can now use e.g.
`@NotMatches(IsArray.class)`.
2021-07-24 23:20:25 +02:00
Stephan Schroevers
03abbbf99c Introduce RefasterAnyOfUsageCheck 2021-07-24 17:08:08 +02:00
Stephan Schroevers
9b845782c2 Cleanup and add package-info.java files 2021-07-24 16:55:46 +02:00
Stephan Schroevers
08ce33fb19 Upgrade, fix typo 2021-07-24 12:18:00 +02:00
Stephan Schroevers
182724bc8e Upgrade dependencies 2021-07-23 08:00:18 +02:00
Stephan Schroevers
e9d361713a Upgrade Error Prone, deduplicate version configuration 2021-07-23 07:55:47 +02:00
Stephan Schroevers
b754880556 Assorted upgrades 2021-07-18 14:59:30 +02:00
Stephan Schroevers
affd5c7b93 Support self-application of the checks 2021-07-18 14:59:30 +02:00
Stephan Schroevers
d86611e66a TimeZoneUsageCheck should not flag Instant.now(clock)
Users _should_ rewrite that to `clock.instant()`, and indeed we have a
Refaster check for that.
2021-07-18 11:04:36 +02:00
Stephan Schroevers
2d6100a679 Further nudge to AssertJ 2021-07-18 10:46:47 +02:00
Stephan Schroevers
912797a55a Bintray is no more; Palantir now deploys to Maven Central 2021-07-18 10:46:47 +02:00
Stephan Schroevers
d097f31124 Assorted upgrades 2021-06-26 10:45:33 +02:00
Stephan Schroevers
eb05582f79 Assorted upgrades 2021-06-19 16:33:24 +02:00
Stephan Schroevers
964fc35b71 Upgrades 2021-05-29 18:04:57 +02:00
Stephan Schroevers
ddc05bf88c Assorted upgrades 2021-05-15 13:07:54 +02:00
Stephan Schroevers
24afa6a755 Some improvements from oss-parent 2021-04-24 00:00:10 +02:00
Stephan Schroevers
8e97121bdf Upgrade dependency 2021-04-23 22:37:19 +02:00
Stephan Schroevers
567c81a93d Upgrade to Error Prone 2.6.0 2021-04-23 22:20:11 +02:00
Stephan Schroevers
c0bfac7b4c Upgrades, some syncing with other parent 2021-04-22 15:10:58 +02:00
Rick Ossendrijver
28138f35eb Assorted upgrades (#15) 2021-04-19 09:51:25 +02:00
Stephan Schroevers
a9b691b856 Assorted upgrades 2021-04-06 17:35:38 +02:00
Ivan Fedorov
acfe87fbc4 Flag Ordering#explicit invocations listing a subset of an enum's values (#14) 2021-03-30 08:19:08 +02:00
Stephan Schroevers
091a6eee7a Fix the fork configuration 2021-03-30 08:04:01 +02:00
Stephan Schroevers
3c06e3ead3 Some consistency changes 2021-03-28 17:28:00 +02:00
Stephan Schroevers
3ecab2f4b9 Reduce memory assigned to Surefire
We may need to reintroduce this change in the future, but for now we can
keep the configuration in sync with other parent POMs.
2021-03-28 15:05:09 +02:00
Stephan Schroevers
4b3e79667d Address deprecations in the upcoming release 2021-03-28 15:05:09 +02:00
Stephan Schroevers
6505535525 Upgrades 2021-03-27 15:28:20 +01:00
Stephan Schroevers
e48bbf3a44 Upgrade to Error Prone 2.5.1 2021-03-27 15:03:50 +01:00
Stephan Schroevers
3391468746 Assorted upgrades 2021-03-20 19:03:37 +01:00
Stephan Schroevers
10172c426d Assorted upgrades 2021-03-14 10:15:00 +01:00
Stephan Schroevers
f2737b4fe9 Fix MissingRefasterAnnotationCheck 2021-03-11 16:37:22 +01:00
Anna Dvorkin
f9a1c82d68 PRP-10968 Flag discouraged time zone-dependent APIs (#9) 2021-03-01 23:08:19 +01:00
Halil İbrahim Şener
cbc886d0c2 PSM-442 Flag likely-wrong @JsonCreator usages (#2) 2021-03-01 18:50:58 +01:00
Rick Ossendrijver
e4e3aded84 Flag methods that appear to lack a Refaster annotation (#13) 2021-02-28 16:29:51 +01:00
Rick Ossendrijver
e84d0e1059 Flag unordered annotation declarations (#11) 2021-02-28 14:42:44 +01:00
137 changed files with 11212 additions and 651 deletions

10
.mvn/jvm.config Normal file
View File

@@ -0,0 +1,10 @@
--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
--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED

View File

@@ -11,10 +11,11 @@ install:
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 Error Prone checks
# available from other artifact repositories.
# 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 -s settings.xml
- ./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

View File

@@ -39,6 +39,12 @@
<artifactId>error_prone_test_helpers</artifactId>
<scope>test</scope>
</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>
@@ -47,6 +53,10 @@
`annotationProcessorPaths` configuration below. -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-support</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
@@ -167,10 +177,20 @@
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
@@ -201,12 +221,33 @@
<artifactId>refaster-resource-compiler</artifactId>
<version>${project.version}</version>
</path>
<path>
<groupId>${project.groupId}</groupId>
<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>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<ignoredUnusedDeclaredDependencies>
<!-- XXX: Figure out why the plugin thinks this
dependency is unused. -->
<ignoredUnusedDeclaredDependency>${project.groupId}:refaster-support</ignoredUnusedDeclaredDependency>
</ignoredUnusedDeclaredDependencies>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>

View File

@@ -0,0 +1,68 @@
package tech.picnic.errorprone.bugpatterns;
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;
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.AnnotationTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Symbol;
import java.util.Map;
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 {
private static final long serialVersionUID = 1L;
private static final Matcher<AnnotationTree> IS_JSON_CREATOR_ANNOTATION =
isType("com.fasterxml.jackson.annotation.JsonCreator");
@Override
public Description matchAnnotation(AnnotationTree tree, VisitorState state) {
if (!IS_JSON_CREATOR_ANNOTATION.matches(tree, state)) {
return Description.NO_MATCH;
}
ClassTree clazz = state.findEnclosing(ClassTree.class);
if (clazz == null || clazz.getKind() != Tree.Kind.ENUM) {
return Description.NO_MATCH;
}
MethodTree method = state.findEnclosing(MethodTree.class);
if (method == null || method.getParameters().size() != 1) {
return Description.NO_MATCH;
}
boolean customMode =
ASTHelpers.getAnnotationMirror(tree).getElementValues().entrySet().stream()
.filter(entry -> entry.getKey().getSimpleName().contentEquals("mode"))
.map(Map.Entry::getValue)
.map(AnnotationValue::getValue)
.filter(Symbol.VarSymbol.class::isInstance)
.map(Symbol.VarSymbol.class::cast)
.anyMatch(varSymbol -> !varSymbol.getSimpleName().contentEquals("DEFAULT"));
return customMode
? Description.NO_MATCH
: describeMatch(
tree, SuggestedFix.replace(tree, "@JsonCreator(mode = JsonCreator.Mode.DELEGATING)"));
}
}

View File

@@ -17,9 +17,11 @@ 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.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import java.util.Optional;
/** A {@link BugChecker} which flags empty methods that seemingly can simply be deleted. */
@AutoService(BugChecker.class)
@@ -31,7 +33,7 @@ import com.sun.tools.javac.code.Symbol.MethodSymbol;
tags = StandardTags.SIMPLIFICATION)
public final class EmptyMethodCheck extends BugChecker implements MethodTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Matcher<Tree> HAS_PERMITTED_ANNOTATION =
private static final Matcher<Tree> PERMITTED_ANNOTATION =
annotations(
AT_LEAST_ONE,
anyOf(isType("java.lang.Override"), isType("org.aspectj.lang.annotation.Pointcut")));
@@ -41,7 +43,8 @@ public final class EmptyMethodCheck extends BugChecker implements MethodTreeMatc
if (tree.getBody() == null
|| !tree.getBody().getStatements().isEmpty()
|| ASTHelpers.containsComments(tree, state)
|| HAS_PERMITTED_ANNOTATION.matches(tree, state)) {
|| PERMITTED_ANNOTATION.matches(tree, state)
|| isInPossibleTestHelperClass(state)) {
return Description.NO_MATCH;
}
@@ -52,4 +55,11 @@ public final class EmptyMethodCheck extends BugChecker implements MethodTreeMatc
return describeMatch(tree, SuggestedFix.delete(tree));
}
private static boolean isInPossibleTestHelperClass(VisitorState state) {
return Optional.ofNullable(ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class))
.map(ClassTree::getSimpleName)
.filter(name -> name.toString().contains("Test"))
.isPresent();
}
}

View File

@@ -0,0 +1,91 @@
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.matchers.method.MethodMatchers.staticMethod;
import static java.util.stream.Collectors.collectingAndThen;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
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;
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.MethodInvocationTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
/**
* A {@link BugChecker} which flags {@link Ordering#explicit(Object, Object[])}} invocations listing
* a subset of an enum type's values.
*/
@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 {
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> EXPLICIT_ORDERING =
staticMethod().onClass(Ordering.class.getName()).named("explicit");
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (!EXPLICIT_ORDERING.matches(tree, state)) {
return Description.NO_MATCH;
}
ImmutableSet<String> missingEnumValues = getMissingEnumValues(tree.getArguments());
if (missingEnumValues.isEmpty()) {
return Description.NO_MATCH;
}
return buildDescription(tree)
.setMessage(
String.format(
"Explicit ordering lacks some enum values: %s",
String.join(", ", missingEnumValues)))
.build();
}
private static ImmutableSet<String> getMissingEnumValues(
List<? extends ExpressionTree> expressions) {
return expressions.stream()
.map(ASTHelpers::getSymbol)
.filter(Symbol::isEnum)
.collect(
collectingAndThen(
toImmutableSetMultimap(Symbol::asType, Symbol::toString),
ExplicitEnumOrderingCheck::getMissingEnumValues));
}
private static ImmutableSet<String> getMissingEnumValues(
ImmutableSetMultimap<Type, String> valuesByType) {
return Multimaps.asMap(valuesByType).entrySet().stream()
.flatMap(e -> getMissingEnumValues(e.getKey(), e.getValue()))
.collect(toImmutableSet());
}
private static Stream<String> getMissingEnumValues(Type enumType, Set<String> values) {
Symbol.TypeSymbol typeSymbol = enumType.asElement();
return Sets.difference(ASTHelpers.enumValues(typeSymbol), values).stream()
.map(v -> String.format("%s.%s", typeSymbol.getSimpleName(), v));
}
}

View File

@@ -0,0 +1,253 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.anyMethod;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
import static com.google.errorprone.matchers.Matchers.not;
import static com.google.errorprone.matchers.Matchers.staticMethod;
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;
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.BinaryTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.ParenthesizedTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.SimpleTreeVisitor;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
* A {@link BugChecker} which flags string concatenations that produce a format string; in such
* cases the string concatenation should instead be deferred to the invoked method.
*
* @implNote This checker is based on the implementation of {@link
* com.google.errorprone.bugpatterns.flogger.FloggerStringConcatenation}.
*/
// XXX: Support arbitrary `@FormatMethod`-annotated methods.
// XXX: For (explicit or delegated) invocations of `java.util.Formatter` _strictly speaking_ we
// should introduce special handling of `Formattable` arguments, as this check would replace a
// `Formattable#toString` invocation with a `Formattable#formatTo` invocation. But likely that
// should be considered a bug fix, too.
// XXX: Introduce a separate check which adds/removes the `Locale` parameter to `String.format`
// 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
implements MethodInvocationTreeMatcher {
private static final long serialVersionUID = 1L;
/**
* AssertJ exposes varargs {@code fail} methods with a {@link Throwable}-accepting overload, the
* latter of which should not be flagged.
*/
private static final Matcher<ExpressionTree> ASSERTJ_FAIL_WITH_THROWABLE_METHOD =
anyMethod()
.anyClass()
.withAnyName()
.withParameters(String.class.getName(), Throwable.class.getName());
// XXX: Drop some of these methods if we use Refaster to replace some with others.
private static final Matcher<ExpressionTree> ASSERTJ_FORMAT_METHOD =
anyOf(
instanceMethod()
.onDescendantOf("org.assertj.core.api.AbstractAssert")
.namedAnyOf("overridingErrorMessage", "withFailMessage"),
allOf(
instanceMethod()
.onDescendantOf("org.assertj.core.api.AbstractSoftAssertions")
.named("fail"),
not(ASSERTJ_FAIL_WITH_THROWABLE_METHOD)),
instanceMethod()
.onDescendantOf("org.assertj.core.api.AbstractStringAssert")
.named("isEqualTo"),
instanceMethod()
.onDescendantOf("org.assertj.core.api.AbstractThrowableAssert")
.namedAnyOf(
"hasMessage",
"hasMessageContaining",
"hasMessageEndingWith",
"hasMessageStartingWith",
"hasRootCauseMessage",
"hasStackTraceContaining"),
instanceMethod()
.onDescendantOf("org.assertj.core.api.Descriptable")
.namedAnyOf("as", "describedAs"),
instanceMethod()
.onDescendantOf("org.assertj.core.api.ThrowableAssertAlternative")
.namedAnyOf(
"withMessage",
"withMessageContaining",
"withMessageEndingWith",
"withMessageStartingWith",
"withStackTraceContaining"),
allOf(
instanceMethod().onDescendantOf("org.assertj.core.api.WithAssertions").named("fail"),
not(ASSERTJ_FAIL_WITH_THROWABLE_METHOD)),
allOf(
staticMethod()
.onClassAny(
"org.assertj.core.api.Assertions",
"org.assertj.core.api.BDDAssertions",
"org.assertj.core.api.Fail")
.named("fail"),
not(ASSERTJ_FAIL_WITH_THROWABLE_METHOD)));
private static final Matcher<ExpressionTree> GUAVA_FORMAT_METHOD =
anyOf(
staticMethod()
.onClass("com.google.common.base.Preconditions")
.namedAnyOf("checkArgument", "checkNotNull", "checkState"),
staticMethod().onClass("com.google.common.base.Verify").named("verify"));
// XXX: Add `PrintWriter`, maybe others.
private static final Matcher<ExpressionTree> JDK_FORMAT_METHOD =
anyOf(
staticMethod().onClass("java.lang.String").named("format"),
instanceMethod().onExactClass("java.util.Formatter").named("format"));
private static final Matcher<ExpressionTree> SLF4J_FORMAT_METHOD =
instanceMethod()
.onDescendantOf("org.slf4j.Logger")
.namedAnyOf("debug", "error", "info", "trace", "warn");
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (hasNonConstantStringConcatenationArgument(tree, 0, state)) {
return flagViolation(tree, ASSERTJ_FORMAT_METHOD, 0, "%s", state)
.or(() -> flagViolation(tree, JDK_FORMAT_METHOD, 0, "%s", state))
.or(() -> flagViolation(tree, SLF4J_FORMAT_METHOD, 0, "{}", state))
.orElse(Description.NO_MATCH);
}
if (hasNonConstantStringConcatenationArgument(tree, 1, state)) {
return flagViolation(tree, GUAVA_FORMAT_METHOD, 1, "%s", state)
.or(() -> flagViolation(tree, JDK_FORMAT_METHOD, 1, "%s", state))
.or(() -> flagViolation(tree, SLF4J_FORMAT_METHOD, 1, "{}", state))
.orElse(Description.NO_MATCH);
}
return Description.NO_MATCH;
}
/**
* Flags the given method invocation if it matches a targeted method and passes a non-compile time
* constant string concatenation as a format string.
*/
private Optional<Description> flagViolation(
MethodInvocationTree tree,
Matcher<ExpressionTree> matcher,
int formatStringParam,
String formatSpecifier,
VisitorState state) {
if (!matcher.matches(tree, state)) {
/* The invoked method is not targeted by this check. */
return Optional.empty();
}
List<? extends ExpressionTree> arguments = tree.getArguments();
if (arguments.size() > formatStringParam + 1) {
/*
* This method invocation uses explicit string concatenation but _also_ already relies on
* format specifiers: flag but don't suggest a fix.
*/
return Optional.of(describeMatch(tree));
}
ExpressionTree formatStringArg = arguments.get(formatStringParam);
ReplacementArgumentsConstructor replacementConstructor =
new ReplacementArgumentsConstructor(formatSpecifier);
formatStringArg.accept(replacementConstructor, state);
return Optional.of(
describeMatch(
tree,
SuggestedFix.replace(
formatStringArg, replacementConstructor.getReplacementArguments(state))));
}
private static boolean hasNonConstantStringConcatenationArgument(
MethodInvocationTree tree, int argPosition, VisitorState state) {
List<? extends ExpressionTree> arguments = tree.getArguments();
if (arguments.size() <= argPosition) {
/* This method doesn't accept enough parameters. */
return false;
}
ExpressionTree argument = ASTHelpers.stripParentheses(arguments.get(argPosition));
return argument instanceof BinaryTree
&& isStringTyped(argument, state)
&& ASTHelpers.constValue(argument, String.class) == null;
}
private static boolean isStringTyped(ExpressionTree tree, VisitorState state) {
return ASTHelpers.isSameType(ASTHelpers.getType(tree), state.getSymtab().stringType, state);
}
private static class ReplacementArgumentsConstructor
extends SimpleTreeVisitor<Void, VisitorState> {
private final StringBuilder formatString = new StringBuilder();
private final List<Tree> formatArguments = new ArrayList<>();
private final String formatSpecifier;
ReplacementArgumentsConstructor(String formatSpecifier) {
this.formatSpecifier = formatSpecifier;
}
@Override
public Void visitBinary(BinaryTree tree, VisitorState state) {
if (tree.getKind() == Kind.PLUS && isStringTyped(tree, state)) {
tree.getLeftOperand().accept(this, state);
tree.getRightOperand().accept(this, state);
} else {
appendExpression(tree);
}
return null;
}
@Override
public Void visitParenthesized(ParenthesizedTree tree, VisitorState state) {
return tree.getExpression().accept(this, state);
}
@Override
protected Void defaultAction(Tree tree, VisitorState state) {
appendExpression(tree);
return null;
}
private void appendExpression(Tree tree) {
if (tree instanceof LiteralTree) {
formatString.append(((LiteralTree) tree).getValue());
} else {
formatString.append(formatSpecifier);
formatArguments.add(tree);
}
}
private String getReplacementArguments(VisitorState state) {
return state.getConstantExpression(formatString.toString())
+ ", "
+ formatArguments.stream()
.map(tree -> Util.treeToString(tree, state))
.collect(joining(", "));
}
}
}

View File

@@ -43,15 +43,15 @@ public final class JUnitMethodDeclarationCheck extends BugChecker implements Met
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> IS_OVERRIDE_METHOD =
private static final MultiMatcher<MethodTree, AnnotationTree> OVERRIDE_METHOD =
annotations(AT_LEAST_ONE, isType("java.lang.Override"));
private static final MultiMatcher<MethodTree, AnnotationTree> IS_TEST_METHOD =
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> IS_SETUP_OR_TEARDOWN_METHOD =
private static final MultiMatcher<MethodTree, AnnotationTree> SETUP_OR_TEARDOWN_METHOD =
annotations(
AT_LEAST_ONE,
anyOf(
@@ -64,12 +64,12 @@ public final class JUnitMethodDeclarationCheck extends BugChecker implements Met
public Description matchMethod(MethodTree tree, VisitorState state) {
// XXX: Perhaps we should also skip analysis of non-`private` non-`final` methods in abstract
// classes?
if (IS_OVERRIDE_METHOD.matches(tree, state)) {
if (OVERRIDE_METHOD.matches(tree, state)) {
return Description.NO_MATCH;
}
boolean isTestMethod = IS_TEST_METHOD.matches(tree, state);
if (!isTestMethod && !IS_SETUP_OR_TEARDOWN_METHOD.matches(tree, state)) {
boolean isTestMethod = TEST_METHOD.matches(tree, state);
if (!isTestMethod && !SETUP_OR_TEARDOWN_METHOD.matches(tree, state)) {
return Description.NO_MATCH;
}
@@ -102,7 +102,7 @@ public final class JUnitMethodDeclarationCheck extends BugChecker implements Met
private static Matcher<AnnotationTree> hasMetaAnnotation(String annotationClassName) {
TypePredicate typePredicate = hasAnnotation(annotationClassName);
return (tree, state) -> {
Symbol sym = ASTHelpers.getDeclaredSymbol(tree);
Symbol sym = ASTHelpers.getSymbol(tree);
return sym != null && typePredicate.apply(sym.type, state);
};
}

View File

@@ -1,5 +1,6 @@
package tech.picnic.errorprone.bugpatterns;
import static java.util.Comparator.comparing;
import static java.util.Comparator.naturalOrder;
import static java.util.stream.Collectors.joining;
@@ -31,7 +32,6 @@ import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
@@ -153,7 +153,7 @@ public final class LexicographicalAnnotationAttributeListingCheck extends BugChe
// XXX: Perhaps we should use `Collator` with `.setStrength(Collator.PRIMARY)` and
// `getCollationKey`. Not clear whether that's worth the hassle at this point.
return ImmutableList.sortedCopyOf(
Comparator.comparing(
comparing(
e -> getStructure(e, state),
Comparators.lexicographical(
Comparators.lexicographical(

View File

@@ -0,0 +1,79 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.collect.ImmutableList.toImmutableList;
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;
import com.google.errorprone.fixes.Fix;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.Description;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.MethodTree;
import java.util.List;
import java.util.Optional;
/**
* A {@link BugChecker} that flags annotations that are not lexicographically sorted.
*
* <p>The idea behind this checker is that maintaining a sorted sequence simplifies conflict
* resolution, and can even avoid it if two branches add the same annotation.
*/
@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
implements MethodTreeMatcher {
private static final long serialVersionUID = 1L;
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
List<? extends AnnotationTree> originalOrdering = tree.getModifiers().getAnnotations();
if (originalOrdering.size() < 2) {
return Description.NO_MATCH;
}
ImmutableList<? extends AnnotationTree> sortedAnnotations = sort(originalOrdering, state);
if (originalOrdering.equals(sortedAnnotations)) {
return Description.NO_MATCH;
}
Optional<Fix> fix = tryFixOrdering(originalOrdering, sortedAnnotations, state);
Description.Builder description = buildDescription(tree);
fix.ifPresent(description::addFix);
return description.build();
}
private static ImmutableList<? extends AnnotationTree> sort(
List<? extends AnnotationTree> annotations, VisitorState state) {
return annotations.stream()
.sorted(comparing(annotation -> Util.treeToString(annotation, state)))
.collect(toImmutableList());
}
private static Optional<Fix> tryFixOrdering(
List<? extends AnnotationTree> originalAnnotations,
ImmutableList<? extends AnnotationTree> sortedAnnotations,
VisitorState state) {
return Streams.zip(
originalAnnotations.stream(),
sortedAnnotations.stream(),
(original, replacement) ->
SuggestedFix.builder().replace(original, Util.treeToString(replacement, state)))
.reduce(SuggestedFix.Builder::merge)
.map(SuggestedFix.Builder::build);
}
}

View File

@@ -47,6 +47,8 @@ import javax.lang.model.element.Name;
// black-and-white. Maybe we can more closely approximate it?
// XXX: With Java 9's introduction of `Predicate.not`, we could write many lambda expressions to
// `not(some::reference)`.
// XXX: This check is extremely inefficient due to its reliance on `SuggestedFixes.compilesWithFix`.
// Palantir's `LambdaMethodReference` check seems to suffer a similar issue at this time.
@AutoService(BugChecker.class)
@BugPattern(
name = "MethodReferenceUsage",
@@ -67,7 +69,10 @@ public final class MethodReferenceUsageCheck extends BugChecker
*/
return constructMethodRef(tree, tree.getBody())
.map(SuggestedFix.Builder::build)
.filter(fix -> SuggestedFixes.compilesWithFix(fix, state))
.filter(
fix ->
SuggestedFixes.compilesWithFix(
fix, state, ImmutableList.of(), /* onlyInSameCompilationUnit= */ true))
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
}

View File

@@ -0,0 +1,55 @@
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 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;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.MultiMatcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
/** 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 {
private static final long serialVersionUID = 1L;
private static final MultiMatcher<Tree, AnnotationTree> REFASTER_ANNOTATION =
annotations(
AT_LEAST_ONE,
anyOf(
isType("com.google.errorprone.refaster.annotation.Placeholder"),
isType("com.google.errorprone.refaster.annotation.BeforeTemplate"),
isType("com.google.errorprone.refaster.annotation.AfterTemplate")));
@Override
public Description matchClass(ClassTree tree, VisitorState state) {
long methodTypes =
tree.getMembers().stream()
.filter(member -> member.getKind() == Tree.Kind.METHOD)
.map(MethodTree.class::cast)
.filter(method -> !ASTHelpers.isGeneratedConstructor(method))
.map(method -> REFASTER_ANNOTATION.matches(method, state))
.distinct()
.count();
return methodTypes < 2 ? Description.NO_MATCH : buildDescription(tree).build();
}
}

View File

@@ -0,0 +1,58 @@
package tech.picnic.errorprone.bugpatterns;
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;
import com.google.errorprone.fixes.SuggestedFix;
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.List;
/**
* A {@link BugChecker} which flags method invocations for which all arguments are wrapped using
* {@link org.mockito.Mockito#eq}; this is redundant.
*/
@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 {
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> MOCKITO_EQ_METHOD =
staticMethod().onClass("org.mockito.ArgumentMatchers").named("eq");
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
List<? extends ExpressionTree> arguments = tree.getArguments();
if (arguments.isEmpty() || !arguments.stream().allMatch(arg -> isEqInvocation(arg, state))) {
return Description.NO_MATCH;
}
SuggestedFix.Builder suggestedFix = SuggestedFix.builder();
for (ExpressionTree arg : arguments) {
suggestedFix.replace(
arg,
Util.treeToString(
Iterables.getOnlyElement(((MethodInvocationTree) arg).getArguments()), state));
}
return describeMatch(tree, suggestedFix.build());
}
private static boolean isEqInvocation(ExpressionTree tree, VisitorState state) {
return tree instanceof MethodInvocationTree && MOCKITO_EQ_METHOD.matches(tree, state);
}
}

View File

@@ -2,7 +2,7 @@ package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.isNonNull;
import static com.google.errorprone.matchers.Matchers.isNonNullUsingDataflow;
import static com.google.errorprone.matchers.Matchers.isSameType;
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
import static com.google.errorprone.matchers.Matchers.not;
@@ -64,7 +64,8 @@ public final class RedundantStringConversionCheck extends BugChecker
private static final Matcher<ExpressionTree> MARKER = isSubtypeOf("org.slf4j.Marker");
private static final Matcher<ExpressionTree> STRING = isSameType(String.class);
private static final Matcher<ExpressionTree> THROWABLE = isSubtypeOf(Throwable.class);
private static final Matcher<ExpressionTree> NON_NULL_STRING = allOf(STRING, isNonNull());
private static final Matcher<ExpressionTree> NON_NULL_STRING =
allOf(STRING, isNonNullUsingDataflow());
private static final Matcher<ExpressionTree> NOT_FORMATTABLE =
not(isSubtypeOf(Formattable.class));
private static final Matcher<ExpressionTree> WELL_KNOWN_STRING_CONVERSION_METHODS =

View File

@@ -0,0 +1,57 @@
package tech.picnic.errorprone.bugpatterns;
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;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.refaster.Refaster;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
/**
* A {@link BugChecker} which flags unnecessary {@link Refaster#anyOf(Object[])} usages.
*
* <p>Note that this logic can't be implemented as a Refaster template, as the {@link Refaster}
* class is treated specially.
*/
@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 {
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> REFASTER_ANY_OF =
staticMethod().onClass(Refaster.class.getName()).named("anyOf");
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (REFASTER_ANY_OF.matches(tree, state)) {
switch (tree.getArguments().size()) {
case 0:
// We can't safely fix this case; dropping the expression may produce non-compilable code.
return describeMatch(tree);
case 1:
return describeMatch(
tree,
SuggestedFix.replace(tree, Util.treeToString(tree.getArguments().get(0), state)));
default:
/* Handled below. */
}
}
return Description.NO_MATCH;
}
}

View File

@@ -2,10 +2,12 @@ package tech.picnic.errorprone.bugpatterns;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableRangeSet.toImmutableRangeSet;
import static java.util.Objects.requireNonNullElseGet;
import static java.util.function.Predicate.not;
import com.google.auto.service.AutoService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
@@ -41,8 +43,8 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Stream;
@@ -62,9 +64,13 @@ import java.util.stream.Stream;
severity = SeverityLevel.SUGGESTION,
tags = StandardTags.SIMPLIFICATION)
public final class RefasterCheck extends BugChecker implements CompilationUnitTreeMatcher {
private static final long serialVersionUID = 1L;
private static final String REFASTER_TEMPLATE_SUFFIX = ".refaster";
private static final String INCLUDED_TEMPLATES_PATTERN_FLAG = "Refaster:NamePattern";
private static final long serialVersionUID = 1L;
@VisibleForTesting
static final Supplier<ImmutableListMultimap<String, CodeTransformer>> ALL_CODE_TRANSFORMERS =
Suppliers.memoize(RefasterCheck::loadAllCodeTransformers);
private final CodeTransformer codeTransformer;
@@ -79,20 +85,23 @@ public final class RefasterCheck extends BugChecker implements CompilationUnitTr
* @param flags Any provided command line flags.
*/
public RefasterCheck(ErrorProneFlags flags) {
codeTransformer = createCompositeCodeTransformer(flags, loadAllCodeTransformers());
}
@VisibleForTesting
RefasterCheck(
ErrorProneFlags flags, ImmutableListMultimap<String, CodeTransformer> allTransformers) {
codeTransformer = createCompositeCodeTransformer(flags, allTransformers);
codeTransformer = createCompositeCodeTransformer(flags);
}
@Override
public Description matchCompilationUnit(CompilationUnitTree tree, VisitorState state) {
/* First, collect all matches. */
List<Description> matches = new ArrayList<>();
codeTransformer.apply(state.getPath(), new SubContext(state.context), matches::add);
try {
codeTransformer.apply(state.getPath(), new SubContext(state.context), matches::add);
} catch (LinkageError e) {
// XXX: This `try/catch` block handles the issue described and resolved in
// https://github.com/google/error-prone/pull/2456. Drop this block once that change is
// released.
// XXX: Find a way to identify that we're running Picnic's Error Prone fork and disable this
// fallback if so, as it might hide other bugs.
return Description.NO_MATCH;
}
/* Then apply them. */
applyMatches(matches, ((JCCompilationUnit) tree).endPositions, state);
@@ -152,8 +161,8 @@ public final class RefasterCheck extends BugChecker implements CompilationUnitTr
return description.fixes.stream().flatMap(fix -> fix.getReplacements(endPositions).stream());
}
private static CodeTransformer createCompositeCodeTransformer(
ErrorProneFlags flags, ImmutableListMultimap<String, CodeTransformer> allTransformers) {
private static CodeTransformer createCompositeCodeTransformer(ErrorProneFlags flags) {
ImmutableListMultimap<String, CodeTransformer> allTransformers = ALL_CODE_TRANSFORMERS.get();
return CompositeCodeTransformer.compose(
flags
.get(INCLUDED_TEMPLATES_PATTERN_FLAG)
@@ -170,8 +179,7 @@ public final class RefasterCheck extends BugChecker implements CompilationUnitTr
.collect(toImmutableList());
}
@VisibleForTesting
static ImmutableListMultimap<String, CodeTransformer> loadAllCodeTransformers() {
private static ImmutableListMultimap<String, CodeTransformer> loadAllCodeTransformers() {
ImmutableListMultimap.Builder<String, CodeTransformer> transformers =
ImmutableListMultimap.builder();
@@ -189,8 +197,8 @@ public final class RefasterCheck extends BugChecker implements CompilationUnitTr
private static ImmutableSet<ResourceInfo> getClassPathResources() {
try {
return ClassPath.from(
Objects.requireNonNullElseGet(
RefasterCheck.class.getClassLoader(), () -> ClassLoader.getSystemClassLoader()))
requireNonNullElseGet(
RefasterCheck.class.getClassLoader(), ClassLoader::getSystemClassLoader))
.getResources();
} catch (IOException e) {
throw new UncheckedIOException("Failed to scan classpath for resources", e);
@@ -212,7 +220,9 @@ public final class RefasterCheck extends BugChecker implements CompilationUnitTr
private static Optional<CodeTransformer> loadCodeTransformer(ResourceInfo resource) {
try (InputStream in = resource.url().openStream();
ObjectInputStream ois = new ObjectInputStream(in)) {
return Optional.of((CodeTransformer) ois.readObject());
@SuppressWarnings("BanSerializableRead" /* Part of the Refaster API. */)
CodeTransformer codeTransformer = (CodeTransformer) ois.readObject();
return Optional.of(codeTransformer);
} catch (NoSuchElementException e) {
/* For some reason we can't load the resource. Skip it. */
// XXX: Should we log this?

View File

@@ -13,7 +13,6 @@ 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.ProvidesFix;
import com.google.errorprone.BugPattern.SeverityLevel;
import com.google.errorprone.BugPattern.StandardTags;
import com.google.errorprone.VisitorState;
@@ -36,8 +35,7 @@ import com.sun.source.tree.Tree;
summary = "Make sure all `@RequestMapping` method parameters are annotated",
linkType = LinkType.NONE,
severity = SeverityLevel.WARNING,
tags = StandardTags.LIKELY_ERROR,
providesFix = ProvidesFix.REQUIRES_HUMAN_ATTENTION)
tags = StandardTags.LIKELY_ERROR)
public final class RequestMappingAnnotationCheck extends BugChecker implements MethodTreeMatcher {
private static final long serialVersionUID = 1L;
private static final String ANN_PACKAGE_PREFIX = "org.springframework.web.bind.annotation.";

View File

@@ -1,5 +1,7 @@
package tech.picnic.errorprone.bugpatterns;
import static java.util.Objects.requireNonNull;
import com.google.auto.service.AutoService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
@@ -20,7 +22,6 @@ import com.google.errorprone.matchers.Description;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.Tree;
import java.util.Objects;
import java.util.Optional;
/** A {@link BugChecker} which flags methods that can and should be statically imported. */
@@ -140,8 +141,7 @@ public final class StaticImportCheck extends BugChecker implements MemberSelectT
private static boolean isCandidate(VisitorState state) {
Tree parentTree =
Objects.requireNonNull(
state.getPath().getParentPath(), "MemberSelectTree lacks enclosing node")
requireNonNull(state.getPath().getParentPath(), "MemberSelectTree lacks enclosing node")
.getLeaf();
switch (parentTree.getKind()) {
case IMPORT:

View File

@@ -0,0 +1,42 @@
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;
}
}

View File

@@ -0,0 +1,70 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.enclosingClass;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
import static com.google.errorprone.matchers.Matchers.not;
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;
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.time.Clock;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
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 {
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> BANNED_TIME_METHOD =
anyOf(
allOf(
instanceMethod()
.onDescendantOf(Clock.class.getName())
.namedAnyOf("getZone", "withZone"),
not(enclosingClass(isSubtypeOf(Clock.class)))),
staticMethod()
.onClass(Clock.class.getName())
.namedAnyOf(
"system",
"systemDefaultZone",
"systemUTC",
"tickMillis",
"tickMinutes",
"tickSeconds"),
staticMethod()
.onClassAny(
LocalDate.class.getName(),
LocalDateTime.class.getName(),
LocalTime.class.getName())
.named("now"),
staticMethod().onClassAny(Instant.class.getName()).named("now").withParameters());
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
return BANNED_TIME_METHOD.matches(tree, state)
? buildDescription(tree).build()
: Description.NO_MATCH;
}
}

View File

@@ -1,7 +1,4 @@
/** Picnic Error Prone Contrib checks. */
@CheckReturnValue
@ParametersAreNonnullByDefault
@com.google.errorprone.annotations.CheckReturnValue
@javax.annotation.ParametersAreNonnullByDefault
package tech.picnic.errorprone.bugpatterns;
import com.google.errorprone.annotations.CheckReturnValue;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -97,12 +97,24 @@ final class AssertJOptionalTemplates {
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
AbstractOptionalAssert<?, T> after(AbstractOptionalAssert<?, T> optionalAssert, T value) {
return optionalAssert.hasValue(value);
}
}
static final class AbstractOptionalAssertContainsSame<T> {
@BeforeTemplate
AbstractAssert<?, ?> before(AbstractOptionalAssert<?, T> optionalAssert, T value) {
return Refaster.anyOf(
optionalAssert.get().isSameAs(value), optionalAssert.isPresent().isSameAs(value));
}
@AfterTemplate
AbstractOptionalAssert<?, T> after(AbstractOptionalAssert<?, T> optionalAssert, T value) {
return optionalAssert.containsSame(value);
}
}
static final class AssertThatOptionalHasValueMatching<T> {
@BeforeTemplate
AbstractOptionalAssert<?, T> before(Optional<T> optional, Predicate<? super T> predicate) {

View File

@@ -16,6 +16,7 @@ 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.NotMatches;
import com.google.errorprone.refaster.annotation.Repeated;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import java.util.ArrayList;
@@ -51,6 +52,7 @@ import org.assertj.core.api.ObjectEnumerableAssert;
import org.assertj.core.api.OptionalDoubleAssert;
import org.assertj.core.api.OptionalIntAssert;
import org.assertj.core.api.OptionalLongAssert;
import tech.picnic.errorprone.refaster.util.IsArray;
/** Refaster templates related to AssertJ expressions and statements. */
// XXX: Most `AbstractIntegerAssert` rules can also be applied for other primitive types. Generate
@@ -338,8 +340,14 @@ final class AssertJTemplates {
ImmutableList.of(element),
Arrays.asList(element),
ImmutableSet.of(element),
ImmutableMultiset.of(element))),
iterAssert.containsExactlyInAnyOrder(element));
ImmutableMultiset.of(element))));
}
@BeforeTemplate
@SuppressWarnings("unchecked")
ObjectEnumerableAssert<?, S> before2(
ObjectEnumerableAssert<?, S> iterAssert, @NotMatches(IsArray.class) T element) {
return iterAssert.containsExactlyInAnyOrder(element);
}
@AfterTemplate
@@ -349,16 +357,27 @@ final class AssertJTemplates {
}
}
static final class AssertThatSetContainsExactlyOneElement<S, T extends S> {
@BeforeTemplate
ObjectEnumerableAssert<?, S> before(Set<S> set, T element) {
return assertThat(set).containsOnly(element);
}
@AfterTemplate
ObjectEnumerableAssert<?, S> after(Set<S> set, T element) {
return assertThat(set).containsExactly(element);
}
}
static final class ObjectEnumerableContainsOneDistinctElement<S, T extends S> {
@BeforeTemplate
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T element) {
return Refaster.anyOf(
iterAssert.hasSameElementsAs(
Refaster.anyOf(
ImmutableList.of(element),
Arrays.asList(element),
ImmutableSet.of(element),
ImmutableMultiset.of(element))));
return iterAssert.hasSameElementsAs(
Refaster.anyOf(
ImmutableList.of(element),
Arrays.asList(element),
ImmutableSet.of(element),
ImmutableMultiset.of(element)));
}
@AfterTemplate
@@ -371,13 +390,12 @@ final class AssertJTemplates {
static final class ObjectEnumerableIsSubsetOfOneElement<S, T extends S> {
@BeforeTemplate
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T element) {
return Refaster.anyOf(
iterAssert.isSubsetOf(
Refaster.anyOf(
ImmutableList.of(element),
Arrays.asList(element),
ImmutableSet.of(element),
ImmutableMultiset.of(element))));
return iterAssert.isSubsetOf(
Refaster.anyOf(
ImmutableList.of(element),
Arrays.asList(element),
ImmutableSet.of(element),
ImmutableMultiset.of(element)));
}
@AfterTemplate
@@ -395,8 +413,8 @@ final class AssertJTemplates {
@BeforeTemplate
void before(Iterable<E> iterable) {
Refaster.anyOf(
assertThat(iterable).hasSize(0),
assertThat(iterable.iterator().hasNext()).isFalse(),
assertThat(Iterables.size(iterable)).isEqualTo(0),
assertThat(Iterables.size(iterable)).isEqualTo(0L),
assertThat(Iterables.size(iterable)).isNotPositive());
}
@@ -405,7 +423,6 @@ final class AssertJTemplates {
void before(Collection<E> iterable) {
Refaster.anyOf(
assertThat(iterable.isEmpty()).isTrue(),
assertThat(iterable.size()).isEqualTo(0),
assertThat(iterable.size()).isEqualTo(0L),
assertThat(iterable.size()).isNotPositive());
}
@@ -602,8 +619,8 @@ final class AssertJTemplates {
@BeforeTemplate
void before(Map<K, V> map) {
Refaster.anyOf(
assertThat(map).hasSize(0),
assertThat(map.isEmpty()).isTrue(),
assertThat(map.size()).isEqualTo(0),
assertThat(map.size()).isEqualTo(0L),
assertThat(map.size()).isNotPositive());
}
@@ -775,18 +792,21 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamContainsAnyOfVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsAnyOf" /* Varargs converted to array. */)
IterableAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends Iterable<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).containsAnyOf(Refaster.asVarargs(elements));
}
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsAnyOf" /* Varargs converted to array. */)
ListAssert<T> before2(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).containsAnyOf(Refaster.asVarargs(elements));
}
@AfterTemplate
@SuppressWarnings("ObjectEnumerableContainsOneElement" /* Not a true singleton. */)
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
return assertThat(stream).containsAnyOf(elements);
@@ -838,12 +858,14 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamContainsVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContains" /* Varargs converted to array. */)
IterableAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends Iterable<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).contains(Refaster.asVarargs(elements));
}
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContains" /* Varargs converted to array. */)
ListAssert<T> before2(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).contains(Refaster.asVarargs(elements));
@@ -889,6 +911,7 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamContainsExactlyVarargs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsExactly" /* Varargs converted to array. */)
ListAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).containsExactly(Refaster.asVarargs(elements));
@@ -947,6 +970,7 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamContainsExactlyInAnyOrderVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsExactlyInAnyOrder" /* Varargs converted to array. */)
ListAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector))
@@ -954,6 +978,7 @@ final class AssertJTemplates {
}
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsExactlyInAnyOrder" /* Varargs converted to array. */)
IterableAssert<T> before2(
Stream<S> stream, Collector<S, ?, ? extends Multiset<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector))
@@ -961,6 +986,7 @@ final class AssertJTemplates {
}
@AfterTemplate
@SuppressWarnings("ObjectEnumerableContainsExactlyOneElement" /* Not a true singleton. */)
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
return assertThat(stream).containsExactlyInAnyOrder(elements);
@@ -991,12 +1017,14 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamContainsSequenceVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsSequence" /* Varargs converted to array. */)
ListAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).containsSequence(Refaster.asVarargs(elements));
}
@AfterTemplate
@SuppressWarnings("ObjectEnumerableContainsOneElement" /* Not a true singleton. */)
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
return assertThat(stream).containsSequence(elements);
@@ -1027,6 +1055,7 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamContainsSubsequenceVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsSubsequence" /* Varargs converted to array. */)
ListAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector))
@@ -1034,6 +1063,7 @@ final class AssertJTemplates {
}
@AfterTemplate
@SuppressWarnings("ObjectEnumerableContainsOneElement" /* Not a true singleton. */)
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
return assertThat(stream).containsSubsequence(elements);
@@ -1085,12 +1115,14 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamDoesNotContainVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamDoesNotContain" /* Varargs converted to array. */)
IterableAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends Iterable<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).doesNotContain(Refaster.asVarargs(elements));
}
@BeforeTemplate
@SuppressWarnings("AssertThatStreamDoesNotContain" /* Varargs converted to array. */)
ListAssert<T> before2(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).doesNotContain(Refaster.asVarargs(elements));
@@ -1127,6 +1159,7 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamDoesNotContainSequenceVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamDoesNotContainSequence" /* Varargs converted to array. */)
ListAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector))
@@ -1134,6 +1167,7 @@ final class AssertJTemplates {
}
@AfterTemplate
@SuppressWarnings("ObjectEnumerableDoesNotContainOneElement" /* Not a true singleton. */)
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
ListAssert<S> after(Stream<S> stream, @Repeated U elements) {
return assertThat(stream).doesNotContainSequence(elements);
@@ -1185,12 +1219,14 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamContainsOnlyVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsOnly" /* Varargs converted to array. */)
IterableAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends Iterable<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).containsOnly(Refaster.asVarargs(elements));
}
@BeforeTemplate
@SuppressWarnings("AssertThatStreamContainsOnly" /* Varargs converted to array. */)
ListAssert<T> before2(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).containsOnly(Refaster.asVarargs(elements));
@@ -1239,12 +1275,14 @@ final class AssertJTemplates {
// XXX: This rule assumes the `collector` doesn't completely discard certain values.
static final class AssertThatStreamIsSubsetOfVarArgs<S, T extends S, U extends T> {
@BeforeTemplate
@SuppressWarnings("AssertThatStreamIsSubsetOf" /* Varargs converted to array. */)
IterableAssert<T> before(
Stream<S> stream, Collector<S, ?, ? extends Iterable<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).isSubsetOf(Refaster.asVarargs(elements));
}
@BeforeTemplate
@SuppressWarnings("AssertThatStreamIsSubsetOf" /* Varargs converted to array. */)
ListAssert<T> before2(
Stream<S> stream, Collector<S, ?, ? extends List<T>> collector, @Repeated U elements) {
return assertThat(stream.collect(collector)).isSubsetOf(Refaster.asVarargs(elements));

View File

@@ -1,9 +1,10 @@
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 java.util.Objects.checkIndex;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -38,12 +39,12 @@ final class AssortedTemplates {
static final class CheckIndex {
@BeforeTemplate
int before(int index, int size) {
return Preconditions.checkElementIndex(index, size);
return checkElementIndex(index, size);
}
@AfterTemplate
int after(int index, int size) {
return Objects.checkIndex(index, size);
return checkIndex(index, size);
}
}
@@ -62,14 +63,14 @@ final class AssortedTemplates {
}
static final class MapGetOrNull<K, V, L> {
@Nullable
@BeforeTemplate
@Nullable
V before(Map<K, V> map, L key) {
return map.getOrDefault(key, null);
}
@Nullable
@AfterTemplate
@Nullable
V after(Map<K, V> map, L key) {
return map.get(key);
}
@@ -107,8 +108,8 @@ final class AssortedTemplates {
Streams.stream(iterator).findAny().orElse(defaultValue));
}
@Nullable
@AfterTemplate
@Nullable
T after(Iterator<T> iterator, T defaultValue) {
return Iterators.getNext(iterator, defaultValue);
}
@@ -256,11 +257,6 @@ final class AssortedTemplates {
//
// @BeforeTemplate
// void before(Supplier<T> supplier) {
// anyStatement(supplier::get);
// }
//
// @BeforeTemplate
// void before2(Supplier<T> supplier) {
// anyStatement(() -> supplier.get());
// }
//

View File

@@ -1,5 +1,10 @@
package tech.picnic.errorprone.refastertemplates;
import static java.util.Comparator.comparing;
import static java.util.Comparator.comparingDouble;
import static java.util.Comparator.comparingInt;
import static java.util.Comparator.comparingLong;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.reverseOrder;
import static java.util.function.Function.identity;
@@ -29,14 +34,13 @@ final class ComparatorTemplates {
@BeforeTemplate
Comparator<T> before() {
return Refaster.anyOf(
Comparator.comparing(Refaster.anyOf(identity(), v -> v)),
Comparator.<T>reverseOrder().reversed());
comparing(Refaster.anyOf(identity(), v -> v)), Comparator.<T>reverseOrder().reversed());
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Comparator<T> after() {
return Comparator.naturalOrder();
return naturalOrder();
}
}
@@ -58,7 +62,7 @@ final class ComparatorTemplates {
// XXX: Drop the `Refaster.anyOf` if/when we decide to rewrite one to the other.
@BeforeTemplate
Comparator<T> before(Comparator<T> cmp) {
return Comparator.comparing(Refaster.anyOf(identity(), v -> v), cmp);
return comparing(Refaster.anyOf(identity(), v -> v), cmp);
}
@AfterTemplate
@@ -72,7 +76,7 @@ final class ComparatorTemplates {
static final class ThenComparing<S, T extends Comparable<? super T>> {
@BeforeTemplate
Comparator<S> before(Comparator<S> cmp, Function<? super S, ? extends T> function) {
return cmp.thenComparing(Comparator.comparing(function));
return cmp.thenComparing(comparing(function));
}
@AfterTemplate
@@ -85,7 +89,7 @@ final class ComparatorTemplates {
static final class ThenComparingReversed<S, T extends Comparable<? super T>> {
@BeforeTemplate
Comparator<S> before(Comparator<S> cmp, Function<? super S, ? extends T> function) {
return cmp.thenComparing(Comparator.comparing(function).reversed());
return cmp.thenComparing(comparing(function).reversed());
}
@AfterTemplate
@@ -100,7 +104,7 @@ final class ComparatorTemplates {
@BeforeTemplate
Comparator<S> before(
Comparator<S> cmp, Function<? super S, ? extends T> function, Comparator<? super T> cmp2) {
return cmp.thenComparing(Comparator.comparing(function, cmp2));
return cmp.thenComparing(comparing(function, cmp2));
}
@AfterTemplate
@@ -115,7 +119,7 @@ final class ComparatorTemplates {
@BeforeTemplate
Comparator<S> before(
Comparator<S> cmp, Function<? super S, ? extends T> function, Comparator<? super T> cmp2) {
return cmp.thenComparing(Comparator.comparing(function, cmp2).reversed());
return cmp.thenComparing(comparing(function, cmp2).reversed());
}
@AfterTemplate
@@ -129,7 +133,7 @@ final class ComparatorTemplates {
static final class ThenComparingDouble<T> {
@BeforeTemplate
Comparator<T> before(Comparator<T> cmp, ToDoubleFunction<? super T> function) {
return cmp.thenComparing(Comparator.comparingDouble(function));
return cmp.thenComparing(comparingDouble(function));
}
@AfterTemplate
@@ -142,7 +146,7 @@ final class ComparatorTemplates {
static final class ThenComparingInt<T> {
@BeforeTemplate
Comparator<T> before(Comparator<T> cmp, ToIntFunction<? super T> function) {
return cmp.thenComparing(Comparator.comparingInt(function));
return cmp.thenComparing(comparingInt(function));
}
@AfterTemplate
@@ -155,7 +159,7 @@ final class ComparatorTemplates {
static final class ThenComparingLong<T> {
@BeforeTemplate
Comparator<T> before(Comparator<T> cmp, ToLongFunction<? super T> function) {
return cmp.thenComparing(Comparator.comparingLong(function));
return cmp.thenComparing(comparingLong(function));
}
@AfterTemplate
@@ -178,7 +182,7 @@ final class ComparatorTemplates {
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Comparator<T> after(Comparator<T> cmp) {
return cmp.thenComparing(Comparator.naturalOrder());
return cmp.thenComparing(naturalOrder());
}
}

View File

@@ -233,10 +233,7 @@ final class DoubleStreamTemplates {
static final class DoubleStreamAllMatch {
@BeforeTemplate
boolean before(DoubleStream stream, DoublePredicate predicate) {
return Refaster.anyOf(
stream.noneMatch(predicate.negate()),
!stream.anyMatch(predicate.negate()),
stream.filter(predicate.negate()).findAny().isEmpty());
return stream.noneMatch(predicate.negate());
}
@AfterTemplate
@@ -251,10 +248,7 @@ final class DoubleStreamTemplates {
@BeforeTemplate
boolean before(DoubleStream stream) {
return Refaster.anyOf(
stream.noneMatch(e -> !test(e)),
!stream.anyMatch(e -> !test(e)),
stream.filter(e -> !test(e)).findAny().isEmpty());
return stream.noneMatch(e -> !test(e));
}
@AfterTemplate

View File

@@ -4,7 +4,6 @@ import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.AlsoNegation;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.NoAutoboxing;
import java.util.Objects;
import java.util.function.Predicate;
@@ -12,26 +11,9 @@ import java.util.function.Predicate;
final class EqualityTemplates {
private EqualityTemplates() {}
/** Prefer primitive/reference-based quality for primitives and enums. */
static final class PrimitiveOrReferenceEquality {
@NoAutoboxing
@BeforeTemplate
boolean before(boolean a, boolean b) {
return Objects.equals(a, b);
}
@NoAutoboxing
@BeforeTemplate
boolean before(long a, long b) {
return Objects.equals(a, b);
}
@NoAutoboxing
@BeforeTemplate
boolean before(double a, double b) {
return Objects.equals(a, b);
}
/** Prefer reference-based quality for enums. */
// Primitive value comparisons are not listed, because Error Prone flags those out of the box.
static final class PrimitiveOrReferenceEquality<T extends Enum<T>> {
/**
* Enums can be compared by reference. It is safe to do so even in the face of refactorings,
* because if the type is ever converted to a non-enum, then Error-Prone will complain about any
@@ -40,13 +22,13 @@ final class EqualityTemplates {
// 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.
@BeforeTemplate
<T extends Enum<T>> boolean before(T a, T b) {
boolean before(T a, T b) {
return Refaster.anyOf(a.equals(b), Objects.equals(a, b));
}
@AlsoNegation
@AfterTemplate
boolean after(boolean a, boolean b) {
@AlsoNegation
boolean after(T a, T b) {
return a == b;
}
}

View File

@@ -56,10 +56,7 @@ final class ImmutableListMultimapTemplates {
static final class EmptyImmutableListMultimap<K, V> {
@BeforeTemplate
ImmutableMultimap<K, V> before() {
return Refaster.anyOf(
ImmutableListMultimap.<K, V>builder().build(),
ImmutableMultimap.<K, V>builder().build(),
ImmutableMultimap.of());
return Refaster.anyOf(ImmutableListMultimap.<K, V>builder().build(), ImmutableMultimap.of());
}
@AfterTemplate
@@ -80,7 +77,6 @@ final class ImmutableListMultimapTemplates {
ImmutableMultimap<K, V> before(K key, V value) {
return Refaster.anyOf(
ImmutableListMultimap.<K, V>builder().put(key, value).build(),
ImmutableMultimap.<K, V>builder().put(key, value).build(),
ImmutableMultimap.of(key, value));
}
@@ -99,9 +95,8 @@ final class ImmutableListMultimapTemplates {
ImmutableMultimap<K, V> before(Map.Entry<? extends K, ? extends V> entry) {
return Refaster.anyOf(
ImmutableListMultimap.<K, V>builder().put(entry).build(),
Stream.of(entry).collect(toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue)),
ImmutableMultimap.<K, V>builder().put(entry).build(),
ImmutableMultimap.of(entry.getKey(), entry.getValue()));
Stream.of(entry)
.collect(toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue)));
}
@AfterTemplate
@@ -118,8 +113,7 @@ final class ImmutableListMultimapTemplates {
ImmutableListMultimap.copyOf(iterable.entries()),
ImmutableListMultimap.<K, V>builder().putAll(iterable).build(),
ImmutableMultimap.copyOf(iterable),
ImmutableMultimap.copyOf(iterable.entries()),
ImmutableMultimap.<K, V>builder().putAll(iterable).build());
ImmutableMultimap.copyOf(iterable.entries()));
}
@BeforeTemplate
@@ -129,7 +123,6 @@ final class ImmutableListMultimapTemplates {
ImmutableListMultimap.<K, V>builder().putAll(iterable).build(),
Streams.stream(iterable)
.collect(toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue)),
ImmutableMultimap.<K, V>builder().putAll(iterable).build(),
ImmutableMultimap.copyOf(iterable));
}

View File

@@ -118,7 +118,6 @@ final class ImmutableListTemplates {
ImmutableList<T> before(Stream<T> stream) {
return Refaster.anyOf(
ImmutableList.copyOf(stream.iterator()),
ImmutableList.copyOf(stream::iterator),
stream.collect(collectingAndThen(toList(), ImmutableList::copyOf)));
}

View File

@@ -92,7 +92,6 @@ final class ImmutableMultisetTemplates {
ImmutableMultiset<T> before(Stream<T> stream) {
return Refaster.anyOf(
ImmutableMultiset.copyOf(stream.iterator()),
ImmutableMultiset.copyOf(stream::iterator),
stream.collect(collectingAndThen(toList(), ImmutableMultiset::copyOf)));
}

View File

@@ -114,7 +114,6 @@ final class ImmutableSetTemplates {
ImmutableSet<T> before(Stream<T> stream) {
return Refaster.anyOf(
ImmutableSet.copyOf(stream.iterator()),
ImmutableSet.copyOf(stream::iterator),
stream.distinct().collect(toImmutableSet()),
stream.collect(collectingAndThen(toList(), ImmutableSet::copyOf)),
stream.collect(collectingAndThen(toSet(), ImmutableSet::copyOf)));

View File

@@ -136,7 +136,6 @@ final class ImmutableSortedMultisetTemplates {
ImmutableSortedMultiset<T> before(Stream<T> stream) {
return Refaster.anyOf(
ImmutableSortedMultiset.copyOf(stream.iterator()),
ImmutableSortedMultiset.copyOf(stream::iterator),
stream.collect(collectingAndThen(toList(), ImmutableSortedMultiset::copyOf)));
}

View File

@@ -136,7 +136,6 @@ final class ImmutableSortedSetTemplates {
ImmutableSortedSet<T> before(Stream<T> stream) {
return Refaster.anyOf(
ImmutableSortedSet.copyOf(stream.iterator()),
ImmutableSortedSet.copyOf(stream::iterator),
stream.collect(collectingAndThen(toList(), ImmutableSortedSet::copyOf)));
}

View File

@@ -246,10 +246,7 @@ final class IntStreamTemplates {
static final class IntStreamAllMatch {
@BeforeTemplate
boolean before(IntStream stream, IntPredicate predicate) {
return Refaster.anyOf(
stream.noneMatch(predicate.negate()),
!stream.anyMatch(predicate.negate()),
stream.filter(predicate.negate()).findAny().isEmpty());
return stream.noneMatch(predicate.negate());
}
@AfterTemplate
@@ -264,10 +261,7 @@ final class IntStreamTemplates {
@BeforeTemplate
boolean before(IntStream stream) {
return Refaster.anyOf(
stream.noneMatch(e -> !test(e)),
!stream.anyMatch(e -> !test(e)),
stream.filter(e -> !test(e)).findAny().isEmpty());
return stream.noneMatch(e -> !test(e));
}
@AfterTemplate

View File

@@ -246,10 +246,7 @@ final class LongStreamTemplates {
static final class LongStreamAllMatch {
@BeforeTemplate
boolean before(LongStream stream, LongPredicate predicate) {
return Refaster.anyOf(
stream.noneMatch(predicate.negate()),
!stream.anyMatch(predicate.negate()),
stream.filter(predicate.negate()).findAny().isEmpty());
return stream.noneMatch(predicate.negate());
}
@AfterTemplate
@@ -264,10 +261,7 @@ final class LongStreamTemplates {
@BeforeTemplate
boolean before(LongStream stream) {
return Refaster.anyOf(
stream.noneMatch(e -> !test(e)),
!stream.anyMatch(e -> !test(e)),
stream.filter(e -> !test(e)).findAny().isEmpty());
return stream.noneMatch(e -> !test(e));
}
@AfterTemplate

View File

@@ -1,5 +1,10 @@
package tech.picnic.errorprone.refastertemplates;
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;
@@ -42,15 +47,13 @@ final class MapEntryTemplates {
static final class MapEntryComparingByKey<K extends Comparable<? super K>, V> {
@BeforeTemplate
Comparator<Map.Entry<K, V>> before() {
return Refaster.anyOf(
Comparator.comparing(Map.Entry::getKey),
Map.Entry.comparingByKey(Comparator.naturalOrder()));
return Refaster.anyOf(comparing(Map.Entry::getKey), comparingByKey(naturalOrder()));
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Comparator<Map.Entry<K, V>> after() {
return Map.Entry.comparingByKey();
return comparingByKey();
}
}
@@ -58,13 +61,13 @@ final class MapEntryTemplates {
static final class MapEntryComparingByKeyWithCustomComparator<K, V> {
@BeforeTemplate
Comparator<Map.Entry<K, V>> before(Comparator<? super K> cmp) {
return Comparator.comparing(Map.Entry::getKey, cmp);
return comparing(Map.Entry::getKey, cmp);
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Comparator<Map.Entry<K, V>> after(Comparator<? super K> cmp) {
return Map.Entry.comparingByKey(cmp);
return comparingByKey(cmp);
}
}
@@ -73,15 +76,13 @@ final class MapEntryTemplates {
static final class MapEntryComparingByValue<K, V extends Comparable<? super V>> {
@BeforeTemplate
Comparator<Map.Entry<K, V>> before() {
return Refaster.anyOf(
Comparator.comparing(Map.Entry::getValue),
Map.Entry.comparingByValue(Comparator.naturalOrder()));
return Refaster.anyOf(comparing(Map.Entry::getValue), comparingByValue(naturalOrder()));
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Comparator<Map.Entry<K, V>> after() {
return Map.Entry.comparingByValue();
return comparingByValue();
}
}
@@ -89,13 +90,13 @@ final class MapEntryTemplates {
static final class MapEntryComparingByValueWithCustomComparator<K, V> {
@BeforeTemplate
Comparator<Map.Entry<K, V>> before(Comparator<? super V> cmp) {
return Comparator.comparing(Map.Entry::getValue, cmp);
return comparing(Map.Entry::getValue, cmp);
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Comparator<Map.Entry<K, V>> after(Comparator<? super V> cmp) {
return Map.Entry.comparingByValue(cmp);
return comparingByValue(cmp);
}
}
}

View File

@@ -1,5 +1,7 @@
package tech.picnic.errorprone.refastertemplates;
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;
@@ -24,7 +26,7 @@ final class NullTemplates {
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
T after(T first, T second) {
return Objects.requireNonNullElse(first, second);
return requireNonNullElse(first, second);
}
}

View File

@@ -20,10 +20,10 @@ final class OptionalTemplates {
private OptionalTemplates() {}
static final class OptionalOfNullable<T> {
@BeforeTemplate
// XXX: Refaster should be smart enough to also rewrite occurrences in which there are
// parentheses around the null check, but that's currently not the case. Try to fix that.
// XXX: This is a special case of `TernaryOperatorOptionalNegativeFiltering`.
@BeforeTemplate
@SuppressWarnings("TernaryOperatorOptionalNegativeFiltering" /* Special case. */)
Optional<T> before(T object) {
return object == null ? Optional.empty() : Optional.of(object);
}

View File

@@ -77,7 +77,7 @@ final class ReactorTemplates {
static final class MonoErrorSupplier<T, E extends Throwable> {
@BeforeTemplate
Mono<T> before(Supplier<E> supplier) {
return Refaster.anyOf(Mono.error(supplier::get), Mono.error(() -> supplier.get()));
return Mono.error(() -> supplier.get());
}
@AfterTemplate
@@ -94,7 +94,7 @@ final class ReactorTemplates {
static final class FluxErrorSupplier<T, E extends Throwable> {
@BeforeTemplate
Flux<T> before(Supplier<E> supplier) {
return Refaster.anyOf(Flux.error(supplier::get), Flux.error(() -> supplier.get()));
return Flux.error(() -> supplier.get());
}
@AfterTemplate

View File

@@ -18,6 +18,19 @@ 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

View File

@@ -0,0 +1,506 @@
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)
}

View File

@@ -0,0 +1,959 @@
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)
}

View File

@@ -0,0 +1,927 @@
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)
}

View File

@@ -0,0 +1,764 @@
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)
}

View File

@@ -0,0 +1,290 @@
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;
// }
// }
}

View File

@@ -0,0 +1,404 @@
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));
}
}
}

View File

@@ -148,6 +148,8 @@ final class StreamTemplates {
*/
// XXX: Consider whether to have a similar rule for `.findAny()`. For parallel streams it
// wouldn't be quite the same....
// XXX: This change is not equivalent for `null`-returning functions, as the original code throws
// an NPE if the first element is `null`, while the latter yields an empty `Optional`.
static final class StreamMapFirst<T, S> {
@BeforeTemplate
Optional<S> before(Stream<T> stream, Function<? super T, S> function) {
@@ -294,10 +296,7 @@ final class StreamTemplates {
static final class StreamAllMatch<T> {
@BeforeTemplate
boolean before(Stream<T> stream, Predicate<? super T> predicate) {
return Refaster.anyOf(
stream.noneMatch(Refaster.anyOf(not(predicate), predicate.negate())),
!stream.anyMatch(Refaster.anyOf(not(predicate), predicate.negate())),
stream.filter(Refaster.anyOf(not(predicate), predicate.negate())).findAny().isEmpty());
return stream.noneMatch(Refaster.anyOf(not(predicate), predicate.negate()));
}
@AfterTemplate
@@ -312,10 +311,7 @@ final class StreamTemplates {
@BeforeTemplate
boolean before(Stream<T> stream) {
return Refaster.anyOf(
stream.noneMatch(e -> !test(e)),
!stream.anyMatch(e -> !test(e)),
stream.filter(e -> !test(e)).findAny().isEmpty());
return stream.noneMatch(e -> !test(e));
}
@AfterTemplate

View File

@@ -1,5 +1,6 @@
package tech.picnic.errorprone.refastertemplates;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.joining;
import com.google.common.base.Joiner;
@@ -10,7 +11,6 @@ import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.AlsoNegation;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
@@ -122,7 +122,7 @@ final class StringTemplates {
static final class Utf8EncodedLength {
@BeforeTemplate
int before(String str) {
return str.getBytes(StandardCharsets.UTF_8).length;
return str.getBytes(UTF_8).length;
}
@AfterTemplate

View File

@@ -16,6 +16,7 @@ import static org.testng.Assert.assertThrows;
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;
@@ -81,6 +82,7 @@ final class TestNGToAssertJTemplates {
}
@AfterTemplate
@DoNotCall
void after() {
throw new AssertionError();
}

View File

@@ -43,10 +43,10 @@ final class TimeTemplates {
static final class UtcConstant {
@BeforeTemplate
ZoneId before() {
// `ZoneId.of("Z")` is not listed, because Error Prone flags it out of the box.
return Refaster.anyOf(
ZoneId.of("GMT"),
ZoneId.of("UTC"),
ZoneId.of("Z"),
ZoneId.of("+0"),
ZoneId.of("-0"),
ZoneOffset.UTC.normalized(),
@@ -62,11 +62,13 @@ final class TimeTemplates {
/** Use {@link Clock#systemUTC()} when possible. */
static final class UtcClock {
@BeforeTemplate
@SuppressWarnings("TimeZoneUsage")
Clock before() {
return Clock.system(ZoneOffset.UTC);
}
@AfterTemplate
@SuppressWarnings("TimeZoneUsage")
Clock after() {
return Clock.systemUTC();
}
@@ -96,8 +98,8 @@ final class TimeTemplates {
return a.compareTo(b) < 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(Instant a, Instant b) {
return a.isBefore(b);
}
@@ -113,8 +115,8 @@ final class TimeTemplates {
return a.compareTo(b) > 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(Instant a, Instant b) {
return a.isAfter(b);
}
@@ -162,8 +164,8 @@ final class TimeTemplates {
return a.compareTo(b) < 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(ChronoLocalDate a, ChronoLocalDate b) {
return a.isBefore(b);
}
@@ -179,8 +181,8 @@ final class TimeTemplates {
return a.compareTo(b) > 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(ChronoLocalDate a, ChronoLocalDate b) {
return a.isAfter(b);
}
@@ -196,8 +198,8 @@ final class TimeTemplates {
return a.compareTo(b) < 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(ChronoLocalDateTime<?> a, ChronoLocalDateTime<?> b) {
return a.isBefore(b);
}
@@ -213,8 +215,8 @@ final class TimeTemplates {
return a.compareTo(b) > 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(ChronoLocalDateTime<?> a, ChronoLocalDateTime<?> b) {
return a.isAfter(b);
}
@@ -230,8 +232,8 @@ final class TimeTemplates {
return a.compareTo(b) < 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(ChronoZonedDateTime<?> a, ChronoZonedDateTime<?> b) {
return a.isBefore(b);
}
@@ -247,8 +249,8 @@ final class TimeTemplates {
return a.compareTo(b) > 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(ChronoZonedDateTime<?> a, ChronoZonedDateTime<?> b) {
return a.isAfter(b);
}
@@ -264,8 +266,8 @@ final class TimeTemplates {
return a.compareTo(b) < 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(OffsetDateTime a, OffsetDateTime b) {
return a.isBefore(b);
}
@@ -281,8 +283,8 @@ final class TimeTemplates {
return a.compareTo(b) > 0;
}
@AlsoNegation
@AfterTemplate
@AlsoNegation
boolean after(OffsetDateTime a, OffsetDateTime b) {
return a.isAfter(b);
}

View File

@@ -0,0 +1,36 @@
package tech.picnic.errorprone.refastertemplates;
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec;
import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
/**
* Refaster templates related to expressions dealing with {@link
* org.springframework.web.reactive.function.client.WebClient} and related types.
*/
final class WebClientTemplates {
private WebClientTemplates() {}
/** Prefer {@link RequestBodySpec#bodyValue(Object)} over more contrived alternatives. */
static final class BodyValue<T> {
@BeforeTemplate
RequestHeadersSpec<?> before(RequestBodySpec requestBodySpec, T value) {
return requestBodySpec.body(fromValue(value));
}
@BeforeTemplate
WebTestClient.RequestHeadersSpec<?> before2(
WebTestClient.RequestBodySpec requestBodySpec, T value) {
return requestBodySpec.body(fromValue(value));
}
@AfterTemplate
RequestHeadersSpec<?> after(RequestBodySpec requestBodySpec, T value) {
return requestBodySpec.bodyValue(value);
}
}
}

View File

@@ -1,7 +1,4 @@
/** Picnic Refaster templates. */
@CheckReturnValue
@ParametersAreNonnullByDefault
@com.google.errorprone.annotations.CheckReturnValue
@javax.annotation.ParametersAreNonnullByDefault
package tech.picnic.errorprone.refastertemplates;
import com.google.errorprone.annotations.CheckReturnValue;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -0,0 +1,149 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.base.Predicates.containsPattern;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class AmbiguousJsonCreatorCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(AmbiguousJsonCreatorCheck.class, getClass())
.expectErrorMessage(
"X",
containsPattern("`JsonCreator.Mode` should be set for single-argument creators"));
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(AmbiguousJsonCreatorCheck.class, getClass());
@Test
void identification() {
compilationTestHelper
.addSourceLines(
"Container.java",
"import com.fasterxml.jackson.annotation.JsonCreator;",
"import com.fasterxml.jackson.annotation.JsonValue;",
"",
"interface Container {",
" enum A {",
" FOO(1);",
"",
" private final int i;",
"",
" A(int i) {",
" this.i = i;",
" }",
"",
" // BUG: Diagnostic matches: X",
" @JsonCreator",
" public static A of(int i) {",
" return FOO;",
" }",
" }",
"",
" enum B {",
" FOO(1);",
"",
" private final int i;",
"",
" B(int i) {",
" this.i = i;",
" }",
"",
" @JsonCreator(mode = JsonCreator.Mode.DELEGATING)",
" public static B of(int i) {",
" return FOO;",
" }",
" }",
"",
" enum C {",
" FOO(1, \"s\");",
"",
" @JsonValue private final int i;",
" private final String s;",
"",
" C(int i, String s) {",
" this.i = i;",
" this.s = s;",
" }",
"",
" // BUG: Diagnostic matches: X",
" @JsonCreator",
" public static C of(int i) {",
" return FOO;",
" }",
" }",
"",
" enum D {",
" FOO(1, \"s\");",
"",
" private final int i;",
" private final String s;",
"",
" D(int i, String s) {",
" this.i = i;",
" this.s = s;",
" }",
"",
" @JsonCreator",
" public static D of(int i, String s) {",
" return FOO;",
" }",
" }",
"",
" enum E {",
" FOO;",
"",
" // BUG: Diagnostic matches: X",
" @JsonCreator",
" public static E of(String s) {",
" return FOO;",
" }",
" }",
"",
" class F {",
" private final String s;",
"",
" F(String s) {",
" this.s = s;",
" }",
"",
" @JsonCreator",
" public static F of(String s) {",
" return new F(s);",
" }",
" }",
"",
"}")
.doTest();
}
@Test
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",
"import com.fasterxml.jackson.annotation.JsonCreator;",
"",
"enum A {",
" FOO;",
"",
" @JsonCreator",
" public static A of(String s) {",
" return FOO;",
" }",
"}")
.addOutputLines(
"out/A.java",
"import com.fasterxml.jackson.annotation.JsonCreator;",
"",
"enum A {",
" FOO;",
"",
" @JsonCreator(mode = JsonCreator.Mode.DELEGATING)",
" public static A of(String s) {",
" return FOO;",
" }",
"}")
.doTest(BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH);
}
}

View File

@@ -8,14 +8,14 @@ import org.junit.jupiter.api.Test;
public final class AnnotationAttributeMatcherTest {
@Test
public void testWithoutListings() {
void withoutListings() {
AnnotationAttributeMatcher matcher =
AnnotationAttributeMatcher.create(Optional.empty(), ImmutableList.of());
assertThat(matcher.matches("foo", "bar")).isTrue();
}
@Test
public void testWithSingleFullAnnotationWhitelist() {
void withSingleFullAnnotationWhitelist() {
AnnotationAttributeMatcher matcher =
AnnotationAttributeMatcher.create(Optional.of(ImmutableList.of("foo")), ImmutableList.of());
assertThat(matcher.matches("foo", "bar")).isTrue();
@@ -24,7 +24,7 @@ public final class AnnotationAttributeMatcherTest {
}
@Test
public void testWithSingleAnnotationAttributeWhitelist() {
void withSingleAnnotationAttributeWhitelist() {
AnnotationAttributeMatcher matcher =
AnnotationAttributeMatcher.create(
Optional.of(ImmutableList.of("foo#bar")), ImmutableList.of());
@@ -34,7 +34,7 @@ public final class AnnotationAttributeMatcherTest {
}
@Test
public void testWithSingleFullAnnotationBlacklist() {
void withSingleFullAnnotationBlacklist() {
AnnotationAttributeMatcher matcher =
AnnotationAttributeMatcher.create(Optional.empty(), ImmutableList.of("foo"));
assertThat(matcher.matches("foo", "bar")).isFalse();
@@ -43,7 +43,7 @@ public final class AnnotationAttributeMatcherTest {
}
@Test
public void testWithSingleAnnotationAttributeBlacklist() {
void withSingleAnnotationAttributeBlacklist() {
AnnotationAttributeMatcher matcher =
AnnotationAttributeMatcher.create(Optional.empty(), ImmutableList.of("foo#bar"));
assertThat(matcher.matches("foo", "bar")).isFalse();
@@ -52,7 +52,7 @@ public final class AnnotationAttributeMatcherTest {
}
@Test
public void testWithComplicatedConfiguration() {
void withComplicatedConfiguration() {
AnnotationAttributeMatcher matcher =
AnnotationAttributeMatcher.create(
Optional.of(ImmutableList.of("foo", "bar", "baz", "baz#1", "baz#2", "quux#1")),

View File

@@ -9,10 +9,10 @@ public final class AutowiredConstructorCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(AutowiredConstructorCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new AutowiredConstructorCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(AutowiredConstructorCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"Container.java",
@@ -62,7 +62,7 @@ public final class AutowiredConstructorCheckTest {
}
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/Container.java",

View File

@@ -9,10 +9,10 @@ public final class CanonicalAnnotationSyntaxCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(CanonicalAnnotationSyntaxCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new CanonicalAnnotationSyntaxCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(CanonicalAnnotationSyntaxCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"pkg/A.java",
@@ -85,7 +85,7 @@ public final class CanonicalAnnotationSyntaxCheckTest {
}
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/pkg/A.java",

View File

@@ -9,10 +9,10 @@ public final class EmptyMethodCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(EmptyMethodCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new EmptyMethodCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(EmptyMethodCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -33,6 +33,10 @@ public final class EmptyMethodCheckTest {
" interface F {",
" void fun();",
" }",
"",
" final class MyTestClass {",
" void helperMethod() {}",
" }",
"}")
.addSourceLines(
"B.java",
@@ -64,7 +68,7 @@ public final class EmptyMethodCheckTest {
}
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",

View File

@@ -0,0 +1,85 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class ExplicitEnumOrderingCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(ExplicitEnumOrderingCheck.class, getClass());
@Test
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.time.chrono.IsoEra.BCE;",
"import static java.time.chrono.IsoEra.CE;",
"",
"import com.google.common.collect.Ordering;",
"import com.google.common.collect.ImmutableList;",
"import java.lang.annotation.RetentionPolicy;",
"import java.time.chrono.IsoEra;",
"",
"class A {",
" {",
" // The `List`-accepting overload is currently ignored.",
" Ordering.explicit(ImmutableList.of(RetentionPolicy.SOURCE, RetentionPolicy.CLASS));",
"",
" Ordering.explicit(IsoEra.BCE, IsoEra.CE);",
" // BUG: Diagnostic contains: IsoEra.CE",
" Ordering.explicit(IsoEra.BCE);",
" // BUG: Diagnostic contains: IsoEra.BCE",
" Ordering.explicit(IsoEra.CE);",
"",
" Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.CLASS, RetentionPolicy.RUNTIME);",
" // BUG: Diagnostic contains: RetentionPolicy.CLASS, RetentionPolicy.RUNTIME",
" Ordering.explicit(RetentionPolicy.SOURCE);",
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME",
" Ordering.explicit(RetentionPolicy.CLASS);",
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.CLASS",
" Ordering.explicit(RetentionPolicy.RUNTIME);",
" // BUG: Diagnostic contains: RetentionPolicy.RUNTIME",
" Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.CLASS);",
" // BUG: Diagnostic contains: RetentionPolicy.CLASS",
" Ordering.explicit(RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME);",
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE",
" Ordering.explicit(RetentionPolicy.CLASS, RetentionPolicy.RUNTIME);",
"",
" Ordering.explicit(BCE, CE);",
" // BUG: Diagnostic contains: IsoEra.CE",
" Ordering.explicit(BCE);",
" // BUG: Diagnostic contains: IsoEra.BCE",
" Ordering.explicit(CE);",
"",
" Ordering.explicit(SOURCE, CLASS, RUNTIME);",
" // BUG: Diagnostic contains: RetentionPolicy.CLASS, RetentionPolicy.RUNTIME",
" Ordering.explicit(SOURCE);",
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.RUNTIME",
" Ordering.explicit(CLASS);",
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, RetentionPolicy.CLASS",
" Ordering.explicit(RUNTIME);",
" // BUG: Diagnostic contains: RetentionPolicy.RUNTIME",
" Ordering.explicit(SOURCE, CLASS);",
" // BUG: Diagnostic contains: RetentionPolicy.CLASS",
" Ordering.explicit(SOURCE, RUNTIME);",
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE",
" Ordering.explicit(CLASS, RUNTIME);",
"",
" Ordering.explicit(RetentionPolicy.SOURCE, BCE, RetentionPolicy.CLASS, CE, RUNTIME);",
" Ordering.explicit(SOURCE, IsoEra.BCE, CLASS, IsoEra.CE, RetentionPolicy.RUNTIME);",
" // BUG: Diagnostic contains: RetentionPolicy.CLASS",
" Ordering.explicit(RetentionPolicy.SOURCE, BCE, CE, RUNTIME);",
" // BUG: Diagnostic contains: RetentionPolicy.CLASS",
" Ordering.explicit(IsoEra.BCE, SOURCE, IsoEra.CE, RetentionPolicy.RUNTIME);",
" // BUG: Diagnostic contains: IsoEra.CE, RetentionPolicy.RUNTIME",
" Ordering.explicit(IsoEra.BCE, SOURCE, RetentionPolicy.CLASS);",
" // BUG: Diagnostic contains: RetentionPolicy.SOURCE, IsoEra.BCE",
" Ordering.explicit(CLASS, RUNTIME, CE);",
" }",
"}")
.doTest();
}
}

View File

@@ -0,0 +1,414 @@
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 FormatStringConcatenationCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(FormatStringConcatenationCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(FormatStringConcatenationCheck.class, getClass());
@Test
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
"import static com.google.common.base.Preconditions.checkArgument;",
"import static com.google.common.base.Preconditions.checkNotNull;",
"import static com.google.common.base.Preconditions.checkState;",
"import static com.google.common.base.Verify.verify;",
"import static org.assertj.core.api.Assertions.assertThat;",
"import static org.assertj.core.api.SoftAssertions.assertSoftly;",
"",
"import java.util.Locale;",
"import java.util.Formatter;",
"import org.assertj.core.api.Assertions;",
"import org.assertj.core.api.BDDAssertions;",
"import org.assertj.core.api.Fail;",
"import org.assertj.core.api.ThrowableAssertAlternative;",
"import org.assertj.core.api.WithAssertions;",
"import org.slf4j.Logger;",
"import org.slf4j.LoggerFactory;",
"import org.slf4j.Marker;",
"",
"class A {",
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
"",
" void negative() {",
" hashCode();",
" equals(new A());",
" equals(toString());",
" equals(0);",
" equals(\"str\");",
" equals(\"str\" + 0);",
" equals(0 + 0);",
" equals(0 - 0);",
" equals(\"str \" + toString());",
" }",
"",
" void assertj() {",
" assertThat(0).overridingErrorMessage(toString());",
" assertThat(0).overridingErrorMessage(\"str\");",
" assertThat(0).overridingErrorMessage(\"str \" + 0);",
" assertThat(0).overridingErrorMessage(\"str %s\", 2 * 3);",
" assertThat(0).overridingErrorMessage(\"str %s\", toString());",
" // BUG: Diagnostic contains:",
" assertThat(0).overridingErrorMessage(\"str \" + hashCode() / 2);",
" // BUG: Diagnostic contains:",
" assertThat(0).overridingErrorMessage((\"str \" + toString()));",
" // BUG: Diagnostic contains:",
" assertThat(0).overridingErrorMessage(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(0).overridingErrorMessage(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(0).withFailMessage(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(0).withFailMessage(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertSoftly(softly -> softly.fail(\"str \" + toString()));",
" // BUG: Diagnostic contains:",
" assertSoftly(softly -> softly.fail(\"%s \" + toString(), \"arg\"));",
" assertSoftly(softly -> softly.fail(\"str \" + toString(), new Throwable()));",
"",
" // BUG: Diagnostic contains:",
" assertThat(\"\").isEqualTo(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(\"\").isEqualTo(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasMessage(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasMessage(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasMessageContaining(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasMessageContaining(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasMessageEndingWith(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasMessageEndingWith(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasMessageStartingWith(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasMessageStartingWith(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasRootCauseMessage(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasRootCauseMessage(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasStackTraceContaining(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(new Error()).hasStackTraceContaining(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(0).as(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(0).as(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" assertThat(0).describedAs(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" assertThat(0).describedAs(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withMessage(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withMessage(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withMessageContaining(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withMessageContaining(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withMessageEndingWith(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withMessageEndingWith(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withMessageStartingWith(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withMessageStartingWith(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withStackTraceContaining(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" ((ThrowableAssertAlternative) null).withStackTraceContaining(\"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" ((WithAssertions) null).fail(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" ((WithAssertions) null).fail(\"%s \" + toString(), \"arg\");",
" ((WithAssertions) null).fail(\"str \" + toString(), new Throwable());",
"",
" // BUG: Diagnostic contains:",
" Assertions.fail(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" Assertions.fail(\"%s \" + toString(), \"arg\");",
" Assertions.fail(\"str \" + toString(), new Throwable());",
"",
" // BUG: Diagnostic contains:",
" BDDAssertions.fail(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" BDDAssertions.fail(\"%s \" + toString(), \"arg\");",
" BDDAssertions.fail(\"str \" + toString(), new Throwable());",
"",
" // BUG: Diagnostic contains:",
" Fail.fail(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" Fail.fail(\"%s \" + toString(), \"arg\");",
" Fail.fail(\"str \" + toString(), new Throwable());",
" }",
"",
" void guava() {",
" checkArgument(true);",
" checkArgument(true, toString());",
" checkArgument(true, \"str\");",
" checkArgument(true, \"str \" + 0);",
" checkArgument(true, \"str %s\", 2 * 3);",
" checkArgument(true, \"str %s\", toString());",
" // BUG: Diagnostic contains:",
" checkArgument(true, \"str \" + hashCode() / 2);",
" // BUG: Diagnostic contains:",
" checkArgument(true, (\"str \" + toString()));",
" // BUG: Diagnostic contains:",
" checkArgument(true, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" checkArgument(true, \"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" checkNotNull(true, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" checkNotNull(true, \"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" checkState(true, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" checkState(true, \"%s \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" verify(true, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" verify(true, \"%s \" + toString(), \"arg\");",
" }",
"",
" void jdk() {",
" String.format(\"str\");",
" String.format(\"str \" + 0);",
" String.format(\"str {}\", 2 * 3);",
" String.format(\"str {}\", toString());",
" // BUG: Diagnostic contains:",
" String.format(\"str \" + hashCode() / 2);",
" // BUG: Diagnostic contains:",
" String.format((\"str \" + toString()));",
" // BUG: Diagnostic contains:",
" String.format(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" String.format(\"{} \" + toString(), \"arg\");",
"",
" String.format(Locale.ROOT, \"str\");",
" String.format(Locale.ROOT, \"str \" + 0);",
" String.format(Locale.ROOT, \"str {}\", 2 * 3);",
" String.format(Locale.ROOT, \"str {}\", toString());",
" // BUG: Diagnostic contains:",
" String.format(Locale.ROOT, (\"str \" + toString()));",
" // BUG: Diagnostic contains:",
" String.format(Locale.ROOT, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" String.format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" new Formatter().format(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" new Formatter().format(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" new Formatter().format(Locale.ROOT, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" new Formatter().format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
" }",
"",
" void slf4j() {",
" LOG.debug(\"str\");",
" LOG.debug(\"str \" + 0);",
" LOG.debug(\"str {}\", 2 * 3);",
" LOG.debug(\"str {}\", toString());",
" // BUG: Diagnostic contains:",
" LOG.debug(\"str \" + hashCode() / 2);",
" // BUG: Diagnostic contains:",
" LOG.debug((\"str \" + toString()));",
" // BUG: Diagnostic contains:",
" LOG.debug(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.debug(\"{} \" + toString(), \"arg\");",
"",
" LOG.debug((Marker) null, \"str\");",
" LOG.debug((Marker) null, \"str \" + 0);",
" LOG.debug((Marker) null, \"str {}\", 2 * 3);",
" LOG.debug((Marker) null, \"str {}\", toString());",
" // BUG: Diagnostic contains:",
" LOG.debug((Marker) null, (\"str \" + toString()));",
" // BUG: Diagnostic contains:",
" LOG.debug((Marker) null, \"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.debug((Marker) null, \"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.error(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.error(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.error((Marker) null,\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.error((Marker) null,\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.info(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.info(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.info((Marker) null,\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.info((Marker) null,\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.trace(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.trace(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.trace((Marker) null,\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.trace((Marker) null,\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.warn(\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.warn(\"{} \" + toString(), \"arg\");",
"",
" // BUG: Diagnostic contains:",
" LOG.warn((Marker) null,\"str \" + toString());",
" // BUG: Diagnostic contains:",
" LOG.warn((Marker) null,\"{} \" + toString(), \"arg\");",
" }",
"}")
.doTest();
}
@Test
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",
"import static com.google.common.base.Preconditions.checkArgument;",
"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;",
"",
"class A {",
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
"",
" void assertj() {",
" assertThat(0).overridingErrorMessage(toString() + \" str\");",
" assertThat(0).overridingErrorMessage(\"str \" + toString());",
" assertThat(0).overridingErrorMessage(toString() + toString());",
" assertThat(0).overridingErrorMessage(\"str \" + toString() + \" word \" + new A().hashCode());",
" assertThat(0).overridingErrorMessage(\"str \" + (toString() + \" word \") + (hashCode() / 2));",
"",
" // Flagged but not auto-fixed.",
" assertThat(0).overridingErrorMessage(\"%s \" + toString(), \"arg\");",
" }",
"",
" void guava() {",
" checkArgument(true, \"str \" + toString());",
"",
" // Flagged but not auto-fixed.",
" checkArgument(true, \"%s \" + toString(), \"arg\");",
" }",
"",
" void jdk() {",
" String.format(\"str \" + toString());",
" String.format(Locale.ROOT, \"str \" + toString());",
"",
" // Flagged but not auto-fixed.",
" String.format(\"{} \" + toString(), \"arg\");",
" String.format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
" }",
"",
" void slf4j() {",
" LOG.debug(\"str \" + toString());",
" LOG.debug((Marker) null, \"str \" + toString());",
"",
" // Flagged but not auto-fixed.",
" LOG.debug(\"{} \" + toString(), \"arg\");",
" LOG.debug((Marker) null, \"{} \" + toString(), \"arg\");",
" }",
"}")
.addOutputLines(
"out/A.java",
"import static com.google.common.base.Preconditions.checkArgument;",
"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;",
"",
"class A {",
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
"",
" void assertj() {",
" assertThat(0).overridingErrorMessage(\"%s str\", toString());",
" assertThat(0).overridingErrorMessage(\"str %s\", toString());",
" assertThat(0).overridingErrorMessage(\"%s%s\", toString(), toString());",
" assertThat(0).overridingErrorMessage(\"str %s word %s\", toString(), new A().hashCode());",
" assertThat(0).overridingErrorMessage(\"str %s word %s\", toString(), hashCode() / 2);",
"",
" // Flagged but not auto-fixed.",
" assertThat(0).overridingErrorMessage(\"%s \" + toString(), \"arg\");",
" }",
"",
" void guava() {",
" checkArgument(true, \"str %s\", toString());",
"",
" // Flagged but not auto-fixed.",
" checkArgument(true, \"%s \" + toString(), \"arg\");",
" }",
"",
" void jdk() {",
" String.format(\"str %s\", toString());",
" String.format(Locale.ROOT, \"str %s\", toString());",
"",
" // Flagged but not auto-fixed.",
" String.format(\"{} \" + toString(), \"arg\");",
" String.format(Locale.ROOT, \"{} \" + toString(), \"arg\");",
" }",
" void slf4j() {",
" LOG.debug(\"str {}\", toString());",
" LOG.debug((Marker) null, \"str {}\", toString());",
"",
" // Flagged but not auto-fixed.",
" LOG.debug(\"{} \" + toString(), \"arg\");",
" LOG.debug((Marker) null, \"{} \" + toString(), \"arg\");",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -9,10 +9,10 @@ public final class JUnitMethodDeclarationCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(JUnitMethodDeclarationCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new JUnitMethodDeclarationCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(JUnitMethodDeclarationCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -91,7 +91,7 @@ public final class JUnitMethodDeclarationCheckTest {
"import org.junit.jupiter.api.Test;",
"import org.junit.jupiter.params.ParameterizedTest;",
"",
"final class B extends A {",
"class B extends A {",
" @Override @BeforeAll void setUp1() {}",
" @Override @BeforeAll public void setUp2() {}",
" @Override @BeforeAll protected void setUp3() {}",
@@ -127,7 +127,7 @@ public final class JUnitMethodDeclarationCheckTest {
}
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",

View File

@@ -19,10 +19,10 @@ public final class LexicographicalAnnotationAttributeListingCheckTest {
"-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value"));
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(
new LexicographicalAnnotationAttributeListingCheck(), getClass());
LexicographicalAnnotationAttributeListingCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -105,7 +105,7 @@ public final class LexicographicalAnnotationAttributeListingCheckTest {
// introduced. Avoiding that might make the code too complex. Instead, users can have the
// `CanonicalAnnotationSyntaxCheck` correct the situation in a subsequent run.
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",
@@ -161,7 +161,7 @@ public final class LexicographicalAnnotationAttributeListingCheckTest {
}
@Test
public void testFiltering() {
void filtering() {
/* Some violations are not flagged because they are not in- or excluded. */
restrictedCompilationTestHelper
.addSourceLines(

View File

@@ -0,0 +1,148 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.base.Predicates.containsPattern;
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 LexicographicalAnnotationListingCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(LexicographicalAnnotationListingCheck.class, getClass())
.expectErrorMessage(
"X", containsPattern("Sort annotations lexicographically where possible"));
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(
LexicographicalAnnotationListingCheck.class, getClass());
@Test
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
"import java.lang.annotation.Repeatable;",
"",
"interface A {",
" @Repeatable(Foos.class)",
" @interface Foo {",
" String[] value() default {};",
" int[] ints() default {};",
" Bar[] anns() default {};",
" }",
"",
" @interface Bar {",
" String[] value() default {};",
" }",
"",
" @interface Baz {",
" String[] str() default {};",
" }",
"",
" @interface Foos {",
" Foo[] value();",
" }",
"",
" // BUG: Diagnostic matches: X",
" @Foo @Bar A unsortedSimpleCase();",
" // BUG: Diagnostic matches: X",
" @Foo() @Bar() A unsortedWithParens();",
" @Foo() A onlyOneAnnotation();",
" @Bar @Foo() A sortedAnnotationsOneWithParens();",
"",
" // BUG: Diagnostic matches: X",
" @Foo @Baz @Bar A threeUnsortedAnnotationsSameInitialLetter();",
" // BUG: Diagnostic matches: X",
" @Bar @Foo() @Baz A firstOrderedWithTwoUnsortedAnnotations();",
" @Bar @Baz @Foo() A threeSortedAnnotations();",
"",
" // BUG: Diagnostic matches: X",
" @Foo({\"b\"}) @Bar({\"a\"}) A unsortedWithStringAttributes();",
" // BUG: Diagnostic matches: X",
" @Baz(str = {\"a\", \"b\"}) @Foo(ints = {1, 0}) @Bar A unsortedWithAttributes();",
" // BUG: Diagnostic matches: X",
" @Bar @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Baz A unsortedWithNestedBar();",
" @Bar @Baz @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) A sortedWithNestedBar();",
"",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Foo(ints = {1, 2}) @Foo({\"b\"}) A sortedRepeatableAnnotation();",
" // BUG: Diagnostic matches: X",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Bar @Foo(ints = {1, 2}) A unsortedRepeatableAnnotation();",
"}")
.doTest();
}
@Test
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",
"import java.lang.annotation.Repeatable;",
"interface A {",
" @Repeatable(Foos.class)",
" @interface Foo {",
" String[] value() default {};",
" int[] ints() default {};",
" Bar[] anns() default {};",
" }",
"",
" @interface Bar {",
" String[] value() default {};",
" }",
"",
" @interface Baz {",
" String[] str() default {};",
" }",
"",
" @interface Foos {",
" Foo[] value();",
" }",
"",
" @Bar A singleAnnotation();",
" @Bar @Foo A sortedAnnotations();",
" @Foo @Bar A unsortedAnnotations();",
" @Foo() @Baz() @Bar A unsortedAnnotationsWithSomeParens();",
"",
" @Bar @Baz(str = {\"a\", \"b\"}) @Foo() A unsortedAnnotationsOneContainingAttributes();",
" @Baz(str = {\"a\", \"b\"}) @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Bar({\"b\"}) A unsortedAnnotationsWithAttributes();",
"",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Foo(ints = {1, 2}) @Foo({\"b\"}) A sortedRepeatableAnnotation();",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Bar @Foo(ints = {1, 2}) A unsortedRepeatableAnnotation();",
"",
"}")
.addOutputLines(
"out/A.java",
"import java.lang.annotation.Repeatable;",
"interface A {",
" @Repeatable(Foos.class)",
" @interface Foo {",
" String[] value() default {};",
" int[] ints() default {};",
" Bar[] anns() default {};",
" }",
"",
" @interface Bar {",
" String[] value() default {};",
" }",
"",
" @interface Baz {",
" String[] str() default {};",
" }",
"",
" @interface Foos {",
" Foo[] value();",
" }",
" @Bar A singleAnnotation();",
" @Bar @Foo A sortedAnnotations();",
" @Bar @Foo A unsortedAnnotations();",
" @Bar @Baz() @Foo() A unsortedAnnotationsWithSomeParens();",
"",
" @Bar @Baz(str = {\"a\", \"b\"}) @Foo() A unsortedAnnotationsOneContainingAttributes();",
" @Bar({\"b\"}) @Baz(str = {\"a\", \"b\"}) @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) A unsortedAnnotationsWithAttributes();",
"",
" @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Foo(ints = {1, 2}) @Foo({\"b\"}) A sortedRepeatableAnnotation();",
" @Bar @Foo(anns = {@Bar(\"b\"), @Bar(\"a\")}) @Foo(ints = {1, 2}) A unsortedRepeatableAnnotation();",
"",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -47,7 +47,7 @@ public final class MethodMatcherFactoryTest {
CompilationTestHelper.newInstance(MatchedMethodsFlagger.class, getClass());
@Test
public void testCreateWithMalformedSignatures() {
void createWithMalformedSignatures() {
MethodMatcherFactory factory = new MethodMatcherFactory();
assertThatThrownBy(() -> factory.create(ImmutableList.of("foo.bar")))
.isInstanceOf(IllegalArgumentException.class);
@@ -60,7 +60,7 @@ public final class MethodMatcherFactoryTest {
}
@Test
public void testMatcher() {
void matcher() {
compilationTestHelper
.addSourceLines(
"com/example/A.java",

View File

@@ -9,10 +9,10 @@ public final class MethodReferenceUsageCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(MethodReferenceUsageCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new MethodReferenceUsageCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(MethodReferenceUsageCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -201,7 +201,7 @@ public final class MethodReferenceUsageCheckTest {
}
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",

View File

@@ -0,0 +1,93 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.base.Predicates.containsPattern;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
public final class MissingRefasterAnnotationCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(MissingRefasterAnnotationCheck.class, getClass())
.expectErrorMessage(
"X",
containsPattern(
"The Refaster template contains a method without any Refaster annotations"));
@Test
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
"import com.google.errorprone.refaster.annotation.AfterTemplate;",
"import com.google.errorprone.refaster.annotation.AlsoNegation;",
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
"import java.util.Map;",
"",
"class A {",
" // BUG: Diagnostic matches: X",
" static final class MethodLacksBeforeTemplateAnnotation {",
" @BeforeTemplate",
" boolean before1(String string) {",
" return string.equals(\"\");",
" }",
"",
" // @BeforeTemplate is missing",
" boolean before2(String string) {",
" return string.length() == 0;",
" }",
"",
" @AfterTemplate",
" @AlsoNegation",
" boolean after(String string) {",
" return string.isEmpty();",
" }",
" }",
"",
" // BUG: Diagnostic matches: X",
" static final class MethodLacksAfterTemplateAnnotation {",
" @BeforeTemplate",
" boolean before(String string) {",
" return string.equals(\"\");",
" }",
"",
" // @AfterTemplate is missing",
" boolean after(String string) {",
" return string.isEmpty();",
" }",
" }",
"",
" // BUG: Diagnostic matches: X",
" abstract class MethodLacksPlaceholderAnnotation<K, V> {",
" // @Placeholder is missing",
" abstract V function(K key);",
"",
" @BeforeTemplate",
" void before(Map<K, V> map, K key) {",
" if (!map.containsKey(key)) {",
" map.put(key, function(key));",
" }",
" }",
"",
" @AfterTemplate",
" void after(Map<K, V> map, K key) {",
" map.computeIfAbsent(key, k -> function(k));",
" }",
" }",
"",
" static final class ValidRefasterTemplate {",
" @BeforeTemplate",
" void unusedPureFunctionCall(Object o) {",
" o.toString();",
" }",
" }",
"",
" static final class NotARefasterTemplate {",
" @Override",
" public String toString() {",
" return \"This is not a Refaster template\";",
" }",
" }",
"}")
.doTest();
}
}

View File

@@ -0,0 +1,101 @@
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 MockitoStubbingCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(MockitoStubbingCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(MockitoStubbingCheck.class, getClass());
@Test
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
"import static org.mockito.ArgumentMatchers.eq;",
"import static org.mockito.ArgumentMatchers.notNull;",
"import static org.mockito.Mockito.doAnswer;",
"import static org.mockito.Mockito.mock;",
"",
"import java.util.function.BiConsumer;",
"import java.util.function.Consumer;",
"import org.mockito.ArgumentMatchers;",
"",
"class A {",
" void m() {",
" Runnable runnable = mock(Runnable.class);",
" doAnswer(inv -> null).when(runnable).run();",
"",
" Consumer<String> consumer = mock(Consumer.class);",
" doAnswer(inv -> null).when(consumer).accept(\"foo\");",
" doAnswer(inv -> null).when(consumer).accept(notNull());",
" // BUG: Diagnostic contains:",
" doAnswer(inv -> null).when(consumer).accept(ArgumentMatchers.eq(\"foo\"));",
" // BUG: Diagnostic contains:",
" doAnswer(inv -> null).when(consumer).accept(eq(toString()));",
"",
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
" doAnswer(inv -> null).when(biConsumer).accept(0, \"foo\");",
" doAnswer(inv -> null).when(biConsumer).accept(eq(0), notNull());",
" doAnswer(inv -> null).when(biConsumer).accept(notNull(), eq(\"foo\"));",
" // BUG: Diagnostic contains:",
" doAnswer(inv -> null).when(biConsumer).accept(ArgumentMatchers.eq(0), ArgumentMatchers.eq(\"foo\"));",
" // BUG: Diagnostic contains:",
" doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));",
" }",
"}")
.doTest();
}
@Test
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",
"import static org.mockito.ArgumentMatchers.eq;",
"import static org.mockito.Mockito.doAnswer;",
"import static org.mockito.Mockito.mock;",
"",
"import java.util.function.BiConsumer;",
"import java.util.function.Consumer;",
"import org.mockito.ArgumentMatchers;",
"",
"class A {",
" void m() {",
" Consumer<String> consumer = mock(Consumer.class);",
" doAnswer(inv -> null).when(consumer).accept(ArgumentMatchers.eq(\"foo\"));",
" doAnswer(inv -> null).when(consumer).accept(eq(toString()));",
"",
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
" doAnswer(inv -> null).when(biConsumer).accept(ArgumentMatchers.eq(0), ArgumentMatchers.eq(\"foo\"));",
" doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));",
" }",
"}")
.addOutputLines(
"out/A.java",
"import static org.mockito.ArgumentMatchers.eq;",
"import static org.mockito.Mockito.doAnswer;",
"import static org.mockito.Mockito.mock;",
"",
"import java.util.function.BiConsumer;",
"import java.util.function.Consumer;",
"import org.mockito.ArgumentMatchers;",
"",
"class A {",
" void m() {",
" Consumer<String> consumer = mock(Consumer.class);",
" doAnswer(inv -> null).when(consumer).accept(\"foo\");",
" doAnswer(inv -> null).when(consumer).accept(toString());",
"",
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
" doAnswer(inv -> null).when(biConsumer).accept(0, \"foo\");",
" doAnswer(inv -> null).when(biConsumer).accept(hashCode(), toString());",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -9,7 +9,7 @@ public final class PrimitiveComparisonCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(PrimitiveComparisonCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new PrimitiveComparisonCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(PrimitiveComparisonCheck.class, getClass());
// XXX: There are no tests for multiple replacements within the same expression:
// - Error Prone doesn't currently support this, it seems.
@@ -19,7 +19,7 @@ public final class PrimitiveComparisonCheckTest {
// The logic for `char` and `short` is exactly analogous to the `byte` case.
@Test
public void testByteComparison() {
void byteComparison() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -108,7 +108,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testIntComparison() {
void intComparison() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -201,7 +201,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testLongComparison() {
void longComparison() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -278,7 +278,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testFloatComparison() {
void floatComparison() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -335,7 +335,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testDoubleComparison() {
void doubleComparison() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -396,7 +396,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testStringComparison() {
void stringComparison() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -429,7 +429,7 @@ public final class PrimitiveComparisonCheckTest {
// XXX: If the explicit `<A, BoxedPrimitive>` generic type information was necessary, then this
// replacement drops too much information.
@Test
public void testReplacementWithPrimitiveVariants() {
void replacementWithPrimitiveVariants() {
refactoringTestHelper
.addInputLines(
"in/A.java",
@@ -483,7 +483,7 @@ public final class PrimitiveComparisonCheckTest {
// XXX: If the explicit `<A>` generic type information was necessary, then this replacement drops
// too much information.
@Test
public void testReplacementWithBoxedVariants() {
void replacementWithBoxedVariants() {
refactoringTestHelper
.addInputLines(
"in/A.java",
@@ -535,7 +535,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testReplacementWithPrimitiveVariantsUsingStaticImports() {
void replacementWithPrimitiveVariantsUsingStaticImports() {
refactoringTestHelper
.addInputLines(
"in/A.java",
@@ -574,7 +574,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testReplacementWithBoxedVariantsUsingStaticImports() {
void replacementWithBoxedVariantsUsingStaticImports() {
refactoringTestHelper
.addInputLines(
"in/A.java",
@@ -615,7 +615,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testReplacementWithPrimitiveVariantsInComplexSyntacticalContext() {
void replacementWithPrimitiveVariantsInComplexSyntacticalContext() {
refactoringTestHelper
.addInputLines(
"in/A.java",
@@ -647,7 +647,7 @@ public final class PrimitiveComparisonCheckTest {
}
@Test
public void testReplacementWithBoxedVariantsInComplexSyntacticalContext() {
void replacementWithBoxedVariantsInComplexSyntacticalContext() {
refactoringTestHelper
.addInputLines(
"in/A.java",

View File

@@ -18,10 +18,10 @@ public final class RedundantStringConversionCheckTest {
ImmutableList.of(
"-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)"));
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new RedundantStringConversionCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(RedundantStringConversionCheck.class, getClass());
@Test
public void testIdentificationOfIdentityTransformation() {
void identificationOfIdentityTransformation() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -44,7 +44,7 @@ public final class RedundantStringConversionCheckTest {
}
@Test
public void testIdentificationWithinMutatingAssignment() {
void identificationWithinMutatingAssignment() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -100,7 +100,7 @@ public final class RedundantStringConversionCheckTest {
}
@Test
public void testIdentificationWithinBinaryOperation() {
void identificationWithinBinaryOperation() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -186,7 +186,7 @@ public final class RedundantStringConversionCheckTest {
}
@Test
public void testIdentificationWithinStringBuilderMethod() {
void identificationWithinStringBuilderMethod() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -235,7 +235,7 @@ public final class RedundantStringConversionCheckTest {
// XXX: Also test the other formatter methods.
@Test
public void testIdentificationWithinFormatterMethod() {
void identificationWithinFormatterMethod() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -280,7 +280,7 @@ public final class RedundantStringConversionCheckTest {
}
@Test
public void testIdentificationWithinGuavaGuardMethod() {
void identificationWithinGuavaGuardMethod() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -340,7 +340,7 @@ public final class RedundantStringConversionCheckTest {
}
@Test
public void testIdentificationWithinSlf4jLoggerMethod() {
void identificationWithinSlf4jLoggerMethod() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -395,7 +395,7 @@ public final class RedundantStringConversionCheckTest {
}
@Test
public void testIdentificationOfCustomConversionMethod() {
void identificationOfCustomConversionMethod() {
customizedCompilationTestHelper
.addSourceLines(
"A.java",
@@ -486,7 +486,7 @@ public final class RedundantStringConversionCheckTest {
}
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",

View File

@@ -0,0 +1,68 @@
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 RefasterAnyOfUsageCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(RefasterAnyOfUsageCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(RefasterAnyOfUsageCheck.class, getClass());
@Test
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
"import com.google.errorprone.refaster.Refaster;",
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
"",
"class A {",
" @BeforeTemplate",
" String before(String str) {",
" // BUG: Diagnostic contains:",
" Refaster.anyOf();",
" // BUG: Diagnostic contains:",
" return Refaster.anyOf(str);",
" }",
"",
" @BeforeTemplate",
" Object before2(String str, Object obj) {",
" return Refaster.anyOf(str, obj);",
" }",
"}")
.doTest();
}
@Test
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",
"import com.google.errorprone.refaster.Refaster;",
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
"",
"class A {",
" @BeforeTemplate",
" String before(String str) {",
" Refaster.anyOf();",
" return Refaster.anyOf(str);",
" }",
"}")
.addOutputLines(
"out/A.java",
"import com.google.errorprone.refaster.Refaster;",
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
"",
"class A {",
" @BeforeTemplate",
" String before(String str) {",
" Refaster.anyOf();",
" return str;",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -5,17 +5,15 @@ import static java.util.function.Function.identity;
import static java.util.function.Predicate.not;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
import com.google.errorprone.CodeTransformer;
import com.google.errorprone.ErrorProneFlags;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -67,19 +65,24 @@ public final class RefasterCheckTest {
"Primitive",
"Reactor",
"RxJava2Adapter",
"RxJavaCompletableToReactor",
"RxJavaFlowableToReactor",
"RxJavaMaybeToReactor",
"RxJavaObservableToReactor",
"RxJavaSingleToReactor",
"RxJavaToReactor",
"RxJavaUnwrap",
"Stream",
"String",
"TestNGToAssertJ",
"Time");
"Time",
"WebClient");
/**
* Matches the parts of the fully-qualified name of a template class that should be removed in
* order to produce the associated {@link #TEMPLATE_GROUPS template group name}.
*/
private static final Pattern TEMPLATE_FQCN_TRIM_FOR_GROUP_NAME =
Pattern.compile(".*\\.|Templates\\$.*");
/** All Refaster templates on the classpath, indexed by their name. */
private static final ImmutableListMultimap<String, CodeTransformer> ALL_CODE_TRANSFORMERS =
RefasterCheck.loadAllCodeTransformers();
/**
* A mapping from template group names to associated template names.
*
@@ -87,13 +90,18 @@ public final class RefasterCheckTest {
* templates, while the keys correspond to the associated top-level "aggregator" classes.
*/
private static final ImmutableSetMultimap<String, String> TEMPLATES_BY_GROUP =
indexTemplateNamesByGroup(ALL_CODE_TRANSFORMERS.keySet());
indexTemplateNamesByGroup(RefasterCheck.ALL_CODE_TRANSFORMERS.get().keySet());
/** Returns every known template group name as a parameterized test argument. */
@SuppressWarnings("UnusedMethod" /* Used as a `@MethodSource`. */)
private static Stream<Arguments> templateGroupsUnderTest() {
// XXX: Drop the filter once we have added tests for AssertJ!
return TEMPLATES_BY_GROUP.keySet().stream().filter(not("AssertJ"::equals)).map(Arguments::of);
return TEMPLATES_BY_GROUP.keySet().stream()
.filter(not("AssertJ"::equals))
.filter(not("Immutable"::equals))
.filter(not("Reactor"::equals))
.filter(not("RxJava2Adapter"::equals))
.map(Arguments::of);
}
/**
@@ -104,7 +112,10 @@ public final class RefasterCheckTest {
// XXX: Drop the filter once we have added tests for AssertJ!
return TEMPLATES_BY_GROUP.entries().stream()
.filter(e -> !"AssertJ".equals(e.getKey()))
.map(e -> Arguments.of(e.getKey(), e.getValue()));
.filter(e -> !"AssertJ".contains(e.getKey()))
.filter(e -> !"Immutable".contains(e.getKey()))
.filter(e -> !"Immutable".equals(e.getKey()))
.map(e -> arguments(e.getKey(), e.getValue()));
}
/**
@@ -112,10 +123,10 @@ public final class RefasterCheckTest {
* for all of the {@link #TEMPLATE_GROUPS}.
*
* <p>This test is just as much about ensuring that {@link #TEMPLATE_GROUPS} is exhaustive, so
* that in turn {@link #testReplacement}'s coverage is exhaustive.
* that in turn {@link #replacement}'s coverage is exhaustive.
*/
@Test
public void testLoadAllCodeTransformers() {
void loadAllCodeTransformers() {
assertThat(TEMPLATES_BY_GROUP.keySet()).hasSameElementsAs(TEMPLATE_GROUPS);
}
@@ -123,9 +134,9 @@ public final class RefasterCheckTest {
* Verifies for each of the {@link #TEMPLATE_GROUPS} that the associated code transformers have
* the desired effect.
*/
@ParameterizedTest
@MethodSource("templateGroupsUnderTest")
public void testReplacement(String group) {
@ParameterizedTest
void replacement(String group) {
verifyRefactoring(group, namePattern(group));
}
@@ -136,9 +147,10 @@ public final class RefasterCheckTest {
* com.google.errorprone.refaster.Refaster#anyOf} branches are tested. Idem for {@link
* com.google.errorprone.refaster.annotation.BeforeTemplate} methods in case there are multiple .
*/
@ParameterizedTest
@Disabled
@MethodSource("templatesUnderTest")
public void testCoverage(String group, String template) {
@ParameterizedTest
void coverage(String group, String template) {
assertThatCode(() -> verifyRefactoring(group, namePattern(group, template)))
.withFailMessage(
"Template %s does not affect the tests for group %s; is it tested?", template, group)
@@ -171,10 +183,7 @@ public final class RefasterCheckTest {
private BugCheckerRefactoringTestHelper createRestrictedRefactoringTestHelper(
String namePattern) {
return BugCheckerRefactoringTestHelper.newInstance(
new RefasterCheck(
ErrorProneFlags.fromMap(ImmutableMap.of("Refaster:NamePattern", namePattern)),
ALL_CODE_TRANSFORMERS),
getClass());
return BugCheckerRefactoringTestHelper.newInstance(RefasterCheck.class, getClass())
.setArgs("-XepOpt:Refaster:NamePattern=" + namePattern);
}
}

View File

@@ -8,7 +8,7 @@ public final class RequestMappingAnnotationCheckTest {
CompilationTestHelper.newInstance(RequestMappingAnnotationCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",

View File

@@ -9,10 +9,10 @@ public final class Slf4jLogStatementCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(Slf4jLogStatementCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new Slf4jLogStatementCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(Slf4jLogStatementCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -92,7 +92,7 @@ public final class Slf4jLogStatementCheckTest {
// XXX: Drop what's unused.
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",

View File

@@ -9,10 +9,10 @@ public final class SpringMvcAnnotationCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(SpringMvcAnnotationCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new SpringMvcAnnotationCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(SpringMvcAnnotationCheck.class, getClass());
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -59,7 +59,7 @@ public final class SpringMvcAnnotationCheckTest {
}
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",

View File

@@ -10,16 +10,16 @@ public final class StaticImportCheckTest {
private final CompilationTestHelper compilationTestHelper =
CompilationTestHelper.newInstance(StaticImportCheck.class, getClass());
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(new StaticImportCheck(), getClass());
BugCheckerRefactoringTestHelper.newInstance(StaticImportCheck.class, getClass());
@Test
public void testCandidateMethodsAreNotRedundant() {
void candidateMethodsAreNotRedundant() {
assertThat(StaticImportCheck.STATIC_IMPORT_CANDIDATE_METHODS.keySet())
.doesNotContainAnyElementsOf(StaticImportCheck.STATIC_IMPORT_CANDIDATE_CLASSES);
}
@Test
public void testIdentification() {
void identification() {
compilationTestHelper
.addSourceLines(
"A.java",
@@ -77,7 +77,7 @@ public final class StaticImportCheckTest {
}
@Test
public void testReplacement() {
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",

View File

@@ -0,0 +1,34 @@
package tech.picnic.errorprone.bugpatterns;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
public final class StringIsEmptyCheckTest {
private final BugCheckerRefactoringTestHelper refactoringTestHelper =
BugCheckerRefactoringTestHelper.newInstance(StringIsEmptyCheck.class, getClass());
@Test
void replacement() {
refactoringTestHelper
.addInputLines(
"in/A.java",
"class A {",
" void replaceEquals() {",
" String s = \"\";",
" boolean b = s.equals(\"\");",
" }",
"}")
.addOutputLines(
"out/A.java",
"class A {",
" void replaceEquals() {",
" String s = \"\";",
" boolean b = s.isEmpty();",
" }",
"}")
.doTest(BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH);
}
}

View File

@@ -0,0 +1,103 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.base.Predicates.containsPattern;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
public final class TimeZoneUsageCheckTest {
private final CompilationTestHelper compilationHelper =
CompilationTestHelper.newInstance(TimeZoneUsageCheck.class, getClass())
.expectErrorMessage(
"X",
containsPattern(
"Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone"));
@Test
void identification() {
compilationHelper
.addSourceLines(
"A.java",
"import static java.time.ZoneOffset.UTC;",
"",
"import java.time.Clock;",
"import java.time.Duration;",
"import java.time.Instant;",
"import java.time.LocalDate;",
"import java.time.LocalDateTime;",
"import java.time.LocalTime;",
"import java.time.ZoneId;",
"",
"class A {",
" void m() {",
" Clock clock = Clock.fixed(Instant.EPOCH, UTC);",
" clock.instant();",
" clock.millis();",
" Clock.offset(clock, Duration.ZERO);",
" Clock.tick(clock, Duration.ZERO);",
"",
" // BUG: Diagnostic matches: X",
" Clock.systemUTC();",
" // BUG: Diagnostic matches: X",
" Clock.systemDefaultZone();",
" // BUG: Diagnostic matches: X",
" Clock.system(UTC);",
" // BUG: Diagnostic matches: X",
" Clock.tickMillis(UTC);",
" // BUG: Diagnostic matches: X",
" Clock.tickMinutes(UTC);",
" // BUG: Diagnostic matches: X",
" Clock.tickSeconds(UTC);",
" // BUG: Diagnostic matches: X",
" clock.getZone();",
" // BUG: Diagnostic matches: X",
" clock.withZone(UTC);",
"",
" // BUG: Diagnostic matches: X",
" Instant.now();",
" // This is equivalent to `clock.instant()`, which is fine.",
" Instant.now(clock);",
"",
" // BUG: Diagnostic matches: X",
" LocalDate.now();",
" // BUG: Diagnostic matches: X",
" LocalDate.now(clock);",
" // BUG: Diagnostic matches: X",
" LocalDate.now(UTC);",
"",
" // BUG: Diagnostic matches: X",
" LocalDateTime.now();",
" // BUG: Diagnostic matches: X",
" LocalDateTime.now(clock);",
" // BUG: Diagnostic matches: X",
" LocalDateTime.now(UTC);",
"",
" // BUG: Diagnostic matches: X",
" LocalTime.now();",
" // BUG: Diagnostic matches: X",
" LocalTime.now(clock);",
" // BUG: Diagnostic matches: X",
" LocalTime.now(UTC);",
" }",
"",
" abstract class ForwardingClock extends Clock {",
" private final Clock clock;",
"",
" ForwardingClock(Clock clock) {",
" this.clock = clock;",
" }",
"",
" @Override",
" public ZoneId getZone() {",
" return clock.getZone();",
" }",
"",
" @Override",
" public Clock withZone(ZoneId zone) {",
" return clock.withZone(zone);",
" }",
" }",
"}")
.doTest();
}
}

View File

@@ -44,6 +44,12 @@ final class AssertJOptionalTemplatesTest implements RefasterTemplateTestCase {
assertThat(Optional.of(4)).isPresent().hasValue(4));
}
ImmutableSet<AbstractAssert<?, ?>> testAbstractOptionalAssertContainsSame() {
return ImmutableSet.of(
assertThat(Optional.of(1)).get().isSameAs(1),
assertThat(Optional.of(2)).isPresent().isSameAs(2));
}
AbstractAssert<?, ?> testAssertThatOptionalHasValueMatching() {
return assertThat(Optional.of("foo").filter(String::isEmpty)).isPresent();
}

View File

@@ -40,6 +40,11 @@ final class AssertJOptionalTemplatesTest implements RefasterTemplateTestCase {
assertThat(Optional.of(4)).hasValue(4));
}
ImmutableSet<AbstractAssert<?, ?>> testAbstractOptionalAssertContainsSame() {
return ImmutableSet.of(
assertThat(Optional.of(1)).containsSame(1), assertThat(Optional.of(2)).containsSame(2));
}
AbstractAssert<?, ?> testAssertThatOptionalHasValueMatching() {
return assertThat(Optional.of("foo")).get().matches(String::isEmpty);
}

View File

@@ -83,18 +83,12 @@ final class DoubleStreamTemplatesTest implements RefasterTemplateTestCase {
DoubleStream.of(2).filter(n -> n > 2).findAny().isPresent());
}
ImmutableSet<Boolean> testDoubleStreamAllMatch() {
boolean testDoubleStreamAllMatch() {
DoublePredicate pred = i -> i > 0;
return ImmutableSet.of(
DoubleStream.of(1).noneMatch(pred.negate()),
!DoubleStream.of(2).anyMatch(pred.negate()),
DoubleStream.of(3).filter(pred.negate()).findAny().isEmpty());
return DoubleStream.of(1).noneMatch(pred.negate());
}
ImmutableSet<Boolean> testDoubleStreamAllMatch2() {
return ImmutableSet.of(
DoubleStream.of(1).noneMatch(n -> !(n > 1)),
!DoubleStream.of(2).anyMatch(n -> !(n > 2)),
DoubleStream.of(3).filter(n -> !(n > 3)).findAny().isEmpty());
boolean testDoubleStreamAllMatch2() {
return DoubleStream.of(1).noneMatch(n -> !(n > 1));
}
}

View File

@@ -82,18 +82,12 @@ final class DoubleStreamTemplatesTest implements RefasterTemplateTestCase {
DoubleStream.of(1).anyMatch(n -> n > 1), DoubleStream.of(2).anyMatch(n -> n > 2));
}
ImmutableSet<Boolean> testDoubleStreamAllMatch() {
boolean testDoubleStreamAllMatch() {
DoublePredicate pred = i -> i > 0;
return ImmutableSet.of(
DoubleStream.of(1).allMatch(pred),
DoubleStream.of(2).allMatch(pred),
DoubleStream.of(3).allMatch(pred));
return DoubleStream.of(1).allMatch(pred);
}
ImmutableSet<Boolean> testDoubleStreamAllMatch2() {
return ImmutableSet.of(
DoubleStream.of(1).allMatch(n -> n > 1),
DoubleStream.of(2).allMatch(n -> n > 2),
DoubleStream.of(3).allMatch(n -> n > 3));
boolean testDoubleStreamAllMatch2() {
return DoubleStream.of(1).allMatch(n -> n > 1);
}
}

View File

@@ -7,38 +7,15 @@ import java.util.Objects;
import java.util.stream.Stream;
final class EqualityTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(Objects.class);
}
ImmutableSet<Boolean> testPrimitiveOrReferenceEquality() {
return ImmutableSet.of(
Objects.equals(true, false),
Objects.equals((byte) 0, (byte) 1),
Objects.equals((short) 0, (short) 1),
Objects.equals(0, 1),
Objects.equals(0L, 1L),
Objects.equals(0F, 1F),
Objects.equals(0.0, 1.0),
Objects.equals(Boolean.TRUE, Boolean.FALSE),
Objects.equals(Byte.valueOf((byte) 0), Byte.valueOf((byte) 1)),
Objects.equals(Short.valueOf((short) 0), Short.valueOf((short) 1)),
Objects.equals(Integer.valueOf(0), Integer.valueOf(1)),
Objects.equals(Long.valueOf(0L), Long.valueOf(1L)),
Objects.equals(Float.valueOf(0F), Float.valueOf(1F)),
Objects.equals(Double.valueOf(0.0), Double.valueOf(1.0)),
RoundingMode.UP.equals(RoundingMode.DOWN),
Objects.equals(RoundingMode.UP, RoundingMode.DOWN),
!Objects.equals(true, false),
!Objects.equals((byte) 0, (byte) 1),
!Objects.equals((short) 0, (short) 1),
!Objects.equals(0, 1),
!Objects.equals(0L, 1L),
!Objects.equals(0F, 1F),
!Objects.equals(0.0, 1.0),
!Objects.equals(Boolean.TRUE, Boolean.FALSE),
!Objects.equals(Byte.valueOf((byte) 0), Byte.valueOf((byte) 1)),
!Objects.equals(Short.valueOf((short) 0), Short.valueOf((short) 1)),
!Objects.equals(Integer.valueOf(0), Integer.valueOf(1)),
!Objects.equals(Long.valueOf(0L), Long.valueOf(1L)),
!Objects.equals(Float.valueOf(0F), Float.valueOf(1F)),
!Objects.equals(Double.valueOf(0.0), Double.valueOf(1.0)),
!RoundingMode.UP.equals(RoundingMode.DOWN),
!Objects.equals(RoundingMode.UP, RoundingMode.DOWN));
}

View File

@@ -7,38 +7,15 @@ import java.util.Objects;
import java.util.stream.Stream;
final class EqualityTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(Objects.class);
}
ImmutableSet<Boolean> testPrimitiveOrReferenceEquality() {
return ImmutableSet.of(
true == false,
(byte) 0 == (byte) 1,
(short) 0 == (short) 1,
0 == 1,
0L == 1L,
0F == 1F,
0.0 == 1.0,
Objects.equals(Boolean.TRUE, Boolean.FALSE),
Objects.equals(Byte.valueOf((byte) 0), Byte.valueOf((byte) 1)),
Objects.equals(Short.valueOf((short) 0), Short.valueOf((short) 1)),
Objects.equals(Integer.valueOf(0), Integer.valueOf(1)),
Objects.equals(Long.valueOf(0L), Long.valueOf(1L)),
Objects.equals(Float.valueOf(0F), Float.valueOf(1F)),
Objects.equals(Double.valueOf(0.0), Double.valueOf(1.0)),
RoundingMode.UP == RoundingMode.DOWN,
RoundingMode.UP == RoundingMode.DOWN,
true != false,
(byte) 0 != (byte) 1,
(short) 0 != (short) 1,
0 != 1,
0L != 1L,
0F != 1F,
0.0 != 1.0,
!Objects.equals(Boolean.TRUE, Boolean.FALSE),
!Objects.equals(Byte.valueOf((byte) 0), Byte.valueOf((byte) 1)),
!Objects.equals(Short.valueOf((short) 0), Short.valueOf((short) 1)),
!Objects.equals(Integer.valueOf(0), Integer.valueOf(1)),
!Objects.equals(Long.valueOf(0L), Long.valueOf(1L)),
!Objects.equals(Float.valueOf(0F), Float.valueOf(1F)),
!Objects.equals(Double.valueOf(0.0), Double.valueOf(1.0)),
RoundingMode.UP != RoundingMode.DOWN,
RoundingMode.UP != RoundingMode.DOWN);
}

View File

@@ -33,25 +33,20 @@ final class ImmutableListMultimapTemplatesTest implements RefasterTemplateTestCa
ImmutableSet<ImmutableMultimap<String, Integer>> testEmptyImmutableListMultimap() {
return ImmutableSet.of(
ImmutableListMultimap.<String, Integer>builder().build(),
ImmutableMultimap.<String, Integer>builder().build(),
ImmutableMultimap.of());
ImmutableListMultimap.<String, Integer>builder().build(), ImmutableMultimap.of());
}
ImmutableSet<ImmutableMultimap<String, Integer>> testPairToImmutableListMultimap() {
return ImmutableSet.of(
ImmutableListMultimap.<String, Integer>builder().put("foo", 1).build(),
ImmutableMultimap.<String, Integer>builder().put("bar", 2).build(),
ImmutableMultimap.of("baz", 3));
ImmutableMultimap.of("bar", 2));
}
ImmutableList<ImmutableMultimap<String, Integer>> testEntryToImmutableListMultimap() {
return ImmutableList.of(
ImmutableListMultimap.<String, Integer>builder().put(Map.entry("foo", 1)).build(),
Stream.of(Map.entry("foo", 1))
.collect(toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue)),
ImmutableMultimap.<String, Integer>builder().put(Map.entry("foo", 1)).build(),
ImmutableMultimap.of(Map.entry("foo", 1).getKey(), Map.entry("foo", 1).getValue()));
.collect(toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue)));
}
ImmutableList<ImmutableMultimap<String, Integer>> testIterableToImmutableListMultimap() {
@@ -69,12 +64,6 @@ final class ImmutableListMultimapTemplatesTest implements RefasterTemplateTestCa
.collect(toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue)),
ImmutableMultimap.copyOf(ImmutableListMultimap.of("foo", 1)),
ImmutableMultimap.copyOf(ImmutableListMultimap.of("foo", 1).entries()),
ImmutableMultimap.<String, Integer>builder()
.putAll(ImmutableListMultimap.of("foo", 1))
.build(),
ImmutableMultimap.<String, Integer>builder()
.putAll(ImmutableListMultimap.of("foo", 1).entries())
.build(),
ImmutableMultimap.copyOf(Iterables.cycle(Map.entry("foo", 1))));
}
@@ -105,7 +94,8 @@ final class ImmutableListMultimapTemplatesTest implements RefasterTemplateTestCa
.collect(
flatteningToImmutableListMultimap(
Map.Entry::getKey, e -> e.getValue().stream().map(Math::toIntExact))),
Multimaps.asMap((Multimap<String, Long>) ImmutableSetMultimap.of("bar", 2L)).entrySet()
Multimaps.asMap((Multimap<String, Long>) ImmutableSetMultimap.of("bar", 2L))
.entrySet()
.stream()
.collect(
flatteningToImmutableListMultimap(

View File

@@ -32,21 +32,15 @@ final class ImmutableListMultimapTemplatesTest implements RefasterTemplateTestCa
}
ImmutableSet<ImmutableMultimap<String, Integer>> testEmptyImmutableListMultimap() {
return ImmutableSet.of(
ImmutableListMultimap.of(), ImmutableListMultimap.of(), ImmutableListMultimap.of());
return ImmutableSet.of(ImmutableListMultimap.of(), ImmutableListMultimap.of());
}
ImmutableSet<ImmutableMultimap<String, Integer>> testPairToImmutableListMultimap() {
return ImmutableSet.of(
ImmutableListMultimap.of("foo", 1),
ImmutableListMultimap.of("bar", 2),
ImmutableListMultimap.of("baz", 3));
return ImmutableSet.of(ImmutableListMultimap.of("foo", 1), ImmutableListMultimap.of("bar", 2));
}
ImmutableList<ImmutableMultimap<String, Integer>> testEntryToImmutableListMultimap() {
return ImmutableList.of(
ImmutableListMultimap.of(Map.entry("foo", 1).getKey(), Map.entry("foo", 1).getValue()),
ImmutableListMultimap.of(Map.entry("foo", 1).getKey(), Map.entry("foo", 1).getValue()),
ImmutableListMultimap.of(Map.entry("foo", 1).getKey(), Map.entry("foo", 1).getValue()),
ImmutableListMultimap.of(Map.entry("foo", 1).getKey(), Map.entry("foo", 1).getValue()));
}
@@ -60,8 +54,6 @@ final class ImmutableListMultimapTemplatesTest implements RefasterTemplateTestCa
ImmutableListMultimap.copyOf(Iterables.cycle(Map.entry("foo", 1))),
ImmutableListMultimap.copyOf(ImmutableListMultimap.of("foo", 1)),
ImmutableListMultimap.copyOf(ImmutableListMultimap.of("foo", 1)),
ImmutableListMultimap.copyOf(ImmutableListMultimap.of("foo", 1)),
ImmutableListMultimap.copyOf(ImmutableListMultimap.of("foo", 1).entries()),
ImmutableListMultimap.copyOf(Iterables.cycle(Map.entry("foo", 1))));
}

View File

@@ -56,8 +56,7 @@ final class ImmutableListTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<ImmutableList<Integer>> testStreamToImmutableList() {
return ImmutableSet.of(
ImmutableList.copyOf(Stream.of(1).iterator()),
ImmutableList.copyOf(Stream.of(2).iterator()),
Stream.of(3).collect(collectingAndThen(toList(), ImmutableList::copyOf)));
Stream.of(2).collect(collectingAndThen(toList(), ImmutableList::copyOf)));
}
ImmutableList<Integer> testImmutableListAsList() {

View File

@@ -54,9 +54,7 @@ final class ImmutableListTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<ImmutableList<Integer>> testStreamToImmutableList() {
return ImmutableSet.of(
Stream.of(1).collect(toImmutableList()),
Stream.of(2).collect(toImmutableList()),
Stream.of(3).collect(toImmutableList()));
Stream.of(1).collect(toImmutableList()), Stream.of(2).collect(toImmutableList()));
}
ImmutableList<Integer> testImmutableListAsList() {

View File

@@ -42,8 +42,7 @@ final class ImmutableMultisetTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<ImmutableMultiset<Integer>> testStreamToImmutableMultiset() {
return ImmutableSet.of(
ImmutableMultiset.copyOf(Stream.of(1).iterator()),
ImmutableMultiset.copyOf(Stream.of(2)::iterator),
Stream.of(3).collect(collectingAndThen(toList(), ImmutableMultiset::copyOf)));
Stream.of(2).collect(collectingAndThen(toList(), ImmutableMultiset::copyOf)));
}
ImmutableMultiset<Integer> testImmutableMultisetCopyOfImmutableMultiset() {

View File

@@ -39,9 +39,7 @@ final class ImmutableMultisetTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<ImmutableMultiset<Integer>> testStreamToImmutableMultiset() {
return ImmutableSet.of(
Stream.of(1).collect(toImmutableMultiset()),
Stream.of(2).collect(toImmutableMultiset()),
Stream.of(3).collect(toImmutableMultiset()));
Stream.of(1).collect(toImmutableMultiset()), Stream.of(2).collect(toImmutableMultiset()));
}
ImmutableMultiset<Integer> testImmutableMultisetCopyOfImmutableMultiset() {

View File

@@ -72,7 +72,8 @@ final class ImmutableSetMultimapTemplatesTest implements RefasterTemplateTestCas
.collect(
flatteningToImmutableSetMultimap(
Map.Entry::getKey, e -> e.getValue().stream().map(Math::toIntExact))),
Multimaps.asMap((Multimap<String, Long>) ImmutableSetMultimap.of("bar", 2L)).entrySet()
Multimaps.asMap((Multimap<String, Long>) ImmutableSetMultimap.of("bar", 2L))
.entrySet()
.stream()
.collect(
flatteningToImmutableSetMultimap(

View File

@@ -54,10 +54,9 @@ final class ImmutableSetTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<ImmutableSet<Integer>> testStreamToImmutableSet() {
return ImmutableSet.of(
ImmutableSet.copyOf(Stream.of(1).iterator()),
ImmutableSet.copyOf(Stream.of(2)::iterator),
Stream.of(3).distinct().collect(toImmutableSet()),
Stream.of(4).collect(collectingAndThen(toList(), ImmutableSet::copyOf)),
Stream.of(5).collect(collectingAndThen(toSet(), ImmutableSet::copyOf)));
Stream.of(2).distinct().collect(toImmutableSet()),
Stream.of(3).collect(collectingAndThen(toList(), ImmutableSet::copyOf)),
Stream.of(4).collect(collectingAndThen(toSet(), ImmutableSet::copyOf)));
}
ImmutableSet<Integer> testImmutableSetCopyOfImmutableSet() {

View File

@@ -55,8 +55,7 @@ final class ImmutableSetTemplatesTest implements RefasterTemplateTestCase {
Stream.of(1).collect(toImmutableSet()),
Stream.of(2).collect(toImmutableSet()),
Stream.of(3).collect(toImmutableSet()),
Stream.of(4).collect(toImmutableSet()),
Stream.of(5).collect(toImmutableSet()));
Stream.of(4).collect(toImmutableSet()));
}
ImmutableSet<Integer> testImmutableSetCopyOfImmutableSet() {

View File

@@ -61,7 +61,6 @@ final class ImmutableSortedMultisetTemplatesTest implements RefasterTemplateTest
ImmutableSet<ImmutableSortedMultiset<Integer>> testStreamToImmutableSortedMultiset() {
return ImmutableSet.of(
ImmutableSortedMultiset.copyOf(Stream.of(1).iterator()),
ImmutableSortedMultiset.copyOf(Stream.of(2)::iterator),
Stream.of(3).collect(collectingAndThen(toList(), ImmutableSortedMultiset::copyOf)));
Stream.of(2).collect(collectingAndThen(toList(), ImmutableSortedMultiset::copyOf)));
}
}

View File

@@ -53,7 +53,6 @@ final class ImmutableSortedMultisetTemplatesTest implements RefasterTemplateTest
ImmutableSet<ImmutableSortedMultiset<Integer>> testStreamToImmutableSortedMultiset() {
return ImmutableSet.of(
Stream.of(1).collect(toImmutableSortedMultiset(naturalOrder())),
Stream.of(2).collect(toImmutableSortedMultiset(naturalOrder())),
Stream.of(3).collect(toImmutableSortedMultiset(naturalOrder())));
Stream.of(2).collect(toImmutableSortedMultiset(naturalOrder())));
}
}

View File

@@ -56,7 +56,6 @@ final class ImmutableSortedSetTemplatesTest implements RefasterTemplateTestCase
ImmutableSet<ImmutableSortedSet<Integer>> testStreamToImmutableSortedSet() {
return ImmutableSet.of(
ImmutableSortedSet.copyOf(Stream.of(1).iterator()),
ImmutableSortedSet.copyOf(Stream.of(2)::iterator),
Stream.of(3).collect(collectingAndThen(toList(), ImmutableSortedSet::copyOf)));
Stream.of(2).collect(collectingAndThen(toList(), ImmutableSortedSet::copyOf)));
}
}

View File

@@ -53,7 +53,6 @@ final class ImmutableSortedSetTemplatesTest implements RefasterTemplateTestCase
ImmutableSet<ImmutableSortedSet<Integer>> testStreamToImmutableSortedSet() {
return ImmutableSet.of(
Stream.of(1).collect(toImmutableSortedSet(naturalOrder())),
Stream.of(2).collect(toImmutableSortedSet(naturalOrder())),
Stream.of(3).collect(toImmutableSortedSet(naturalOrder())));
Stream.of(2).collect(toImmutableSortedSet(naturalOrder())));
}
}

View File

@@ -87,18 +87,12 @@ final class IntStreamTemplatesTest implements RefasterTemplateTestCase {
IntStream.of(2).filter(n -> n > 2).findAny().isPresent());
}
ImmutableSet<Boolean> testIntStreamAllMatch() {
boolean testIntStreamAllMatch() {
IntPredicate pred = i -> i > 0;
return ImmutableSet.of(
IntStream.of(1).noneMatch(pred.negate()),
!IntStream.of(2).anyMatch(pred.negate()),
IntStream.of(3).filter(pred.negate()).findAny().isEmpty());
return IntStream.of(1).noneMatch(pred.negate());
}
ImmutableSet<Boolean> testIntStreamAllMatch2() {
return ImmutableSet.of(
IntStream.of(1).noneMatch(n -> !(n > 1)),
!IntStream.of(2).anyMatch(n -> !(n > 2)),
IntStream.of(3).filter(n -> !(n > 3)).findAny().isEmpty());
boolean testIntStreamAllMatch2() {
return IntStream.of(1).noneMatch(n -> !(n > 1));
}
}

View File

@@ -86,18 +86,12 @@ final class IntStreamTemplatesTest implements RefasterTemplateTestCase {
IntStream.of(1).anyMatch(n -> n > 1), IntStream.of(2).anyMatch(n -> n > 2));
}
ImmutableSet<Boolean> testIntStreamAllMatch() {
boolean testIntStreamAllMatch() {
IntPredicate pred = i -> i > 0;
return ImmutableSet.of(
IntStream.of(1).allMatch(pred),
IntStream.of(2).allMatch(pred),
IntStream.of(3).allMatch(pred));
return IntStream.of(1).allMatch(pred);
}
ImmutableSet<Boolean> testIntStreamAllMatch2() {
return ImmutableSet.of(
IntStream.of(1).allMatch(n -> n > 1),
IntStream.of(2).allMatch(n -> n > 2),
IntStream.of(3).allMatch(n -> n > 3));
boolean testIntStreamAllMatch2() {
return IntStream.of(1).allMatch(n -> n > 1);
}
}

View File

@@ -87,18 +87,12 @@ final class LongStreamTemplatesTest implements RefasterTemplateTestCase {
LongStream.of(2).filter(n -> n > 2).findAny().isPresent());
}
ImmutableSet<Boolean> testLongStreamAllMatch() {
boolean testLongStreamAllMatch() {
LongPredicate pred = i -> i > 0;
return ImmutableSet.of(
LongStream.of(1).noneMatch(pred.negate()),
!LongStream.of(2).anyMatch(pred.negate()),
LongStream.of(3).filter(pred.negate()).findAny().isEmpty());
return LongStream.of(1).noneMatch(pred.negate());
}
ImmutableSet<Boolean> testLongStreamAllMatch2() {
return ImmutableSet.of(
LongStream.of(1).noneMatch(n -> !(n > 1)),
!LongStream.of(2).anyMatch(n -> !(n > 2)),
LongStream.of(3).filter(n -> !(n > 3)).findAny().isEmpty());
boolean testLongStreamAllMatch2() {
return LongStream.of(1).noneMatch(n -> !(n > 1));
}
}

View File

@@ -86,18 +86,12 @@ final class LongStreamTemplatesTest implements RefasterTemplateTestCase {
LongStream.of(1).anyMatch(n -> n > 1), LongStream.of(2).anyMatch(n -> n > 2));
}
ImmutableSet<Boolean> testLongStreamAllMatch() {
boolean testLongStreamAllMatch() {
LongPredicate pred = i -> i > 0;
return ImmutableSet.of(
LongStream.of(1).allMatch(pred),
LongStream.of(2).allMatch(pred),
LongStream.of(3).allMatch(pred));
return LongStream.of(1).allMatch(pred);
}
ImmutableSet<Boolean> testLongStreamAllMatch2() {
return ImmutableSet.of(
LongStream.of(1).allMatch(n -> n > 1),
LongStream.of(2).allMatch(n -> n > 2),
LongStream.of(3).allMatch(n -> n > 3));
boolean testLongStreamAllMatch2() {
return LongStream.of(1).allMatch(n -> n > 1);
}
}

Some files were not shown because too many files have changed in this diff Show More