Compare commits

...

177 Commits

Author SHA1 Message Date
Rick Ossendrijver
7b31e32aee Introduce MonoSingle Refaster rule 2023-06-29 14:40:55 +02:00
Pieter Dirk Soels
08298c48e3 Specify correct Error Prone version
For first build, run with `-Dversion.error-prone-orig=2.20.0`.
2023-06-22 15:34:50 +02:00
Pieter Dirk Soels
c7aa58409c Post rebase fix 2023-06-22 13:29:49 +02:00
Rick Ossendrijver
727bf4ebe1 Format and migration-util/pom.xml version bump 2023-06-22 13:28:02 +02:00
Rick Ossendrijver
aadffd7c97 Add NotMatches part 2023-06-22 13:28:02 +02:00
Rick Ossendrijver
9f0331e7ef Bring branch up to date with new setup 2023-06-22 13:28:01 +02:00
Rick Ossendrijver
1dddb0917c Add things to make the branch work again 2023-06-22 13:28:01 +02:00
Rick Ossendrijver
0362ad27e8 Resolve conflicts after rebasing, updating stuff 2023-06-22 13:28:00 +02:00
Rick Ossendrijver
1a26a23c2a Add templates for RxJava types #timeout(long, TimeUnit) 2023-06-22 13:28:00 +02:00
Rick Ossendrijver
cbea5d9868 Introduce MonoFlatMapIterable 2023-06-22 13:27:59 +02:00
Rick Ossendrijver
9cc62d2c50 Add Reactor templates based on feedback of Enric and Phil 2023-06-22 13:27:58 +02:00
Rick Ossendrijver
b1da6443f7 Removing Mono<Void> -> Completable identity conversion rewrite with then() 2023-06-22 13:27:58 +02:00
Rick Ossendrijver
a0f3a79c79 Add template to improve ImmutableList#copyOf(Flux#toIterable) 2023-06-22 13:27:57 +02:00
Rick Ossendrijver
4f3956b97f Add MonoThenMany template 2023-06-22 13:27:57 +02:00
Rick Ossendrijver
c89c9267c2 Introduce MonoBlock template 2023-06-22 13:27:56 +02:00
Rick Ossendrijver
61e4a360c7 Remove warnings, improve code, and remove XXXsg 2023-06-22 13:27:56 +02:00
Rick Ossendrijver
1f4f4bb0cd Add assorted tests to fix XXXs 2023-06-22 13:27:55 +02:00
Rick Ossendrijver
491d71a8a9 Improve templates after migrating delivery-service 2023-06-22 13:27:55 +02:00
Rick Ossendrijver
c4bfd2cb87 Add FluxSingle template 2023-06-22 13:27:54 +02:00
Rick Ossendrijver
fff86ea618 Add Reactor improvements based on feedback from Enric 2023-06-22 13:27:53 +02:00
Rick Ossendrijver
091f3ac459 Add Refaster templates to optimize Reactor code 2023-06-22 13:27:53 +02:00
Rick Ossendrijver
d9fa33ee58 Rename Templates and add templates for migration 2023-06-22 13:27:52 +02:00
Rick Ossendrijver
05b6aa03df Add Flowable#blockingIterable Refaster template 2023-06-22 13:27:52 +02:00
Rick Ossendrijver
e6ea9fd37e Improve the Single#never template 2023-06-22 13:27:51 +02:00
Rick Ossendrijver
6a43edcd41 Add Single#never() template 2023-06-22 13:27:51 +02:00
Rick Ossendrijver
12af1e767c Cleanup, sorting, moving, tests 2023-06-22 13:27:50 +02:00
Rick Ossendrijver
edebc1a7d2 Add templates for Gravitee migration 2023-06-22 13:27:50 +02:00
Rick Ossendrijver
3d4ed4daa8 Improve template generic types 2023-06-22 13:27:49 +02:00
Rick Ossendrijver
deb8e9f192 Run textwidth=72 2023-06-22 13:27:48 +02:00
Rick Ossendrijver
218107d486 Many rewrites 2023-06-22 13:27:48 +02:00
Stephan Schroevers
6c406f919f Submit defeat 2023-06-22 13:27:47 +02:00
Rick Ossendrijver
23291e3e76 Add fix for every occurence but is still problem 2023-06-22 13:27:47 +02:00
Rick Ossendrijver
20d787d694 Many rewrite from .as() to RxJava2Adapter.() 2023-06-22 13:27:46 +02:00
Stephan Schroevers
65ca655360 Generalize 2023-06-22 13:27:46 +02:00
Rick Ossendrijver
ebe38e1d0f Push 2023-06-22 13:27:45 +02:00
Rick Ossendrijver
24abb53ef8 Move some templates and temporarily turn off for start of migration 2023-06-22 13:27:44 +02:00
Rick Ossendrijver
a405afb33f Add new templates 2023-06-22 13:27:44 +02:00
Rick Ossendrijver
e86b3b4f8b Add assorted templates to improve the migration 2023-06-22 13:27:43 +02:00
Rick Ossendrijver
bebfb81dd4 Add exttra rule for Flux.array with single element 2023-06-22 13:27:43 +02:00
Rick Ossendrijver
a460591d3f Add extra cases for test.await.assertXXX 2023-06-22 13:27:42 +02:00
Rick Ossendrijver
7eec69cbc3 Add extra templates 2023-06-22 13:27:41 +02:00
Rick Ossendrijver
d4a3083e28 Add extra templates and tests 2023-06-22 13:27:41 +02:00
Rick Ossendrijver
eb482ae5e8 Apply suggestions and add templates 2023-06-22 13:27:40 +02:00
Rick Ossendrijver
6ab90b2ad8 Fix tests and improve imports of the tests 2023-06-22 13:27:40 +02:00
Rick Ossendrijver
0a135c8db0 Add unwrap methods 2023-06-22 13:27:39 +02:00
Rick Ossendrijver
b45e5bf43d Add RxJavaUnwrapTemplates 2023-06-22 13:27:39 +02:00
Rick Ossendrijver
a80ca8b0cd Format for Stephan ;) 2023-06-22 13:27:38 +02:00
Rick Ossendrijver
a8bdaea5d6 Update the templates by removing some flat/concat|maps and adding tests 2023-06-22 13:27:37 +02:00
Rick Ossendrijver
48a463405f Add minor improvements and cleanup 2023-06-22 13:27:37 +02:00
Rick Ossendrijver
623e63b655 Add clean up Refaster templates 2023-06-22 13:27:36 +02:00
Rick Ossendrijver
d48855cbb4 Improve some templates and add one for every RxJava type for assertNoValues() 2023-06-22 13:27:36 +02:00
Rick Ossendrijver
184059a80c Write templates and fix edge cases 2023-06-22 13:27:35 +02:00
Rick Ossendrijver
d9526c886d Improve templates and cleanup tests 2023-06-22 13:27:35 +02:00
Stephan Schroevers
a2ba2a4110 As discussed 2023-06-22 13:27:34 +02:00
Rick Ossendrijver
50beb3aa17 Improve templates so that they match PRP code 2023-06-22 13:27:33 +02:00
Rick Ossendrijver
429e87bec5 Add two examples that work for flatMapCompletable single and flowable 2023-06-22 13:27:33 +02:00
Rick Ossendrijver
6390a02528 YESSSS fix the flatmapCompletable for Single and Flowable 2023-06-22 13:27:32 +02:00
Stephan Schroevers
a790ff0b65 Ideation 2023-06-22 13:27:32 +02:00
Rick Ossendrijver
cc2ce34e2a Quick push 2023-06-22 13:27:31 +02:00
Stephan Schroevers
8c8d6bd466 Pair programming 2023-06-22 13:27:31 +02:00
Rick Ossendrijver
9efb86709e Do more things 2023-06-22 13:27:30 +02:00
Rick Ossendrijver
a2e8f7cc32 Add templates for assertFailure and a MonoNestedPublisher 2023-06-22 13:27:29 +02:00
Rick Ossendrijver
bd7dad5b33 Many tweaks and improvements 2023-06-22 13:27:29 +02:00
Rick Ossendrijver
296ae53d08 Update the templates and format 2023-06-22 13:27:28 +02:00
Rick Ossendrijver
0692fb0c6d Add extra case of assertValue with assertComplete 2023-06-22 13:27:28 +02:00
Rick Ossendrijver
af259ce97e Add AssertValue for 4 types 2023-06-22 13:27:27 +02:00
Rick Ossendrijver
6405f5560b Add the test conversions to StepVerifier for Completable 2023-06-22 13:27:27 +02:00
Rick Ossendrijver
ee89694628 Add RxJava test to StepVerifier tests templates 2023-06-22 13:27:26 +02:00
Rick Ossendrijver
2eaa77799a Add import to test output file 2023-06-22 13:27:25 +02:00
Rick Ossendrijver
d9b06d98e4 Add filtering 2023-06-22 13:27:25 +02:00
Rick Ossendrijver
b856e936ed Cleanup code and tests 2023-06-22 13:27:24 +02:00
Rick Ossendrijver
27d262d5ef Add templates and cleanup todos 2023-06-22 13:27:24 +02:00
Rick Ossendrijver
b825d2653f Fix some todos and remove some annotations sadly enough 2023-06-22 13:27:23 +02:00
Rick Ossendrijver
e40f386bd2 Solve XXXs and add tests and templates 2023-06-22 13:27:23 +02:00
Rick Ossendrijver
374aab3b6b Add todos and information 2023-06-22 13:27:22 +02:00
Rick Ossendrijver
8fc432a49a Update many templates and move the MigrationUtil to own module 2023-06-22 13:27:21 +02:00
Rick Ossendrijver
87c7c8772b Fix bug in test 2023-06-22 13:27:21 +02:00
Rick Ossendrijver
d9dd12c058 Some errors in there, but push many new templates 2023-06-22 13:27:20 +02:00
Rick Ossendrijver
5777c510fd Add many templates and tiny improvements. Note: tests are broken now because building against picnic-error-prone 2023-06-22 13:27:20 +02:00
Rick Ossendrijver
4cc885c6e4 Make EPS use the HEAD-SNAPSHOT of Error Prone for CanBeTransformedTo 2023-06-22 13:27:19 +02:00
Rick Ossendrijver
c36850b10a Add templates and tests 2023-06-22 13:27:19 +02:00
Rick Ossendrijver
b707dfa382 Improve the templates and add many tests 2023-06-22 13:27:18 +02:00
Rick Ossendrijver
a481ba3add Turn on extra tests and fix many issues, but leave a few for next time. 2023-06-22 13:27:17 +02:00
Rick Ossendrijver
583705f0cc Small improvements 2023-06-22 13:27:17 +02:00
Rick Ossendrijver
3bfdd2d550 Add todos and some cases 2023-06-22 13:27:16 +02:00
Rick Ossendrijver
a2a684fa0a Add templates and tests 2023-06-22 13:27:16 +02:00
Rick Ossendrijver
439c0ed71f Add some templates 2023-06-22 13:27:15 +02:00
Rick Ossendrijver
37529ac23b Add FlowableZipWith 2023-06-22 13:27:15 +02:00
Stephan Schroevers
03f6929de8 Pair programming 2023-06-22 13:27:14 +02:00
Rick Ossendrijver
d2927feb52 Add todos and implements some templates 2023-06-22 13:27:14 +02:00
Rick Ossendrijver
93c1f85df8 Remove public modifiers from the XXXs and add two templates 2023-06-22 13:27:13 +02:00
Rick Ossendrijver
ef94344325 Improve templates with assorted methods 2023-06-22 13:27:12 +02:00
Rick Ossendrijver
097939c8c6 Remove old ideation on the CanBeCoercedTo problem and an early version of the MyUtil with conversion of io.reactivex.function to java.util.function 2023-06-22 13:27:12 +02:00
Rick Ossendrijver
6c8d71845b Move every template to their respective class and cleanup RxJavaToReactorTemplates.java 2023-06-22 13:27:11 +02:00
Rick Ossendrijver
7662b67b85 Add test templates to the RefasterCheckTest 2023-06-22 13:27:11 +02:00
Stephan Schroevers
95972a8441 Fix it 2023-06-22 13:27:10 +02:00
Rick Ossendrijver
f0f20702dd Quick commit 2023-06-22 13:27:10 +02:00
Rick Ossendrijver
fe5abe0bec Add the testFlowableCombineLatest 2023-06-22 13:27:09 +02:00
Rick Ossendrijver
254c5bc6a5 Add some templates like fromCallable and FromAction and fromFuture 2023-06-22 13:27:09 +02:00
Rick Ossendrijver
951bad0b03 Add some templates with Amb and add the RxJavaMaybeToReactor file 2023-06-22 13:27:08 +02:00
Rick Ossendrijver
24b2d60c82 Add Templates for the RxJava types that we want to migrate to Reactor 2023-06-22 13:27:07 +02:00
Rick Ossendrijver
5738f87d5b Update the ordering of the Templates and the tests to be in alphabetical order 2023-06-22 13:27:07 +02:00
Rick Ossendrijver
c0ea2c2e51 Remove some warnings 2023-06-22 13:27:06 +02:00
Rick Ossendrijver
3a6416bcdc Try to fix the tests 2023-06-22 13:27:06 +02:00
Rick Ossendrijver
6bd3ae5f3d Add 1/4 templates for Flowable.concatWith 2023-06-22 13:27:05 +02:00
Stephan Schroevers
b7bc2e7581 One more 2023-06-22 13:27:05 +02:00
Stephan Schroevers
73af34f075 Ideation 2023-06-22 13:27:04 +02:00
Rick Ossendrijver
53e9088225 Fix typo 2023-06-22 13:27:04 +02:00
Rick Ossendrijver
3c4bf15c73 Update templates and fix some tests for the new templates and reorder some 2023-06-22 13:27:03 +02:00
Stephan Schroevers
7548ede38f WIP 2023-06-22 13:27:02 +02:00
Rick Ossendrijver
cfaae68a9f Add some examples because im not sure how it works now 2023-06-22 13:27:02 +02:00
Rick Ossendrijver
de9defd58f Add some tests for the new templates 2023-06-22 13:27:01 +02:00
Stephan Schroevers
c66eb42357 Pair programming 2023-06-22 13:27:01 +02:00
Rick Ossendrijver
62ce7c26de Improve some comments and add an extra template 2023-06-22 13:27:00 +02:00
Rick Ossendrijver
fdf202812e Update templates and add a few commented templates to discuss with Stephan 2023-06-22 13:27:00 +02:00
Rick Ossendrijver
33b3d44fe8 Add tests for added templates 2023-06-22 13:26:59 +02:00
Rick Ossendrijver
59e1debdab Change order of functions and add a failing one 2023-06-22 13:26:59 +02:00
Rick Ossendrijver
323138c1d7 Fix last part of test 2023-06-22 13:26:58 +02:00
Rick Ossendrijver
a963e2e887 Do some renaming and improve almost all tests 2023-06-22 13:26:57 +02:00
Stephan Schroevers
299d964e4a Pair programming 2023-06-22 13:26:57 +02:00
Stephan Schroevers
a8c9f1ecc8 Fix it 2023-06-22 13:26:56 +02:00
Rick Ossendrijver
cf450783e3 Improve the templates 2023-06-22 13:26:56 +02:00
Rick Ossendrijver
c7901bc5c7 Update some of the Templates 2023-06-22 13:26:55 +02:00
Rick Ossendrijver
d44d03f9b1 Add RxJavaToReactorTemplates class with Input and Output Test files. 2023-06-22 13:26:55 +02:00
Picnic-Bot
2837a04433 Upgrade New Relic Java Agent 8.3.0 -> 8.4.0 (#690)
See:
- https://github.com/newrelic/newrelic-java-agent/releases/tag/v8.4.0
- https://github.com/newrelic/newrelic-java-agent/compare/v8.3.0...v8.4.0
2023-06-22 11:55:19 +02:00
Picnic-Bot
74222e8fa5 Upgrade Arcmutate 1.0.5 -> 1.1.0 (#692) 2023-06-22 09:25:43 +02:00
Stephan Schroevers
dc36ff2c0b [maven-release-plugin] prepare for next development iteration 2023-06-21 21:15:38 +02:00
Stephan Schroevers
09208aa49a [maven-release-plugin] prepare release v0.12.0 2023-06-21 21:15:38 +02:00
Stephan Schroevers
b81ec973a1 Upgrade Error Prone 2.19.1 -> 2.20.0 (#685)
Summary of key changes:
- The `MissingRefasterAnnotation` check was contributed to Error Prone,
  and so is deleted here (multiple checks with the same name are not
  supported).
- Similarly, Error Prone now supports the `-XepAllSuggestionsAsWarnings`
  flag out of the box. So the `ErrorProneFork` class is deleted, as it
  has currently no further use.

While there, include a tweak to `run-mutation-tests.sh`.

Fixes #686.

See:
- https://github.com/google/error-prone/releases/tag/v2.20.0
- https://github.com/google/error-prone/compare/v2.19.1...v2.20.0
- https://github.com/PicnicSupermarket/error-prone/compare/v2.19.1-picnic-1...v2.20.0-picnic-1
2023-06-20 15:52:26 +02:00
Picnic-Bot
8fb57b5bab Upgrade actions/upload-artifact v3.1.1 -> v3.1.2 (#664)
See:
- https://github.com/actions/upload-artifact/releases/tag/v3.1.2
2023-06-20 09:01:33 +02:00
Picnic-Bot
f4aaa5852c Upgrade dawidd6/action-download-artifact v2.24.2 -> v2.27.0 (#669)
See:
- https://github.com/dawidd6/action-download-artifact/compare/v2.26.1...v2.27.0
- https://github.com/dawidd6/action-download-artifact/compare/v2.26.0...v2.26.1
- https://github.com/dawidd6/action-download-artifact/compare/v2.25.0...v2.26.0
- https://github.com/dawidd6/action-download-artifact/compare/v2.24.4...v2.25.0
- https://github.com/dawidd6/action-download-artifact/compare/v2.24.3...v2.24.4
- https://github.com/dawidd6/action-download-artifact/compare/v2.24.2...v2.24.3
2023-06-19 11:54:34 +02:00
Picnic-Bot
2148b7ede4 Upgrade actions/upload-pages-artifact v1.0.5 -> v1.0.9 (#665)
See:
- https://github.com/actions/upload-pages-artifact/releases/tag/v1.0.9
- https://github.com/actions/upload-pages-artifact/releases/tag/v1.0.8
- https://github.com/actions/upload-pages-artifact/releases/tag/v1.0.7
- https://github.com/actions/upload-pages-artifact/releases/tag/v1.0.6
2023-06-19 11:30:48 +02:00
Picnic-Bot
b2320779e7 Upgrade actions/configure-pages v2.1.3 -> v3.0.6 (#673)
See:
- https://github.com/actions/configure-pages/releases/tag/v3.0.6
- https://github.com/actions/configure-pages/releases/tag/v3.0.5
- https://github.com/actions/configure-pages/releases/tag/v3.0.4
- https://github.com/actions/configure-pages/releases/tag/v3.0.3
- https://github.com/actions/configure-pages/releases/tag/v3.0.2
- https://github.com/actions/configure-pages/releases/tag/v3.0.1
- https://github.com/actions/configure-pages/releases/tag/v3.0.0
2023-06-19 11:13:20 +02:00
Picnic-Bot
ef0d65d360 Upgrade actions/deploy-pages v1.2.8 -> v2.0.2 (#674)
See:
- https://github.com/actions/deploy-pages/releases/tag/v2.0.2
- https://github.com/actions/deploy-pages/releases/tag/v2.0.1
- https://github.com/actions/deploy-pages/releases/tag/v2.0.0
2023-06-19 11:01:54 +02:00
Picnic-Bot
d29fde8856 Upgrade actions/checkout v3.1.0 -> v3.5.3 (#667)
See:
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v353
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v352
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v351
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v350
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v340
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v330
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v320
2023-06-19 09:18:01 +02:00
Picnic-Bot
524c7efb48 Upgrade actions/deploy-pages v1.2.3 -> v1.2.8 (#663)
See:
- https://github.com/actions/deploy-pages/releases/tag/v1.2.8
- https://github.com/actions/deploy-pages/releases/tag/v1.2.7
- https://github.com/actions/deploy-pages/releases/tag/v1.2.6
- https://github.com/actions/deploy-pages/releases/tag/v1.2.5
- https://github.com/actions/deploy-pages/releases/tag/v1.2.4
2023-06-19 08:56:31 +02:00
Picnic-Bot
a62acfd7b5 Upgrade Project Reactor 2022.0.7 -> 2022.0.8 (#683)
See:
- https://github.com/reactor/reactor/releases/tag/2022.0.8
- https://github.com/reactor/reactor/compare/2022.0.7...2022.0.8
2023-06-16 16:16:06 +02:00
Picnic-Bot
c40e1d6691 Upgrade actions/setup-java v3.8.0 -> v3.11.0 (#668)
See:
- https://github.com/actions/setup-java/releases/tag/v3.9.0
- https://github.com/actions/setup-java/releases/tag/v3.10.0
- https://github.com/actions/setup-java/releases/tag/v3.11.0
2023-06-16 15:35:04 +02:00
Picnic-Bot
57a22bf9de Upgrade Swagger 2.2.11 -> 2.2.12 (#684)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.12
- https://github.com/swagger-api/swagger-core/compare/v2.2.11...v2.2.12
2023-06-16 15:12:15 +02:00
Picnic-Bot
ec982fe011 Upgrade AutoService 1.1.0 -> 1.1.1 (#682)
See:
- https://github.com/google/auto/releases/tag/auto-service-1.1.1
- https://github.com/google/auto/compare/auto-service-1.1.0...auto-service-1.1.1
2023-06-14 12:35:41 +02:00
Picnic-Bot
1860e24e65 Upgrade Guava 32.0.0-jre -> 32.0.1-jre (#677)
See:
- https://github.com/google/guava/releases/tag/v32.0.1
- https://github.com/google/guava/compare/v32.0.0...v32.0.1
2023-06-12 19:04:31 +02:00
Picnic-Bot
cce248c306 Upgrade Surefire 3.1.0 -> 3.1.2 (#666)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20SUREFIRE%20AND%20fixVersion%20%3E%203.1.0%20AND%20fixVersion%20%3C%3D%203.1.2
- https://github.com/apache/maven-surefire/releases/tag/surefire-3.1.2
- https://github.com/apache/maven-surefire/compare/surefire-3.1.0...surefire-3.1.2
2023-06-12 11:56:20 +02:00
Picnic-Bot
96aca8ea2b Upgrade versions-maven-plugin 2.15.0 -> 2.16.0 (#678)
See:
- https://github.com/mojohaus/versions/releases/tag/2.16.0
- https://github.com/mojohaus/versions-maven-plugin/compare/2.15.0...2.16.0
2023-06-10 14:21:16 +02:00
Picnic-Bot
70d2bf9016 Upgrade license-maven-plugin 2.0.1 -> 2.1.0 (#671)
See:
- https://github.com/mojohaus/license-maven-plugin/releases/tag/2.1.0
- https://github.com/mojohaus/license-maven-plugin/compare/2.0.1...2.1.0
2023-06-08 14:25:34 +02:00
Rick Ossendrijver
cee3c58d07 Configure Renovate to pin GitHub Action digests (#675) 2023-06-08 10:23:05 +02:00
Picnic-Bot
c141ebe05d Upgrade swagger-annotations 2.2.10 -> 2.2.11 (#657)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.11
- https://github.com/swagger-api/swagger-core/compare/v2.2.10...v2.2.11
2023-06-07 11:40:15 +02:00
Picnic-Bot
f5a8c412af Upgrade Byte Buddy 1.14.4 -> 1.14.5 (#658)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.5
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.4...byte-buddy-1.14.5
2023-06-07 10:48:54 +02:00
Picnic-Bot
93440826ed Upgrade Arcmutate 1.0.4 -> 1.0.5 (#656) 2023-06-07 08:02:44 +02:00
Picnic-Bot
80dcae319e Upgrade Jackson 2.15.1 -> 2.15.2 (#652)
See:
- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.15.2
- https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.15.1...jackson-bom-2.15.2
2023-06-06 16:30:09 +02:00
Picnic-Bot
7371d03db8 Upgrade Truth 1.1.3 -> 1.1.4 (#653)
See:
- https://github.com/google/truth/releases/tag/v1.1.4
- https://github.com/google/truth/compare/release_1_1_3...v1.1.4
2023-06-06 09:47:09 +02:00
Picnic-Bot
c6b98e61ff Upgrade maven-release-plugin 3.0.0 -> 3.0.1 (#662)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MRELEASE%20AND%20fixVersion%20%3E%203.0.0%20AND%20fixVersion%20%3C%3D%203.0.1
- https://github.com/apache/maven-release/releases/tag/maven-release-3.0.1
- https://github.com/apache/maven-release/compare/maven-release-3.0.0...maven-release-3.0.1
2023-06-06 08:34:35 +02:00
Picnic-Bot
ce8f9f60c8 Upgrade New Relic Java Agent 8.2.0 -> 8.3.0 (#659)
See:
- https://github.com/newrelic/newrelic-java-agent/releases/tag/v8.3.0
- https://github.com/newrelic/newrelic-java-agent/compare/v8.2.0...v8.3.0
2023-06-06 07:50:01 +02:00
Picnic-Bot
cdf27acd9c Upgrade Checker Framework Annotations 3.34.0 -> 3.35.0 (#660)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.35.0
- https://github.com/typetools/checker-framework/compare/checker-framework-3.34.0...checker-framework-3.35.0
2023-06-06 07:40:05 +02:00
Picnic-Bot
49e5fd1273 Upgrade extra-enforcer-rules 1.6.2 -> 1.7.0 (#661)
See:
- https://github.com/mojohaus/extra-enforcer-rules/releases/tag/1.7.0
- https://github.com/mojohaus/extra-enforcer-rules/compare/1.6.2...1.7.0
2023-06-06 07:20:46 +02:00
Picnic-Bot
5085db25c0 Upgrade Guava 31.1-jre -> 32.0.0-jre (#650)
See:
- https://guava.dev/releases/32.0.0-jre/api/diffs/
- https://github.com/google/guava/releases/tag/v32.0.0
- https://github.com/google/guava/compare/v31.1...v32.0.0
2023-05-30 16:49:11 +02:00
Picnic-Bot
125d24bc13 Upgrade Checkstyle 10.11.0 -> 10.12.0 (#651)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.12.0
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.11.0...checkstyle-10.12.0
2023-05-30 08:44:15 +02:00
Picnic-Bot
ea02144bff Upgrade pitest-maven-plugin 1.14.0 -> 1.14.1 (#648)
See:
- https://github.com/hcoles/pitest/releases/tag/1.14.1
- https://github.com/hcoles/pitest/compare/1.14.0...1.14.1
2023-05-26 10:13:47 +02:00
Luke Prananta
cc2c49edc3 Introduce OptionalOrElseGet Refaster rule (#527)
While there, introduce `IsLikelyTrivialComputation` Matcher.
2023-05-26 09:19:51 +02:00
Stephan Schroevers
8bc878a05c Improve AbstractMatcherTestChecker (#599)
These changes enable testing of a wider range of `Matcher` implementations. In
a nutshell:
- The `Matcher` under test is now passed `VisitorState` instances with an
  accurate `TreePath`.
- The `Matcher` under test is no longer consulted for method select and cast
  type expressions, mirroring Refaster behavior.
2023-05-26 08:29:26 +02:00
Picnic-Bot
b399ef8910 Upgrade Spring Boot 2.7.11 -> 2.7.12 (#637)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v2.7.12
- https://github.com/spring-projects/spring-boot/compare/v2.7.11...v2.7.12
2023-05-24 19:03:38 +02:00
Picnic-Bot
7dba641a79 Upgrade pitest-junit5-plugin 1.1.2 -> 1.2.0 (#638)
See https://github.com/pitest/pitest-junit5-plugin/compare/1.1.2...1.2.0
2023-05-24 17:20:57 +02:00
Picnic-Bot
da1528129f Upgrade maven-source-plugin 3.2.1 -> 3.3.0 (#643)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MSOURCES%20AND%20fixVersion%20%3E%203.2.1%20AND%20fixVersion%20%3C%3D%203.3.0
- https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.1...maven-source-plugin-3.3.0
2023-05-24 17:08:20 +02:00
Picnic-Bot
d0bbc5c14b Upgrade pitest-maven-plugin 1.13.1 -> 1.14.0 (#633)
See:
- https://github.com/hcoles/pitest/releases/tag/1.13.2
- https://github.com/hcoles/pitest/releases/tag/1.14.0
- https://github.com/hcoles/pitest/compare/1.13.1...1.14.0
2023-05-24 16:30:06 +02:00
Picnic-Bot
da532c79c7 Upgrade Pitest Git plugins 1.0.10 -> 1.0.11 (#634) 2023-05-24 16:10:58 +02:00
Picnic-Bot
04e2900a48 Upgrade git-commit-id-maven-plugin 5.0.0 -> 6.0.0 (#635)
See:
- https://github.com/git-commit-id/git-commit-id-maven-plugin/releases/tag/v6.0.0
- https://github.com/git-commit-id/git-commit-id-maven-plugin/compare/v5.0.0...v6.0.0
2023-05-24 16:00:11 +02:00
Picnic-Bot
f097095398 Upgrade AutoService 1.0.1 -> 1.1.0 (#647)
See:
- https://github.com/google/auto/releases/tag/auto-service-1.0.2
- https://github.com/google/auto/releases/tag/auto-service-1.1.0
- https://github.com/google/auto/compare/auto-service-1.0.1...auto-service-1.1.0
2023-05-24 13:25:40 +02:00
Philip Leonard
c53a3f64b6 Qualify non-static TestMode imports across BugChecker test classes (#630)
Prefer non-static imports and qualification of
`BugCheckerRefactoringTestHelper#TestMode` members across bug checker test
classes.
2023-05-23 09:31:59 +02:00
Picnic-Bot
cdfcecc204 Upgrade maven-dependency-plugin 3.5.0 -> 3.6.0 (#646)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MDEP%20AND%20fixVersion%20%3E%203.5.0%20AND%20fixVersion%20%3C%3D%203.6.0
- https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.5.0...maven-dependency-plugin-3.6.0
2023-05-23 08:43:31 +02:00
Picnic-Bot
4f4b3fb865 Upgrade maven-checkstyle-plugin 3.2.2 -> 3.3.0 (#645)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MCHECKSTYLE%20AND%20fixVersion%20%3E%203.2.2%20AND%20fixVersion%20%3C%3D%203.3.0
- https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.2.2...maven-checkstyle-plugin-3.3.0
2023-05-23 07:32:41 +02:00
Picnic-Bot
cce36d24df Upgrade TestNG 7.7.1 -> 7.8.0 (#639)
See:
- https://github.com/testng-team/testng/releases/tag/7.8.0
- https://github.com/testng-team/testng/compare/7.7.1...7.8.0
2023-05-22 08:39:36 +02:00
Picnic-Bot
3bbae43da8 Upgrade swagger-annotations 1.6.10 -> 1.6.11 (#629)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v1.6.11
- https://github.com/swagger-api/swagger-core/compare/v1.6.10...v1.6.11
2023-05-17 13:18:26 +02:00
Picnic-Bot
3217a6974d Upgrade swagger-annotations 2.2.9 -> 2.2.10 (#628)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.10
- https://github.com/swagger-api/swagger-core/compare/v2.2.9...v2.2.10
2023-05-17 12:19:30 +02:00
Picnic-Bot
7b71e4ea3e Upgrade Jackson 2.15.0 -> 2.15.1 (#631)
See:
- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.15.1
- https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.15.0...jackson-bom-2.15.1
2023-05-17 11:28:55 +02:00
Stephan Schroevers
3df6dc957d [maven-release-plugin] prepare for next development iteration 2023-05-16 17:38:46 +02:00
Stephan Schroevers
a1ecd816ff [maven-release-plugin] prepare release v0.11.1 2023-05-16 17:38:46 +02:00
Stephan Schroevers
03af05889a Make ThirdPartyLibrary compatible with -source 8 (#627)
When targeting Java 8, `unnamedModule` is not properly initialized,
causing an NPE when trying to load a class from it. In that context
`noModule` should be used instead.

Fixes #626.
2023-05-16 09:53:52 +02:00
Stephan Schroevers
f52a93cc4e [maven-release-plugin] prepare for next development iteration 2023-05-14 17:09:09 +02:00
66 changed files with 10503 additions and 427 deletions

View File

@@ -31,11 +31,11 @@ jobs:
# additionally enabling all checks defined in this project and any Error
# Prone checks available only from other artifact repositories.
- name: Check out code
uses: actions/checkout@v3.1.0
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
persist-credentials: false
- name: Set up JDK
uses: actions/setup-java@v3.8.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
java-version: ${{ matrix.jdk }}
distribution: ${{ matrix.distribution }}

View File

@@ -22,11 +22,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out code
uses: actions/checkout@v3.1.0
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
persist-credentials: false
- name: Set up JDK
uses: actions/setup-java@v3.8.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
java-version: 17.0.7
distribution: temurin

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out code
uses: actions/checkout@v3.1.0
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
persist-credentials: false
- uses: ruby/setup-ruby@v1.126.0
@@ -20,7 +20,7 @@ jobs:
working-directory: ./website
bundler-cache: true
- name: Configure Github Pages
uses: actions/configure-pages@v2.1.3
uses: actions/configure-pages@f156874f8191504dae5b037505266ed5dda6c382 # v3.0.6
- name: Generate documentation
run: ./generate-docs.sh
- name: Build website with Jekyll
@@ -32,7 +32,7 @@ jobs:
# "Refaster rules" terminology on our website and in the code.
run: bundle exec htmlproofer --disable_external true --check-external-hash false ./_site
- name: Upload website as artifact
uses: actions/upload-pages-artifact@v1.0.5
uses: actions/upload-pages-artifact@66b63f4a7de003f4f00cc8e9af4b83b8f2abdb96 # v1.0.9
with:
path: ./website/_site
deploy:
@@ -48,4 +48,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1.2.3
uses: actions/deploy-pages@ee48c7b82e077d7b8ef30b50a719e6a792a50c9a # v2.0.2

View File

@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out code
uses: actions/checkout@v3.1.0
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
persist-credentials: false
- name: Run OpenSSF Scorecard analysis

View File

@@ -12,12 +12,12 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out code
uses: actions/checkout@v3.1.0
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
fetch-depth: 2
persist-credentials: false
- name: Set up JDK
uses: actions/setup-java@v3.8.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
java-version: 17.0.7
distribution: temurin
@@ -32,7 +32,7 @@ jobs:
- name: Aggregate Pitest reports
run: mvn pitest-git:aggregate -DkilledEmoji=":tada:" -DmutantEmoji=":zombie:" -DtrailingText="Mutation testing report by [Pitest](https://pitest.org/). Review any surviving mutants by inspecting the line comments under [_Files changed_](${{ github.event.number }}/files)."
- name: Upload Pitest reports as artifact
uses: actions/upload-artifact@v3.1.1
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: pitest-reports
path: ./target/pit-reports-ci

View File

@@ -20,17 +20,17 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out code
uses: actions/checkout@v3.1.0
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
persist-credentials: false
- name: Set up JDK
uses: actions/setup-java@v3.8.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
java-version: 17.0.7
distribution: temurin
cache: maven
- name: Download Pitest analysis artifact
uses: dawidd6/action-download-artifact@v2.24.2
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: pitest-reports

View File

@@ -16,12 +16,12 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Check out code
uses: actions/checkout@v3.1.0
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
fetch-depth: 0
persist-credentials: false
- name: Set up JDK
uses: actions/setup-java@v3.8.0
uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0
with:
java-version: 17.0.7
distribution: temurin

View File

@@ -1,5 +1,8 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"helpers:pinGitHubActionDigests"
],
"packageRules": [
{
"matchPackagePatterns": [

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.11.0</version>
<version>0.12.1-SNAPSHOT</version>
</parent>
<artifactId>documentation-support</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.11.0</version>
<version>0.12.1-SNAPSHOT</version>
</parent>
<artifactId>error-prone-contrib</artifactId>
@@ -49,9 +49,22 @@
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-support</artifactId>
<artifactId>migration-util</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-compiler</artifactId>
<!-- This dependency is declared only as a hint to Maven that
compilation depends on it; see the `maven-compiler-plugin`'s
`annotationProcessorPaths` configuration below. -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-support</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-test-support</artifactId>
@@ -241,6 +254,11 @@
<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:RefasterRuleCompiler</arg>

View File

@@ -1,59 +0,0 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
import static com.google.errorprone.matchers.Matchers.annotations;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.isType;
import static tech.picnic.errorprone.bugpatterns.util.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.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(
summary = "The Refaster rule contains a method without any Refaster annotations",
link = BUG_PATTERNS_BASE_URL + "MissingRefasterAnnotation",
linkType = CUSTOM,
severity = WARNING,
tags = LIKELY_ERROR)
public final class MissingRefasterAnnotation extends BugChecker implements ClassTreeMatcher {
private static final long serialVersionUID = 1L;
private static final MultiMatcher<Tree, AnnotationTree> REFASTER_ANNOTATION =
annotations(
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")));
/** Instantiates a new {@link MissingRefasterAnnotation} instance. */
public MissingRefasterAnnotation() {}
@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

@@ -4,7 +4,10 @@ import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.suppliers.Supplier;
import com.sun.tools.javac.code.ClassFinder;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.util.Name;
/**
@@ -86,9 +89,15 @@ public enum ThirdPartyLibrary {
private static boolean canLoadClass(String className, VisitorState state) {
ClassFinder classFinder = ClassFinder.instance(state.context);
Symtab symtab = state.getSymtab();
// XXX: Drop support for targeting Java 8 once the oldest supported JDK drops such support.
ModuleSymbol module =
Source.instance(state.context).compareTo(Source.JDK9) < 0
? symtab.noModule
: symtab.unnamedModule;
Name binaryName = state.binaryNameFromClassname(className);
try {
classFinder.loadClass(state.getSymtab().unnamedModule, binaryName);
classFinder.loadClass(module, binaryName);
return true;
} catch (
@SuppressWarnings("java:S1166" /* Not exceptional. */)

View File

@@ -164,6 +164,8 @@ final class CollectionRules {
}
/** Prefer {@link ArrayList#ArrayList(Collection)} over the Guava alternative. */
@SuppressWarnings(
"NonApiType" /* Matching against `List` would unnecessarily constrain the rule. */)
static final class NewArrayListFromCollection<T> {
@BeforeTemplate
ArrayList<T> before(Collection<T> collection) {

View File

@@ -188,6 +188,8 @@ final class ImmutableMapRules {
/**
* Prefer creating an immutable copy of the result of {@link Maps#transformValues(Map,
* com.google.common.base.Function)} over more contrived alternatives.
*
* <p>Additionally, this way it is easier to see that only values are being transformed.
*/
abstract static class TransformMapValuesToImmutableMap<K, V1, V2> {
@Placeholder(allowsIdentity = true)

View File

@@ -8,6 +8,7 @@ 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.NotMatches;
import com.google.errorprone.refaster.annotation.Placeholder;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import java.util.Comparator;
@@ -19,6 +20,7 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
import tech.picnic.errorprone.refaster.matchers.IsLikelyTrivialComputation;
/** Refaster rules related to expressions dealing with {@link Optional}s. */
@OnlineDocumentation
@@ -118,7 +120,7 @@ final class OptionalRules {
/** Prefer {@link Optional#filter(Predicate)} over usage of the ternary operator. */
// XXX: This rule may introduce a compilation error: the `test` expression may reference a
// non-effectively final variable, which is not allowed in the replacement lambda expression.
// Maybe our `Refaster` checker should test `compilesWithFix`?
// Review whether a `@Matcher` can be used to avoid this.
abstract static class TernaryOperatorOptionalPositiveFiltering<T> {
@Placeholder
abstract boolean test(T value);
@@ -138,7 +140,7 @@ final class OptionalRules {
/** Prefer {@link Optional#filter(Predicate)} over usage of the ternary operator. */
// XXX: This rule may introduce a compilation error: the `test` expression may reference a
// non-effectively final variable, which is not allowed in the replacement lambda expression.
// Maybe our `Refaster` checker should test `compilesWithFix`?
// Review whether a `@Matcher` can be used to avoid this.
abstract static class TernaryOperatorOptionalNegativeFiltering<T> {
@Placeholder
abstract boolean test(T value);
@@ -161,6 +163,7 @@ final class OptionalRules {
*/
static final class MapOptionalToBoolean<T> {
@BeforeTemplate
@SuppressWarnings("OptionalOrElseGet" /* Rule is confused by `Refaster#anyOf` usage. */)
boolean before(Optional<T> optional, Function<? super T, Boolean> predicate) {
return optional.map(predicate).orElse(Refaster.anyOf(false, Boolean.FALSE));
}
@@ -224,6 +227,28 @@ final class OptionalRules {
}
}
/**
* Prefer {@link Optional#orElseGet(Supplier)} over {@link Optional#orElse(Object)} if the
* fallback value is not the result of a trivial computation.
*/
// XXX: This rule may introduce a compilation error: the `value` expression may reference a
// non-effectively final variable, which is not allowed in the replacement lambda expression.
// Review whether a `@Matcher` can be used to avoid this.
// XXX: Once `MethodReferenceUsage` is "production ready", replace
// `@NotMatches(IsLikelyTrivialComputation.class)` with `@Matches(RequiresComputation.class)` (and
// reimplement the matcher accordingly).
static final class OptionalOrElseGet<T> {
@BeforeTemplate
T before(Optional<T> optional, @NotMatches(IsLikelyTrivialComputation.class) T value) {
return optional.orElse(value);
}
@AfterTemplate
T after(Optional<T> optional, T value) {
return optional.orElseGet(() -> value);
}
}
/**
* Flatten a stream of {@link Optional}s using {@link Optional#stream()}, rather than using one of
* the more verbose alternatives.
@@ -325,6 +350,9 @@ final class OptionalRules {
Optional<T> before(Optional<T> optional1, Optional<T> optional2) {
// XXX: Note that rewriting the first and third variant will change the code's behavior if
// `optional2` has side-effects.
// XXX: Note that rewriting the first and third variant will introduce a compilation error if
// `optional2` is not effectively final. Review whether a `@Matcher` can be used to avoid
// this.
return Refaster.anyOf(
optional1.map(Optional::of).orElse(optional2),
optional1.map(Optional::of).orElseGet(() -> optional2),

View File

@@ -418,6 +418,22 @@ final class ReactorRules {
}
}
/**
* Don't unnecessarily transform a {@link Mono} to a {@link Flux} before calling {@link
* Mono#single()}.
*/
static final class MonoSingle<T> {
@BeforeTemplate
Mono<T> before(Mono<T> mono) {
return mono.flux().single();
}
@AfterTemplate
Mono<T> after(Mono<T> mono) {
return mono.single();
}
}
/** Don't unnecessarily pass an empty publisher to {@link Flux#switchIfEmpty(Publisher)}. */
static final class FluxSwitchIfEmptyOfEmptyPublisher<T> {
@BeforeTemplate

View File

@@ -0,0 +1,435 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.MoreCollectors.toOptional;
import com.google.common.collect.MoreCollectors;
import com.google.errorprone.refaster.ImportPolicy;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
import com.google.errorprone.refaster.annotation.Placeholder;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import java.time.Duration;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import reactor.test.publisher.PublisherProbe;
/** Refaster templates related to Reactor expressions and statements. */
final class ReactorTemplates {
private ReactorTemplates() {}
/** Prefer {@link Mono#justOrEmpty(Optional)} over more verbose alternatives. */
// XXX: If `optional` is a constant and effectively-final expression then the `Mono.defer` can be
// dropped. Should look into Refaster support for identifying this.
static final class MonoFromOptional<T> {
@BeforeTemplate
Mono<T> before(Optional<T> optional) {
return Refaster.anyOf(
Mono.fromCallable(() -> optional.orElse(null)),
Mono.fromSupplier(() -> optional.orElse(null)));
}
@AfterTemplate
Mono<T> after(Optional<T> optional) {
return Mono.defer(() -> Mono.justOrEmpty(optional));
}
}
// XXX: Fix this after knowing how to add Matches for CanBeCoercedToRunnable.
//
// abstract static class MonoFromRunnable<T> {
// @Placeholder
// abstract boolean test(); // Improve return type here and naming of method.
//
// @BeforeTemplate
// Mono<Void> before(Supplier<T> supplier) {
// return Mono.fromSupplier(() -> test()).then();
// }
//
// @AfterTemplate
// Mono<Void> after(Runnable supplier) {
// return Mono.fromRunnable(supplier);
// }
// }
/** Don't unnecessarily defer {@link Mono#error(Throwable)}. */
static final class MonoDeferredError<T> {
@BeforeTemplate
Mono<T> before(Throwable throwable) {
return Mono.defer(() -> Mono.error(throwable));
}
@AfterTemplate
Mono<T> after(Throwable throwable) {
return Mono.error(() -> throwable);
}
}
/** Don't unnecessarily defer {@link Flux#error(Throwable)}. */
static final class FluxDeferredError<T> {
@BeforeTemplate
Flux<T> before(Throwable throwable) {
return Flux.defer(() -> Flux.error(throwable));
}
@AfterTemplate
Flux<T> after(Throwable throwable) {
return Flux.error(() -> throwable);
}
}
/**
* Don't unnecessarily pass {@link Mono#error(Supplier)} a method reference or lambda expression.
*/
// XXX: Drop this rule once the more general rule `AssortedTemplates#SupplierAsSupplier` works
// reliably.
static final class MonoErrorSupplier<T, E extends Throwable> {
@BeforeTemplate
Mono<T> before(Supplier<E> supplier) {
return Mono.error(() -> supplier.get());
}
@AfterTemplate
Mono<T> after(Supplier<E> supplier) {
return Mono.error(supplier);
}
}
/**
* Don't unnecessarily pass {@link Flux#error(Supplier)} a method reference or lambda expression.
*/
// XXX: Drop this rule once the more general rule `AssortedTemplates#SupplierAsSupplier` works
// reliably.
static final class FluxErrorSupplier<T, E extends Throwable> {
@BeforeTemplate
Flux<T> before(Supplier<E> supplier) {
return Flux.error(() -> supplier.get());
}
@AfterTemplate
Flux<T> after(Supplier<E> supplier) {
return Flux.error(supplier);
}
}
/** Prefer {@link Mono#thenReturn(Object)} over more verbose alternatives. */
static final class MonoThenReturn<T, S> {
@BeforeTemplate
Mono<S> before(Mono<T> mono, S object) {
return mono.then(Mono.just(object));
}
@AfterTemplate
Mono<S> after(Mono<T> mono, S object) {
return mono.thenReturn(object);
}
}
/** Don't unnecessarily pass an empty publisher to {@link Mono#switchIfEmpty(Mono)}. */
static final class MonoSwitchIfEmptyOfEmptyPublisher<T> {
@BeforeTemplate
Mono<T> before(Mono<T> mono) {
return mono.switchIfEmpty(Mono.empty());
}
@AfterTemplate
Mono<T> after(Mono<T> mono) {
return mono;
}
}
/** Don't unnecessarily pass an empty publisher to {@link Flux#switchIfEmpty(Publisher)}. */
static final class FluxSwitchIfEmptyOfEmptyPublisher<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux) {
return flux.switchIfEmpty(Refaster.anyOf(Mono.empty(), Flux.empty()));
}
@AfterTemplate
Flux<T> after(Flux<T> flux) {
return flux;
}
}
/** Prefer {@link Flux#concatMap(Function)} over more contrived alternatives. */
static final class FluxConcatMap<T, S> {
@BeforeTemplate
Flux<S> before(Flux<T> flux, Function<? super T, ? extends Publisher<? extends S>> function) {
return Refaster.anyOf(flux.flatMap(function, 1), flux.flatMapSequential(function, 1));
}
@AfterTemplate
Flux<S> after(Flux<T> flux, Function<? super T, ? extends Publisher<? extends S>> function) {
return flux.concatMap(function);
}
}
/**
* Prefer {@link Flux#concatMapIterable(Function)} over {@link Flux#concatMapIterable(Function)},
* as the former has equivalent semantics but a clearer name.
*/
static final class FluxConcatMapIterable<T, S> {
@BeforeTemplate
Flux<S> before(Flux<T> flux, Function<? super T, ? extends Iterable<? extends S>> function) {
return flux.flatMapIterable(function);
}
@AfterTemplate
Flux<S> after(Flux<T> flux, Function<? super T, ? extends Iterable<? extends S>> function) {
return flux.concatMapIterable(function);
}
}
/** Don't unnecessarily call {@link Mono#flux()}. */
static final class MonoFlatMapIterable<T, R> {
@BeforeTemplate
Flux<R> before(Mono<T> mono, Function<? super T, ? extends Iterable<? extends R>> mapper) {
return mono.flux().concatMapIterable(mapper);
}
@AfterTemplate
Flux<R> after(Mono<T> mono, Function<? super T, ? extends Iterable<? extends R>> mapper) {
return mono.flatMapIterable(mapper);
}
}
/**
* Don't use {@link Mono#flatMapMany(Function)} to implicitly convert a {@link Mono} to a {@link
* Flux}.
*/
abstract static class MonoFlatMapToFlux<T, S> {
@Placeholder(allowsIdentity = true)
abstract Mono<S> valueTransformation(@MayOptionallyUse T value);
@BeforeTemplate
Flux<S> before(Mono<T> mono) {
return mono.flatMapMany(v -> valueTransformation(v));
}
@AfterTemplate
Flux<S> after(Mono<T> mono) {
return mono.flatMap(v -> valueTransformation(v)).flux();
}
}
/** Prefer {@link Mono#flux()}} over more contrived alternatives. */
static final class MonoFlux<T> {
@BeforeTemplate
Flux<T> before(Mono<T> mono) {
return Flux.concat(mono);
}
@AfterTemplate
Flux<T> after(Mono<T> mono) {
return mono.flux();
}
}
/** Don't unnecessarily invoke {@link Flux#concat(Publisher)}. */
static final class FluxIdentity<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux) {
return Flux.concat(flux);
}
@AfterTemplate
Flux<T> after(Flux<T> flux) {
return flux;
}
}
/**
* Prefer a collection using {@link MoreCollectors#toOptional()} over more contrived alternatives.
*/
// XXX: Consider creating a plugin which flags/discourages `Mono<Optional<T>>` method return
// types, just as we discourage nullable `Boolean`s and `Optional`s.
static final class MonoCollectToOptional<T> {
@BeforeTemplate
Mono<Optional<T>> before(Mono<T> mono) {
return Refaster.anyOf(
mono.map(Optional::of).defaultIfEmpty(Optional.empty()),
mono.map(Optional::of).switchIfEmpty(Mono.just(Optional.empty())));
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Mono<Optional<T>> after(Mono<T> mono) {
return mono.flux().collect(toOptional());
}
}
/** Prefer {@link PublisherProbe#empty()}} over more verbose alternatives. */
static final class PublisherProbeEmpty<T> {
@BeforeTemplate
PublisherProbe<T> before() {
return Refaster.anyOf(PublisherProbe.of(Mono.empty()), PublisherProbe.of(Flux.empty()));
}
@AfterTemplate
PublisherProbe<T> after() {
return PublisherProbe.empty();
}
}
/** Prefer {@link Mono#as(Function)} when creating a {@link StepVerifier}. */
static final class StepVerifierFromMono<T> {
@BeforeTemplate
StepVerifier.FirstStep<? extends T> before(Mono<T> mono) {
return StepVerifier.create(mono);
}
@AfterTemplate
StepVerifier.FirstStep<? extends T> after(Mono<T> mono) {
return mono.as(StepVerifier::create);
}
}
/** Prefer {@link Flux#as(Function)} when creating a {@link StepVerifier}. */
static final class StepVerifierFromFlux<T> {
@BeforeTemplate
StepVerifier.FirstStep<? extends T> before(Flux<T> flux) {
return StepVerifier.create(flux);
}
@AfterTemplate
StepVerifier.FirstStep<? extends T> after(Flux<T> flux) {
return flux.as(StepVerifier::create);
}
}
/** Don't unnecessarily call {@link StepVerifier.Step#expectNext(Object[])}. */
static final class StepVerifierStepExpectNextEmpty<T> {
@BeforeTemplate
@SuppressWarnings("unchecked")
StepVerifier.Step<T> before(StepVerifier.Step<T> step) {
return step.expectNext();
}
@AfterTemplate
StepVerifier.Step<T> after(StepVerifier.Step<T> step) {
return step;
}
}
/** Prefer {@link StepVerifier.Step#expectNext(Object)} over more verbose alternatives. */
static final class StepVerifierStepExpectNext<T> {
@BeforeTemplate
StepVerifier.Step<T> before(StepVerifier.Step<T> step, T object) {
return Refaster.anyOf(
step.expectNextMatches(e -> e.equals(object)), step.expectNextMatches(object::equals));
}
@AfterTemplate
StepVerifier.Step<T> after(StepVerifier.Step<T> step, T object) {
return step.expectNext(object);
}
}
/** Prefer {@link StepVerifier.LastStep#verifyComplete()} over more verbose alternatives. */
static final class StepVerifierLastStepVerifyComplete {
@BeforeTemplate
Duration before(StepVerifier.LastStep step) {
return step.expectComplete().verify();
}
@AfterTemplate
Duration after(StepVerifier.LastStep step) {
return step.verifyComplete();
}
}
/** Prefer {@link StepVerifier.LastStep#verifyError()} over more verbose alternatives. */
static final class StepVerifierLastStepVerifyError {
@BeforeTemplate
Duration before(StepVerifier.LastStep step) {
return step.expectError().verify();
}
@AfterTemplate
Duration after(StepVerifier.LastStep step) {
return step.verifyError();
}
}
/** Prefer {@link StepVerifier.LastStep#verifyError(Class)} over more verbose alternatives. */
static final class StepVerifierLastStepVerifyErrorClass<T extends Throwable> {
@BeforeTemplate
Duration before(StepVerifier.LastStep step, Class<T> clazz) {
return step.expectError(clazz).verify();
}
@AfterTemplate
Duration after(StepVerifier.LastStep step, Class<T> clazz) {
return step.verifyError(clazz);
}
}
/**
* Prefer {@link StepVerifier.LastStep#verifyErrorMatches(Predicate)} over more verbose
* alternatives.
*/
static final class StepVerifierLastStepVerifyErrorMatches {
@BeforeTemplate
Duration before(StepVerifier.LastStep step, Predicate<Throwable> predicate) {
return step.expectErrorMatches(predicate).verify();
}
@AfterTemplate
Duration after(StepVerifier.LastStep step, Predicate<Throwable> predicate) {
return step.verifyErrorMatches(predicate);
}
}
/**
* Prefer {@link StepVerifier.LastStep#verifyErrorSatisfies(Consumer)} over more verbose
* alternatives.
*/
static final class StepVerifierLastStepVerifyErrorSatisfies {
@BeforeTemplate
Duration before(StepVerifier.LastStep step, Consumer<Throwable> consumer) {
return step.expectErrorSatisfies(consumer).verify();
}
@AfterTemplate
Duration after(StepVerifier.LastStep step, Consumer<Throwable> consumer) {
return step.verifyErrorSatisfies(consumer);
}
}
/**
* Prefer {@link StepVerifier.LastStep#verifyErrorMessage(String)} over more verbose alternatives.
*/
static final class StepVerifierLastStepVerifyErrorMessage {
@BeforeTemplate
Duration before(StepVerifier.LastStep step, String message) {
return step.expectErrorMessage(message).verify();
}
@AfterTemplate
Duration after(StepVerifier.LastStep step, String message) {
return step.verifyErrorMessage(message);
}
}
/**
* Prefer {@link StepVerifier.LastStep#verifyTimeout(Duration)} over more verbose alternatives.
*/
static final class StepVerifierLastStepVerifyTimeout {
@BeforeTemplate
Duration before(StepVerifier.LastStep step, Duration duration) {
return step.expectTimeout(duration).verify();
}
@AfterTemplate
Duration after(StepVerifier.LastStep step, Duration duration) {
return step.verifyTimeout(duration);
}
}
}

View File

@@ -20,6 +20,19 @@ import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
final class RxJava2AdapterRules {
private RxJava2AdapterRules() {}
/** 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,525 @@
package tech.picnic.errorprone.refasterrules;
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.time.Duration;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
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 {@link Completable} 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 {
@BeforeTemplate
Completable before(Completable completable) {
return completable.onErrorComplete();
}
@AfterTemplate
Completable after(Completable completable) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(completable).onErrorStop());
}
}
static final class CompletableOnErrorCompletePredicate {
@BeforeTemplate
Completable before(Completable completable, Predicate<? super Throwable> predicate) {
return completable.onErrorComplete(predicate);
}
@AfterTemplate
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)
static final class CompletableTimeoutLongTimeUnit {
@BeforeTemplate
Completable before(Completable completable, long timeout, TimeUnit unit) {
return completable.timeout(timeout, unit);
}
@AfterTemplate
Completable after(Completable completable, long timeout, TimeUnit unit) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(completable)
.timeout(Duration.of(timeout, unit.toChronoUnit())));
}
}
// 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,944 @@
package tech.picnic.errorprone.refasterrules;
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.time.Duration;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
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 {@link Observable} 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)
// Default BackpressureStrategy.BUFFER is set
static final class ObservableTimeoutLongTimeUnit<T> {
@BeforeTemplate
Observable<T> before(Observable<T> observable, long timeout, TimeUnit unit) {
return observable.timeout(timeout, unit);
}
@AfterTemplate
Observable<T> after(Observable<T> observable, long timeout, TimeUnit unit) {
return RxJava2Adapter.fluxToObservable(
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.timeout(Duration.of(timeout, unit.toChronoUnit())));
}
}
// 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 ObservableToFlowable<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
@SuppressWarnings("unchecked")
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,816 @@
package tech.picnic.errorprone.refasterrules;
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.time.Duration;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
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 {@link Single} 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
@SuppressWarnings("Convert2MethodRef")
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)
static final class SingleNever<T> {
@BeforeTemplate
Single<T> before() {
return Single.never();
}
@AfterTemplate
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: Add test -> Works in PRP.
abstract static class SingleOnErrorReturn<T, S extends T> {
@Placeholder
abstract S placeholder(@MayOptionallyUse Throwable throwable);
@BeforeTemplate
Single<T> before(Single<T> single) {
return single.onErrorReturn(t -> placeholder(t));
}
@AfterTemplate
Single<T> after(Single<T> single) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single).onErrorResume(t -> Mono.just(placeholder(t))));
}
}
// 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)
static final class SingleTimeoutLongTimeUnit<T> {
@BeforeTemplate
Single<T> before(Single<T> single, long timeout, TimeUnit unit) {
return single.timeout(timeout, unit);
}
@AfterTemplate
Single<T> after(Single<T> single, long timeout, TimeUnit unit) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single).timeout(Duration.of(timeout, unit.toChronoUnit())));
}
}
// XXX: public final Single timeout(long,TimeUnit,Scheduler)
// XXX: public final Single timeout(long,TimeUnit,Scheduler,SingleSource)
static final class SingleTimeoutLongTimeUnitSingleSource<T> {
@BeforeTemplate
Single<T> before(
Single<T> single, long timeout, TimeUnit unit, SingleSource<? extends T> other) {
return single.timeout(timeout, unit, other);
}
@AfterTemplate
Single<T> after(
Single<T> single, long timeout, TimeUnit unit, SingleSource<? extends T> other) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.timeout(
Duration.of(timeout, unit.toChronoUnit()),
RxJava2Adapter.singleToMono(Single.wrap(other))));
}
}
// 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
@SuppressWarnings("unchecked")
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,495 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.function.Function.identity;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.matchers.IsMethodReferenceOrLambdaHasReturnStatement;
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.CanTransformToTargetType;
import com.google.errorprone.refaster.annotation.NotMatches;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
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.Predicate;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Function;
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. */
final class RxJavaToReactorTemplates {
private RxJavaToReactorTemplates() {}
@SuppressWarnings("NullableProblems")
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;
}
}
@SuppressWarnings("NullableProblems")
static final class MonoToFlowableToMono<T> {
@BeforeTemplate
Mono<T> before(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));
}
@AfterTemplate
Mono<T> after(Mono<T> mono) {
return mono;
}
}
@SuppressWarnings("NullableProblems")
static final class MonoToFlowableToMonoThen<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<Void> before2(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<Void> after(Mono<T> mono) {
return mono.then();
}
}
// XXX: Add test cases
static final class MonoToFlowableToFlux<T> {
@BeforeTemplate
@SuppressWarnings("NullableProblems")
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(
@NotMatches(IsMethodReferenceOrLambdaHasReturnStatement.class) @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<? extends I, ? extends O> before(
@NotMatches(IsMethodReferenceOrLambdaHasReturnStatement.class) @CanTransformToTargetType
io.reactivex.functions.Function<? extends I, ? extends O> function) {
return RxJavaReactorMigrationUtil.toJdkFunction(function);
}
@AfterTemplate
java.util.function.Function<? extends I, ? extends O> after(
java.util.function.Function<? extends I, ? extends 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();
}
}
/** Remove unnecessary {@code Mono#then}. */
static final class MonoThen<T, S> {
@BeforeTemplate
Mono<S> before(Mono<T> mono, Mono<S> other) {
return mono.then().then(other);
}
@AfterTemplate
Mono<S> after(Mono<T> mono, Mono<S> other) {
return mono.then(other);
}
}
/** Prefer {@link Mono#thenMany(Publisher)} without first calling {@code Mono#then}. */
static final class MonoThenMany<T> {
@BeforeTemplate
Flux<T> before(Mono<T> mono, Publisher<T> publisher) {
return mono.then().thenMany(publisher);
}
@AfterTemplate
Flux<T> after(Mono<T> mono, Publisher<T> publisher) {
return mono.thenMany(publisher);
}
}
/** Remove unnecessary {@code Flux#ignoreElements} */
static final class FluxThen<T> {
@BeforeTemplate
Mono<Void> before(Flux<T> flux) {
return flux.ignoreElements().then();
}
@AfterTemplate
Mono<Void> after(Flux<T> flux) {
return flux.then();
}
}
static final class MonoCollectToImmutableList<T> {
@BeforeTemplate
Mono<List<T>> before(Flux<T> flux) {
return flux.collectList();
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Mono<List<T>> after(Flux<T> flux) {
return flux.collect(toImmutableList());
}
}
static final class MonoDefaultIfEmpty<T> {
@BeforeTemplate
Mono<T> before(Mono<T> mono, T item) {
return mono.switchIfEmpty(Mono.just(item));
}
@AfterTemplate
Mono<T> after(Mono<T> mono, T item) {
return mono.defaultIfEmpty(item);
}
}
static final class FluxDefaultIfEmpty<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux, T item) {
return flux.switchIfEmpty(Flux.just(item));
}
@AfterTemplate
Flux<T> after(Flux<T> flux, T item) {
return flux.defaultIfEmpty(item);
}
}
/** Remove unnecessary {@code Mono#then} */
static final class MonoVoid {
@BeforeTemplate
Mono<Void> before(Mono<Void> mono) {
return mono.then();
}
@AfterTemplate
Mono<Void> after(Mono<Void> mono) {
return mono;
}
}
static final class FlatMapFluxFromArray<T> {
@BeforeTemplate
@SuppressWarnings("unchecked")
Flux<Object> before(Flux<T[]> flux) {
return flux.flatMap(Flowable::fromArray);
}
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
@AfterTemplate
Flux<Object> after(Flux<T[]> flux) {
return flux.flatMap(Flux::fromArray);
}
}
// XXX: Move this to correct class later on.
static final class FluxToImmutableSet<T> {
@BeforeTemplate
Mono<ImmutableSet<T>> before(Flux<T> flux) {
return flux.collect(toImmutableList()).map(ImmutableSet::copyOf);
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Mono<ImmutableSet<T>> after(Flux<T> flux) {
return flux.collect(toImmutableSet());
}
}
static final class MonoBlock<T> {
@BeforeTemplate
T before(Mono<T> mono, Duration timeout) {
return mono.timeout(timeout).block();
}
@AfterTemplate
T after(Mono<T> mono, Duration timeout) {
return mono.block(timeout);
}
}
ImmutableSet<Flux<String>> testConcatMapIterable() {
return ImmutableSet.of(
Flux.just(ImmutableList.of("1")).flatMap(Flux::fromIterable),
Flux.just(ImmutableList.of("2")).concatMap(Flux::fromIterable));
}
static final class FluxCollectBlock<T> {
@BeforeTemplate
ImmutableList<T> before(Flux<T> flux) {
return ImmutableList.copyOf(flux.toIterable());
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
ImmutableList<T> after(Flux<T> flux) {
return flux.collect(toImmutableList()).block();
}
}
static final class ConcatMapIterable<T> {
@BeforeTemplate
Flux<T> before(Flux<? extends Iterable<? extends T>> flux) {
return Refaster.anyOf(flux.flatMap(Flux::fromIterable), flux.concatMap(Flux::fromIterable));
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Flux<T> after(Flux<? extends Iterable<? extends T>> flux) {
return flux.concatMapIterable(identity());
}
}
static final class CollectToImmutableMap<K, V> {
@BeforeTemplate
Mono<Map<K, V>> before(Flux<V> flux, Function<? super V, ? extends K> keyExtractor) {
return flux.collectMap(keyExtractor);
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.STATIC_IMPORT_ALWAYS)
Mono<Map<K, V>> after(Flux<V> flux, Function<? super V, ? extends K> keyExtractor) {
return flux.collect(toImmutableMap(keyExtractor, identity()));
}
}
// /** Remove unnecessary {@code Flux#next}. This is not *strictly* behavior preserving. */
// static final class FluxSingle<T> {
// @BeforeTemplate
// Mono<T> before(Flux<T> flux) {
// return flux.next().single();
// }
//
// @AfterTemplate
// Mono<T> after(Flux<T> flux) {
// return flux.single();
// }
// }
// 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,441 @@
package tech.picnic.errorprone.refasterrules;
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;
/** Templates to clean up nested lambdas. */
@SuppressWarnings({"Convert2MethodRef", "NoFunctionalReturnType"})
final class RxJavaToReactorUnwrapTemplates {
private RxJavaToReactorUnwrapTemplates() {}
// XXX: Add test
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
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
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
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("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("unchecked")
abstract static class SingleOnResumeUnwrapLambdaSpecialCase<T, R> {
@Placeholder
abstract Mono<R> placeholder(@MayOptionallyUse Throwable input);
@BeforeTemplate
java.util.function.Function<? extends Throwable, ? extends Mono<? extends R>> before() {
return e ->
RxJava2Adapter.singleToMono(
RxJavaReactorMigrationUtil.<Throwable, Single<R>>toJdkFunction(
t -> RxJava2Adapter.monoToSingle(placeholder(t)))
.apply(e));
}
@AfterTemplate
java.util.function.Function<Throwable, ? extends Mono<? extends R>> after() {
return v -> placeholder(v);
}
}
// XXX: Add test
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
abstract static class FlowableFlatMapCompletableUnwrapLambda<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>)
(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(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, CompletableSource>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
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)));
}
}
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)));
}
}
abstract static class UnwrapCompletableExtendsMono<T, R> {
@Placeholder
abstract Mono<? extends R> 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(
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
.apply(e)));
}
@AfterTemplate
java.util.function.Function<T, Mono<? extends R>> after() {
return v -> placeholder(v);
}
}
// XXX: Add test
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
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
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.
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

@@ -1,8 +1,7 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
@@ -54,6 +53,6 @@ final class AssertJIsNullTest {
" assertThat(\"foo\").isNull();",
" }",
"}")
.doTest(TEXT_MATCH);
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -1,89 +0,0 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.base.Predicates.containsPattern;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class MissingRefasterAnnotationTest {
@Test
void identification() {
CompilationTestHelper.newInstance(MissingRefasterAnnotation.class, getClass())
.expectErrorMessage(
"X",
containsPattern("The Refaster rule contains a method without any Refaster annotations"))
.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 ValidRefasterRule {",
" @BeforeTemplate",
" void unusedPureFunctionCall(Object o) {",
" o.toString();",
" }",
" }",
"",
" static final class NotARefasterRule {",
" @Override",
" public String toString() {",
" return \"This is not a Refaster rule\";",
" }",
" }",
"}")
.doTest();
}
}

View File

@@ -1,8 +1,7 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode.TEXT_MATCH;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
@@ -145,6 +144,6 @@ final class NonEmptyMonoTest {
" Mono.just(2).hasElement();",
" }",
"}")
.doTest(TEXT_MATCH);
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -0,0 +1,192 @@
// package tech.picnic.errorprone.bugpatterns;
//
// import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap;
// 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.ImmutableSet;
// import com.google.common.collect.ImmutableSetMultimap;
// import com.google.errorprone.BugCheckerRefactoringTestHelper;
// import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
// 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;
// import org.junit.jupiter.params.provider.MethodSource;
//
// public final class RefasterCheckTest {
// /** The names of all Refaster template groups defined in this module. */
// private static final ImmutableSet<String> TEMPLATE_GROUPS =
// ImmutableSet.of(
// "AssertJ",
// "AssertJBigDecimal",
// "AssertJBigInteger",
// "AssertJBoolean",
// "AssertJByte",
// "AssertJCharSequence",
// "AssertJDouble",
// "AssertJEnumerable",
// "AssertJFloat",
// "AssertJInteger",
// "AssertJLong",
// "AssertJNumber",
// "AssertJObject",
// "AssertJOptional",
// "AssertJShort",
// "AssertJString",
// "Assorted",
// "BigDecimal",
// "Collection",
// "Comparator",
// "DoubleStream",
// "Equality",
// "ImmutableList",
// "ImmutableListMultimap",
// "ImmutableMap",
// "ImmutableMultiset",
// "ImmutableSet",
// "ImmutableSetMultimap",
// "ImmutableSortedMap",
// "ImmutableSortedMultiset",
// "ImmutableSortedSet",
// "IntStream",
// "JUnit",
// "LongStream",
// "MapEntry",
// "Mockito",
// "Multimap",
// "Null",
// "Optional",
// "Primitive",
// "Reactor",
// "RxJava2Adapter",
// "RxJavaCompletableToReactor",
// "RxJavaFlowableToReactor",
// "RxJavaMaybeToReactor",
// "RxJavaObservableToReactor",
// "RxJavaSingleToReactor",
// "RxJavaToReactor",
// "RxJavaToReactorUnwrap",
// "Stream",
// "String",
// "TestNGToAssertJ",
// "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\\$.*");
// /**
// * A mapping from template group names to associated template names.
// *
// * <p>In effect, the values correspond to nested classes that represent individual Refaster
// * templates, while the keys correspond to the associated top-level "aggregator" classes.
// */
// private static final ImmutableSetMultimap<String, String> TEMPLATES_BY_GROUP =
// 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))
// .filter(not("Immutable"::equals))
// .filter(not("Reactor"::equals))
// .filter(not("RxJava2Adapter"::equals))
// .map(Arguments::of);
// }
//
// /**
// * Returns every known (template group name, template name) pair as a parameterized test
// argument.
// */
// @SuppressWarnings("UnusedMethod" /* Used as a `@MethodSource`. */)
// private static Stream<Arguments> templatesUnderTest() {
// // XXX: Drop the filter once we have added tests for AssertJ!
// return TEMPLATES_BY_GROUP.entries().stream()
// .filter(e -> !"AssertJ".equals(e.getKey()))
// .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()));
// }
//
// /**
// * Verifies that {@link RefasterCheck#loadAllCodeTransformers} finds at least one code
// transformer
// * 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 #replacement}'s coverage is exhaustive.
// */
// @Test
// void loadAllCodeTransformers() {
// assertThat(TEMPLATES_BY_GROUP.keySet()).hasSameElementsAs(TEMPLATE_GROUPS);
// }
//
// /**
// * Verifies for each of the {@link #TEMPLATE_GROUPS} that the associated code transformers have
// * the desired effect.
// */
// @MethodSource("templateGroupsUnderTest")
// @ParameterizedTest
// void replacement(String group) {
// verifyRefactoring(group, namePattern(group));
// }
//
// /**
// * Verifies that all loaded Refaster templates are covered by at least one test.
// *
// * <p>Note that this doesn't guarantee full coverage: this test cannot ascertain that all {@link
// * com.google.errorprone.refaster.Refaster#anyOf} branches are tested. Idem for {@link
// * com.google.errorprone.refaster.annotation.BeforeTemplate} methods in case there are multiple
// .
// */
// @Disabled
// @MethodSource("templatesUnderTest")
// @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)
// .isInstanceOf(AssertionError.class)
// .hasMessageFindingMatch("^(diff|expected):");
// }
//
// private static ImmutableSetMultimap<String, String> indexTemplateNamesByGroup(
// ImmutableSet<String> templateNames) {
// return templateNames.stream()
// .collect(
// toImmutableSetMultimap(
// n -> TEMPLATE_FQCN_TRIM_FOR_GROUP_NAME.matcher(n).replaceAll(""), identity()));
// }
//
// private static String namePattern(String groupName, String excludedTemplate) {
// return "(?!" + Pattern.quote(excludedTemplate) + ')' + namePattern(groupName);
// }
//
// private static String namePattern(String groupName) {
// return Pattern.compile(Pattern.quote(groupName)) + "Templates.*";
// }
//
// private void verifyRefactoring(String groupName, String templateNamePattern) {
// createRestrictedRefactoringTestHelper(templateNamePattern)
// .addInput(groupName + "TemplatesTestInput.java")
// .addOutput(groupName + "TemplatesTestOutput.java")
// .doTest(TestMode.TEXT_MATCH);
// }
//
// private BugCheckerRefactoringTestHelper createRestrictedRefactoringTestHelper(
// String namePattern) {
// return BugCheckerRefactoringTestHelper.newInstance(RefasterCheck.class, getClass())
// .setArgs("-XepOpt:Refaster:NamePattern=" + namePattern);
// }
// }

View File

@@ -119,4 +119,11 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
Optional<String> testOptionalMap() {
return Optional.of(1).stream().map(String::valueOf).findAny();
}
ImmutableSet<String> testOptionalOrElseGet() {
return ImmutableSet.of(
Optional.of("foo").orElse("bar"),
Optional.of("baz").orElse(toString()),
Optional.of("qux").orElse(String.valueOf(true)));
}
}

View File

@@ -112,4 +112,11 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
Optional<String> testOptionalMap() {
return Optional.of(1).map(String::valueOf);
}
ImmutableSet<String> testOptionalOrElseGet() {
return ImmutableSet.of(
Optional.of("foo").orElse("bar"),
Optional.of("baz").orElse(toString()),
Optional.of("qux").orElseGet(() -> String.valueOf(true)));
}
}

View File

@@ -145,6 +145,10 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Mono.<ImmutableList<String>>empty().map(ImmutableList::copyOf));
}
Mono<Integer> testMonoSingle() {
return Mono.just(1).flux().single();
}
ImmutableSet<Flux<Integer>> testFluxSwitchIfEmptyOfEmptyPublisher() {
return ImmutableSet.of(
Flux.just(1).switchIfEmpty(Mono.empty()), Flux.just(2).switchIfEmpty(Flux.empty()));

View File

@@ -150,6 +150,10 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Mono.<ImmutableList<String>>empty());
}
Mono<Integer> testMonoSingle() {
return Mono.just(1).single();
}
ImmutableSet<Flux<Integer>> testFluxSwitchIfEmptyOfEmptyPublisher() {
return ImmutableSet.of(Flux.just(1), Flux.just(2));
}

View File

@@ -0,0 +1,131 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.time.Duration;
import java.util.Optional;
import java.util.function.Supplier;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import reactor.test.publisher.PublisherProbe;
final class ReactorTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<Mono<Integer>> testMonoFromOptional() {
return ImmutableSet.of(
Mono.fromCallable(() -> Optional.of(1).orElse(null)),
Mono.fromSupplier(() -> Optional.of(2).orElse(null)));
}
Mono<Void> testMonoDeferredError() {
return Mono.defer(() -> Mono.error(new IllegalStateException()));
}
Flux<Void> testFluxDeferredError() {
return Flux.defer(() -> Flux.error(new IllegalStateException()));
}
Mono<Void> testMonoErrorSupplier() {
return Mono.error(() -> ((Supplier<RuntimeException>) null).get());
}
Flux<Void> testFluxErrorSupplier() {
return Flux.error(() -> ((Supplier<RuntimeException>) null).get());
}
Mono<String> testMonoThenReturn() {
return Mono.empty().then(Mono.just("foo"));
}
Mono<Integer> testMonoSwitchIfEmptyOfEmptyPublisher() {
return Mono.just(1).switchIfEmpty(Mono.empty());
}
ImmutableSet<Flux<Integer>> testFluxSwitchIfEmptyOfEmptyPublisher() {
return ImmutableSet.of(
Flux.just(1).switchIfEmpty(Mono.empty()), Flux.just(2).switchIfEmpty(Flux.empty()));
}
ImmutableSet<Flux<Integer>> testFluxConcatMap() {
return ImmutableSet.of(
Flux.just(1).flatMap(Mono::just, 1), Flux.just(2).flatMapSequential(Mono::just, 1));
}
Flux<Integer> testFluxConcatMapIterable() {
return Flux.just(1, 2).flatMapIterable(ImmutableList::of);
}
Flux<Integer> testMonoFlatMapIterable() {
return Mono.just(1).flux().concatMapIterable(ImmutableList::of);
}
Flux<String> testMonoFlatMapToFlux() {
return Mono.just("foo").flatMapMany(s -> Mono.just(s + s));
}
Flux<String> testMonoFlux() {
return Flux.concat(Mono.just("foo"));
}
Flux<String> testFluxIdentity() {
return Flux.concat(Flux.just("foo"));
}
ImmutableSet<Mono<Optional<String>>> testMonoCollectToOptional() {
return ImmutableSet.of(
Mono.just("foo").map(Optional::of).defaultIfEmpty(Optional.empty()),
Mono.just("bar").map(Optional::of).switchIfEmpty(Mono.just(Optional.empty())));
}
ImmutableSet<PublisherProbe<Void>> testPublisherProbeEmpty() {
return ImmutableSet.of(PublisherProbe.of(Mono.empty()), PublisherProbe.of(Flux.empty()));
}
StepVerifier.FirstStep<Integer> testStepVerifierFromMono() {
return StepVerifier.create(Mono.just(1));
}
StepVerifier.FirstStep<Integer> testStepVerifierFromFlux() {
return StepVerifier.create(Flux.just(1));
}
StepVerifier.Step<Integer> testStepVerifierStepExpectNextEmpty() {
return StepVerifier.create(Mono.just(0)).expectNext();
}
ImmutableSet<StepVerifier.Step<String>> testStepVerifierStepExpectNext() {
return ImmutableSet.of(
StepVerifier.create(Mono.just("foo")).expectNextMatches(s -> s.equals("bar")),
StepVerifier.create(Mono.just("baz")).expectNextMatches("qux"::equals));
}
Duration testStepVerifierLastStepVerifyComplete() {
return StepVerifier.create(Mono.empty()).expectComplete().verify();
}
Duration testStepVerifierLastStepVerifyError() {
return StepVerifier.create(Mono.empty()).expectError().verify();
}
Duration testStepVerifierLastStepVerifyErrorClass() {
return StepVerifier.create(Mono.empty()).expectError(IllegalArgumentException.class).verify();
}
Duration testStepVerifierLastStepVerifyErrorMatches() {
return StepVerifier.create(Mono.empty())
.expectErrorMatches(IllegalArgumentException.class::equals)
.verify();
}
Duration testStepVerifierLastStepVerifyErrorSatisfies() {
return StepVerifier.create(Mono.empty()).expectErrorSatisfies(t -> {}).verify();
}
Duration testStepVerifierLastStepVerifyErrorMessage() {
return StepVerifier.create(Mono.empty()).expectErrorMessage("foo").verify();
}
Duration testStepVerifierLastStepVerifyTimeout() {
return StepVerifier.create(Mono.empty()).expectTimeout(Duration.ZERO).verify();
}
}

View File

@@ -0,0 +1,130 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.collect.MoreCollectors.toOptional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.time.Duration;
import java.util.Optional;
import java.util.function.Supplier;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import reactor.test.publisher.PublisherProbe;
final class ReactorTemplatesTest implements RefasterTemplateTestCase {
ImmutableSet<Mono<Integer>> testMonoFromOptional() {
return ImmutableSet.of(
Mono.defer(() -> Mono.justOrEmpty(Optional.of(1))),
Mono.defer(() -> Mono.justOrEmpty(Optional.of(2))));
}
Mono<Void> testMonoDeferredError() {
return Mono.error(() -> new IllegalStateException());
}
Flux<Void> testFluxDeferredError() {
return Flux.error(() -> new IllegalStateException());
}
Mono<Void> testMonoErrorSupplier() {
return Mono.error(((Supplier<RuntimeException>) null));
}
Flux<Void> testFluxErrorSupplier() {
return Flux.error(((Supplier<RuntimeException>) null));
}
Mono<String> testMonoThenReturn() {
return Mono.empty().thenReturn("foo");
}
Mono<Integer> testMonoSwitchIfEmptyOfEmptyPublisher() {
return Mono.just(1);
}
ImmutableSet<Flux<Integer>> testFluxSwitchIfEmptyOfEmptyPublisher() {
return ImmutableSet.of(Flux.just(1), Flux.just(2));
}
ImmutableSet<Flux<Integer>> testFluxConcatMap() {
return ImmutableSet.of(Flux.just(1).concatMap(Mono::just), Flux.just(2).concatMap(Mono::just));
}
Flux<Integer> testFluxConcatMapIterable() {
return Flux.just(1, 2).concatMapIterable(ImmutableList::of);
}
Flux<Integer> testMonoFlatMapIterable() {
return Mono.just(1).flatMapIterable(ImmutableList::of);
}
Flux<String> testMonoFlatMapToFlux() {
return Mono.just("foo").flatMap(s -> Mono.just(s + s)).flux();
}
Flux<String> testMonoFlux() {
return Mono.just("foo").flux();
}
Flux<String> testFluxIdentity() {
return Flux.just("foo");
}
ImmutableSet<Mono<Optional<String>>> testMonoCollectToOptional() {
return ImmutableSet.of(
Mono.just("foo").flux().collect(toOptional()),
Mono.just("bar").flux().collect(toOptional()));
}
ImmutableSet<PublisherProbe<Void>> testPublisherProbeEmpty() {
return ImmutableSet.of(PublisherProbe.empty(), PublisherProbe.empty());
}
StepVerifier.FirstStep<Integer> testStepVerifierFromMono() {
return Mono.just(1).as(StepVerifier::create);
}
StepVerifier.FirstStep<Integer> testStepVerifierFromFlux() {
return Flux.just(1).as(StepVerifier::create);
}
StepVerifier.Step<Integer> testStepVerifierStepExpectNextEmpty() {
return StepVerifier.create(Mono.just(0));
}
ImmutableSet<StepVerifier.Step<String>> testStepVerifierStepExpectNext() {
return ImmutableSet.of(
StepVerifier.create(Mono.just("foo")).expectNext("bar"),
StepVerifier.create(Mono.just("baz")).expectNext("qux"));
}
Duration testStepVerifierLastStepVerifyComplete() {
return StepVerifier.create(Mono.empty()).verifyComplete();
}
Duration testStepVerifierLastStepVerifyError() {
return StepVerifier.create(Mono.empty()).verifyError();
}
Duration testStepVerifierLastStepVerifyErrorClass() {
return StepVerifier.create(Mono.empty()).verifyError(IllegalArgumentException.class);
}
Duration testStepVerifierLastStepVerifyErrorMatches() {
return StepVerifier.create(Mono.empty())
.verifyErrorMatches(IllegalArgumentException.class::equals);
}
Duration testStepVerifierLastStepVerifyErrorSatisfies() {
return StepVerifier.create(Mono.empty()).verifyErrorSatisfies(t -> {});
}
Duration testStepVerifierLastStepVerifyErrorMessage() {
return StepVerifier.create(Mono.empty()).verifyErrorMessage("foo");
}
Duration testStepVerifierLastStepVerifyTimeout() {
return StepVerifier.create(Mono.empty()).verifyTimeout(Duration.ZERO);
}
}

View File

@@ -13,6 +13,12 @@ import reactor.core.publisher.Mono;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class RxJava2AdapterRulesTest implements RefasterRuleCollectionTestCase {
ImmutableSet<Flux<Integer>> testFluxToFlowableToFlux() {
return ImmutableSet.of(
RxJava2Adapter.flowableToFlux(RxJava2Adapter.fluxToFlowable(Flux.just(1))),
RxJava2Adapter.flowableToFlux(RxJava2Adapter.fluxToFlowable(Flux.just(2))));
}
ImmutableSet<Mono<Void>> testCompletableToMono() {
return ImmutableSet.of(
RxJava2Adapter.completableToMono(Completable.complete()),

View File

@@ -13,6 +13,10 @@ import reactor.core.publisher.Mono;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class RxJava2AdapterRulesTest implements RefasterRuleCollectionTestCase {
ImmutableSet<Flux<Integer>> testFluxToFlowableToFlux() {
return ImmutableSet.of(Flux.just(1), Flux.just(2));
}
ImmutableSet<Mono<Void>> testCompletableToMono() {
return ImmutableSet.of(
Completable.complete().as(RxJava2Adapter::completableToMono),

View File

@@ -0,0 +1,144 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
final class RxJavaCompletableReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(Maybe.class);
}
Completable testCompletableAmb() {
return Completable.amb(Arrays.asList(Completable.complete(), Completable.complete()));
}
Completable testCompletableComplete() {
return Completable.complete();
}
Completable testCompletableDefer() {
return Completable.defer(() -> Completable.complete());
}
Completable testCompletableErrorThrowable() {
return Completable.error(new IllegalStateException());
}
Completable testCompletableErrorCallable() {
return Completable.error(
() -> {
throw new IllegalStateException();
});
}
Completable testCompletableFromAction() {
return Completable.fromAction(() -> {});
}
Completable testCompletableFromCallable() {
return Completable.fromCallable(
() -> {
return 1;
});
}
Completable testCompletableFromPublisher() {
return Completable.fromPublisher(Flowable.just(1));
}
Completable testCompletableFromRunnable() {
return Completable.fromRunnable(() -> {});
}
Completable testCompletableWrap() {
return Completable.wrap(Completable.complete());
}
Completable testCompletableAndThenCompletable() {
return Completable.complete().andThen(Completable.complete());
}
Maybe<Integer> testCompletableAndThenMaybe() {
return Completable.complete().andThen(Maybe.just(1));
}
Flowable<Integer> testCompletableAndThenPublisher() {
return Completable.complete().andThen(Flowable.just(1));
}
Single<Integer> testCompletableAndThenSingle() {
return Completable.complete().andThen(Single.just(1));
}
void testCompletableBlockingAwait() {
Completable.complete().blockingAwait();
}
Completable testCompletableDoOnError() {
return Completable.complete().doOnError(System.out::println);
}
Completable testCompletableOnErrorComplete() {
return Completable.complete().onErrorComplete();
}
Completable testCompletableOnErrorCompletePredicate() {
Completable.complete().onErrorComplete(t -> t instanceof IOException);
return Completable.complete().onErrorComplete(throwable -> true);
}
Completable testCompletableTimeoutLongTimeUnit() {
return Completable.complete().timeout(1000, TimeUnit.MILLISECONDS);
}
Flowable<Void> testCompletableToFlowable() {
return Completable.complete().toFlowable();
}
Maybe<Void> testCompletableToMaybe() {
return Completable.complete().toMaybe();
}
void testCompletableTestAssertResult() throws InterruptedException {
Completable.complete().test().await().assertResult();
}
void testCompletableTestAssertComplete() throws InterruptedException {
Completable.complete().test().await().assertComplete();
}
void testCompletableTestAssertErrorClass() throws InterruptedException {
Completable.complete().test().await().assertError(InterruptedException.class);
}
void testCompletableTestAssertNoErrors() throws InterruptedException {
Completable.complete().test().await().assertNoErrors();
}
void testCompletableTestAssertValueCount() throws InterruptedException {
Completable.complete().test().await().assertValueCount(1);
}
void testCompletableTestAssertFailure() throws InterruptedException {
Completable.complete().test().await().assertFailure(IllegalArgumentException.class);
}
void testCompletableTestAssertNoValues() throws InterruptedException {
Completable.complete().test().await().assertNoValues();
}
void testCompletableTestAssertFailureAndMessage() throws InterruptedException {
Completable.complete()
.test()
.await()
.assertFailureAndMessage(IllegalArgumentException.class, "foo");
}
}

View File

@@ -0,0 +1,203 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.assertj.core.api.Assertions;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaCompletableReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(Maybe.class);
}
Completable testCompletableAmb() {
return RxJava2Adapter.monoToCompletable(
Mono.firstWithSignal(
Streams.stream(Arrays.asList(Completable.complete(), Completable.complete()))
.map(RxJava2Adapter::completableToMono)
.collect(ImmutableList.toImmutableList())));
}
Completable testCompletableComplete() {
return RxJava2Adapter.monoToCompletable(Mono.empty());
}
Completable testCompletableDefer() {
return RxJava2Adapter.monoToCompletable(
Mono.defer(
() ->
RxJava2Adapter.completableToMono(
RxJavaReactorMigrationUtil.callableAsSupplier(() -> Completable.complete())
.get())));
}
Completable testCompletableErrorThrowable() {
return RxJava2Adapter.monoToCompletable(Mono.error(new IllegalStateException()));
}
Completable testCompletableErrorCallable() {
return RxJava2Adapter.monoToCompletable(
Mono.error(
() -> {
throw new IllegalStateException();
}));
}
Completable testCompletableFromAction() {
return RxJava2Adapter.monoToCompletable(
Mono.fromRunnable(RxJavaReactorMigrationUtil.toRunnable(() -> {})));
}
Completable testCompletableFromCallable() {
return RxJava2Adapter.monoToCompletable(
Mono.fromCallable(
() -> {
return 1;
}));
}
Completable testCompletableFromPublisher() {
return RxJava2Adapter.monoToCompletable(Mono.from(Flowable.just(1)));
}
Completable testCompletableFromRunnable() {
return RxJava2Adapter.monoToCompletable(Mono.fromRunnable(() -> {}));
}
Completable testCompletableWrap() {
return Completable.complete();
}
Completable testCompletableAndThenCompletable() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(Completable.complete())
.then(RxJava2Adapter.completableToMono(Completable.wrap(Completable.complete()))));
}
Maybe<Integer> testCompletableAndThenMaybe() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.completableToMono(Completable.complete())
.then(RxJava2Adapter.maybeToMono(Maybe.wrap(Maybe.just(1)))));
}
Flowable<Integer> testCompletableAndThenPublisher() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.completableToMono(Completable.complete()).thenMany(Flowable.just(1)));
}
Single<Integer> testCompletableAndThenSingle() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.completableToMono(Completable.complete())
.then(RxJava2Adapter.singleToMono(Single.wrap(Single.just(1)))));
}
void testCompletableBlockingAwait() {
RxJava2Adapter.completableToMono(Completable.complete()).block();
}
Completable testCompletableDoOnError() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(Completable.complete())
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(System.out::println)));
}
Completable testCompletableOnErrorComplete() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(Completable.complete()).onErrorStop());
}
Completable testCompletableOnErrorCompletePredicate() {
RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(Completable.complete())
.onErrorResume(
RxJavaReactorMigrationUtil.toJdkPredicate(t -> t instanceof IOException),
t -> Mono.empty()));
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(Completable.complete())
.onErrorResume(
RxJavaReactorMigrationUtil.toJdkPredicate(throwable -> true), t -> Mono.empty()));
}
Completable testCompletableTimeoutLongTimeUnit() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(Completable.complete())
.timeout(Duration.of(1000, TimeUnit.MILLISECONDS.toChronoUnit())));
}
Flowable<Void> testCompletableToFlowable() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.completableToMono(Completable.complete()).flux());
}
Maybe<Void> testCompletableToMaybe() {
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.completableToMono(Completable.complete()));
}
void testCompletableTestAssertResult() throws InterruptedException {
RxJava2Adapter.completableToMono(Completable.complete())
.as(StepVerifier::create)
.verifyComplete();
}
void testCompletableTestAssertComplete() throws InterruptedException {
RxJava2Adapter.completableToMono(Completable.complete())
.as(StepVerifier::create)
.verifyComplete();
}
void testCompletableTestAssertErrorClass() throws InterruptedException {
RxJava2Adapter.completableToMono(Completable.complete())
.as(StepVerifier::create)
.verifyError(InterruptedException.class);
}
void testCompletableTestAssertNoErrors() throws InterruptedException {
RxJava2Adapter.completableToMono(Completable.complete())
.as(StepVerifier::create)
.verifyComplete();
}
void testCompletableTestAssertValueCount() throws InterruptedException {
RxJava2Adapter.completableToMono(Completable.complete())
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
void testCompletableTestAssertFailure() throws InterruptedException {
RxJava2Adapter.completableToMono(Completable.complete())
.as(StepVerifier::create)
.verifyError(IllegalArgumentException.class);
}
void testCompletableTestAssertNoValues() throws InterruptedException {
RxJava2Adapter.completableToMono(Completable.complete())
.as(StepVerifier::create)
.verifyComplete();
}
void testCompletableTestAssertFailureAndMessage() throws InterruptedException {
RxJava2Adapter.completableToMono(Completable.complete())
.as(StepVerifier::create)
.expectErrorSatisfies(
t ->
Assertions.assertThat(t)
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("foo"))
.verify();
}
}

View File

@@ -0,0 +1,285 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
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.functions.Function;
import io.reactivex.internal.functions.Functions;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaFlowableToReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(CompletableSource.class, MaybeSource.class, Functions.class);
}
Flowable<Integer> testFlowableAmbArray() {
return Flowable.ambArray(Flowable.just(1), Flowable.just(2));
}
Flowable<Integer> testFlowableCombineLatest() {
return Flowable.combineLatest(Flowable.just(1), Flowable.just(2), Integer::sum);
}
Flowable<Integer> testFlowableConcatWithPublisher() {
return Flowable.just(1).concatWith(Flowable.just(2));
}
Flowable<Integer> testFlowableDefer() {
return Flowable.defer(() -> Flowable.just(1));
}
Flowable<Object> testFlowableEmpty() {
return Flowable.empty();
}
Flowable<Object> testFlowableErrorThrowable() {
return Flowable.error(new IllegalStateException());
}
Flowable<Object> testFlowableErrorCallable() {
return Flowable.error(
() -> {
throw new IllegalStateException();
});
}
Flowable<Integer> testFlowableFromArray() {
return Flowable.fromArray(1, 2, 3);
}
Flowable<Integer> testFlowableFromCallable() {
return Flowable.fromCallable(() -> 1);
}
Flowable<Integer> testFlowableFromIterable() {
return Flowable.fromIterable(ImmutableList.of(1, 2, 3));
}
Flowable<Integer> testFlowableFromPublisher() {
return Flowable.fromPublisher(Flowable.just(1));
}
Flowable<Integer> testFlowableFilter() {
return Flowable.just(1).filter(i -> i > 2);
}
Flowable<Integer> testFlowableDistinct() {
return Flowable.just(1).distinct();
}
Maybe<Integer> testFlowableFirstElement() {
return Flowable.just(1).firstElement();
}
Single<Integer> testFlowableFirstOrError() {
return Flowable.just(1).firstOrError();
}
Completable testFlowableFlatMapCompletable() {
return Flowable.just(1).flatMapCompletable(integer2 -> Completable.complete());
}
Completable testFlowableFlatMapCompletableUnwrap() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.flatMap(
y ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<Integer, Completable>)
integer2 -> Completable.complete())
.apply(y))))
.then());
}
Flowable<Object> testFlowableFlatMap() {
Flowable.just(1).flatMap(this::exampleMethod2);
return Flowable.just(1).flatMap(i -> ImmutableSet::of);
}
private Maybe<Integer> exampleMethod(Integer x) {
return null;
}
private Flowable<Integer> exampleMethod2(Integer x) {
return null;
}
ImmutableList<Flowable<Integer>> testFlowableJust() {
return ImmutableList.of(
Flowable.just(1),
Flowable.just(1, 2),
Flowable.just(1, 2, 3),
Flowable.just(1, 2, 3, 4),
Flowable.just(1, 2, 3, 4, 5));
}
Flowable<Integer> testFlowableMergePublisherPublisher() {
return Flowable.merge(Flowable.just(1), Flowable.just(2));
}
Flowable<Integer> testFlowableRange() {
return Flowable.range(1, 10);
}
Flowable<?> testFlowableRangeLong() {
return Flowable.rangeLong(1, 10);
}
Flowable<Integer> testFlowableZip() {
return Flowable.zip(Flowable.just(1), Flowable.just(2), (i1, i2) -> i1 + i2);
}
Single<Boolean> testFlowableAll() {
return Flowable.just(true, true).all(Boolean::booleanValue);
}
Single<Boolean> testFlowableAny() {
return Flowable.just(true, true).any(Boolean::booleanValue);
}
Object testFlowableBlockingFirst() {
return Flowable.just(1).blockingFirst();
}
Iterable<Integer> testFlowableBlockingIterable() {
return Flowable.just(1).blockingIterable();
}
Flowable<Integer> testFlowableConcatMap() {
return Flowable.just(1).concatMap(e -> Flowable::just);
}
Completable testFlowableConcatMapCompletable() {
return Flowable.just(1).concatMapCompletable(c -> Completable.complete());
}
Flowable<Integer> testFlowableConcatMapMaybe() {
return Flowable.just(1).concatMapMaybe(integer -> Maybe.just(integer));
}
Flowable<Integer> testFlowableConcatMapMaybeDelayError() {
return Flowable.just(1).concatMapMaybeDelayError(Maybe::just);
}
ImmutableSet<Flowable<Integer>> testFlowableFlatMapMaybe() {
return ImmutableSet.of(
Flowable.just(1).flatMapMaybe(Maybe::just),
Flowable.zip(Flowable.just(1), Flowable.just(2), (i1, i2) -> Maybe.just(i1 + i2))
.flatMapMaybe(Functions.identity()));
}
Flowable<Integer> testFlowableMap() {
return Flowable.just(1).map(i -> i + 1);
}
Flowable<Integer> testFlowableMergeWith() {
return Flowable.just(1).mergeWith(Single.just(1));
}
Flowable<Integer> testFlowableOnErrorResumeNext() {
return Flowable.just(1).onErrorResumeNext((Throwable throwable) -> Flux.just(1));
}
Single<Integer> testFlowableSingleDefault() {
return Flowable.just(1).single(2);
}
Maybe<Integer> testFlowableSingleElement() {
return Flowable.just(1).singleElement();
}
Single<Integer> testFlowableSingleOrError() {
return Flowable.just(1).singleOrError();
}
Flowable<Integer> testFlowableSorted() {
return Flowable.just(1).sorted();
}
Flowable<Integer> testFlowableSortedComparator() {
return Flowable.just(1).sorted((i1, i2) -> 0);
}
Flowable<Integer> testFlowableSwitchIfEmptyPublisher() {
return Flowable.just(1)
.switchIfEmpty(
Flowable.error(
() -> {
throw new IllegalStateException();
}));
}
void testFlowableSubscribeTwoConsumersWithAction() {
Flowable.just(1).subscribe(i -> {}, i -> {}, () -> {});
}
Flowable<Integer> testFlowableTimeoutLongTimeUnit() {
return Flowable.just(1).timeout(1000, TimeUnit.MILLISECONDS);
}
Single<List<Integer>> testFlowableToList() {
return Flowable.just(1, 2).toList();
}
Single<Map<Boolean, Integer>> testFlowableToMap() {
return Flowable.just(1).toMap(i -> i > 1);
}
Observable<Integer> testFlowableToObservable() {
return Flowable.just(1).toObservable();
}
Flowable<Integer> testFlowableZipWith() {
return Flowable.just(1).zipWith(ImmutableList.of(1, 2), (a, b) -> a + b);
}
void testFlowableTestAssertResultItem() throws InterruptedException {
Flowable.just(1).test().await().assertResult(1);
Flowable.just(2).test().await().assertValue(2);
}
void testFlowableTestAssertResult() throws InterruptedException {
Flowable.just(1).test().await().assertResult();
}
void testFlowableTestAssertValue() throws InterruptedException {
Flowable.just(1).test().await().assertValue(i -> i > 2);
Flowable.just(3).test().await().assertValue(i -> i > 4).assertComplete();
}
void testFlowableTestAssertResultValues() throws InterruptedException {
Flowable.just(1, 2, 3).test().await().assertResult(1, 2, 3);
Flowable.just(4, 5, 6).test().await().assertValues(4, 5, 6);
}
void testFlowableTestAssertComplete() throws InterruptedException {
Flowable.just(1).test().await().assertComplete();
}
void testFlowableTestAssertErrorClass() throws InterruptedException {
Flowable.just(1).test().await().assertError(InterruptedException.class);
}
void testFlowableTestAssertNoErrors() throws InterruptedException {
Flowable.just(1).test().await().assertNoErrors();
}
void testFlowableTestAssertValueCount() throws InterruptedException {
Flowable.just(1).test().await().assertValueCount(1);
}
}

View File

@@ -0,0 +1,403 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
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.functions.Function;
import io.reactivex.internal.functions.Functions;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
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;
final class RxJavaFlowableToReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(CompletableSource.class, MaybeSource.class, Functions.class);
}
Flowable<Integer> testFlowableAmbArray() {
return RxJava2Adapter.fluxToFlowable(Flux.firstWithSignal(Flowable.just(1), Flowable.just(2)));
}
Flowable<Integer> testFlowableCombineLatest() {
return RxJava2Adapter.fluxToFlowable(
Flux.<Integer, Integer, Integer>combineLatest(
Flowable.just(1),
Flowable.just(2),
RxJavaReactorMigrationUtil.toJdkBiFunction(Integer::sum)));
}
Flowable<Integer> testFlowableConcatWithPublisher() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1)).concatWith(Flowable.just(2)));
}
Flowable<Integer> testFlowableDefer() {
return RxJava2Adapter.fluxToFlowable(
Flux.defer(RxJavaReactorMigrationUtil.callableAsSupplier(() -> Flowable.just(1))));
}
Flowable<Object> testFlowableEmpty() {
return RxJava2Adapter.fluxToFlowable(Flux.empty());
}
Flowable<Object> testFlowableErrorThrowable() {
return RxJava2Adapter.fluxToFlowable(Flux.error(new IllegalStateException()));
}
Flowable<Object> testFlowableErrorCallable() {
return RxJava2Adapter.fluxToFlowable(
Flux.error(
RxJavaReactorMigrationUtil.callableAsSupplier(
() -> {
throw new IllegalStateException();
})));
}
Flowable<Integer> testFlowableFromArray() {
return Flowable.fromArray(1, 2, 3);
}
Flowable<Integer> testFlowableFromCallable() {
return RxJava2Adapter.monoToFlowable(Mono.fromCallable(() -> 1));
}
Flowable<Integer> testFlowableFromIterable() {
return RxJava2Adapter.fluxToFlowable(Flux.fromIterable(ImmutableList.of(1, 2, 3)));
}
Flowable<Integer> testFlowableFromPublisher() {
return RxJava2Adapter.fluxToFlowable(Flux.from(Flowable.just(1)));
}
Flowable<Integer> testFlowableFilter() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 2)));
}
Flowable<Integer> testFlowableDistinct() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1)).distinct());
}
Maybe<Integer> testFlowableFirstElement() {
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.flowableToFlux(Flowable.just(1)).next());
}
Single<Integer> testFlowableFirstOrError() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.flowableToFlux(Flowable.just(1)).next().single());
}
Completable testFlowableFlatMapCompletable() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.flatMap(
x ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<Integer, CompletableSource>toJdkFunction(
integer2 -> Completable.complete())
.apply(x))))
.then());
}
Completable testFlowableFlatMapCompletableUnwrap() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.flowableToFlux(RxJava2Adapter.fluxToFlowable(Flux.just(1)))
.flatMap(
y ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<Integer, Completable>)
integer2 -> Completable.complete())
.apply(y))))
.then());
}
Flowable<Object> testFlowableFlatMap() {
RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.flatMap(RxJavaReactorMigrationUtil.toJdkFunction(this::exampleMethod2)));
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.flatMap(RxJavaReactorMigrationUtil.toJdkFunction(i -> ImmutableSet::of)));
}
private Maybe<Integer> exampleMethod(Integer x) {
return null;
}
private Flowable<Integer> exampleMethod2(Integer x) {
return null;
}
ImmutableList<Flowable<Integer>> testFlowableJust() {
return ImmutableList.of(
RxJava2Adapter.fluxToFlowable(Flux.just(1)),
RxJava2Adapter.fluxToFlowable(Flux.just(1, 2)),
RxJava2Adapter.fluxToFlowable(Flux.just(1, 2, 3)),
RxJava2Adapter.fluxToFlowable(Flux.just(1, 2, 3, 4)),
RxJava2Adapter.fluxToFlowable(Flux.just(1, 2, 3, 4, 5)));
}
Flowable<Integer> testFlowableMergePublisherPublisher() {
return RxJava2Adapter.fluxToFlowable(Flux.merge(Flowable.just(1), Flowable.just(2)));
}
Flowable<Integer> testFlowableRange() {
return RxJava2Adapter.fluxToFlowable(Flux.range(1, 10));
}
Flowable<?> testFlowableRangeLong() {
return RxJava2Adapter.fluxToFlowable(Flux.range(1, 10));
}
Flowable<Integer> testFlowableZip() {
return RxJava2Adapter.fluxToFlowable(
Flux.<Integer, Integer, Integer>zip(
Flowable.just(1),
Flowable.just(2),
RxJavaReactorMigrationUtil.toJdkBiFunction((i1, i2) -> i1 + i2)));
}
Single<Boolean> testFlowableAll() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.flowableToFlux(Flowable.just(true, true))
.all(RxJavaReactorMigrationUtil.toJdkPredicate(Boolean::booleanValue)));
}
Single<Boolean> testFlowableAny() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.flowableToFlux(Flowable.just(true, true))
.any(RxJavaReactorMigrationUtil.toJdkPredicate(Boolean::booleanValue)));
}
Object testFlowableBlockingFirst() {
return RxJava2Adapter.flowableToFlux(Flowable.just(1)).blockFirst();
}
Iterable<Integer> testFlowableBlockingIterable() {
return RxJava2Adapter.flowableToFlux(Flowable.just(1)).toIterable();
}
Flowable<Integer> testFlowableConcatMap() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.concatMap(RxJavaReactorMigrationUtil.toJdkFunction(e -> Flowable::just)));
}
Completable testFlowableConcatMapCompletable() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.concatMap(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(c -> Completable.complete())
.apply(e))))
.then());
}
Flowable<Integer> testFlowableConcatMapMaybe() {
return RxJava2Adapter.fluxToFlowable(Flux.just(1))
.concatMapMaybe(integer -> Maybe.just(integer));
}
Flowable<Integer> testFlowableConcatMapMaybeDelayError() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.concatMapDelayError(
e ->
Maybe.wrap(
RxJavaReactorMigrationUtil.<Integer, MaybeSource<Integer>>toJdkFunction(
Maybe::just)
.apply(e))
.toFlowable()));
}
ImmutableSet<Flowable<Integer>> testFlowableFlatMapMaybe() {
return ImmutableSet.of(
RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.flatMap(
e ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil
.<Integer, MaybeSource<Integer>>toJdkFunction(Maybe::just)
.apply(e))))),
RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(
Flowable.zip(
Flowable.just(1), Flowable.just(2), (i1, i2) -> Maybe.just(i1 + i2)))
.flatMap(
e ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil
.<MaybeSource<Integer>, MaybeSource<Integer>>toJdkFunction(
Functions.identity())
.apply(e))))));
}
Flowable<Integer> testFlowableMap() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.map(RxJavaReactorMigrationUtil.toJdkFunction(i -> i + 1)));
}
Flowable<Integer> testFlowableMergeWith() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.mergeWith(RxJava2Adapter.singleToMono(Single.wrap(Single.just(1)))));
}
Flowable<Integer> testFlowableOnErrorResumeNext() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.onErrorResume(
RxJavaReactorMigrationUtil.toJdkFunction((Throwable throwable) -> Flux.just(1))));
}
Single<Integer> testFlowableSingleDefault() {
return RxJava2Adapter.monoToSingle(RxJava2Adapter.flowableToFlux(Flowable.just(1)).single(2));
}
Maybe<Integer> testFlowableSingleElement() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.flowableToFlux(Flowable.just(1)).singleOrEmpty());
}
Single<Integer> testFlowableSingleOrError() {
return RxJava2Adapter.monoToSingle(RxJava2Adapter.flowableToFlux(Flowable.just(1)).single());
}
Flowable<Integer> testFlowableSorted() {
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.flowableToFlux(Flowable.just(1)).sort());
}
Flowable<Integer> testFlowableSortedComparator() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1)).sort((i1, i2) -> 0));
}
Flowable<Integer> testFlowableSwitchIfEmptyPublisher() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.switchIfEmpty(
Flowable.error(
() -> {
throw new IllegalStateException();
})));
}
void testFlowableSubscribeTwoConsumersWithAction() {
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.subscribe(
RxJavaReactorMigrationUtil.toJdkConsumer(i -> {}),
RxJavaReactorMigrationUtil.toJdkConsumer(i -> {}),
RxJavaReactorMigrationUtil.toRunnable(() -> {}));
}
Flowable<Integer> testFlowableTimeoutLongTimeUnit() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.timeout(Duration.of(1000, TimeUnit.MILLISECONDS.toChronoUnit())));
}
Single<List<Integer>> testFlowableToList() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.flowableToFlux(Flowable.just(1, 2)).collectList());
}
Single<Map<Boolean, Integer>> testFlowableToMap() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.flowableToFlux(Flowable.just(1)).collectMap(i -> i > 1));
}
Observable<Integer> testFlowableToObservable() {
return RxJava2Adapter.fluxToFlowable(Flux.just(1)).toObservable();
}
Flowable<Integer> testFlowableZipWith() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.zipWithIterable(
ImmutableList.of(1, 2),
RxJavaReactorMigrationUtil.toJdkBiFunction((a, b) -> a + b)));
}
void testFlowableTestAssertResultItem() throws InterruptedException {
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.as(StepVerifier::create)
.expectNext(1)
.verifyComplete();
RxJava2Adapter.flowableToFlux(Flowable.just(2))
.as(StepVerifier::create)
.expectNext(2)
.verifyComplete();
}
void testFlowableTestAssertResult() throws InterruptedException {
RxJava2Adapter.flowableToFlux(Flowable.just(1)).as(StepVerifier::create).verifyComplete();
}
void testFlowableTestAssertValue() throws InterruptedException {
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 2))
.verifyComplete();
RxJava2Adapter.flowableToFlux(Flowable.just(3))
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 4))
.verifyComplete();
}
void testFlowableTestAssertResultValues() throws InterruptedException {
RxJava2Adapter.flowableToFlux(Flowable.just(1, 2, 3))
.as(StepVerifier::create)
.expectNext(1, 2, 3)
.verifyComplete();
RxJava2Adapter.flowableToFlux(Flowable.just(4, 5, 6))
.as(StepVerifier::create)
.expectNext(4, 5, 6)
.verifyComplete();
}
void testFlowableTestAssertComplete() throws InterruptedException {
RxJava2Adapter.flowableToFlux(Flowable.just(1)).as(StepVerifier::create).verifyComplete();
}
void testFlowableTestAssertErrorClass() throws InterruptedException {
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.as(StepVerifier::create)
.verifyError(InterruptedException.class);
}
void testFlowableTestAssertNoErrors() throws InterruptedException {
RxJava2Adapter.flowableToFlux(Flowable.just(1)).as(StepVerifier::create).verifyComplete();
}
void testFlowableTestAssertValueCount() throws InterruptedException {
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
}

View File

@@ -0,0 +1,257 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.MaybeSource;
import io.reactivex.Observable;
import io.reactivex.Single;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Mono;
final class RxJavaMaybeToReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(Observable.class);
}
Maybe<String> testMaybeAmb() {
return Maybe.amb(ImmutableList.of(Maybe.just("foo"), Maybe.just("bar")));
}
// XXX: Template turned off for now.
Maybe<String> testMaybeAmbArray() {
return Maybe.ambArray(Maybe.just("foo"), Maybe.just("bar"));
}
Flowable<Integer> testMaybeConcatArray() {
return Flowable.empty();
}
Mono<String> testMaybeDefer() {
return Maybe.defer(() -> Maybe.just("test")).as(RxJava2Adapter::maybeToMono);
}
Maybe<Integer> testMaybeEmpty() {
return Maybe.empty();
}
Maybe<Object> testMaybeErrorThrowable() {
return Maybe.error(new IllegalStateException());
}
Maybe<Object> testMaybeErrorCallable() {
return Maybe.error(
() -> {
throw new IllegalStateException();
});
}
Maybe<Object> testMaybeFromAction() {
return Maybe.fromAction(
() -> {
String s = "foo";
});
}
Maybe<Object> testMaybeFromCallable() {
return Maybe.fromCallable(
() -> {
String s = "foo";
return null;
});
}
Maybe<Integer> testMaybeFromFuture() {
return Maybe.fromFuture(new CompletableFuture<>());
}
Maybe<Integer> testMaybeFromRunnable() {
return Maybe.fromRunnable(
() -> {
int i = 1 + 1;
});
}
Maybe<Integer> testMaybeFromSingle() {
return Maybe.fromSingle(Single.just(1));
}
Maybe<Integer> testMaybeJust() {
return Maybe.just(1);
}
Maybe<Integer> testMaybeWrap() {
return Maybe.wrap(Maybe.just(1));
}
Maybe<String> testMaybeAmbWith() {
return Maybe.just("foo").ambWith(Maybe.just("bar"));
}
Integer testMaybeBlockingGet() {
return Maybe.just(1).blockingGet();
}
Maybe<String> testMaybeCastPositive() {
return Maybe.just("string").cast(String.class);
}
@SuppressWarnings("MaybeJust")
Maybe<Object> testMaybeCastNegative() {
return Maybe.just("string").cast(Object.class);
}
Maybe<Integer> testMaybeDefaultIfEmpty() {
return Maybe.just(1).defaultIfEmpty(0);
}
Maybe<Integer> testMaybeDoOnError() {
return Maybe.just(1).doOnError(System.out::println);
}
Maybe<Integer> testMaybeDoOnSuccess() {
return Maybe.just(1).doOnSuccess(System.out::println);
}
Maybe<Integer> testMaybeFilter() {
return Maybe.just(1).filter(i -> i > 1);
}
@SuppressWarnings("MaybeJust")
Maybe<Integer> testMaybeFlatMapFunction() {
Maybe.just(1).flatMap(this::exampleMethod);
return Maybe.just(1).flatMap(exampleFunction());
}
private io.reactivex.functions.Function<Integer, MaybeSource<Integer>> exampleFunction() {
return null;
}
Maybe<Integer> testMaybeFlatMapLambda() {
return Maybe.just(1).flatMap(i -> Maybe.just(i * 2));
}
Maybe<Integer> testMaybeFlatMapMethodReference() {
return Maybe.just(1).flatMap(this::exampleMethod);
}
private Maybe<Integer> exampleMethod(Integer x) {
return null;
}
Single<Integer> testMaybeFlatMapPublisher() {
return Maybe.just(1).flatMapSingle(e -> Single.just(1));
}
Maybe<Integer> testMaybeFlatMapSingleElement() {
return Maybe.just(1).flatMapSingleElement(x -> Single.just(x));
}
Completable testMaybeIgnoreElement() {
return Maybe.just(1).ignoreElement();
}
Single<Boolean> testMaybeIsEmpty() {
return Maybe.just(1).isEmpty();
}
Maybe<String> testMaybeMap() {
return Maybe.just(1).map(String::valueOf);
}
Maybe<Integer> testMaybeOnErrorReturn() {
return Maybe.just(1).onErrorReturn(t -> Integer.valueOf(1));
}
void testMaybeSubscribe() {
Maybe.just(1).subscribe();
}
void testMaybeSubscribeConsumer() {
Maybe.just(1).subscribe(i -> {});
}
void testMaybeSubscribeTwoConsumers() {
Maybe.just(1).subscribe(i -> {}, i -> {});
}
void testMaybeSubscribeTwoConsumersWithAction() {
Maybe.just(1).subscribe(i -> {}, i -> {}, () -> {});
}
Maybe<Integer> testMaybeSourceSwitchIfEmpty() {
return Maybe.just(1)
.switchIfEmpty(
Maybe.<Integer>error(
() -> {
throw new IllegalStateException();
}));
}
Single<Integer> testMaybeSwitchIfEmpty() {
return Maybe.just(1)
.switchIfEmpty(
Single.<Integer>error(
() -> {
throw new IllegalStateException();
}));
}
Maybe<Integer> testMaybeTimeoutLongTimeUnit() {
return Maybe.just(1).timeout(1000, TimeUnit.MILLISECONDS);
}
Maybe<Object> testMaybeTimeOut() {
return Maybe.empty().timeout(100, TimeUnit.MILLISECONDS, Maybe.just(2));
}
Flowable<Integer> testMaybeToFlowable() {
return Maybe.just(1).toFlowable();
}
Observable<Integer> testMaybeToObservable() {
return Maybe.just(1).toObservable();
}
@SuppressWarnings("MaybeJust")
private Maybe<Integer> getMaybe() {
return Maybe.just(3);
}
void MaybeTestAssertResultItem() throws InterruptedException {
Maybe.just(1).test().await().assertResult(1);
Maybe.just(2).test().await().assertValue(2);
}
void MaybeTestAssertResult() throws InterruptedException {
Maybe.just(1).test().await().assertResult();
}
void MaybeTestAssertValue() throws InterruptedException {
Maybe.just(1).test().await().assertValue(i -> i > 2);
Maybe.just(3).test().await().assertValue(i -> i > 4).assertComplete();
}
void testMaybeTestAssertComplete() throws InterruptedException {
Maybe.just(1).test().await().assertComplete();
}
void testMaybeTestAssertErrorClass() throws InterruptedException {
Maybe.just(1).test().await().assertError(InterruptedException.class);
}
void testMaybeTestAssertNoErrors() throws InterruptedException {
Maybe.just(1).test().await().assertNoErrors();
}
void testMaybeTestAssertValueCount() throws InterruptedException {
Maybe.just(1).test().await().assertValueCount(1);
}
}

View File

@@ -0,0 +1,368 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import io.reactivex.Completable;
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.functions.Function;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaMaybeToReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(Observable.class);
}
Maybe<String> testMaybeAmb() {
return RxJava2Adapter.monoToMaybe(
Mono.firstWithSignal(
Streams.stream(ImmutableList.of(Maybe.just("foo"), Maybe.just("bar")))
.map(RxJava2Adapter::maybeToMono)
.collect(ImmutableList.toImmutableList())));
}
// XXX: Template turned off for now.
Maybe<String> testMaybeAmbArray() {
return Maybe.ambArray(
RxJava2Adapter.monoToMaybe(Mono.just("foo")), RxJava2Adapter.monoToMaybe(Mono.just("bar")));
}
Flowable<Integer> testMaybeConcatArray() {
return Flowable.empty();
}
Mono<String> testMaybeDefer() {
return Mono.defer(() -> RxJava2Adapter.maybeToMono(Maybe.just("test")));
}
Maybe<Integer> testMaybeEmpty() {
return RxJava2Adapter.monoToMaybe(Mono.empty());
}
Maybe<Object> testMaybeErrorThrowable() {
return RxJava2Adapter.monoToMaybe(Mono.error(new IllegalStateException()));
}
Maybe<Object> testMaybeErrorCallable() {
return RxJava2Adapter.monoToMaybe(
Mono.error(
RxJavaReactorMigrationUtil.callableAsSupplier(
() -> {
throw new IllegalStateException();
})));
}
Maybe<Object> testMaybeFromAction() {
return RxJava2Adapter.monoToMaybe(
Mono.fromRunnable(
RxJavaReactorMigrationUtil.toRunnable(
() -> {
String s = "foo";
})));
}
Maybe<Object> testMaybeFromCallable() {
return RxJava2Adapter.monoToMaybe(
Mono.fromSupplier(
RxJavaReactorMigrationUtil.callableAsSupplier(
() -> {
String s = "foo";
return null;
})));
}
Maybe<Integer> testMaybeFromFuture() {
return RxJava2Adapter.monoToMaybe(Mono.fromFuture(new CompletableFuture<>()));
}
Maybe<Integer> testMaybeFromRunnable() {
return RxJava2Adapter.monoToMaybe(
Mono.fromRunnable(
() -> {
int i = 1 + 1;
}));
}
Maybe<Integer> testMaybeFromSingle() {
return RxJava2Adapter.monoToMaybe(
Mono.from(RxJava2Adapter.singleToMono(Single.wrap(Single.just(1)))));
}
Maybe<Integer> testMaybeJust() {
return RxJava2Adapter.monoToMaybe(Mono.just(1));
}
Maybe<Integer> testMaybeWrap() {
return Maybe.just(1);
}
Maybe<String> testMaybeAmbWith() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just("foo"))
.or(RxJava2Adapter.maybeToMono(Maybe.just("bar"))));
}
Integer testMaybeBlockingGet() {
return RxJava2Adapter.maybeToMono(Maybe.just(1)).block();
}
Maybe<String> testMaybeCastPositive() {
return Maybe.just("string");
}
@SuppressWarnings("MaybeJust")
Maybe<Object> testMaybeCastNegative() {
return Maybe.just("string").cast(Object.class);
}
Maybe<Integer> testMaybeDefaultIfEmpty() {
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.maybeToMono(Maybe.just(1)).defaultIfEmpty(0));
}
Maybe<Integer> testMaybeDoOnError() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(System.out::println)));
}
Maybe<Integer> testMaybeDoOnSuccess() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.doOnSuccess(RxJavaReactorMigrationUtil.toJdkConsumer(System.out::println)));
}
Maybe<Integer> testMaybeFilter() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 1)));
}
@SuppressWarnings("MaybeJust")
Maybe<Integer> testMaybeFlatMapFunction() {
RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.flatMap(
v ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.<Integer, MaybeSource<Integer>>toJdkFunction(
this::exampleMethod)
.apply(v)))));
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.flatMap(
v ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.<Integer, MaybeSource<Integer>>toJdkFunction(
exampleFunction())
.apply(v)))));
}
private io.reactivex.functions.Function<Integer, MaybeSource<Integer>> exampleFunction() {
return null;
}
Maybe<Integer> testMaybeFlatMapLambda() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.flatMap(z -> Maybe.just(z * 2).as(RxJava2Adapter::maybeToMono)));
}
Maybe<Integer> testMaybeFlatMapMethodReference() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.flatMap(
v ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.<Integer, MaybeSource<Integer>>toJdkFunction(
this::exampleMethod)
.apply(v)))));
}
private Maybe<Integer> exampleMethod(Integer x) {
return null;
}
Single<Integer> testMaybeFlatMapPublisher() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.flatMap(
y ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil
.<Integer, SingleSource<Integer>>toJdkFunction(e -> Single.just(1))
.apply(y)))));
}
Maybe<Integer> testMaybeFlatMapSingleElement() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.flatMap(
e ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<Integer, SingleSource<Integer>>) x -> Single.just(x))
.apply(e)))));
}
Completable testMaybeIgnoreElement() {
return RxJava2Adapter.monoToCompletable(RxJava2Adapter.maybeToMono(Maybe.just(1)).then());
}
Single<Boolean> testMaybeIsEmpty() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.maybeToMono(Maybe.just(1)).hasElement().map(hasElement -> !hasElement));
}
Maybe<String> testMaybeMap() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.map(RxJavaReactorMigrationUtil.toJdkFunction(String::valueOf)));
}
Maybe<Integer> testMaybeOnErrorReturn() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.onErrorResume(t -> Mono.just(Integer.valueOf(1))));
}
void testMaybeSubscribe() {
RxJava2Adapter.maybeToMono(Maybe.just(1)).subscribe();
}
void testMaybeSubscribeConsumer() {
RxJava2Adapter.maybeToMono(Maybe.just(1))
.subscribe(RxJavaReactorMigrationUtil.toJdkConsumer(i -> {}));
}
void testMaybeSubscribeTwoConsumers() {
RxJava2Adapter.maybeToMono(Maybe.just(1))
.subscribe(
RxJavaReactorMigrationUtil.toJdkConsumer(i -> {}),
RxJavaReactorMigrationUtil.toJdkConsumer(i -> {}));
}
void testMaybeSubscribeTwoConsumersWithAction() {
RxJava2Adapter.maybeToMono(Maybe.just(1))
.subscribe(
RxJavaReactorMigrationUtil.toJdkConsumer(i -> {}),
RxJavaReactorMigrationUtil.toJdkConsumer(i -> {}),
RxJavaReactorMigrationUtil.toRunnable(() -> {}));
}
Maybe<Integer> testMaybeSourceSwitchIfEmpty() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.switchIfEmpty(
RxJava2Adapter.maybeToMono(
Maybe.wrap(
Maybe.<Integer>error(
() -> {
throw new IllegalStateException();
})))));
}
Single<Integer> testMaybeSwitchIfEmpty() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.switchIfEmpty(
RxJava2Adapter.singleToMono(
Single.wrap(
Single.<Integer>error(
() -> {
throw new IllegalStateException();
})))));
}
Maybe<Integer> testMaybeTimeoutLongTimeUnit() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.timeout(Duration.of(1000, TimeUnit.MILLISECONDS.toChronoUnit())));
}
Maybe<Object> testMaybeTimeOut() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(Maybe.empty())
.timeout(
Duration.of(100, TimeUnit.MILLISECONDS.toChronoUnit()),
RxJava2Adapter.maybeToMono(Maybe.wrap(Maybe.just(2)))));
}
Flowable<Integer> testMaybeToFlowable() {
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.maybeToMono(Maybe.just(1)).flux());
}
Observable<Integer> testMaybeToObservable() {
return RxJava2Adapter.fluxToObservable(RxJava2Adapter.maybeToMono(Maybe.just(1)).flux());
}
@SuppressWarnings("MaybeJust")
private Maybe<Integer> getMaybe() {
return Maybe.just(3);
}
void MaybeTestAssertResultItem() throws InterruptedException {
RxJava2Adapter.maybeToMono(Maybe.just(1))
.as(StepVerifier::create)
.expectNext(1)
.verifyComplete();
RxJava2Adapter.maybeToMono(Maybe.just(2))
.as(StepVerifier::create)
.expectNext(2)
.verifyComplete();
}
void MaybeTestAssertResult() throws InterruptedException {
RxJava2Adapter.maybeToMono(Maybe.just(1)).as(StepVerifier::create).verifyComplete();
}
void MaybeTestAssertValue() throws InterruptedException {
RxJava2Adapter.maybeToMono(Maybe.just(1))
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 2))
.verifyComplete();
RxJava2Adapter.maybeToMono(Maybe.just(3))
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 4))
.verifyComplete();
}
void testMaybeTestAssertComplete() throws InterruptedException {
RxJava2Adapter.maybeToMono(Maybe.just(1)).as(StepVerifier::create).verifyComplete();
}
void testMaybeTestAssertErrorClass() throws InterruptedException {
RxJava2Adapter.maybeToMono(Maybe.just(1))
.as(StepVerifier::create)
.verifyError(InterruptedException.class);
}
void testMaybeTestAssertNoErrors() throws InterruptedException {
RxJava2Adapter.maybeToMono(Maybe.just(1)).as(StepVerifier::create).verifyComplete();
}
void testMaybeTestAssertValueCount() throws InterruptedException {
RxJava2Adapter.maybeToMono(Maybe.just(1))
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
}

View File

@@ -0,0 +1,87 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import java.util.concurrent.TimeUnit;
final class RxJavaObservableToReactorTemplatesTest implements RefasterTemplateTestCase {
Observable<Integer> testObservableAmb() {
return Observable.amb(ImmutableList.of(Observable.just(1), Observable.just(2)));
}
Observable<Integer> testObservableEmpty() {
return Observable.empty();
}
Observable<Integer> testObservableJust() {
return Observable.just(1);
}
Observable<Integer> testObservableJustTwo() {
return Observable.just(1, 2);
}
Observable<Integer> testObservableJustThree() {
return Observable.just(1, 2, 3);
}
Maybe<Integer> testMaybeFirstElement() {
return Observable.just(1).firstElement();
}
Observable<Integer> testObservableFilter() {
return Observable.just(1).filter(i -> i > 1);
}
Completable testObservableIgnoreElements() {
return Observable.just(1, 2).ignoreElements();
}
Observable<Integer> testObservableTimeoutLongTimeUnit() {
return Observable.just(1).timeout(1000, TimeUnit.MILLISECONDS);
}
Flowable<Integer> testObservableToFlowable() {
return Observable.just(1).toFlowable(BackpressureStrategy.BUFFER);
}
void testObservableTestAssertResultItem() throws InterruptedException {
Observable.just(1).test().await().assertResult(1);
Observable.just(2).test().await().assertValue(2);
}
void testObservableTestAssertResult() throws InterruptedException {
Observable.just(1).test().await().assertResult();
}
void testObservableTestAssertValue() throws InterruptedException {
Observable.just(1).test().await().assertValue(i -> i > 2);
Observable.just(3).test().await().assertValue(i -> i > 4).assertComplete();
}
void testObservableTestAssertResultValues() throws InterruptedException {
Observable.just(1, 2, 3).test().await().assertResult(1, 2, 3);
Observable.just(4, 5, 6).test().await().assertValues(4, 5, 6);
}
void testObservableTestAssertComplete() throws InterruptedException {
Observable.just(1).test().await().assertComplete();
}
void testObservableTestAssertErrorClass() throws InterruptedException {
Observable.just(1).test().await().assertError(InterruptedException.class);
}
void testObservableTestAssertNoErrors() throws InterruptedException {
Observable.just(1).test().await().assertNoErrors();
}
void testObservableTestAssertValueCount() throws InterruptedException {
Observable.just(1).test().await().assertValueCount(1);
}
}

View File

@@ -0,0 +1,136 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaObservableToReactorTemplatesTest implements RefasterTemplateTestCase {
Observable<Integer> testObservableAmb() {
return RxJava2Adapter.fluxToObservable(
Flux.<Integer>firstWithSignal(
Streams.stream(ImmutableList.of(Observable.just(1), Observable.just(2)))
.map(e -> e.toFlowable(BackpressureStrategy.BUFFER))
.map(RxJava2Adapter::flowableToFlux)
.collect(ImmutableList.toImmutableList())));
}
Observable<Integer> testObservableEmpty() {
return RxJava2Adapter.fluxToObservable(Flux.empty());
}
Observable<Integer> testObservableJust() {
return RxJava2Adapter.fluxToObservable(Flux.just(1));
}
Observable<Integer> testObservableJustTwo() {
return RxJava2Adapter.fluxToObservable(Flux.just(1, 2));
}
Observable<Integer> testObservableJustThree() {
return RxJava2Adapter.fluxToObservable(Flux.just(1, 2, 3));
}
Maybe<Integer> testMaybeFirstElement() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER).next());
}
Observable<Integer> testObservableFilter() {
return RxJava2Adapter.fluxToObservable(
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 1)));
}
Completable testObservableIgnoreElements() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.observableToFlux(Observable.just(1, 2), BackpressureStrategy.BUFFER)
.ignoreElements()
.then());
}
Observable<Integer> testObservableTimeoutLongTimeUnit() {
return RxJava2Adapter.fluxToObservable(
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.timeout(Duration.of(1000, TimeUnit.MILLISECONDS.toChronoUnit())));
}
Flowable<Integer> testObservableToFlowable() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER));
}
void testObservableTestAssertResultItem() throws InterruptedException {
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNext(1)
.verifyComplete();
RxJava2Adapter.observableToFlux(Observable.just(2), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNext(2)
.verifyComplete();
}
void testObservableTestAssertResult() throws InterruptedException {
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyComplete();
}
void testObservableTestAssertValue() throws InterruptedException {
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 2))
.verifyComplete();
RxJava2Adapter.observableToFlux(Observable.just(3), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 4))
.verifyComplete();
}
void testObservableTestAssertResultValues() throws InterruptedException {
RxJava2Adapter.observableToFlux(Observable.just(1, 2, 3), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNext(1, 2, 3)
.verifyComplete();
RxJava2Adapter.observableToFlux(Observable.just(4, 5, 6), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNext(4, 5, 6)
.verifyComplete();
}
void testObservableTestAssertComplete() throws InterruptedException {
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyComplete();
}
void testObservableTestAssertErrorClass() throws InterruptedException {
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyError(InterruptedException.class);
}
void testObservableTestAssertNoErrors() throws InterruptedException {
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyComplete();
}
void testObservableTestAssertValueCount() throws InterruptedException {
RxJava2Adapter.observableToFlux(Observable.just(1), BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
}

View File

@@ -0,0 +1,152 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.util.List;
import java.util.concurrent.TimeUnit;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Mono;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaSingleToReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(List.class);
}
Single<Object> testSingleErrorThrowable() {
return Single.error(new IllegalStateException());
}
Single<Integer> testSingleDefer() {
return Single.defer(() -> Single.just(1));
}
Single<Object> testSingleErrorCallable() {
return Single.error(
() -> {
throw new IllegalStateException();
});
}
Single<Integer> testSingleFromCallable() {
return Single.fromCallable(() -> 1);
}
Single<Integer> testSingleJust() {
return Single.just(1);
}
Single<Object> testSingleNever() {
return Single.never();
}
Single<Integer> testSingleWrap() {
return Single.wrap(Single.just(1));
}
Integer testSingleBlockingGet() {
return Single.just(1).blockingGet();
}
Flowable<Integer> testSingleConcatWith() {
return Single.just(1).concatWith(Single.just(2));
}
Single<Integer> testSingleDoOnError() {
return Single.just(1).doOnError(System.out::println);
}
Single<Integer> testSingleDoOnSuccess() {
return Single.just(1).doOnSuccess(System.out::println);
}
Maybe<Integer> testSingleFilter() {
return Single.just(1).filter(i -> i > 2);
}
public Mono<String> testUnwrapLambdaSingle() {
return Mono.just("1")
.flatMap(
v ->
RxJava2Adapter.singleToMono(
(Single<String>)
RxJavaReactorMigrationUtil.toJdkFunction(
(String ident) -> RxJava2Adapter.monoToSingle(Mono.just(ident)))
.apply(v)));
}
Single<Integer> testSingleFlatMapLambda() {
return Single.just(1).flatMap(i -> Single.just(i * 2));
}
Completable testSingleFlatMapCompletable() {
return Single.just(1).flatMapCompletable(integer -> Completable.complete());
}
Flowable<Integer> testSingleFlatMapPublisher() {
return Single.just(1).flatMapPublisher(i -> Flowable::just);
}
Completable testCompletableIgnoreElement() {
return Single.just(1).ignoreElement();
}
Single<Integer> testSingleMap() {
return Single.just(1).map(i -> i + 1);
}
Flowable<Integer> testSingleToFlowable() {
return Single.just(1).toFlowable();
}
Single<Integer> testSingleTimeoutLongTimeUnit() {
return Single.just(1).timeout(1000, TimeUnit.MILLISECONDS);
}
Single<Integer> testSingleTimeoutLongTimeUnitSingleSource() {
return Single.just(1).timeout(1000, TimeUnit.MILLISECONDS, Single.just(2));
}
Maybe<Integer> testSingleToMaybe() {
return Single.just(1).toMaybe();
}
Single<Integer> testSingleZipWith() {
return Single.just(1).zipWith(Single.just(2), (integer, integer2) -> integer + integer2);
}
void testSingleTestAssertResultItem() throws InterruptedException {
Single.just(1).test().await().assertResult(1);
Single.just(2).test().await().assertValue(2);
}
void testSingleTestAssertResult() throws InterruptedException {
Single.just(1).test().await().assertResult();
}
void testSingleTestAssertValue() throws InterruptedException {
Single.just(1).test().await().assertValue(i -> i > 2);
Single.just(3).test().await().assertValue(i -> i > 4).assertComplete();
}
void testSingleTestAssertComplete() throws InterruptedException {
Single.just(1).test().await().assertComplete();
}
void testSingleTestAssertErrorClass() throws InterruptedException {
Single.just(1).test().await().assertError(InterruptedException.class);
}
void testSingleTestAssertNoErrors() throws InterruptedException {
Single.just(1).test().await().assertNoErrors();
}
void testSingleTestAssertValueCount() throws InterruptedException {
Single.just(1).test().await().assertValueCount(1);
}
}

View File

@@ -0,0 +1,210 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Completable;
import io.reactivex.CompletableSource;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaSingleToReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(List.class);
}
Single<Object> testSingleErrorThrowable() {
return RxJava2Adapter.monoToSingle(Mono.error(new IllegalStateException()));
}
Single<Integer> testSingleDefer() {
return RxJava2Adapter.monoToSingle(
Mono.defer(() -> RxJava2Adapter.singleToMono(Single.just(1))));
}
Single<Object> testSingleErrorCallable() {
return RxJava2Adapter.monoToSingle(
Mono.error(
RxJavaReactorMigrationUtil.callableAsSupplier(
() -> {
throw new IllegalStateException();
})));
}
Single<Integer> testSingleFromCallable() {
return RxJava2Adapter.monoToSingle(
Mono.fromSupplier(RxJavaReactorMigrationUtil.callableAsSupplier(() -> 1)));
}
Single<Integer> testSingleJust() {
return RxJava2Adapter.monoToSingle(Mono.just(1));
}
Single<Object> testSingleNever() {
return RxJava2Adapter.monoToSingle(Mono.never());
}
Single<Integer> testSingleWrap() {
return Single.just(1);
}
Integer testSingleBlockingGet() {
return RxJava2Adapter.singleToMono(Single.just(1)).block();
}
Flowable<Integer> testSingleConcatWith() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.singleToMono(Single.just(1))
.concatWith(RxJava2Adapter.singleToMono(Single.wrap(Single.just(2)))));
}
Single<Integer> testSingleDoOnError() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(Single.just(1))
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(System.out::println)));
}
Single<Integer> testSingleDoOnSuccess() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(Single.just(1))
.doOnSuccess(RxJavaReactorMigrationUtil.toJdkConsumer(System.out::println)));
}
Maybe<Integer> testSingleFilter() {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.singleToMono(Single.just(1))
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 2)));
}
public Mono<String> testUnwrapLambdaSingle() {
return Mono.just("1")
.flatMap(
v ->
RxJava2Adapter.singleToMono(
(Single<String>)
RxJavaReactorMigrationUtil.toJdkFunction(
(String ident) -> RxJava2Adapter.monoToSingle(Mono.just(ident)))
.apply(v)));
}
Single<Integer> testSingleFlatMapLambda() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(Single.just(1))
.flatMap(i -> RxJava2Adapter.singleToMono(Single.just(i * 2))));
}
Completable testSingleFlatMapCompletable() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.singleToMono(Single.just(1))
.flatMap(
z ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<Integer, CompletableSource>toJdkFunction(
integer -> Completable.complete())
.apply(z))))
.then());
}
Flowable<Integer> testSingleFlatMapPublisher() {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.singleToMono(Single.just(1))
.flatMapMany(RxJavaReactorMigrationUtil.toJdkFunction(i -> Flowable::just)));
}
Completable testCompletableIgnoreElement() {
return RxJava2Adapter.monoToCompletable(RxJava2Adapter.singleToMono(Single.just(1)).then());
}
Single<Integer> testSingleMap() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(Single.just(1))
.map(RxJavaReactorMigrationUtil.toJdkFunction(i -> i + 1)));
}
Flowable<Integer> testSingleToFlowable() {
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.singleToMono(Single.just(1)).flux());
}
Single<Integer> testSingleTimeoutLongTimeUnit() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(Single.just(1))
.timeout(Duration.of(1000, TimeUnit.MILLISECONDS.toChronoUnit())));
}
Single<Integer> testSingleTimeoutLongTimeUnitSingleSource() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(Single.just(1))
.timeout(
Duration.of(1000, TimeUnit.MILLISECONDS.toChronoUnit()),
RxJava2Adapter.singleToMono(Single.wrap(Single.just(2)))));
}
Maybe<Integer> testSingleToMaybe() {
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.singleToMono(Single.just(1)));
}
Single<Integer> testSingleZipWith() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(Single.just(1))
.zipWith(
RxJava2Adapter.singleToMono(Single.wrap(Single.just(2))),
RxJavaReactorMigrationUtil.toJdkBiFunction(
(integer, integer2) -> integer + integer2)));
}
void testSingleTestAssertResultItem() throws InterruptedException {
RxJava2Adapter.singleToMono(Single.just(1))
.as(StepVerifier::create)
.expectNext(1)
.verifyComplete();
RxJava2Adapter.singleToMono(Single.just(2))
.as(StepVerifier::create)
.expectNext(2)
.verifyComplete();
}
void testSingleTestAssertResult() throws InterruptedException {
RxJava2Adapter.singleToMono(Single.just(1)).as(StepVerifier::create).verifyComplete();
}
void testSingleTestAssertValue() throws InterruptedException {
RxJava2Adapter.singleToMono(Single.just(1))
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 2))
.verifyComplete();
RxJava2Adapter.singleToMono(Single.just(3))
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 4))
.verifyComplete();
}
void testSingleTestAssertComplete() throws InterruptedException {
RxJava2Adapter.singleToMono(Single.just(1)).as(StepVerifier::create).verifyComplete();
}
void testSingleTestAssertErrorClass() throws InterruptedException {
RxJava2Adapter.singleToMono(Single.just(1))
.as(StepVerifier::create)
.verifyError(InterruptedException.class);
}
void testSingleTestAssertNoErrors() throws InterruptedException {
RxJava2Adapter.singleToMono(Single.just(1)).as(StepVerifier::create).verifyComplete();
}
void testSingleTestAssertValueCount() throws InterruptedException {
RxJava2Adapter.singleToMono(Single.just(1))
.as(StepVerifier::create)
.expectNextCount(1)
.verifyComplete();
}
}

View File

@@ -0,0 +1,165 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.collect.ImmutableList.toImmutableList;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaToReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(RxJavaReactorMigrationUtil.class);
}
Flux<Integer> testFluxToFlowableToFlux() {
Flowable.just(1)
.as(RxJava2Adapter::flowableToFlux)
.map(e -> e + e)
.as(RxJava2Adapter::fluxToFlowable)
.as(RxJava2Adapter::flowableToFlux)
.flatMap(e -> ImmutableSet::of)
.as(RxJava2Adapter::fluxToFlowable);
return Flux.just(2).as(RxJava2Adapter::fluxToFlowable).as(RxJava2Adapter::flowableToFlux);
}
Mono<Integer> testMonoToFlowableToMono() {
Single.just(1)
.as(RxJava2Adapter::singleToMono)
.map(e -> e + e)
.as(RxJava2Adapter::monoToSingle)
.as(RxJava2Adapter::singleToMono)
.filter(i -> i > 2)
.as(RxJava2Adapter::monoToSingle);
Mono.empty().then().as(RxJava2Adapter::monoToCompletable).as(RxJava2Adapter::completableToMono);
return Mono.just(3).as(RxJava2Adapter::monoToMaybe).as(RxJava2Adapter::maybeToMono);
}
// This one doesnt work
Maybe<String> testRemoveRedundantCast() {
return (Maybe<String>) Maybe.just("foo");
}
Mono<Integer> testMonoErrorCallableSupplierUtil() {
return Mono.just(1)
.switchIfEmpty(
Mono.error(
RxJavaReactorMigrationUtil.callableAsSupplier(() -> new IllegalStateException())));
}
Maybe<Integer> testRemoveUtilCallable() {
return RxJava2Adapter.monoToMaybe(
Mono.fromSupplier(
RxJavaReactorMigrationUtil.callableAsSupplier(
() -> {
String s = "foo";
return null;
})));
}
Flowable<String> testUnnecessaryFunctionConversion() {
Flowable.just(1)
.as(RxJava2Adapter::flowableToFlux)
.map(RxJavaReactorMigrationUtil.<Integer, String>toJdkFunction(String::valueOf))
.as(RxJava2Adapter::fluxToFlowable);
return Flowable.just(1)
.as(RxJava2Adapter::flowableToFlux)
.map(RxJavaReactorMigrationUtil.toJdkFunction(e -> String.valueOf(e)))
.as(RxJava2Adapter::fluxToFlowable);
}
Flowable<Integer> testUnnecessaryBiFunctionConversion() {
return RxJava2Adapter.fluxToFlowable(
Flux.zip(
Flowable.just(1),
Flowable.just(2),
RxJavaReactorMigrationUtil.toJdkBiFunction((i1, i2) -> i1 + i2)));
}
Single<Integer> testUnnecessaryConsumerConversion() {
return Single.just(1)
.as(RxJava2Adapter::singleToMono)
.doOnSuccess(RxJavaReactorMigrationUtil.toJdkConsumer(System.out::println))
.as(RxJava2Adapter::monoToSingle);
}
Maybe<Integer> testUnnecessaryPredicateConversion() {
return Single.just(1)
.as(RxJava2Adapter::singleToMono)
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(i -> i > 2))
.as(RxJava2Adapter::monoToMaybe);
}
Mono<Integer> testMonoFromNestedPublisher() {
return Mono.from(RxJava2Adapter.fluxToFlowable(Flux.just(1)));
}
Mono<Integer> testMonoThen() {
return Mono.just(1).then().then(Mono.just(2));
}
Flux<Integer> testMonoThenMany() {
return Mono.just(1).then().thenMany(Flux.just(1));
}
Mono<Void> testFluxThen() {
return Flux.just(1).ignoreElements().then();
}
Mono<List<Integer>> testMonoCollectToImmutableList() {
return Flux.just(1).collectList();
}
Mono<Integer> testMonoDefaultIfEmpty() {
return Mono.just(1).switchIfEmpty(Mono.just(2));
}
Flux<Integer> testFluxDefaultIfEmpty() {
return Flux.just(1).switchIfEmpty(Flux.just(2));
}
Mono<Void> testMonoVoid() {
return Mono.when(Flux.just(1)).then();
}
Flux<Object> testFlatMapFluxFromArray() {
Flux<String[]> test = null;
return test.flatMap(Flowable::fromArray);
}
Mono<ImmutableSet<Integer>> testFluxToImmutableSet() {
return Flux.just(1).collect(toImmutableList()).map(ImmutableSet::copyOf);
}
Integer testMonoBlock() {
return Mono.just(1).timeout(Duration.ofMillis(1)).block();
}
ImmutableList<Integer> testFluxCollectBlock() {
return ImmutableList.copyOf(Flux.just(1).toIterable());
}
ImmutableSet<Flux<String>> testConcatMapIterable() {
return ImmutableSet.of(
Flux.just(ImmutableList.of("1")).flatMap(Flux::fromIterable),
Flux.just(ImmutableList.of("2")).concatMap(Flux::fromIterable));
}
Mono<Map<Integer, Integer>> testCollectToImmutableMap() {
return Flux.just(1).collectMap(i -> i);
}
}

View File

@@ -0,0 +1,158 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.function.Function.identity;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaToReactorTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(RxJavaReactorMigrationUtil.class);
}
Flux<Integer> testFluxToFlowableToFlux() {
Flowable.just(1)
.as(RxJava2Adapter::flowableToFlux)
.map(e -> e + e)
.flatMap(e -> ImmutableSet::of)
.as(RxJava2Adapter::fluxToFlowable);
return Flux.just(2);
}
Mono<Integer> testMonoToFlowableToMono() {
Single.just(1)
.as(RxJava2Adapter::singleToMono)
.map(e -> e + e)
.filter(i -> i > 2)
.as(RxJava2Adapter::monoToSingle);
Mono.empty().then().then();
return Mono.just(3);
}
// This one doesnt work
Maybe<String> testRemoveRedundantCast() {
return (Maybe<String>) Maybe.just("foo");
}
Mono<Integer> testMonoErrorCallableSupplierUtil() {
return Mono.just(1).switchIfEmpty(Mono.error(() -> new IllegalStateException()));
}
Maybe<Integer> testRemoveUtilCallable() {
return RxJava2Adapter.monoToMaybe(
Mono.fromSupplier(
() -> {
String s = "foo";
return null;
}));
}
Flowable<String> testUnnecessaryFunctionConversion() {
Flowable.just(1)
.as(RxJava2Adapter::flowableToFlux)
.map(String::valueOf)
.as(RxJava2Adapter::fluxToFlowable);
return Flowable.just(1)
.as(RxJava2Adapter::flowableToFlux)
.map(e -> String.valueOf(e))
.as(RxJava2Adapter::fluxToFlowable);
}
Flowable<Integer> testUnnecessaryBiFunctionConversion() {
return RxJava2Adapter.fluxToFlowable(
Flux.<Integer, Integer, Integer>zip(
Flowable.just(1), Flowable.just(2), (i1, i2) -> i1 + i2));
}
Single<Integer> testUnnecessaryConsumerConversion() {
return Single.just(1)
.as(RxJava2Adapter::singleToMono)
.doOnSuccess(System.out::println)
.as(RxJava2Adapter::monoToSingle);
}
Maybe<Integer> testUnnecessaryPredicateConversion() {
return Single.just(1)
.as(RxJava2Adapter::singleToMono)
.filter(i -> i > 2)
.as(RxJava2Adapter::monoToMaybe);
}
Mono<Integer> testMonoFromNestedPublisher() {
return Mono.from(Flux.just(1));
}
Mono<Integer> testMonoThen() {
return Mono.just(1).then(Mono.just(2));
}
Flux<Integer> testMonoThenMany() {
return Mono.just(1).thenMany(Flux.just(1));
}
Mono<Void> testFluxThen() {
return Flux.just(1).then();
}
Mono<List<Integer>> testMonoCollectToImmutableList() {
return Flux.just(1).collect(toImmutableList());
}
Mono<Integer> testMonoDefaultIfEmpty() {
return Mono.just(1).defaultIfEmpty(2);
}
Flux<Integer> testFluxDefaultIfEmpty() {
return Flux.just(1).defaultIfEmpty(2);
}
Mono<Void> testMonoVoid() {
return Mono.when(Flux.just(1));
}
Flux<Object> testFlatMapFluxFromArray() {
Flux<String[]> test = null;
return test.flatMap(Flux::fromArray);
}
Mono<ImmutableSet<Integer>> testFluxToImmutableSet() {
return Flux.just(1).collect(toImmutableSet());
}
Integer testMonoBlock() {
return Mono.just(1).block(Duration.ofMillis(1));
}
ImmutableList<Integer> testFluxCollectBlock() {
return Flux.just(1).collect(toImmutableList()).block();
}
ImmutableSet<Flux<String>> testConcatMapIterable() {
return ImmutableSet.of(
Flux.just(ImmutableList.of("1")).concatMapIterable(identity()),
Flux.just(ImmutableList.of("2")).concatMapIterable(identity()));
}
Mono<Map<Integer, Integer>> testCollectToImmutableMap() {
return Flux.just(1).collect(toImmutableMap(i -> i, identity()));
}
}

View File

@@ -0,0 +1,85 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Completable;
import io.reactivex.CompletableSource;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.functions.Function;
import java.util.List;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaToReactorUnwrapTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(
CompletableSource.class, Function.class, RxJavaReactorMigrationUtil.class, List.class);
}
Completable testFlowableFlatMapUnwrapLambda() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.flatMap(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<Integer, CompletableSource>toJdkFunction(
(Function<Integer, CompletableSource>)
v -> RxJava2Adapter.monoToCompletable(Mono.empty()))
.apply(e))))
.then());
}
Completable testSingleRemoveLambdaWithCast() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.singleToMono(Single.just(1))
.flatMap(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<Integer, Completable>toJdkFunction(
(Function<Integer, Completable>)
v ->
RxJava2Adapter.monoToCompletable(
Mono.justOrEmpty(null)))
.apply(e))))
.then());
}
Mono<Void> testSingleRemoveLambdaWithCompletable() {
return Flux.just(1, 2)
.collectList()
.flatMap(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<List<Integer>, CompletableSource>)
u -> Completable.complete())
.apply(e))))
.then();
}
Mono<Void> testUnwrapCompletableExtendsMono() {
return Mono.just(1)
.flatMap(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<Integer, CompletableSource>toJdkFunction(
(Integer ident) ->
RxJava2Adapter.monoToCompletable(
produceMessage_migrated(ident)))
.apply(e))))
.then();
}
private Mono<Void> produceMessage_migrated(Integer integer) {
return Mono.empty();
}
// Many tests for the `RxJavaUnwrapTemplates` class are not written due to time constraints.
}

View File

@@ -0,0 +1,53 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Completable;
import io.reactivex.CompletableSource;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.functions.Function;
import java.util.List;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
final class RxJavaToReactorUnwrapTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(
CompletableSource.class, Function.class, RxJavaReactorMigrationUtil.class, List.class);
}
Completable testFlowableFlatMapUnwrapLambda() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.flowableToFlux(Flowable.just(1))
.flatMap(
v ->
RxJava2Adapter.completableToMono(
Completable.wrap(RxJava2Adapter.monoToCompletable(Mono.empty()))))
.then());
}
Completable testSingleRemoveLambdaWithCast() {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.singleToMono(Single.just(1)).flatMap(v -> Mono.justOrEmpty(null)).then());
}
Mono<Void> testSingleRemoveLambdaWithCompletable() {
return Flux.just(1, 2)
.collectList()
.flatMap(u -> RxJava2Adapter.completableToMono(Completable.complete()))
.then();
}
Mono<Void> testUnwrapCompletableExtendsMono() {
return Mono.just(1).flatMap(v -> produceMessage_migrated(v)).then();
}
private Mono<Void> produceMessage_migrated(Integer integer) {
return Mono.empty();
}
// Many tests for the `RxJavaUnwrapTemplates` class are not written due to time constraints.
}

33
migration-util/pom.xml Normal file
View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.12.1-SNAPSHOT</version>
</parent>
<artifactId>migration-util</artifactId>
<dependencies>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,376 @@
package tech.picnic.errorprone.migration.util;
import io.reactivex.flowables.GroupedFlowable;
import io.reactivex.functions.Action;
import io.reactivex.internal.fuseable.ConditionalSubscriber;
import io.reactivex.internal.fuseable.QueueSubscription;
import java.util.concurrent.Callable;
import java.util.function.Supplier;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.CoreSubscriber;
import reactor.core.Exceptions;
import reactor.core.Fuseable;
import reactor.core.publisher.GroupedFlux;
import reactor.core.publisher.Operators;
/**
* This util helps bridge the gap between RxJava and Reactor. The methods are used to safely rewrite
* RxJava code to Reactor.
*/
public final class RxJavaReactorMigrationUtil {
private RxJavaReactorMigrationUtil() {}
/**
* Convert {@code Callable<T>} to T
*
* @param callable XXX
* @param <T> XXX
* @return XXX
*/
// XXX: Rename.
@SuppressWarnings("IllegalCatch")
public static <T> T getUnchecked(Callable<T> callable) {
try {
return callable.call();
} catch (Exception e) {
throw new IllegalArgumentException("Callable threw checked exception", e);
}
}
/**
* Convert {@link io.reactivex.functions.Function} to {@link java.util.function.Function}
*
* @param function XXX
* @param <T> XXX
* @param <R> XXX
* @return XXX
*/
// XXX: Rename.
@SuppressWarnings("IllegalCatch")
public static <T, R> java.util.function.Function<T, R> toJdkFunction(
io.reactivex.functions.Function<T, R> function) {
return (t) -> {
try {
return function.apply(t);
} catch (Exception e) {
throw new IllegalArgumentException("BiFunction threw checked exception", e);
}
};
}
/**
* Convert {@link io.reactivex.functions.BiFunction} to {@link java.util.function.BiFunction}
*
* @param biFunction XXX
* @param <T> XXX
* @param <U> XXX
* @param <R> XXX
* @return XXX
*/
@SuppressWarnings("IllegalCatch")
public static <T, U, R> java.util.function.BiFunction<T, U, R> toJdkBiFunction(
io.reactivex.functions.BiFunction<T, U, R> biFunction) {
return (t, u) -> {
try {
return biFunction.apply(t, u);
} catch (Exception e) {
throw new IllegalArgumentException("BiFunction threw checked exception", e);
}
};
}
/**
* Convert {@link java.util.concurrent.Callable} to {@link java.util.function.Supplier}
*
* @param callable XXX
* @param <T> XXX
* @return XXX
*/
@SuppressWarnings("IllegalCatch")
public static <T> Supplier<T> callableAsSupplier(Callable<T> callable) {
return () -> {
try {
return callable.call();
} catch (Exception e) {
throw new IllegalArgumentException("Callable threw checked exception", e);
}
};
}
/**
* Convert {@link io.reactivex.functions.Predicate} to {@link java.util.function.Predicate}
*
* @param predicate XXX
* @param <T> XXX
* @return XXX
*/
// XXX: Rename.
@SuppressWarnings("IllegalCatch")
public static <T> java.util.function.Predicate<T> toJdkPredicate(
io.reactivex.functions.Predicate<T> predicate) {
return (t) -> {
try {
return predicate.test(t);
} catch (Exception e) {
throw new IllegalArgumentException("Predicate threw checked exception", e);
}
};
}
/**
* Convert {@link io.reactivex.functions.Consumer} to {@link java.util.function.Consumer}
*
* @param consumer XXX
* @param <T> XXX
* @return XXX
*/
// XXX: Rename.
@SuppressWarnings("IllegalCatch")
public static <T> java.util.function.Consumer<T> toJdkConsumer(
io.reactivex.functions.Consumer<T> consumer) {
return (t) -> {
try {
consumer.accept(t);
} catch (Exception e) {
throw new IllegalArgumentException("Consumer threw checked exception", e);
}
};
}
/**
* Convert an {@link Action} to a {@link Runnable}.
*
* @param action the {@link Action} to convert.
* @return a {@link Runnable}
*/
@SuppressWarnings("IllegalCatch")
public static Runnable toRunnable(Action action) {
return () -> {
try {
action.run();
} catch (Exception e) {
throw new IllegalArgumentException("Action threw checked exception", e);
}
};
}
// "Coersion" (find better name):
// instanceof (support this?)
// two functional interfaces with:
// B.return type extends A.return type
// A.param 1 type extends B.param 1 type
// ....
// B throws a subset of the exceptions thrown by A
/**
* Utility used to migrate from {@link GroupedFlowable} to {@link GroupedFlux}.
*
* @param source the {@link GroupedFlux} to convert
* @param <K> XXX
* @param <V> XXX
* @return the GroupedFlowable
*/
public static <K, V> GroupedFlowable<K, V> groupedFluxToGroupedFlowable(
GroupedFlux<K, V> source) {
return new GroupedFluxAsGroupedFlowable<>(source);
}
private static final class GroupedFluxAsGroupedFlowable<K, V> extends GroupedFlowable<K, V> {
private final GroupedFlux<K, V> source;
GroupedFluxAsGroupedFlowable(GroupedFlux<K, V> source) {
super(source.key());
this.source = source;
}
@Override
@SuppressWarnings("unchecked")
public void subscribeActual(Subscriber<? super V> s) {
if (s instanceof ConditionalSubscriber) {
source.subscribe(
new FluxAsFlowableConditionalSubscriber<>((ConditionalSubscriber<? super V>) s));
} else {
source.subscribe(new FluxAsFlowableSubscriber<>(s));
}
}
private static final class FluxAsFlowableSubscriber<T>
implements CoreSubscriber<T>, QueueSubscription<T> {
private final Subscriber<? super T> actual;
private Subscription subscription;
private Fuseable.QueueSubscription<T> qs;
FluxAsFlowableSubscriber(Subscriber<? super T> actual) {
this.actual = actual;
}
@Override
@SuppressWarnings("unchecked")
// XXX: Add `@Nonnull` here?
public void onSubscribe(Subscription s) {
if (Operators.validate(this.subscription, s)) {
this.subscription = s;
if (s instanceof Fuseable.QueueSubscription) {
this.qs = (Fuseable.QueueSubscription<T>) s;
}
actual.onSubscribe(this);
}
}
@Override
public void onNext(T t) {
actual.onNext(t);
}
@Override
public void onError(Throwable t) {
actual.onError(t);
}
@Override
public void onComplete() {
actual.onComplete();
}
@Override
public void request(long n) {
subscription.request(n);
}
@Override
public void cancel() {
subscription.cancel();
}
@Override
public T poll() {
return qs.poll();
}
@Override
public boolean isEmpty() {
return qs.isEmpty();
}
@Override
public void clear() {
qs.clear();
}
@Override
public int requestFusion(int requestedMode) {
if (qs != null) {
return qs.requestFusion(requestedMode);
}
return Fuseable.NONE;
}
@Override
public boolean offer(T value) {
throw new UnsupportedOperationException("Should not be called");
}
@Override
public boolean offer(T v1, T v2) {
throw new UnsupportedOperationException("Should not be called");
}
}
private static final class FluxAsFlowableConditionalSubscriber<T>
implements Fuseable.ConditionalSubscriber<T>, QueueSubscription<T> {
private final ConditionalSubscriber<? super T> actual;
private Subscription subscription;
private QueueSubscription<T> qs;
FluxAsFlowableConditionalSubscriber(ConditionalSubscriber<? super T> actual) {
this.actual = actual;
}
@Override
@SuppressWarnings("unchecked")
public void onSubscribe(Subscription s) {
if (Operators.validate(this.subscription, s)) {
this.subscription = s;
if (s instanceof QueueSubscription) {
this.qs = (QueueSubscription<T>) s;
}
actual.onSubscribe(this);
}
}
@Override
public void onNext(T t) {
actual.onNext(t);
}
@Override
public boolean tryOnNext(T t) {
return actual.tryOnNext(t);
}
@Override
public void onError(Throwable t) {
actual.onError(t);
}
@Override
public void onComplete() {
actual.onComplete();
}
@Override
public void request(long n) {
subscription.request(n);
}
@Override
public void cancel() {
subscription.cancel();
}
@Override
@SuppressWarnings("IllegalCatch")
public T poll() {
try {
return qs.poll();
} catch (Exception ex) {
throw Exceptions.bubble(ex);
}
}
@Override
public boolean isEmpty() {
return qs.isEmpty();
}
@Override
public void clear() {
qs.clear();
}
@Override
public int requestFusion(int requestedMode) {
if (qs != null) {
return qs.requestFusion(requestedMode);
}
return NONE;
}
@Override
public boolean offer(T v1) {
throw new UnsupportedOperationException("Should not be called!");
}
@Override
public boolean offer(T v1, T v2) {
throw new UnsupportedOperationException("Should not be called!");
}
}
}
}

87
pom.xml
View File

@@ -4,7 +4,7 @@
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.11.0</version>
<version>0.12.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Picnic :: Error Prone Support</name>
@@ -41,6 +41,7 @@
<modules>
<module>documentation-support</module>
<module>error-prone-contrib</module>
<module>migration-util</module>
<module>refaster-compiler</module>
<module>refaster-runner</module>
<module>refaster-support</module>
@@ -49,7 +50,7 @@
<scm>
<developerConnection>scm:git:git@github.com:PicnicSupermarket/error-prone-support.git</developerConnection>
<tag>v0.11.0</tag>
<tag>v0.12.0</tag>
<url>https://github.com/PicnicSupermarket/error-prone-support</url>
</scm>
<issueManagement>
@@ -141,7 +142,7 @@
<groupId.error-prone>com.google.errorprone</groupId.error-prone>
<!-- The build timestamp is derived from the most recent commit
timestamp in support of reproducible builds. -->
<project.build.outputTimestamp>2023-05-14T15:07:55Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2023-06-21T19:15:38Z</project.build.outputTimestamp>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Glob pattern identifying Refaster rule definition files. These
Java classes don't contain "regular" code, and thus require special
@@ -197,11 +198,11 @@
<!-- Dependency and plugin versions that are referenced in more than
one place. We use these to keep dependencies in sync. Version numbers
that need to be referenced only once should *not* be listed here. -->
<version.auto-service>1.0.1</version.auto-service>
<version.auto-service>1.1.1</version.auto-service>
<version.auto-value>1.10.1</version.auto-value>
<version.error-prone>${version.error-prone-orig}</version.error-prone>
<version.error-prone-fork>v${version.error-prone-orig}-picnic-1</version.error-prone-fork>
<version.error-prone-orig>2.19.1</version.error-prone-orig>
<version.error-prone-fork>${version.error-prone-orig}</version.error-prone-fork>
<version.error-prone-orig>HEAD-SNAPSHOT</version.error-prone-orig>
<version.error-prone-slf4j>0.1.18</version.error-prone-slf4j>
<version.guava-beta-checker>1.0</version.guava-beta-checker>
<version.jdk>11</version.jdk>
@@ -209,8 +210,8 @@
<version.mockito>5.3.1</version.mockito>
<version.nopen-checker>1.0.1</version.nopen-checker>
<version.nullaway>0.10.10</version.nullaway>
<version.pitest-git>1.0.10</version.pitest-git>
<version.surefire>3.1.0</version.surefire>
<version.pitest-git>1.0.11</version.pitest-git>
<version.surefire>3.1.2</version.surefire>
</properties>
<dependencyManagement>
@@ -245,6 +246,11 @@
<artifactId>documentation-support</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>migration-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-compiler</artifactId>
@@ -268,7 +274,7 @@
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>2.15.0</version>
<version>2.15.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -307,14 +313,14 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-bom</artifactId>
<version>31.1-jre</version>
<version>32.0.1-jre</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<version>1.1.3</version>
<version>1.1.4</version>
</dependency>
<!-- Specified as a workaround for
https://github.com/mojohaus/versions-maven-plugin/issues/244. -->
@@ -326,7 +332,7 @@
<dependency>
<groupId>com.newrelic.agent.java</groupId>
<artifactId>newrelic-api</artifactId>
<version>8.2.0</version>
<version>8.4.0</version>
</dependency>
<!-- Specified as a workaround for
https://github.com/mojohaus/versions-maven-plugin/issues/244. -->
@@ -338,7 +344,7 @@
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-bom</artifactId>
<version>2022.0.7</version>
<version>2022.0.8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -350,12 +356,12 @@
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.10</version>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.2.9</version>
<version>2.2.12</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
@@ -387,7 +393,7 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.14.4</version>
<version>1.14.5</version>
</dependency>
<!-- Specified so that Renovate will file Maven upgrade PRs, which
subsequently will cause `maven-enforcer-plugin` to require that
@@ -412,7 +418,7 @@
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.34.0</version>
<version>3.35.0</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
@@ -458,12 +464,12 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.7.11</version>
<version>2.7.12</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.7.1</version>
<version>7.8.0</version>
</dependency>
</dependencies>
</dependencyManagement>
@@ -570,7 +576,7 @@
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
<version>5.0.0</version>
<version>6.0.0</version>
<configuration>
<injectAllReactorProjects>true</injectAllReactorProjects>
<runOnlyOnce>true</runOnlyOnce>
@@ -589,7 +595,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.2</version>
<version>3.3.0</version>
<configuration>
<checkstyleRules>
<!-- We only enable rules that are not enforced by
@@ -839,7 +845,7 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.11.0</version>
<version>10.12.0</version>
</dependency>
<dependency>
<groupId>io.spring.nohttp</groupId>
@@ -940,7 +946,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.5.0</version>
<version>3.6.0</version>
<configuration>
<!-- XXX: Drop `ignoreAllNonTestScoped` once
https://issues.apache.org/jira/browse/MNG-6058 is
@@ -972,7 +978,7 @@
<banDuplicateClasses>
<dependencies>
<dependency>
<groupId>org.checkerframework</groupId>
<groupId>io.github.eisop</groupId>
<artifactId>dataflow-errorprone</artifactId>
<!-- This package is contained in
Checker Framework's `checker-qual` and
@@ -1051,7 +1057,7 @@
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.6.2</version>
<version>1.7.0</version>
</dependency>
</dependencies>
<executions>
@@ -1141,7 +1147,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>3.0.0</version>
<version>3.0.1</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<preparationProfiles>release</preparationProfiles>
@@ -1168,7 +1174,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<version>3.3.0</version>
<executions>
<execution>
<id>generate-source-jar</id>
@@ -1202,7 +1208,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>2.0.1</version>
<version>2.1.0</version>
<configuration>
<includedLicenses>
<!-- The SPDX IDs of licenses of third-party
@@ -1305,7 +1311,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.15.0</version>
<version>2.16.0</version>
<configuration>
<updateBuildOutputTimestampPolicy>never</updateBuildOutputTimestampPolicy>
</configuration>
@@ -1356,7 +1362,7 @@
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.13.1</version>
<version>1.14.1</version>
<configuration>
<excludedClasses>
<!-- AutoValue generated classes. -->
@@ -1385,7 +1391,7 @@
<dependency>
<groupId>com.groupcdg.arcmutate</groupId>
<artifactId>base</artifactId>
<version>1.0.4</version>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.groupcdg.pitest</groupId>
@@ -1395,7 +1401,7 @@
<dependency>
<groupId>org.pitest</groupId>
<artifactId>pitest-junit5-plugin</artifactId>
<version>1.1.2</version>
<version>1.2.0</version>
</dependency>
</dependencies>
<executions>
@@ -1438,13 +1444,13 @@
fork, some other dependencies depend on the official (i.e.,
non-forked) `error_prone_annotations`. Here we fix which
version is pulled in. -->
<dependencies>
<dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
<version>${version.error-prone-orig}</version>
</dependency>
</dependencies>
<!-- <dependencies>-->
<!-- <dependency>-->
<!-- <groupId>com.google.errorprone</groupId>-->
<!-- <artifactId>error_prone_annotations</artifactId>-->
<!-- <version>${version.error-prone-orig}</version>-->
<!-- </dependency>-->
<!-- </dependencies>-->
</dependencyManagement>
<build>
<pluginManagement>
@@ -1720,6 +1726,9 @@
-Xep:Java7ApiChecker:OFF
<!-- We don't target JDK 8. -->
-Xep:Java8ApiChecker:OFF
<!-- XXX: Triggers an IOOBE. See
https://github.com/google/error-prone/pull/3976. -->
-Xep:MemberName:OFF
<!-- We don't target Android. -->
-Xep:StaticOrDefaultInterfaceMethod:OFF
<!-- We generally discourage `var` use. -->

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.11.0</version>
<version>0.12.1-SNAPSHOT</version>
</parent>
<artifactId>refaster-compiler</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.11.0</version>
<version>0.12.1-SNAPSHOT</version>
</parent>
<artifactId>refaster-runner</artifactId>
@@ -45,6 +45,7 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-support</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>

View File

@@ -22,7 +22,6 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import tech.picnic.errorprone.refaster.ErrorProneFork;
final class RefasterTest {
private final CompilationTestHelper compilationHelper =
@@ -80,74 +79,66 @@ final class RefasterTest {
SeverityLevel defaultSeverity = BugCheckerInfo.create(Refaster.class).defaultSeverity();
/* { arguments, expectedSeverities } */
return Stream.concat(
Stream.of(
arguments(
ImmutableList.of(), ImmutableList.of(defaultSeverity, WARNING, ERROR, SUGGESTION)),
arguments(ImmutableList.of("-Xep:Refaster:OFF"), ImmutableList.of()),
arguments(
ImmutableList.of("-Xep:Refaster:DEFAULT"),
ImmutableList.of(defaultSeverity, WARNING, ERROR, SUGGESTION)),
arguments(
ImmutableList.of("-Xep:Refaster:WARN"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:ERROR"),
ImmutableList.of(ERROR, ERROR, ERROR, ERROR)),
arguments(
ImmutableList.of("-XepAllErrorsAsWarnings"),
ImmutableList.of(defaultSeverity, WARNING, WARNING, SUGGESTION)),
arguments(
ImmutableList.of("-Xep:Refaster:OFF", "-XepAllErrorsAsWarnings"),
ImmutableList.of()),
arguments(
ImmutableList.of("-Xep:Refaster:DEFAULT", "-XepAllErrorsAsWarnings"),
ImmutableList.of(defaultSeverity, WARNING, WARNING, SUGGESTION)),
arguments(
ImmutableList.of("-Xep:Refaster:WARN", "-XepAllErrorsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:ERROR", "-XepAllErrorsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING))),
ErrorProneFork.isErrorProneForkAvailable()
? Stream.of(
arguments(
ImmutableList.of("-Xep:Refaster:OFF", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of()),
arguments(
ImmutableList.of("-Xep:Refaster:DEFAULT", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, ERROR, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:WARN", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:ERROR", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(ERROR, ERROR, ERROR, ERROR)),
arguments(
ImmutableList.of(
"-Xep:Refaster:OFF",
"-XepAllErrorsAsWarnings",
"-XepAllSuggestionsAsWarnings"),
ImmutableList.of()),
arguments(
ImmutableList.of(
"-Xep:Refaster:DEFAULT",
"-XepAllErrorsAsWarnings",
"-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of(
"-Xep:Refaster:WARN",
"-XepAllErrorsAsWarnings",
"-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of(
"-Xep:Refaster:ERROR",
"-XepAllErrorsAsWarnings",
"-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)))
: Stream.empty());
return Stream.of(
arguments(
ImmutableList.of(), ImmutableList.of(defaultSeverity, WARNING, ERROR, SUGGESTION)),
arguments(ImmutableList.of("-Xep:Refaster:OFF"), ImmutableList.of()),
arguments(
ImmutableList.of("-Xep:Refaster:DEFAULT"),
ImmutableList.of(defaultSeverity, WARNING, ERROR, SUGGESTION)),
arguments(
ImmutableList.of("-Xep:Refaster:WARN"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:ERROR"), ImmutableList.of(ERROR, ERROR, ERROR, ERROR)),
arguments(
ImmutableList.of("-XepAllErrorsAsWarnings"),
ImmutableList.of(defaultSeverity, WARNING, WARNING, SUGGESTION)),
arguments(
ImmutableList.of("-Xep:Refaster:OFF", "-XepAllErrorsAsWarnings"), ImmutableList.of()),
arguments(
ImmutableList.of("-Xep:Refaster:DEFAULT", "-XepAllErrorsAsWarnings"),
ImmutableList.of(defaultSeverity, WARNING, WARNING, SUGGESTION)),
arguments(
ImmutableList.of("-Xep:Refaster:WARN", "-XepAllErrorsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:ERROR", "-XepAllErrorsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of("-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, ERROR, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:OFF", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of()),
arguments(
ImmutableList.of("-Xep:Refaster:DEFAULT", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, ERROR, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:WARN", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of("-Xep:Refaster:ERROR", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(ERROR, ERROR, ERROR, ERROR)),
arguments(
ImmutableList.of("-XepAllErrorsAsWarnings", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of(
"-Xep:Refaster:OFF", "-XepAllErrorsAsWarnings", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of()),
arguments(
ImmutableList.of(
"-Xep:Refaster:DEFAULT", "-XepAllErrorsAsWarnings", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of(
"-Xep:Refaster:WARN", "-XepAllErrorsAsWarnings", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)),
arguments(
ImmutableList.of(
"-Xep:Refaster:ERROR", "-XepAllErrorsAsWarnings", "-XepAllSuggestionsAsWarnings"),
ImmutableList.of(WARNING, WARNING, WARNING, WARNING)));
}
/**

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.11.0</version>
<version>0.12.1-SNAPSHOT</version>
</parent>
<artifactId>refaster-support</artifactId>

View File

@@ -148,8 +148,7 @@ public abstract class AnnotatedCompositeCodeTransformer implements CodeTransform
private static SeverityLevel overrideSeverity(SeverityLevel severity, Context context) {
ErrorProneOptions options = context.get(ErrorProneOptions.class);
SeverityLevel minSeverity =
ErrorProneFork.isSuggestionsAsWarningsEnabled(options) ? WARNING : SUGGESTION;
SeverityLevel minSeverity = options.isSuggestionsAsWarnings() ? WARNING : SUGGESTION;
SeverityLevel maxSeverity = options.isDropErrorsToWarnings() ? WARNING : ERROR;
return Comparators.max(Comparators.min(severity, minSeverity), maxSeverity);

View File

@@ -1,56 +0,0 @@
package tech.picnic.errorprone.refaster;
import com.google.errorprone.ErrorProneOptions;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Optional;
/**
* Utility class that enables the runtime to determine whether Picnic's fork of Error Prone is on
* the classpath.
*
* @see <a href="https://github.com/PicnicSupermarket/error-prone">Picnic's Error Prone fork</a>
*/
public final class ErrorProneFork {
private static final Optional<Method> ERROR_PRONE_OPTIONS_IS_SUGGESTIONS_AS_WARNINGS_METHOD =
Arrays.stream(ErrorProneOptions.class.getDeclaredMethods())
.filter(m -> Modifier.isPublic(m.getModifiers()))
.filter(m -> "isSuggestionsAsWarnings".equals(m.getName()))
.findFirst();
private ErrorProneFork() {}
/**
* Tells whether Picnic's fork of Error Prone is available.
*
* @return {@code true} iff classpath introspection indicates the presence of Error Prone
* modifications that are assumed to be present only in Picnic's fork.
*/
public static boolean isErrorProneForkAvailable() {
return ERROR_PRONE_OPTIONS_IS_SUGGESTIONS_AS_WARNINGS_METHOD.isPresent();
}
/**
* Tells whether the custom {@code -XepAllSuggestionsAsWarnings} flag is set.
*
* @param options The currently active Error Prone options.
* @return {@code true} iff {@link #isErrorProneForkAvailable() the Error Prone fork is available}
* and the aforementioned flag is set.
* @see <a href="https://github.com/google/error-prone/pull/3301">google/error-prone#3301</a>
*/
public static boolean isSuggestionsAsWarningsEnabled(ErrorProneOptions options) {
return ERROR_PRONE_OPTIONS_IS_SUGGESTIONS_AS_WARNINGS_METHOD
.filter(m -> Boolean.TRUE.equals(invoke(m, options)))
.isPresent();
}
private static Object invoke(Method method, Object obj, Object... args) {
try {
return method.invoke(obj, args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException(String.format("Failed to invoke method '%s'", method), e);
}
}
}

View File

@@ -0,0 +1,92 @@
package tech.picnic.errorprone.refaster.matchers;
import com.google.errorprone.VisitorState;
import com.google.errorprone.matchers.Matcher;
import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.ParenthesizedTree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.UnaryTree;
/** A matcher of expressions that likely require little to no computation. */
public final class IsLikelyTrivialComputation implements Matcher<ExpressionTree> {
private static final long serialVersionUID = 1L;
/** Instantiates a new {@link IsLikelyTrivialComputation} instance. */
public IsLikelyTrivialComputation() {}
@Override
public boolean matches(ExpressionTree expressionTree, VisitorState state) {
if (expressionTree instanceof MethodInvocationTree) {
// XXX: Method invocations are generally *not* trivial computations, but we make an exception
// for nullary method invocations on the result of a trivial computation. This exception
// allows this `Matcher` to by the `OptionalOrElseGet` Refaster rule, such that it does not
// suggest the introduction of lambda expressions that are better expressed as method
// references. Once the `MethodReferenceUsage` bug checker is production-ready, this exception
// should be removed. (But at that point, instead defining a `RequiresComputation` matcher may
// be more appropriate.)
MethodInvocationTree methodInvocation = (MethodInvocationTree) expressionTree;
if (methodInvocation.getArguments().isEmpty()
&& matches(methodInvocation.getMethodSelect())) {
return true;
}
}
return matches(expressionTree);
}
// XXX: Some `BinaryTree`s may represent what could be considered "trivial computations".
// Depending on feedback such trees may be matched in the future.
private static boolean matches(ExpressionTree expressionTree) {
if (expressionTree instanceof ArrayAccessTree) {
return matches(((ArrayAccessTree) expressionTree).getExpression())
&& matches(((ArrayAccessTree) expressionTree).getIndex());
}
if (expressionTree instanceof LiteralTree) {
return true;
}
if (expressionTree instanceof LambdaExpressionTree) {
/*
* Lambda expressions encapsulate computations, but their definition does not involve
* significant computation.
*/
return true;
}
if (expressionTree instanceof IdentifierTree) {
return true;
}
if (expressionTree instanceof MemberReferenceTree) {
return matches(((MemberReferenceTree) expressionTree).getQualifierExpression());
}
if (expressionTree instanceof MemberSelectTree) {
return matches(((MemberSelectTree) expressionTree).getExpression());
}
if (expressionTree instanceof ParenthesizedTree) {
return matches(((ParenthesizedTree) expressionTree).getExpression());
}
if (expressionTree instanceof TypeCastTree) {
return matches(((TypeCastTree) expressionTree).getExpression());
}
if (expressionTree instanceof UnaryTree) {
// XXX: Arguably side-effectful options such as pre- and post-increment and -decrement are not
// trivial.
return matches(((UnaryTree) expressionTree).getExpression());
}
return false;
}
}

View File

@@ -1,67 +0,0 @@
package tech.picnic.errorprone.refaster;
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import com.google.errorprone.BugPattern;
import com.google.errorprone.CompilationTestHelper;
import com.google.errorprone.ErrorProneOptions;
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.sun.source.tree.ClassTree;
import org.junit.jupiter.api.Test;
final class ErrorProneForkTest {
@Test
void isErrorProneForkAvailable() {
assertThat(ErrorProneFork.isErrorProneForkAvailable())
.isEqualTo(Boolean.TRUE.toString().equals(System.getProperty("error-prone-fork-in-use")));
}
@Test
void isSuggestionsAsWarningsEnabledWithoutFlag() {
CompilationTestHelper.newInstance(TestChecker.class, getClass())
.addSourceLines(
"A.java",
"// BUG: Diagnostic contains: Suggestions as warnings enabled: false",
"class A {}")
.doTest();
}
@Test
void isSuggestionsAsWarningsEnabledWithFlag() {
assumeTrue(
ErrorProneFork.isErrorProneForkAvailable(),
"Picnic's Error Prone fork is not on the classpath");
CompilationTestHelper.newInstance(TestChecker.class, getClass())
.setArgs("-XepAllSuggestionsAsWarnings")
.addSourceLines(
"A.java",
"// BUG: Diagnostic contains: Suggestions as warnings enabled: true",
"class A {}")
.doTest();
}
/**
* A {@link BugChecker} that reports the result of {@link
* ErrorProneFork#isSuggestionsAsWarningsEnabled(ErrorProneOptions)}.
*/
@BugPattern(summary = "Flags classes with a custom error message", severity = ERROR)
public static final class TestChecker extends BugChecker implements ClassTreeMatcher {
private static final long serialVersionUID = 1L;
@Override
public Description matchClass(ClassTree tree, VisitorState state) {
return buildDescription(tree)
.setMessage(
String.format(
"Suggestions as warnings enabled: %s",
ErrorProneFork.isSuggestionsAsWarningsEnabled(state.errorProneOptions())))
.build();
}
}
}

View File

@@ -8,8 +8,11 @@ import com.google.errorprone.matchers.Matcher;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreeScanner;
import org.jspecify.annotations.Nullable;
@@ -31,18 +34,27 @@ abstract class AbstractMatcherTestChecker extends BugChecker implements Compilat
@Override
public Description matchCompilationUnit(CompilationUnitTree compilationUnit, VisitorState state) {
new TreeScanner<@Nullable Void, @Nullable Void>() {
new TreeScanner<@Nullable Void, TreePath>() {
@Override
public @Nullable Void scan(Tree tree, @Nullable Void unused) {
if (tree instanceof ExpressionTree && delegate.matches((ExpressionTree) tree, state)) {
state.reportMatch(describeMatch(tree));
public @Nullable Void scan(@Nullable Tree tree, TreePath treePath) {
if (tree == null) {
return null;
}
return super.scan(tree, unused);
TreePath path = new TreePath(treePath, tree);
if (tree instanceof ExpressionTree) {
ExpressionTree expressionTree = (ExpressionTree) tree;
if (!isMethodSelect(expressionTree, path)
&& delegate.matches(expressionTree, state.withPath(path))) {
state.reportMatch(describeMatch(tree));
}
}
return super.scan(tree, path);
}
@Override
public @Nullable Void visitImport(ImportTree node, @Nullable Void unused) {
public @Nullable Void visitImport(ImportTree tree, TreePath path) {
/*
* We're not interested in matching import statements. While components of these
* can be `ExpressionTree`s, they will never be matched by Refaster.
@@ -51,15 +63,42 @@ abstract class AbstractMatcherTestChecker extends BugChecker implements Compilat
}
@Override
public @Nullable Void visitMethod(MethodTree node, @Nullable Void unused) {
public @Nullable Void visitMethod(MethodTree tree, TreePath path) {
/*
* We're not interested in matching e.g. parameter and return type declarations. While these
* can be `ExpressionTree`s, they will never be matched by Refaster.
*/
return scan(node.getBody(), unused);
return scan(tree.getBody(), new TreePath(path, tree));
}
}.scan(compilationUnit, null);
@Override
public @Nullable Void visitTypeCast(TypeCastTree tree, TreePath path) {
/*
* We're not interested in matching the parenthesized type subtree that is part of a type
* cast expression. While such trees can be `ExpressionTree`s, they will never be matched by
* Refaster.
*/
return scan(tree.getExpression(), new TreePath(path, tree));
}
}.scan(compilationUnit, state.getPath());
return Description.NO_MATCH;
}
/**
* Tells whether the given {@link ExpressionTree} is the {@link
* MethodInvocationTree#getMethodSelect() method select} portion of a method invocation.
*
* <p>Such {@link ExpressionTree}s will never be matched by Refaster.
*/
private static boolean isMethodSelect(ExpressionTree tree, TreePath path) {
TreePath parentPath = path.getParentPath();
if (parentPath == null) {
return false;
}
Tree parentTree = parentPath.getLeaf();
return parentTree instanceof MethodInvocationTree
&& ((MethodInvocationTree) parentTree).getMethodSelect().equals(tree);
}
}

View File

@@ -0,0 +1,147 @@
package tech.picnic.errorprone.refaster.matchers;
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
import com.google.errorprone.BugPattern;
import com.google.errorprone.CompilationTestHelper;
import com.google.errorprone.bugpatterns.BugChecker;
import com.sun.source.tree.ReturnTree;
import org.junit.jupiter.api.Test;
final class IsLikelyTrivialComputationTest {
@Test
void matches() {
CompilationTestHelper.newInstance(MatcherTestChecker.class, getClass())
.addSourceLines(
"A.java",
"import java.util.function.Predicate;",
"",
"class A {",
" String negative1() {",
" return String.valueOf(1);",
" }",
"",
" String negative2() {",
" return toString().toString();",
" }",
"",
" String negative3() {",
" return \"foo\" + toString();",
" }",
"",
" byte negative4() {",
" return \"foo\".getBytes()[0];",
" }",
"",
" int negative5() {",
" int[] arr = new int[0];",
" return arr[hashCode()];",
" }",
"",
" int negative6() {",
" return 1 * 2;",
" }",
"",
" Predicate<String> negative7() {",
" return toString()::equals;",
" }",
"",
" String negative8() {",
" return (toString());",
" }",
"",
" Object negative9() {",
" return (Object) toString();",
" }",
"",
" int negative10() {",
" return -hashCode();",
" }",
"",
" String positive1() {",
" // BUG: Diagnostic contains:",
" return toString();",
" }",
"",
" String positive2() {",
" // BUG: Diagnostic contains:",
" return this.toString();",
" }",
"",
" int positive3() {",
" int[] arr = new int[0];",
" // BUG: Diagnostic contains:",
" return arr[0];",
" }",
"",
" String positive4() {",
" // BUG: Diagnostic contains:",
" return null;",
" }",
"",
" boolean positive5() {",
" // BUG: Diagnostic contains:",
" return false;",
" }",
"",
" int positive6() {",
" // BUG: Diagnostic contains:",
" return 0;",
" }",
"",
" String positive7() {",
" // BUG: Diagnostic contains:",
" return \"foo\" + \"bar\";",
" }",
"",
" Predicate<String> positive8() {",
" // BUG: Diagnostic contains:",
" return v -> \"foo\".equals(v);",
" }",
"",
" A positive9() {",
" // BUG: Diagnostic contains:",
" return this;",
" }",
"",
" Predicate<String> positive10() {",
" // BUG: Diagnostic contains:",
" return \"foo\"::equals;",
" }",
"",
" A positive11() {",
" // BUG: Diagnostic contains:",
" return (this);",
" }",
"",
" Object positive12() {",
" // BUG: Diagnostic contains:",
" return (Object) this;",
" }",
"",
" boolean positive13() {",
" // BUG: Diagnostic contains:",
" return !false;",
" }",
"}")
.doTest();
}
/** A {@link BugChecker} that simply delegates to {@link IsLikelyTrivialComputation}. */
@BugPattern(
summary = "Flags return statement expressions matched by `IsLikelyTrivialComputation`",
severity = ERROR)
public static final class MatcherTestChecker extends AbstractMatcherTestChecker {
private static final long serialVersionUID = 1L;
// XXX: This is a false positive reported by Checkstyle. See
// https://github.com/checkstyle/checkstyle/issues/10161#issuecomment-1242732120.
@SuppressWarnings("RedundantModifier")
public MatcherTestChecker() {
super(
(expressionTree, state) ->
state.getPath().getParentPath().getLeaf() instanceof ReturnTree
&& new IsLikelyTrivialComputation().matches(expressionTree, state));
}
}
}

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.11.0</version>
<version>0.12.1-SNAPSHOT</version>
</parent>
<artifactId>refaster-test-support</artifactId>

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# Executes Pitest to determine the code base' mutation test coverage. The set
# of tests executed can optionally be restricted by name. The results are found
# in each Maven module's `target/pit-reports` directory.
# Executes Pitest to determine the code's mutation test coverage. The set of
# tests executed can optionally be restricted by name. The results are found in
# each Maven module's `target/pit-reports` directory.
set -e -u -o pipefail
@@ -11,7 +11,7 @@ if [ "${#}" -gt 1 ]; then
exit 1
fi
targetTests=${1:-*}
targetTests="${1:-*}"
mvn clean test pitest:mutationCoverage \
-DargLine.xmx=2048m \