Compare commits

...

126 Commits

Author SHA1 Message Date
Rick Ossendrijver
db949f852b Remove things for SS 2021-11-18 13:11:49 +01:00
Rick Ossendrijver
0d574016d0 Improve the retrieval of receiver 2021-11-17 13:58:20 +01:00
Rick Ossendrijver
a0b9a7eb64 Introduce first version of StringIsEmpty BugPattern for demo purposes 2021-11-17 13:47:22 +01:00
Rick Ossendrijver
6528175120 Add Single#never() template 2021-11-12 15:03:06 +01:00
Rick Ossendrijver
078aeb431b Cleanup, sorting, moving, tests 2021-11-11 08:38:30 +01:00
Rick Ossendrijver
1343ddf5ac Add templates for Gravitee migration 2021-10-17 15:12:20 +02:00
Rick Ossendrijver
3b5d3604aa Improve template generic types 2021-10-16 13:27:52 +02:00
Rick Ossendrijver
28905107a0 Run textwidth=72 2021-10-15 20:37:05 +02:00
Rick Ossendrijver
8e8d75792a Many rewrites 2021-10-15 13:03:02 +02:00
Stephan Schroevers
d9f1c1aef6 Submit defeat 2021-10-14 18:12:23 +02:00
Rick Ossendrijver
899e3f7d8f Add fix for every occurence but is still problem 2021-10-14 17:21:34 +02:00
Rick Ossendrijver
7a38970c77 Many rewrite from .as() to RxJava2Adapter.() 2021-10-14 17:03:21 +02:00
Stephan Schroevers
dccd031846 Generalize 2021-10-14 15:50:21 +02:00
Rick Ossendrijver
0268418f8d Push 2021-10-14 15:34:53 +02:00
Rick Ossendrijver
4ab1ecafd4 Move some templates and temporarily turn off for start of migration 2021-10-14 12:43:51 +02:00
Rick Ossendrijver
b4ece293ef Add new templates 2021-10-12 14:06:30 +02:00
Rick Ossendrijver
52244dc28f Add assorted templates to improve the migration 2021-10-11 22:07:55 +02:00
Rick Ossendrijver
05e7a064fa Add exttra rule for Flux.array with single element 2021-10-08 18:42:04 +02:00
Rick Ossendrijver
6a55177e08 Add extra cases for test.await.assertXXX 2021-10-07 11:26:32 +02:00
Rick Ossendrijver
d69c442e2d Add extra templates 2021-10-07 09:43:49 +02:00
Rick Ossendrijver
c61851a373 Add extra templates and tests 2021-10-05 15:53:49 +02:00
Rick Ossendrijver
27cade2fc7 Apply suggestions and add templates 2021-10-05 13:32:26 +02:00
Rick Ossendrijver
d218b6f4d8 Fix tests and improve imports of the tests 2021-10-05 09:45:18 +02:00
Rick Ossendrijver
d6c3128940 Add unwrap methods 2021-10-04 19:55:47 +02:00
Rick Ossendrijver
a9c08e0c75 Add RxJavaUnwrapTemplates 2021-10-04 13:27:09 +02:00
Rick Ossendrijver
04e5cf4f03 Format for Stephan ;) 2021-10-02 17:08:40 +02:00
Rick Ossendrijver
8235c0649f Update the templates by removing some flat/concat|maps and adding tests 2021-10-02 17:07:15 +02:00
Rick Ossendrijver
a5ac555a04 Add minor improvements and cleanup 2021-10-01 15:22:55 +02:00
Rick Ossendrijver
cdefaf1b36 Add clean up Refaster templates 2021-09-28 16:32:15 +02:00
Rick Ossendrijver
2a70576662 Improve some templates and add one for every RxJava type for assertNoValues() 2021-09-28 14:07:50 +02:00
Rick Ossendrijver
4531720691 Write templates and fix edge cases 2021-09-28 09:28:07 +02:00
Rick Ossendrijver
e202422f34 Improve templates and cleanup tests 2021-09-27 10:32:32 +02:00
Stephan Schroevers
efea6c0ca9 As discussed 2021-09-25 12:58:35 +02:00
Rick Ossendrijver
796608a777 Improve templates so that they match PRP code 2021-09-24 14:43:58 +02:00
Rick Ossendrijver
5049044579 Add two examples that work for flatMapCompletable single and flowable 2021-09-24 13:01:14 +02:00
Rick Ossendrijver
6c6c21f8fb YESSSS fix the flatmapCompletable for Single and Flowable 2021-09-23 18:41:24 +02:00
Stephan Schroevers
b66d3afc7d Ideation 2021-09-23 16:28:46 +02:00
Rick Ossendrijver
050b85b58a Quick push 2021-09-23 16:11:21 +02:00
Stephan Schroevers
5db4e30140 Pair programming 2021-09-23 11:21:13 +02:00
Rick Ossendrijver
702987e2ca Do more things 2021-09-23 10:06:57 +02:00
Rick Ossendrijver
9995e65f7c Add templates for assertFailure and a MonoNestedPublisher 2021-09-22 21:59:36 +02:00
Rick Ossendrijver
061bc07b2f Many tweaks and improvements 2021-09-22 21:24:15 +02:00
Rick Ossendrijver
445fd26942 Update the templates and format 2021-09-21 13:52:13 +02:00
Rick Ossendrijver
5703608f66 Add extra case of assertValue with assertComplete 2021-09-21 09:46:01 +02:00
Rick Ossendrijver
47a9571035 Add AssertValue for 4 types 2021-09-21 09:33:12 +02:00
Rick Ossendrijver
0d92ae93e9 Add the test conversions to StepVerifier for Completable 2021-09-21 09:09:33 +02:00
Rick Ossendrijver
24d8535f20 Add RxJava test to StepVerifier tests templates 2021-09-21 08:42:01 +02:00
Rick Ossendrijver
0c2715e4e3 Add import to test output file 2021-09-20 11:28:33 +02:00
Rick Ossendrijver
54584a89a0 Add filtering 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
fe3e4bac9c Cleanup code and tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
7ac9650775 Add templates and cleanup todos 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
f96e6ab7cd Fix some todos and remove some annotations sadly enough 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e1d4917772 Solve XXXs and add tests and templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
6a229f86cb Add todos and information 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
224b9cf2a9 Update many templates and move the MigrationUtil to own module 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
84b5f99d23 Fix bug in test 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
5635538013 Some errors in there, but push many new templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e66e2be8ff Add many templates and tiny improvements. Note: tests are broken now because building against picnic-error-prone 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
773eeae53b Make EPS use the HEAD-SNAPSHOT of Error Prone for CanBeTransformedTo 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
0e511e3fde Add templates and tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
d5912cc80a Improve the templates and add many tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
3fd8570831 Turn on extra tests and fix many issues, but leave a few for next time. 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
73810e0676 Small improvements 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
78aeea5242 Add todos and some cases 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
83535739d8 Add templates and tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
af1be5e2e1 Add some templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
ca751c74c9 Add FlowableZipWith 2021-09-20 11:25:51 +02:00
Stephan Schroevers
52f6ff607b Pair programming 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
398f554f34 Add todos and implements some templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e3f9966011 Remove public modifiers from the XXXs and add two templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e6381f6b5f Improve templates with assorted methods 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
4e5624240c Remove old ideation on the CanBeCoercedTo problem and an early version of the MyUtil with conversion of io.reactivex.function to java.util.function 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
b1305814e3 Move every template to their respective class and cleanup RxJavaToReactorTemplates.java 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
8292e50d4f Add test templates to the RefasterCheckTest 2021-09-20 11:25:51 +02:00
Stephan Schroevers
681d59b754 Fix it 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
a57b4d5731 Quick commit 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
704705e47b Add the testFlowableCombineLatest 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
256a4b6cac Add some templates like fromCallable and FromAction and fromFuture 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
23da8ed2c3 Add some templates with Amb and add the RxJavaMaybeToReactor file 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
2b20eb887f Add Templates for the RxJava types that we want to migrate to Reactor 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
8aba6197d3 Update the ordering of the Templates and the tests to be in alphabetical order 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
ce4a1ce411 Remove some warnings 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
8d97ae281d Try to fix the tests 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
b38f5eaedd Add 1/4 templates for Flowable.concatWith 2021-09-20 11:25:51 +02:00
Stephan Schroevers
e1697db0d1 One more 2021-09-20 11:25:51 +02:00
Stephan Schroevers
9caff73b00 Ideation 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
bcc0b8a5ea Fix typo 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
7b819dce09 Update templates and fix some tests for the new templates and reorder some 2021-09-20 11:25:51 +02:00
Stephan Schroevers
2875a95374 WIP 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
11eaa182e5 Add some examples because im not sure how it works now 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
df6e76befc Add some tests for the new templates 2021-09-20 11:25:51 +02:00
Stephan Schroevers
a4d2f0d6aa Pair programming 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
5ea89ef59c Improve some comments and add an extra template 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
e2be932179 Update templates and add a few commented templates to discuss with Stephan 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
6b535aa8fc Add tests for added templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
5a3691740b Change order of functions and add a failing one 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
9d8e21a304 Fix last part of test 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
5b6d0c3738 Do some renaming and improve almost all tests 2021-09-20 11:25:51 +02:00
Stephan Schroevers
31a67b6865 Pair programming 2021-09-20 11:25:51 +02:00
Stephan Schroevers
af1c2380a6 Fix it 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
fbda14828a Improve the templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
85cc0ed073 Update some of the Templates 2021-09-20 11:25:51 +02:00
Rick Ossendrijver
8e28241c4e Add RxJavaToReactorTemplates class with Input and Output Test files. 2021-09-20 11:25:51 +02:00
Stephan Schroevers
c1e5dc4339 Assorted upgrades 2021-09-19 21:07:40 +02:00
Stephan Schroevers
7218006b3c Assorted upgrades 2021-09-03 07:42:57 +02:00
Rick Ossendrijver
a3f599ba1b Introduce WebClientTemplates (#16) 2021-08-30 21:54:28 +02:00
Stephan Schroevers
f819a3e42f Assorted upgrades 2021-08-20 08:50:15 +02:00
Stephan Schroevers
7fc865c769 Light RefasterRuleResourceCompilerTaskListener cleanup 2021-08-19 22:43:10 +02:00
Stephan Schroevers
0287060d96 Fix and optimize FormatStringConcatenationCheck 2021-08-19 22:42:41 +02:00
Stephan Schroevers
ac4e81f2c7 Support running the build using JDK 16+ 2021-08-14 19:29:55 +02:00
Stephan Schroevers
350f028781 Sync with PSM parent 2021-08-14 19:13:31 +02:00
Stephan Schroevers
299ce7b800 Assorted upgrades 2021-08-14 19:13:31 +02:00
Stephan Schroevers
f3a929a3bb Upgrade fmt-maven-plugin, reformat 2021-08-04 10:59:23 +02:00
Stephan Schroevers
625a55add5 Add extra Refaster rule, document possible FormatStringConcatenation extension 2021-08-04 10:58:16 +02:00
Stephan Schroevers
ef59340987 Assorted upgrades 2021-08-04 10:58:05 +02:00
Stephan Schroevers
f2aea38b17 Introduce AbstractOptionalAssertContainsSame Refaster template 2021-08-03 13:53:44 +02:00
Stephan Schroevers
5cd8863eb5 Slightly optimize MethodReferenceUsage check 2021-08-01 19:10:46 +02:00
Stephan Schroevers
5b57b4720b Introduce MockitoStubbing check 2021-08-01 18:29:54 +02:00
Stephan Schroevers
5224571407 Assorted FormatStringConcatenationCheck improvements 2021-08-01 15:56:32 +02:00
Stephan Schroevers
c8189e9431 Document RefasterCheck follow-up task 2021-08-01 12:41:00 +02:00
Stephan Schroevers
0fe42f1ea6 Introduce FormatStringConcatenation check 2021-08-01 12:32:08 +02:00
Stephan Schroevers
78b29107a3 Upgrade dependencies 2021-07-29 12:09:19 +02:00
Stephan Schroevers
7ae7d5105a Document StreamMapFirst gotcha, courtesy of Nathan 2021-07-29 11:51:11 +02:00
Stephan Schroevers
0976b33d61 Support Refaster templates without an @AfterTemplate method 2021-07-29 11:48:51 +02:00
Stephan Schroevers
4b6f81c4fa imeZoneUsageCheck: dDon't flag likely overrides 2021-07-27 17:44:04 +02:00
Stephan Schroevers
1e879c175e Don't flag empty test (helper) methods 2021-07-27 17:43:08 +02:00
53 changed files with 9492 additions and 86 deletions

10
.mvn/jvm.config Normal file
View File

@@ -0,0 +1,10 @@
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED

View File

@@ -39,6 +39,12 @@
<artifactId>error_prone_test_helpers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>migration-util</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-resource-compiler</artifactId>
@@ -171,10 +177,20 @@
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>test</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
@@ -210,6 +226,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:RefasterRuleResourceCompiler</arg>

View File

@@ -17,9 +17,11 @@ import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import java.util.Optional;
/** A {@link BugChecker} which flags empty methods that seemingly can simply be deleted. */
@AutoService(BugChecker.class)
@@ -41,7 +43,8 @@ public final class EmptyMethodCheck extends BugChecker implements MethodTreeMatc
if (tree.getBody() == null
|| !tree.getBody().getStatements().isEmpty()
|| ASTHelpers.containsComments(tree, state)
|| PERMITTED_ANNOTATION.matches(tree, state)) {
|| PERMITTED_ANNOTATION.matches(tree, state)
|| isInPossibleTestHelperClass(state)) {
return Description.NO_MATCH;
}
@@ -52,4 +55,11 @@ public final class EmptyMethodCheck extends BugChecker implements MethodTreeMatc
return describeMatch(tree, SuggestedFix.delete(tree));
}
private static boolean isInPossibleTestHelperClass(VisitorState state) {
return Optional.ofNullable(ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class))
.map(ClassTree::getSimpleName)
.filter(name -> name.toString().contains("Test"))
.isPresent();
}
}

View File

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

View File

@@ -69,7 +69,10 @@ public final class MethodReferenceUsageCheck extends BugChecker
*/
return constructMethodRef(tree, tree.getBody())
.map(SuggestedFix.Builder::build)
.filter(fix -> SuggestedFixes.compilesWithFix(fix, state))
.filter(
fix ->
SuggestedFixes.compilesWithFix(
fix, state, ImmutableList.of(), /* onlyInSameCompilationUnit= */ true))
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
}

View File

@@ -0,0 +1,58 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.matchers.Matchers.staticMethod;
import com.google.auto.service.AutoService;
import com.google.common.collect.Iterables;
import com.google.errorprone.BugPattern;
import com.google.errorprone.BugPattern.LinkType;
import com.google.errorprone.BugPattern.SeverityLevel;
import com.google.errorprone.BugPattern.StandardTags;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import java.util.List;
/**
* A {@link BugChecker} which flags method invocations for which all arguments are wrapped using
* {@link org.mockito.Mockito#eq}; this is redundant.
*/
@AutoService(BugChecker.class)
@BugPattern(
name = "MockitoStubbing",
summary = "Don't unnecessarily use Mockito's `eq(...)`",
linkType = LinkType.NONE,
severity = SeverityLevel.SUGGESTION,
tags = StandardTags.SIMPLIFICATION)
public final class MockitoStubbingCheck extends BugChecker implements MethodInvocationTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> MOCKITO_EQ_METHOD =
staticMethod().onClass("org.mockito.ArgumentMatchers").named("eq");
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
List<? extends ExpressionTree> arguments = tree.getArguments();
if (arguments.isEmpty() || !arguments.stream().allMatch(arg -> isEqInvocation(arg, state))) {
return Description.NO_MATCH;
}
SuggestedFix.Builder suggestedFix = SuggestedFix.builder();
for (ExpressionTree arg : arguments) {
suggestedFix.replace(
arg,
Util.treeToString(
Iterables.getOnlyElement(((MethodInvocationTree) arg).getArguments()), state));
}
return describeMatch(tree, suggestedFix.build());
}
private static boolean isEqInvocation(ExpressionTree tree, VisitorState state) {
return tree instanceof MethodInvocationTree && MOCKITO_EQ_METHOD.matches(tree, state);
}
}

View File

@@ -98,6 +98,8 @@ public final class RefasterCheck extends BugChecker implements CompilationUnitTr
// XXX: This `try/catch` block handles the issue described and resolved in
// https://github.com/google/error-prone/pull/2456. Drop this block once that change is
// released.
// XXX: Find a way to identify that we're running Picnic's Error Prone fork and disable this
// fallback if so, as it might hide other bugs.
return Description.NO_MATCH;
}
/* Then apply them. */

View File

@@ -0,0 +1,42 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType;
import static com.google.errorprone.BugPattern.SeverityLevel;
import static com.google.errorprone.BugPattern.StandardTags;
import static com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
import static com.google.errorprone.matchers.method.MethodMatchers.instanceMethod;
import static com.sun.source.tree.Tree.Kind;
import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MethodInvocationTree;
@AutoService(BugChecker.class)
@BugPattern(
name = "StringIsEmpty",
summary = "Prefer `String#isEmpty` over `String#equals`",
severity = SeverityLevel.SUGGESTION,
tags = StandardTags.STYLE)
public final class StringIsEmptyCheck extends BugChecker implements MethodInvocationTreeMatcher {
private static final Matcher<ExpressionTree> STRING_EQUALS_INVOCATION =
instanceMethod().onDescendantOf("java.lang.String").named("equals");
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (STRING_EQUALS_INVOCATION.matches(tree, state)
&& tree.getArguments().get(0).getKind() == Kind.STRING_LITERAL
&& ((LiteralTree) tree.getArguments().get(0)).getValue().equals("")) {
return describeMatch(
tree, SuggestedFix.replace(tree, ASTHelpers.getReceiver(tree) + ".isEmpty()"));
}
return Description.NO_MATCH;
}
}

View File

@@ -1,7 +1,11 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.enclosingClass;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
import static com.google.errorprone.matchers.Matchers.not;
import static com.google.errorprone.matchers.Matchers.staticMethod;
import com.google.auto.service.AutoService;
@@ -35,7 +39,11 @@ public final class TimeZoneUsageCheck extends BugChecker implements MethodInvoca
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> BANNED_TIME_METHOD =
anyOf(
instanceMethod().onDescendantOf(Clock.class.getName()).namedAnyOf("getZone", "withZone"),
allOf(
instanceMethod()
.onDescendantOf(Clock.class.getName())
.namedAnyOf("getZone", "withZone"),
not(enclosingClass(isSubtypeOf(Clock.class)))),
staticMethod()
.onClass(Clock.class.getName())
.namedAnyOf(

View File

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

View File

@@ -357,6 +357,18 @@ final class AssertJTemplates {
}
}
static final class AssertThatSetContainsExactlyOneElement<S, T extends S> {
@BeforeTemplate
ObjectEnumerableAssert<?, S> before(Set<S> set, T element) {
return assertThat(set).containsOnly(element);
}
@AfterTemplate
ObjectEnumerableAssert<?, S> after(Set<S> set, T element) {
return assertThat(set).containsExactly(element);
}
}
static final class ObjectEnumerableContainsOneDistinctElement<S, T extends S> {
@BeforeTemplate
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T element) {

View File

@@ -18,6 +18,19 @@ import reactor.core.publisher.Mono;
final class RxJava2AdapterTemplates {
private RxJava2AdapterTemplates() {}
/** Remove double conversion of ... */
static final class FluxToFlowableToFlux<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux) {
return RxJava2Adapter.flowableToFlux(RxJava2Adapter.fluxToFlowable(flux));
}
@AfterTemplate
Flux<T> after(Flux<T> flux) {
return flux;
}
}
/** Use the fluent API style when using {@link RxJava2Adapter#completableToMono}. */
static final class CompletableToMono {
@BeforeTemplate

View File

@@ -0,0 +1,506 @@
package tech.picnic.errorprone.refastertemplates;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.collect.Streams;
import com.google.errorprone.refaster.ImportPolicy;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import io.reactivex.Completable;
import io.reactivex.CompletableSource;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.MaybeSource;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Predicate;
import java.util.concurrent.Callable;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
/** The Refaster templates for the migration of the RxJava Completable type to Reactor */
final class RxJavaCompletableToReactorTemplates {
private RxJavaCompletableToReactorTemplates() {}
static final class CompletableAmb {
@BeforeTemplate
Completable before(Iterable<? extends Completable> sources) {
return Completable.amb(sources);
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
Completable after(Iterable<? extends Completable> sources) {
return RxJava2Adapter.monoToCompletable(
Mono.firstWithSignal(
Streams.stream(sources)
.map(RxJava2Adapter::completableToMono)
.collect(toImmutableList())));
}
}
// XXX: public static Completable ambArray(CompletableSource[])
static final class CompletableComplete {
@BeforeTemplate
Completable before() {
return Completable.complete();
}
@AfterTemplate
Completable after() {
return RxJava2Adapter.monoToCompletable(Mono.empty());
}
}
// XXX: public static Completable concat(Iterable)
// XXX: public static Completable concat(Publisher)
// XXX: public static Completable concat(Publisher,int)
// XXX: public static Completable concatArray(CompletableSource[])
// XXX: public static Completable create(CompletableOnSubscribe)
// XXX: The types of the @Before and @After are not matching
static final class CompletableDefer {
@BeforeTemplate
Completable before(Callable<? extends CompletableSource> supplier) {
return Completable.defer(supplier);
}
@AfterTemplate
Completable after(Callable<? extends Completable> supplier) {
return RxJava2Adapter.monoToCompletable(
Mono.defer(
() ->
RxJava2Adapter.completableToMono(
RxJavaReactorMigrationUtil.callableAsSupplier(supplier).get())));
}
}
static final class CompletableErrorCallable {
@BeforeTemplate
Completable before(Callable<? extends Throwable> throwable) {
return Completable.error(throwable);
}
@AfterTemplate
Completable after(Supplier<? extends Throwable> throwable) {
return RxJava2Adapter.monoToCompletable(Mono.error(throwable));
}
}
static final class CompletableErrorThrowable {
@BeforeTemplate
Completable before(Throwable throwable) {
return Completable.error(throwable);
}
@AfterTemplate
Completable after(Throwable throwable) {
return RxJava2Adapter.monoToCompletable(Mono.error(throwable));
}
}
static final class CompletableFromAction {
@BeforeTemplate
Completable before(Action action) {
return Completable.fromAction(action);
}
@AfterTemplate
Completable after(Action action) {
return RxJava2Adapter.monoToCompletable(
Mono.fromRunnable(RxJavaReactorMigrationUtil.toRunnable(action)));
}
}
static final class CompletableFromCallable {
@BeforeTemplate
Completable before(Callable<?> supplier) {
return Completable.fromCallable(supplier);
}
@AfterTemplate
Completable after(Callable<?> supplier) {
return RxJava2Adapter.monoToCompletable(Mono.fromCallable(supplier));
}
}
// XXX: public static Completable fromFuture(Future)
// XXX: public static Completable fromMaybe(MaybeSource)
// XXX: public static Completable fromObservable(ObservableSource)
static final class CompletableFromPublisher<T> {
@BeforeTemplate
Completable before(Publisher<T> source) {
return Completable.fromPublisher(source);
}
@AfterTemplate
Completable after(Publisher<T> source) {
return RxJava2Adapter.monoToCompletable(Mono.from(source));
}
}
static final class CompletableFromRunnable {
@BeforeTemplate
Completable before(Runnable runnable) {
return Completable.fromRunnable(runnable);
}
@AfterTemplate
Completable after(Runnable runnable) {
return RxJava2Adapter.monoToCompletable(Mono.fromRunnable(runnable));
}
}
// XXX: public static Completable fromSingle(SingleSource)
// XXX: public static Completable merge(Iterable)
// XXX: public static Completable merge(Publisher)
// XXX: public static Completable merge(Publisher,int)
// XXX: public static Completable mergeArray(CompletableSource[])
// XXX: public static Completable mergeArrayDelayError(CompletableSource[])
// XXX: public static Completable mergeDelayError(Iterable)
// XXX: public static Completable mergeDelayError(Publisher)
// XXX: public static Completable mergeDelayError(Publisher,int)
// XXX: public static Completable never()
// XXX: public static Completable timer(long,TimeUnit)
// XXX: public static Completable timer(long,TimeUnit,Scheduler)
// XXX: public static Completable unsafeCreate(CompletableSource)
// XXX: public static Completable using(Callable,Function,Consumer)
// XXX: public static Completable using(Callable,Function,Consumer,boolean)
static final class CompletableWrap {
@BeforeTemplate
Completable before(Completable source) {
return Completable.wrap(source);
}
@AfterTemplate
Completable after(Completable source) {
return source;
}
}
// XXX: public final Completable ambWith(CompletableSource)
static final class CompletableAndThenCompletable {
@BeforeTemplate
Completable before(Completable completable, CompletableSource source) {
return completable.andThen(source);
}
@AfterTemplate
Completable after(Completable completable, CompletableSource source) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(completable)
.then(RxJava2Adapter.completableToMono(Completable.wrap(source))));
}
}
static final class CompletableAndThenMaybe<T> {
@BeforeTemplate
Maybe<T> before(Completable completable, MaybeSource<T> source) {
return completable.andThen(source);
}
@AfterTemplate
Maybe<T> after(Completable completable, MaybeSource<T> source) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.completableToMono(completable)
.then(RxJava2Adapter.maybeToMono(Maybe.wrap(source))));
}
}
// XXX: public final Observable andThen(ObservableSource)
static final class CompletableAndThenPublisher<T> {
@BeforeTemplate
Flowable<T> before(Completable completable, Publisher<T> source) {
return completable.andThen(source);
}
@AfterTemplate
Flowable<T> after(Completable completable, Publisher<T> source) {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.completableToMono(completable).thenMany(source));
}
}
static final class CompletableAndThenSingle<T> {
@BeforeTemplate
Single<T> before(Completable completable, SingleSource<T> source) {
return completable.andThen(source);
}
@AfterTemplate
Single<T> after(Completable completable, SingleSource<T> source) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.completableToMono(completable)
.then(RxJava2Adapter.singleToMono(Single.wrap(source))));
}
}
// XXX: public final Object as(CompletableConverter)
static final class CompletableBlockingAwait {
@BeforeTemplate
void before(Completable completable) {
completable.blockingAwait();
}
@AfterTemplate
void after(Completable completable) {
RxJava2Adapter.completableToMono(completable).block();
}
}
// XXX: public final boolean blockingAwait(long,TimeUnit)
// XXX: public final Throwable blockingGet()
// XXX: public final Throwable blockingGet(long,TimeUnit)
// XXX: public final Completable cache()
// XXX: public final Completable compose(CompletableTransformer)
// XXX: public final Completable concatWith(CompletableSource)
// XXX: public final Completable delay(long,TimeUnit)
// XXX: public final Completable delay(long,TimeUnit,Scheduler)
// XXX: public final Completable delay(long,TimeUnit,Scheduler,boolean)
// XXX: public final Completable delaySubscription(long,TimeUnit)
// XXX: public final Completable delaySubscription(long,TimeUnit,Scheduler)
// XXX: public final Completable doAfterTerminate(Action)
// XXX: public final Completable doFinally(Action)
// XXX: public final Completable doOnComplete(Action)
// XXX: public final Completable doOnDispose(Action)
// XXX: public final Completable doOnError(Consumer)
// XXX: public final Completable doOnEvent(Consumer)
// XXX: public final Completable doOnSubscribe(Consumer)
static final class CompletableDoOnError {
@BeforeTemplate
Completable before(Completable completable, Consumer<? super Throwable> consumer) {
return completable.doOnError(consumer);
}
@AfterTemplate
Completable after(Completable completable, Consumer<? super Throwable> consumer) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(completable)
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
}
}
// XXX: public final Completable doOnTerminate(Action)
// XXX: public final Completable hide()
// XXX: public final Completable lift(CompletableOperator)
// XXX: public final Single materialize()
// XXX: public final Completable mergeWith(CompletableSource)
// XXX: public final Completable observeOn(Scheduler)
// XXX: Verify whether this is the correct equivalent.
static final class CompletableOnErrorComplete {
Completable before(Completable completable) {
return completable.onErrorComplete();
}
Completable after(Completable completable) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(completable).onErrorStop());
}
}
static final class CompletableOnErrorCompletePredicate {
Completable before(Completable completable, Predicate<? super Throwable> predicate) {
return completable.onErrorComplete(predicate);
}
Completable after(Completable completable, Predicate<? super Throwable> predicate) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.completableToMono(completable)
.onErrorResume(
RxJavaReactorMigrationUtil.toJdkPredicate(predicate), t -> Mono.empty()));
}
}
// XXX: public final Completable onErrorComplete(Predicate)
// XXX: public final Completable onErrorResumeNext(Function)
// XXX: public final Completable onTerminateDetach()
// XXX: public final Completable repeat()
// XXX: public final Completable repeat(long)
// XXX: public final Completable repeatUntil(BooleanSupplier)
// XXX: public final Completable repeatWhen(Function)
// XXX: public final Completable retry()
// XXX: public final Completable retry(BiPredicate)
// XXX: public final Completable retry(long)
// XXX: public final Completable retry(long,Predicate)
// XXX: public final Completable retry(Predicate)
// XXX: public final Completable retryWhen(Function)
// XXX: public final Completable startWith(CompletableSource)
// XXX: public final Observable startWith(Observable)
// XXX: public final Flowable startWith(Publisher)
// XXX: public final Disposable subscribe()
// XXX: public final Disposable subscribe(Action)
// XXX: public final Disposable subscribe(Action,Consumer)
// XXX: public final void subscribe(CompletableObserver)
// XXX: public final Completable subscribeOn(Scheduler)
// XXX: public final CompletableObserver subscribeWith(CompletableObserver)
// XXX: public final Completable takeUntil(CompletableSource)
// XXX: public final Completable timeout(long,TimeUnit)
// XXX: public final Completable timeout(long,TimeUnit,CompletableSource)
// XXX: public final Completable timeout(long,TimeUnit,Scheduler)
// XXX: public final Completable timeout(long,TimeUnit,Scheduler,CompletableSource)
// XXX: public final Object to(Function)
static final class CompletableToFlowable {
@BeforeTemplate
Flowable<Void> before(Completable completable) {
return completable.toFlowable();
}
@AfterTemplate
Flowable<Void> after(Completable completable) {
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.completableToMono(completable).flux());
}
}
// XXX: Requires investigation. Should not be Void...
static final class CompletableToMaybe {
@BeforeTemplate
Maybe<Void> before(Completable completable) {
return completable.toMaybe();
}
@AfterTemplate
Maybe<Void> after(Completable completable) {
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.completableToMono(completable));
}
}
// XXX: public final Observable toObservable()
// XXX: public final Single toSingle(Callable)
// XXX: public final Single toSingleDefault(Object)
// XXX: public final Completable unsubscribeOn(Scheduler)
static final class CompletableTestAssertResult {
@BeforeTemplate
void before(Completable completable) throws InterruptedException {
Refaster.anyOf(
completable.test().await().assertResult(),
completable.test().assertResult(),
completable.test().await());
}
@AfterTemplate
void after(Completable completable) {
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyComplete();
}
}
static final class CompletableTestAssertComplete {
@BeforeTemplate
void before(Completable completable) throws InterruptedException {
Refaster.anyOf(
completable.test().await().assertComplete(), completable.test().assertComplete());
}
@AfterTemplate
void after(Completable completable) {
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyComplete();
}
}
static final class CompletableTestAssertErrorClass {
@BeforeTemplate
void before(Completable completable, Class<? extends Throwable> errorClass)
throws InterruptedException {
Refaster.anyOf(
completable.test().await().assertError(errorClass),
completable.test().assertError(errorClass));
}
@AfterTemplate
void after(Completable completable, Class<? extends Throwable> errorClass) {
RxJava2Adapter.completableToMono(completable)
.as(StepVerifier::create)
.verifyError(errorClass);
}
}
static final class CompletableTestAssertNoErrors {
@BeforeTemplate
void before(Completable completable) throws InterruptedException {
completable.test().await().assertNoErrors();
}
@AfterTemplate
void after(Completable completable) {
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyComplete();
}
}
static final class CompletableTestAssertValueCount {
@BeforeTemplate
void before(Completable completable, int count) throws InterruptedException {
completable.test().await().assertValueCount(count);
}
@AfterTemplate
void after(Completable completable, int count) {
RxJava2Adapter.completableToMono(completable)
.as(StepVerifier::create)
.expectNextCount(count)
.verifyComplete();
}
}
static final class CompletableTestAssertFailure {
@BeforeTemplate
void before(Completable completable, Class<? extends Throwable> error)
throws InterruptedException {
completable.test().await().assertFailure(error);
}
@AfterTemplate
void after(Completable completable, Class<? extends Throwable> error) {
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyError(error);
}
}
static final class CompletableTestAssertNoValues {
@BeforeTemplate
void before(Completable completable) throws InterruptedException {
completable.test().await().assertNoValues();
}
@AfterTemplate
void after(Completable completable) {
RxJava2Adapter.completableToMono(completable).as(StepVerifier::create).verifyComplete();
}
}
static final class CompletableTestAssertFailureAndMessage {
@BeforeTemplate
void before(Completable completable, Class<? extends Throwable> error, String message)
throws InterruptedException {
completable.test().await().assertFailureAndMessage(error, message);
}
@AfterTemplate
void after(Completable completable, Class<? extends Throwable> error, String message) {
RxJava2Adapter.completableToMono(completable)
.as(StepVerifier::create)
.expectErrorSatisfies(
t -> assertThat(t).isInstanceOf(error).hasMessageContaining(message))
.verify();
}
}
// XXX: public final TestObserver test(boolean)
}

View File

@@ -0,0 +1,959 @@
package tech.picnic.errorprone.refastertemplates;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.collect.Streams;
import com.google.errorprone.refaster.ImportPolicy;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
import com.google.errorprone.refaster.annotation.Placeholder;
import com.google.errorprone.refaster.annotation.Repeated;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import io.reactivex.Completable;
import io.reactivex.CompletableSource;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.MaybeSource;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Action;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import org.reactivestreams.Publisher;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
/** The Refaster templates for the migration of the RxJava Maybe type to Reactor */
final class RxJavaMaybeToReactorTemplates {
private RxJavaMaybeToReactorTemplates() {}
static final class MaybeAmb<T> {
@BeforeTemplate
Maybe<T> before(Iterable<? extends Maybe<? extends T>> iterable) {
return Maybe.amb(iterable);
}
@AfterTemplate
Maybe<T> after(Iterable<? extends Maybe<? extends T>> iterable) {
return RxJava2Adapter.monoToMaybe(
Mono.firstWithSignal(
Streams.stream(iterable)
.map(RxJava2Adapter::maybeToMono)
.collect(toImmutableList())));
}
}
// XXX: public static Maybe ambArray(MaybeSource... sources)
// XXX: public static Flowable concat(Iterable)
// XXX: public static Flowable concat(MaybeSource,MaybeSource)
// XXX: public static Flowable concat(MaybeSource,MaybeSource,MaybeSource)
// XXX: public static Flowable concat(MaybeSource,MaybeSource,MaybeSource,MaybeSource)
// XXX: public static Flowable concat(Publisher)
// XXX: public static Flowable concat(Publisher,int)
// XXX: How to make this conversion correct? Turned off test for now.
static final class MaybeConcatArray<T> {
@BeforeTemplate
Flowable<T> before(@Repeated Maybe<T> sources) {
return Maybe.concatArray(Refaster.asVarargs(sources));
}
@AfterTemplate
Flowable<T> after(@Repeated Maybe<T> sources) {
return RxJava2Adapter.fluxToFlowable(
Flux.concat(
Arrays.stream(Refaster.asVarargs(sources))
.map(RxJava2Adapter::maybeToMono)
.collect(toImmutableList())));
}
}
// XXX: public static Flowable concatArrayDelayError(MaybeSource[])
// XXX: public static Flowable concatArrayEager(MaybeSource[])
// XXX: public static Flowable concatDelayError(Iterable)
// XXX: public static Flowable concatDelayError(Publisher)
// XXX: public static Flowable concatEager(Iterable)
// XXX: public static Flowable concatEager(Publisher)
// XXX: public static Maybe create(MaybeOnSubscribe)
/// XXX: Add test
abstract static class MaybeDeferFirst<T> {
@Placeholder
abstract Maybe<T> maybeProducer();
@BeforeTemplate
Maybe<T> before() {
return Maybe.defer(() -> maybeProducer());
}
@AfterTemplate
Maybe<T> after() {
return RxJava2Adapter.monoToMaybe(
Mono.defer(() -> RxJava2Adapter.maybeToMono(maybeProducer())));
}
}
abstract static class MaybeDefer<T> {
@Placeholder
abstract Maybe<T> maybeProducer();
@BeforeTemplate
Mono<T> before() {
return Maybe.defer(() -> maybeProducer()).as(RxJava2Adapter::maybeToMono);
}
@AfterTemplate
Mono<T> after() {
return Mono.defer(() -> RxJava2Adapter.maybeToMono(maybeProducer()));
}
}
static final class MaybeEmpty<T> {
@BeforeTemplate
Maybe<T> before() {
return Maybe.empty();
}
@AfterTemplate
Maybe<T> after() {
return RxJava2Adapter.monoToMaybe(Mono.empty());
}
}
static final class MaybeErrorCallable<T> {
@BeforeTemplate
Maybe<T> before(Callable<? extends Throwable> throwable) {
return Maybe.error(throwable);
}
@AfterTemplate
Maybe<T> after(Callable<? extends Throwable> throwable) {
return RxJava2Adapter.monoToMaybe(
Mono.error(RxJavaReactorMigrationUtil.callableAsSupplier(throwable)));
}
}
static final class MaybeErrorThrowable<T> {
@BeforeTemplate
Maybe<T> before(Throwable throwable) {
return Maybe.error(throwable);
}
@AfterTemplate
Maybe<T> after(Throwable throwable) {
return RxJava2Adapter.monoToMaybe(Mono.error(throwable));
}
}
static final class MaybeFromAction<T> {
@BeforeTemplate
Maybe<T> before(Action action) {
return Maybe.fromAction(action);
}
@AfterTemplate
Maybe<T> after(Action action) {
return RxJava2Adapter.monoToMaybe(
Mono.fromRunnable(RxJavaReactorMigrationUtil.toRunnable(action)));
}
}
static final class MaybeFromCallable<T> {
@BeforeTemplate
Maybe<T> before(Callable<? extends T> callable) {
return Maybe.fromCallable(callable);
}
@AfterTemplate
Maybe<T> after(Callable<? extends T> callable) {
return RxJava2Adapter.monoToMaybe(
Mono.fromSupplier(RxJavaReactorMigrationUtil.callableAsSupplier(callable)));
}
}
// XXX: public static Maybe fromCompletable(CompletableSource)
// XXX: Also handle `Future`s that don't extend `CompletableFuture`.
static final class MaybeFromFuture<T> {
@BeforeTemplate
Maybe<T> before(CompletableFuture<? extends T> future) {
return Maybe.fromFuture(future);
}
@AfterTemplate
Maybe<T> after(CompletableFuture<? extends T> future) {
return RxJava2Adapter.monoToMaybe(Mono.fromFuture(future));
}
}
// XXX: public static Maybe fromFuture(Future,long,TimeUnit)
static final class MaybeFromRunnable<T> {
@BeforeTemplate
Maybe<T> before(Runnable runnable) {
return Maybe.fromRunnable(runnable);
}
@AfterTemplate
Maybe<T> after(Runnable runnable) {
return RxJava2Adapter.monoToMaybe(Mono.fromRunnable(runnable));
}
}
static final class MaybeFromSingle<T> {
@BeforeTemplate
Maybe<T> before(SingleSource<T> source) {
return Maybe.fromSingle(source);
}
@AfterTemplate
Maybe<T> after(SingleSource<T> source) {
return RxJava2Adapter.monoToMaybe(
Mono.from(RxJava2Adapter.singleToMono(Single.wrap(source))));
}
}
static final class MaybeJust<T> {
@BeforeTemplate
Maybe<T> before(T item) {
return Maybe.just(item);
}
@AfterTemplate
Maybe<T> after(T item) {
return RxJava2Adapter.monoToMaybe(Mono.just(item));
}
}
// XXX: public static Flowable merge(Iterable)
// XXX: public static Maybe merge(MaybeSource)
// XXX: public static Flowable merge(MaybeSource,MaybeSource)
// XXX: public static Flowable merge(MaybeSource,MaybeSource,MaybeSource)
// XXX: public static Flowable merge(MaybeSource,MaybeSource,MaybeSource,MaybeSource)
// XXX: public static Flowable merge(Publisher)
// XXX: public static Flowable merge(Publisher,int)
// XXX: public static Flowable mergeArray(MaybeSource[])
// XXX: public static Flowable mergeArrayDelayError(MaybeSource[])
// XXX: public static Flowable mergeDelayError(Iterable)
// XXX: public static Flowable mergeDelayError(MaybeSource,MaybeSource)
// XXX: public static Flowable mergeDelayError(MaybeSource,MaybeSource,MaybeSource)
// XXX: public static Flowable mergeDelayError(MaybeSource,MaybeSource,MaybeSource,MaybeSource)
// XXX: public static Flowable mergeDelayError(Publisher)
// XXX: public static Flowable mergeDelayError(Publisher,int)
// XXX: public static Maybe never()
// XXX: public static Single sequenceEqual(MaybeSource,MaybeSource)
// XXX: public static Single sequenceEqual(MaybeSource,MaybeSource,BiPredicate)
// XXX: public static Maybe timer(long,TimeUnit)
// XXX: public static Maybe timer(long,TimeUnit,Scheduler)
// XXX: public static Maybe unsafeCreate(MaybeSource)
// XXX: public static Maybe using(Callable,Function,Consumer)
// XXX: public static Maybe using(Callable,Function,Consumer,boolean)
static final class MaybeWrap<T> {
@BeforeTemplate
Maybe<T> before(Maybe<T> maybe) {
return Maybe.wrap(maybe);
}
@AfterTemplate
Maybe<T> after(Maybe<T> maybe) {
return maybe;
}
}
// XXX: public static Maybe zip(Iterable,Function)
// XXX: public static Maybe zip(MaybeSource,MaybeSource,BiFunction)
// XXX: public static Maybe zip(MaybeSource,MaybeSource,MaybeSource,Function3)
// XXX: public static Maybe zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function4)
// XXX: public static Maybe
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function5)
// XXX: public static Maybe
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function6)
// XXX: public static Maybe
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function7)
// XXX: public static Maybe
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function8)
// XXX: public static Maybe
// zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function9)
// XXX: public static Maybe zipArray(Function,MaybeSource[])
static final class MaybeAmbWith<T> {
@BeforeTemplate
Maybe<T> before(Maybe<T> maybe, Maybe<? extends T> otherMaybe) {
return maybe.ambWith(otherMaybe);
}
@AfterTemplate
Maybe<T> after(Maybe<T> maybe, Maybe<? extends T> otherMaybe) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe).or(RxJava2Adapter.maybeToMono(otherMaybe)));
}
}
// XXX: public final Object as(MaybeConverter)
static final class MaybeBlockingGet<T> {
@BeforeTemplate
Object before(Maybe<T> maybe) {
return maybe.blockingGet();
}
@AfterTemplate
Object after(Maybe<T> maybe) {
return RxJava2Adapter.maybeToMono(maybe).block();
}
}
// XXX: public final Object blockingGet(Object)
// XXX: public final Maybe cache()
static final class MaybeCast<T> {
@BeforeTemplate
Maybe<T> before(Maybe<T> maybe) {
return maybe.cast(Refaster.<T>clazz());
}
@AfterTemplate
Maybe<T> after(Maybe<T> maybe) {
return maybe;
}
}
// XXX: public final Maybe compose(MaybeTransformer)
// XXX: public final Maybe concatMap(Function)
// XXX: public final Flowable concatWith(MaybeSource)
// XXX: public final Single contains(Object)
// XXX: public final Single count()
static final class MaybeDefaultIfEmpty<T> {
@BeforeTemplate
Maybe<T> before(Maybe<T> maybe, T item) {
return maybe.defaultIfEmpty(item);
}
@AfterTemplate
Maybe<T> after(Maybe<T> maybe, T item) {
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.maybeToMono(maybe).defaultIfEmpty(item));
}
}
// XXX: public final Maybe delay(long,TimeUnit)
// XXX: public final Maybe delay(long,TimeUnit,Scheduler)
// XXX: public final Maybe delay(Publisher)
// XXX: public final Maybe delaySubscription(long,TimeUnit)
// XXX: public final Maybe delaySubscription(long,TimeUnit,Scheduler)
// XXX: public final Maybe delaySubscription(Publisher)
// XXX: public final Maybe doAfterSuccess(Consumer)
// XXX: public final Maybe doAfterTerminate(Action)
// XXX: public final Maybe doFinally(Action)
// XXX: public final Maybe doOnComplete(Action)
// XXX: public final Maybe doOnDispose(Action)
static final class MaybeDoOnError<T> {
@BeforeTemplate
Maybe<T> before(Maybe<T> maybe, Consumer<? super Throwable> consumer) {
return maybe.doOnError(consumer);
}
@AfterTemplate
Maybe<T> after(Maybe<T> maybe, Consumer<? super Throwable> consumer) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe)
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
}
}
// XXX: public final Maybe doOnEvent(BiConsumer)
// XXX: public final Maybe doOnSubscribe(Consumer)
static final class MaybeDoOnSuccess<T> {
@BeforeTemplate
Maybe<T> before(Maybe<T> maybe, Consumer<T> consumer) {
return maybe.doOnSuccess(consumer);
}
@AfterTemplate
Maybe<T> after(Maybe<T> maybe, Consumer<T> consumer) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe)
.doOnSuccess(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
}
}
// XXX: public final Maybe doOnTerminate(Action)
static final class MaybeFilter<T> {
@BeforeTemplate
Maybe<T> before(Maybe<T> maybe, Predicate<T> predicate) {
return maybe.filter(predicate);
}
@AfterTemplate
Maybe<T> after(Maybe<T> maybe, Predicate<T> predicate) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe)
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate)));
}
}
static final class MaybeFlatMapFunction<
I, T extends I, O, X extends O, M extends MaybeSource<X>> {
@BeforeTemplate
Maybe<O> before(
Maybe<T> maybe, Function<? super T, ? extends MaybeSource<? extends O>> function) {
return maybe.flatMap(function);
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
Maybe<O> after(Maybe<T> maybe, Function<I, M> function) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe)
.flatMap(
v ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.<I, M>toJdkFunction(function).apply(v)))));
}
}
// XXX: There is no link to an original public method for this, but it is important.
abstract static class MaybeFlatMapLambda<S, T> {
@Placeholder
abstract Maybe<T> toMaybeFunction(@MayOptionallyUse S element);
@BeforeTemplate
Maybe<T> before(Maybe<S> maybe) {
return maybe.flatMap(v -> toMaybeFunction(v));
}
@AfterTemplate
Maybe<T> after(Maybe<S> maybe) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe)
.flatMap(z -> toMaybeFunction(z).as(RxJava2Adapter::maybeToMono)));
}
}
// XXX: public final Maybe flatMap(Function,BiFunction)
// XXX: public final Maybe flatMap(Function,Function,Callable)
// XXX: Add test
static final class MaybeFlatMapCompletable<T, R extends CompletableSource> {
@BeforeTemplate
Completable before(Maybe<T> maybe, Function<T, R> function) {
return maybe.flatMapCompletable(function);
}
@AfterTemplate
Completable after(Maybe<T> maybe, Function<T, R> function) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.maybeToMono(maybe)
.flatMap(
y ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.toJdkFunction((Function<T, R>) function)
.apply(y))))
.then());
}
}
// XXX: public final Observable flatMapObservable(Function)
static final class MaybeFlatMapPublisher<T, O extends T, R extends Publisher<O>> {
@BeforeTemplate
Flowable<O> before(
Maybe<T> maybe, Function<? super T, ? extends Publisher<? extends O>> function) {
return maybe.flatMapPublisher(function);
}
@AfterTemplate
Flowable<O> after(Maybe<T> maybe, Function<T, R> function) {
return RxJava2Adapter.monoToFlowable(
RxJava2Adapter.maybeToMono(maybe)
.flatMap(
y ->
Mono.from(
RxJavaReactorMigrationUtil.<T, R>toJdkFunction(function).apply(y))));
}
}
static final class MaybeFlatMapSingle<T, O extends T, R extends SingleSource<O>> {
@BeforeTemplate
Single<O> before(
Maybe<T> maybe, Function<? super T, ? extends SingleSource<? extends O>> function) {
return maybe.flatMapSingle(function);
}
@AfterTemplate
Single<O> after(Maybe<T> maybe, Function<T, R> function) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.maybeToMono(maybe)
.flatMap(
y ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil.<T, R>toJdkFunction(function).apply(y)))));
}
}
// XXX: Improve the @AfterTemplate to not have a cast
@SuppressWarnings("unchecked")
static final class MaybeFlatMapSingleElement<T, O> {
@BeforeTemplate
Maybe<O> before(
Maybe<T> maybe, Function<? super T, ? extends SingleSource<? extends O>> function) {
return maybe.flatMapSingleElement(function);
}
@AfterTemplate
Maybe<O> after(
Maybe<T> maybe, Function<? super T, ? extends SingleSource<? extends O>> function) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe)
.flatMap(
e ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<T, SingleSource<O>>) function)
.apply(e)))));
}
}
// XXX: public final Flowable flattenAsFlowable(Function)
// XXX: public final Observable flattenAsObservable(Function)
// XXX: public final Maybe hide()
static final class MaybeIgnoreElement<T> {
@BeforeTemplate
Completable before(Maybe<T> maybe) {
return maybe.ignoreElement();
}
@AfterTemplate
Completable after(Maybe<T> maybe) {
return RxJava2Adapter.monoToCompletable(RxJava2Adapter.maybeToMono(maybe).then());
}
}
// XXX: Add test
static final class MaybeIsEmpty<T> {
@BeforeTemplate
Single<Boolean> before(Maybe<T> maybe) {
return maybe.isEmpty();
}
@AfterTemplate
Single<Boolean> after(Maybe<T> maybe) {
return RxJava2Adapter.monoToSingle(RxJava2Adapter.maybeToMono(maybe).hasElement());
}
}
// XXX: public final Maybe lift(MaybeOperator)
// XXX: public final Maybe map(Function)
static final class MaybeMap<T, R> {
@BeforeTemplate
Maybe<R> before(Maybe<T> maybe, Function<T, R> mapper) {
return maybe.map(mapper);
}
@AfterTemplate
Maybe<R> after(Maybe<T> maybe, Function<T, R> mapper) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe).map(RxJavaReactorMigrationUtil.toJdkFunction(mapper)));
}
}
// XXX: public final Single materialize()
// XXX: public final Flowable mergeWith(MaybeSource)
// XXX: public final Maybe observeOn(Scheduler)
// XXX: public final Maybe ofType(Class)
// XXX: public final Maybe onErrorComplete()
// XXX: public final Maybe onErrorComplete(Predicate)
// XXX: public final Maybe onErrorResumeNext(Function)
// XXX: public final Maybe onErrorResumeNext(MaybeSource)
// XXX: public final Maybe onErrorReturn(Function)
abstract static class MaybeOnErrorReturn<T, R> {
@Placeholder
abstract T placeholder(@MayOptionallyUse Throwable throwable);
@BeforeTemplate
Maybe<T> before(Maybe<T> maybe) {
return maybe.onErrorReturn(t -> placeholder(t));
}
@AfterTemplate
Maybe<T> after(Maybe<T> maybe) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe).onErrorResume(t -> Mono.just(placeholder(t))));
}
}
// XXX: public final Maybe onErrorReturnItem(Object)
// XXX: public final Maybe onExceptionResumeNext(MaybeSource)
// XXX: public final Maybe onTerminateDetach()
// XXX: public final Flowable repeat()
// XXX: public final Flowable repeat(long)
// XXX: public final Flowable repeatUntil(BooleanSupplier)
// XXX: public final Flowable repeatWhen(Function)
// XXX: public final Maybe retry()
// XXX: public final Maybe retry(BiPredicate)
// XXX: public final Maybe retry(long)
// XXX: public final Maybe retry(long,Predicate)
// XXX: public final Maybe retry(Predicate)
// XXX: public final Maybe retryUntil(BooleanSupplier)
// XXX: public final Maybe retryWhen(Function)
// XXX: Add test
static final class MaybeSubscribe<T> {
@BeforeTemplate
Disposable before(Maybe<T> maybe) {
return maybe.subscribe();
}
@AfterTemplate
reactor.core.Disposable after(Maybe<T> maybe) {
return RxJava2Adapter.maybeToMono(maybe).subscribe();
}
}
// XXX: Add test
static final class MaybeSubscribeConsumer<T> {
@BeforeTemplate
Disposable before(Maybe<T> maybe, Consumer<? super T> consumer) {
return maybe.subscribe(consumer);
}
@AfterTemplate
reactor.core.Disposable after(Maybe<T> maybe, Consumer<? super T> consumer) {
return RxJava2Adapter.maybeToMono(maybe)
.subscribe(RxJavaReactorMigrationUtil.toJdkConsumer(consumer));
}
}
// XXX: Add test
static final class MaybeSubscribeTwoConsumers<T> {
@BeforeTemplate
Disposable before(
Maybe<T> maybe, Consumer<? super T> consumer1, Consumer<? super Throwable> consumer2) {
return maybe.subscribe(consumer1, consumer2);
}
@AfterTemplate
reactor.core.Disposable after(
Maybe<T> maybe, Consumer<? super T> consumer1, Consumer<? super Throwable> consumer2) {
return RxJava2Adapter.maybeToMono(maybe)
.subscribe(
RxJavaReactorMigrationUtil.toJdkConsumer(consumer1),
RxJavaReactorMigrationUtil.toJdkConsumer(consumer2));
}
}
// XXX: Add test
static final class MaybeSubscribeTwoConsumersWithAction<T> {
@BeforeTemplate
Disposable before(
Maybe<T> maybe,
Consumer<? super T> consumer1,
Consumer<? super Throwable> consumer2,
Action action) {
return maybe.subscribe(consumer1, consumer2, action);
}
@AfterTemplate
reactor.core.Disposable after(
Maybe<T> maybe,
Consumer<? super T> consumer1,
Consumer<? super Throwable> consumer2,
Action action) {
return RxJava2Adapter.maybeToMono(maybe)
.subscribe(
RxJavaReactorMigrationUtil.toJdkConsumer(consumer1),
RxJavaReactorMigrationUtil.toJdkConsumer(consumer2),
RxJavaReactorMigrationUtil.toRunnable(action));
}
}
// XXX: public final void subscribe(MaybeObserver)
// XXX: public final Maybe subscribeOn(Scheduler)
// XXX: public final MaybeObserver subscribeWith(MaybeObserver)
// XXX: Add test
static final class MaybeSourceSwitchIfEmpty<S, T extends S> {
@BeforeTemplate
Maybe<S> before(Maybe<S> maybe, MaybeSource<T> maybeSource) {
return maybe.switchIfEmpty(maybeSource);
}
@AfterTemplate
Maybe<S> after(Maybe<S> maybe, MaybeSource<T> maybeSource) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe)
.switchIfEmpty(RxJava2Adapter.maybeToMono(Maybe.wrap(maybeSource))));
}
}
static final class MaybeSwitchIfEmpty<S, T extends S> {
@BeforeTemplate
Single<S> before(Maybe<S> maybe, SingleSource<T> single) {
return maybe.switchIfEmpty(single);
}
@AfterTemplate
Single<S> after(Maybe<S> maybe, SingleSource<T> single) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.maybeToMono(maybe)
.switchIfEmpty(RxJava2Adapter.singleToMono(Single.wrap(single))));
}
}
// XXX: public final Maybe takeUntil(MaybeSource)
// XXX: public final Maybe takeUntil(Publisher)
// XXX: public final Maybe timeout(long,TimeUnit)
// XXX: public final Maybe timeout(long,TimeUnit,MaybeSource)
// XXX: public final Maybe timeout(long,TimeUnit,Scheduler)
// XXX: public final Maybe timeout(long,TimeUnit,Scheduler,MaybeSource)
// XXX: public final Maybe timeout(MaybeSource)
// XXX: public final Maybe timeout(MaybeSource,MaybeSource)
// XXX: public final Maybe timeout(Publisher)
// XXX: public final Maybe timeout(Publisher,MaybeSource)
// XXX: public final Object to(Function)
static final class MaybeToFlowable<T> {
@BeforeTemplate
Flowable<T> before(Maybe<T> maybe) {
return maybe.toFlowable();
}
@AfterTemplate
Flowable<T> after(Maybe<T> maybe) {
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.maybeToMono(maybe).flux());
}
}
static final class MaybeToObservable<T> {
@BeforeTemplate
Observable<T> before(Maybe<T> maybe) {
return maybe.toObservable();
}
@AfterTemplate
Observable<T> after(Maybe<T> maybe) {
return RxJava2Adapter.fluxToObservable(RxJava2Adapter.maybeToMono(maybe).flux());
}
}
// XXX: Add test
static final class MaybeToSingle<T> {
@BeforeTemplate
Single<T> before(Maybe<T> maybe) {
return maybe.toSingle();
}
@AfterTemplate
Single<T> after(Maybe<T> maybe) {
return RxJava2Adapter.monoToSingle(RxJava2Adapter.maybeToMono(maybe).single());
}
}
// XXX: public final Single toSingle(Object)
// XXX: public final Maybe unsubscribeOn(Scheduler)
// XXX: Add test
static final class MaybeZipWith<T, R, U> {
@BeforeTemplate
Maybe<R> before(
Maybe<T> maybe,
MaybeSource<U> source,
BiFunction<? super T, ? super U, ? extends R> biFunction) {
return maybe.zipWith(source, biFunction);
}
@AfterTemplate
Maybe<R> after(
Maybe<T> maybe,
MaybeSource<U> source,
BiFunction<? super T, ? super U, ? extends R> biFunction) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.maybeToMono(maybe)
.zipWith(
RxJava2Adapter.maybeToMono(Maybe.wrap(source)),
RxJavaReactorMigrationUtil.toJdkBiFunction(biFunction)));
}
}
@SuppressWarnings("unchecked")
static final class MaybeTestAssertResultItem<T> {
@BeforeTemplate
void before(Maybe<T> maybe, T item) throws InterruptedException {
Refaster.anyOf(
maybe.test().await().assertResult(item),
maybe.test().await().assertResult(item).assertComplete(),
maybe.test().await().assertComplete().assertResult(item),
maybe.test().await().assertValue(item),
maybe.test().await().assertValue(item).assertComplete(),
maybe.test().await().assertComplete().assertValue(item),
// XXX: Move this to correct method
maybe.test().await().assertValues(item));
}
@AfterTemplate
void after(Maybe<T> maybe, T item) {
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).expectNext(item).verifyComplete();
}
}
@SuppressWarnings("unchecked")
static final class MaybeTestAssertResult<T> {
@BeforeTemplate
void before(Maybe<T> maybe) throws InterruptedException {
maybe.test().await().assertResult();
}
@AfterTemplate
void after(Maybe<T> maybe) {
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyComplete();
}
}
static final class MaybeTestAssertValue<T> {
@BeforeTemplate
void before(Maybe<T> maybe, Predicate<T> predicate) throws InterruptedException {
Refaster.anyOf(
maybe.test().await().assertValue(predicate),
maybe.test().await().assertValue(predicate).assertComplete(),
maybe.test().await().assertValue(predicate).assertNoErrors().assertComplete(),
maybe.test().await().assertComplete().assertValue(predicate));
}
@AfterTemplate
void after(Maybe<T> maybe, Predicate<T> predicate) {
RxJava2Adapter.maybeToMono(maybe)
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(predicate))
.verifyComplete();
}
}
static final class MaybeTestAssertComplete<T> {
@BeforeTemplate
void before(Maybe<T> maybe) throws InterruptedException {
maybe.test().await().assertComplete();
}
@AfterTemplate
void after(Maybe<T> maybe) {
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyComplete();
}
}
static final class MaybeTestAssertErrorClass<T> {
@BeforeTemplate
void before(Maybe<T> maybe, Class<? extends Throwable> errorClass) throws InterruptedException {
maybe.test().await().assertError(errorClass);
}
@AfterTemplate
void after(Maybe<T> maybe, Class<? extends Throwable> errorClass) {
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyError(errorClass);
}
}
static final class MaybeTestAssertNoErrors<T> {
@BeforeTemplate
void before(Maybe<T> maybe) throws InterruptedException {
maybe.test().await().assertNoErrors();
}
@AfterTemplate
void after(Maybe<T> maybe) {
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyComplete();
}
}
static final class MaybeTestAssertValueCount<T> {
@BeforeTemplate
void before(Maybe<T> maybe, int count) throws InterruptedException {
maybe.test().await().assertValueCount(count);
}
@AfterTemplate
void after(Maybe<T> maybe, int count) {
RxJava2Adapter.maybeToMono(maybe)
.as(StepVerifier::create)
.expectNextCount(count)
.verifyComplete();
}
}
// XXX: Add test
@SuppressWarnings("unchecked")
static final class MaybeTestAssertFailure<T> {
@BeforeTemplate
void before(Maybe<T> maybe, Class<? extends Throwable> error) throws InterruptedException {
maybe.test().await().assertFailure(error);
}
@AfterTemplate
void after(Maybe<T> maybe, Class<? extends Throwable> error) {
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyError(error);
}
}
// XXX: Add test
static final class MaybeTestAssertNoValues<T> {
@BeforeTemplate
void before(Maybe<T> maybe) throws InterruptedException {
Refaster.anyOf(
maybe.test().await().assertNoValues(),
maybe.test().assertNoValues(),
maybe.test().assertNoValues().assertComplete(),
maybe.test().await().assertNoValues().assertComplete(),
maybe.test().await().assertComplete().assertNoValues());
}
@AfterTemplate
void after(Maybe<T> maybe) {
RxJava2Adapter.maybeToMono(maybe).as(StepVerifier::create).verifyComplete();
}
}
// XXX: Add test
// XXX: This introduces AssertJ dependency
@SuppressWarnings("unchecked")
static final class MaybeTestAssertFailureAndMessage<T> {
@BeforeTemplate
void before(Maybe<T> maybe, Class<? extends Throwable> error, String message)
throws InterruptedException {
maybe.test().await().assertFailureAndMessage(error, message);
}
@AfterTemplate
void after(Maybe<T> maybe, Class<? extends Throwable> error, String message) {
RxJava2Adapter.maybeToMono(maybe)
.as(StepVerifier::create)
.expectErrorSatisfies(
t -> assertThat(t).isInstanceOf(error).hasMessageContaining(message))
.verify();
}
}
// XXX: public final TestObserver test(boolean)
}

View File

@@ -0,0 +1,927 @@
package tech.picnic.errorprone.refastertemplates;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.collect.Streams;
import com.google.errorprone.refaster.ImportPolicy;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.Repeated;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.MaybeSource;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import java.util.concurrent.Callable;
import org.reactivestreams.Publisher;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
/** The Refaster templates for the migration of the RxJava Observable type to Reactor */
final class RxJavaObservableToReactorTemplates {
private RxJavaObservableToReactorTemplates() {}
static final class ObservableAmb<T> {
@BeforeTemplate
Observable<T> before(Iterable<? extends Observable<T>> sources) {
return Observable.amb(sources);
}
@AfterTemplate
Observable<T> after(Iterable<? extends Observable<T>> sources) {
return RxJava2Adapter.fluxToObservable(
Flux.<T>firstWithSignal(
Streams.stream(sources)
.map(e -> e.toFlowable(BackpressureStrategy.BUFFER))
.map(RxJava2Adapter::flowableToFlux)
.collect(toImmutableList())));
}
}
// XXX: public static Observable ambArray(ObservableSource[])
// XXX: public static int bufferSize()
// XXX: public static Observable combineLatest(Function,int,ObservableSource[])
// XXX: public static Observable combineLatest(Iterable,Function)
// XXX: public static Observable combineLatest(Iterable,Function,int)
// XXX: public static Observable combineLatest(ObservableSource[],Function)
// XXX: public static Observable combineLatest(ObservableSource[],Function,int)
// XXX: public static Observable combineLatest(ObservableSource,ObservableSource,BiFunction)
// XXX: public static Observable
// combineLatest(ObservableSource,ObservableSource,ObservableSource,Function3)
// XXX: public static Observable
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function4)
// XXX: public static Observable
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function5)
// XXX: public static Observable
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function6)
// XXX: public static Observable
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function7)
// XXX: public static Observable
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function8)
// XXX: public static Observable
// combineLatest(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function9)
// XXX: public static Observable combineLatestDelayError(Function,int,ObservableSource[])
// XXX: public static Observable combineLatestDelayError(Iterable,Function)
// XXX: public static Observable combineLatestDelayError(Iterable,Function,int)
// XXX: public static Observable combineLatestDelayError(ObservableSource[],Function)
// XXX: public static Observable combineLatestDelayError(ObservableSource[],Function,int)
// XXX: public static Observable concat(Iterable)
// XXX: public static Observable concat(ObservableSource)
// XXX: public static Observable concat(ObservableSource,int)
// XXX: public static Observable concat(ObservableSource,ObservableSource)
// XXX: public static Observable concat(ObservableSource,ObservableSource,ObservableSource)
// XXX: public static Observable
// concat(ObservableSource,ObservableSource,ObservableSource,ObservableSource)
// XXX: public static Observable concatArray(ObservableSource[])
// XXX: public static Observable concatArrayDelayError(ObservableSource[])
// XXX: public static Observable concatArrayEager(int,int,ObservableSource[])
// XXX: public static Observable concatArrayEager(ObservableSource[])
// XXX: public static Observable concatArrayEagerDelayError(int,int,ObservableSource[])
// XXX: public static Observable concatArrayEagerDelayError(ObservableSource[])
// XXX: public static Observable concatDelayError(Iterable)
// XXX: public static Observable concatDelayError(ObservableSource)
// XXX: public static Observable concatDelayError(ObservableSource,int,boolean)
// XXX: public static Observable concatEager(Iterable)
// XXX: public static Observable concatEager(Iterable,int,int)
// XXX: public static Observable concatEager(ObservableSource)
// XXX: public static Observable concatEager(ObservableSource,int,int)
// XXX: public static Observable create(ObservableOnSubscribe)
// XXX: public static Observable defer(Callable)
static final class ObservableEmpty<T> {
@BeforeTemplate
Observable<T> before() {
return Observable.empty();
}
@AfterTemplate
Observable<T> after() {
return RxJava2Adapter.fluxToObservable(Flux.empty());
}
}
// XXX: public static Observable error(Callable)
// XXX: public static Observable error(Throwable)
// XXX: public static Observable fromArray(Object[])
static final class ObservableFromCallable<T> {
@BeforeTemplate
Observable<? extends T> before(Callable<? extends T> callable) {
return Observable.fromCallable(callable);
}
@AfterTemplate
Observable<? extends T> after(Callable<? extends T> callable) {
return RxJava2Adapter.fluxToObservable(
Mono.fromSupplier(RxJavaReactorMigrationUtil.callableAsSupplier(callable)).flux());
}
}
// XXX: public static Observable fromFuture(Future)
// XXX: public static Observable fromFuture(Future,long,TimeUnit)
// XXX: public static Observable fromFuture(Future,long,TimeUnit,Scheduler)
// XXX: public static Observable fromFuture(Future,Scheduler)
// XXX: public static Observable fromIterable(Iterable)
static final class ObservableFromPublisher<T> {
@BeforeTemplate
Observable<T> before(Publisher<? extends T> source) {
return Observable.fromPublisher(source);
}
@AfterTemplate
Observable<T> after(Publisher<? extends T> source) {
return RxJava2Adapter.fluxToObservable(Flux.from(source));
}
}
// XXX: public static Observable generate(Callable,BiConsumer)
// XXX: public static Observable generate(Callable,BiConsumer,Consumer)
// XXX: public static Observable generate(Callable,BiFunction)
// XXX: public static Observable generate(Callable,BiFunction,Consumer)
// XXX: public static Observable generate(Consumer)
// XXX: public static Observable interval(long,long,TimeUnit)
// XXX: public static Observable interval(long,long,TimeUnit,Scheduler)
// XXX: public static Observable interval(long,TimeUnit)
// XXX: public static Observable interval(long,TimeUnit,Scheduler)
// XXX: public static Observable intervalRange(long,long,long,long,TimeUnit)
// XXX: public static Observable intervalRange(long,long,long,long,TimeUnit,Scheduler)
static final class ObservableJust<T> {
@BeforeTemplate
Observable<T> before(T t) {
return Observable.just(t);
}
@AfterTemplate
Observable<T> after(T t) {
return RxJava2Adapter.fluxToObservable(Flux.just(t));
}
}
static final class ObservableJustTwo<T> {
@BeforeTemplate
Observable<T> before(T t, T t2) {
return Observable.just(t, t2);
}
@AfterTemplate
Observable<T> after(T t, T t2) {
return RxJava2Adapter.fluxToObservable(Flux.just(t, t2));
}
}
static final class ObservableJustThree<T> {
@BeforeTemplate
Observable<T> before(T t, T t2, T t3) {
return Observable.just(t, t2, t3);
}
@AfterTemplate
Observable<T> after(T t, T t2, T t3) {
return RxJava2Adapter.fluxToObservable(Flux.just(t, t2, t3));
}
}
// XXX: public static Observable just(Object,Object,Object,Object)
// XXX: public static Observable just(Object,Object,Object,Object,Object)
// XXX: public static Observable just(Object,Object,Object,Object,Object,Object)
// XXX: public static Observable just(Object,Object,Object,Object,Object,Object,Object)
// XXX: public static Observable just(Object,Object,Object,Object,Object,Object,Object,Object)
// XXX: public static Observable
// just(Object,Object,Object,Object,Object,Object,Object,Object,Object)
// XXX: public static Observable
// just(Object,Object,Object,Object,Object,Object,Object,Object,Object,Object)
// XXX: public static Observable merge(Iterable)
// XXX: public static Observable merge(Iterable,int)
// XXX: public static Observable merge(Iterable,int,int)
// XXX: public static Observable merge(ObservableSource)
// XXX: public static Observable merge(ObservableSource,int)
// XXX: public static Observable merge(ObservableSource,ObservableSource)
// XXX: public static Observable merge(ObservableSource,ObservableSource,ObservableSource)
// XXX: public static Observable
// merge(ObservableSource,ObservableSource,ObservableSource,ObservableSource)
// XXX: public static Observable mergeArray(int,int,ObservableSource[])
// XXX: public static Observable mergeArray(ObservableSource[])
// XXX: public static Observable mergeArrayDelayError(int,int,ObservableSource[])
// XXX: public static Observable mergeArrayDelayError(ObservableSource[])
// XXX: public static Observable mergeDelayError(Iterable)
// XXX: public static Observable mergeDelayError(Iterable,int)
// XXX: public static Observable mergeDelayError(Iterable,int,int)
// XXX: public static Observable mergeDelayError(ObservableSource)
// XXX: public static Observable mergeDelayError(ObservableSource,int)
// XXX: public static Observable mergeDelayError(ObservableSource,ObservableSource)
// XXX: public static Observable
// mergeDelayError(ObservableSource,ObservableSource,ObservableSource)
// XXX: public static Observable
// mergeDelayError(ObservableSource,ObservableSource,ObservableSource,ObservableSource)
// XXX: public static Observable never()
// XXX: public static Observable range(int,int)
// XXX: public static Observable rangeLong(long,long)
// XXX: public static Single sequenceEqual(ObservableSource,ObservableSource)
// XXX: public static Single sequenceEqual(ObservableSource,ObservableSource,BiPredicate)
// XXX: public static Single sequenceEqual(ObservableSource,ObservableSource,BiPredicate,int)
// XXX: public static Single sequenceEqual(ObservableSource,ObservableSource,int)
// XXX: public static Observable switchOnNext(ObservableSource)
// XXX: public static Observable switchOnNext(ObservableSource,int)
// XXX: public static Observable switchOnNextDelayError(ObservableSource)
// XXX: public static Observable switchOnNextDelayError(ObservableSource,int)
// XXX: public static Observable timer(long,TimeUnit)
// XXX: public static Observable timer(long,TimeUnit,Scheduler)
// XXX: public static Observable unsafeCreate(ObservableSource)
// XXX: public static Observable using(Callable,Function,Consumer)
// XXX: public static Observable using(Callable,Function,Consumer,boolean)
// XXX: public static Observable wrap(ObservableSource)
// XXX: public static Observable zip(Iterable,Function)
// XXX: public static Observable zip(ObservableSource,Function)
// XXX: public static Observable zip(ObservableSource,ObservableSource,BiFunction)
// XXX: public static Observable zip(ObservableSource,ObservableSource,BiFunction,boolean)
// XXX: public static Observable zip(ObservableSource,ObservableSource,BiFunction,boolean,int)
// XXX: public static Observable zip(ObservableSource,ObservableSource,ObservableSource,Function3)
// XXX: public static Observable
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function4)
// XXX: public static Observable
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function5)
// XXX: public static Observable
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function6)
// XXX: public static Observable
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function7)
// XXX: public static Observable
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function8)
// XXX: public static Observable
// zip(ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function9)
// XXX: public static Observable zipArray(Function,boolean,int,ObservableSource[])
// XXX: public static Observable zipIterable(Iterable,Function,boolean,int)
// XXX: public final Single all(Predicate)
// XXX: public final Observable ambWith(ObservableSource)
// XXX: public final Single any(Predicate)
// XXX: public final Object as(ObservableConverter)
// XXX: public final Object blockingFirst()
// XXX: public final Object blockingFirst(Object)
// XXX: public final void blockingForEach(Consumer)
// XXX: public final Iterable blockingIterable()
// XXX: public final Iterable blockingIterable(int)
// XXX: public final Object blockingLast()
// XXX: public final Object blockingLast(Object)
// XXX: public final Iterable blockingLatest()
// XXX: public final Iterable blockingMostRecent(Object)
// XXX: public final Iterable blockingNext()
// XXX: public final Object blockingSingle()
// XXX: public final Object blockingSingle(Object)
// XXX: public final void blockingSubscribe()
// XXX: public final void blockingSubscribe(Consumer)
// XXX: public final void blockingSubscribe(Consumer,Consumer)
// XXX: public final void blockingSubscribe(Consumer,Consumer,Action)
// XXX: public final void blockingSubscribe(Observer)
// XXX: public final Observable buffer(Callable)
// XXX: public final Observable buffer(Callable,Callable)
// XXX: public final Observable buffer(int)
// XXX: public final Observable buffer(int,Callable)
// XXX: public final Observable buffer(int,int)
// XXX: public final Observable buffer(int,int,Callable)
// XXX: public final Observable buffer(long,long,TimeUnit)
// XXX: public final Observable buffer(long,long,TimeUnit,Scheduler)
// XXX: public final Observable buffer(long,long,TimeUnit,Scheduler,Callable)
// XXX: public final Observable buffer(long,TimeUnit)
// XXX: public final Observable buffer(long,TimeUnit,int)
// XXX: public final Observable buffer(long,TimeUnit,Scheduler)
// XXX: public final Observable buffer(long,TimeUnit,Scheduler,int)
// XXX: public final Observable buffer(long,TimeUnit,Scheduler,int,Callable,boolean)
// XXX: public final Observable buffer(ObservableSource)
// XXX: public final Observable buffer(ObservableSource,Callable)
// XXX: public final Observable buffer(ObservableSource,Function)
// XXX: public final Observable buffer(ObservableSource,Function,Callable)
// XXX: public final Observable buffer(ObservableSource,int)
// XXX: public final Observable cache()
// XXX: public final Observable cacheWithInitialCapacity(int)
// XXX: public final Observable cast(Class)
// XXX: public final Single collect(Callable,BiConsumer)
// XXX: public final Single collectInto(Object,BiConsumer)
// XXX: public final Observable compose(ObservableTransformer)
// XXX: public final Observable concatMap(Function)
// XXX: public final Observable concatMap(Function,int)
// XXX: public final Completable concatMapCompletable(Function)
// XXX: public final Completable concatMapCompletable(Function,int)
// XXX: public final Completable concatMapCompletableDelayError(Function)
// XXX: public final Completable concatMapCompletableDelayError(Function,boolean)
// XXX: public final Completable concatMapCompletableDelayError(Function,boolean,int)
// XXX: public final Observable concatMapDelayError(Function)
// XXX: public final Observable concatMapDelayError(Function,int,boolean)
// XXX: public final Observable concatMapEager(Function)
// XXX: public final Observable concatMapEager(Function,int,int)
// XXX: public final Observable concatMapEagerDelayError(Function,boolean)
// XXX: public final Observable concatMapEagerDelayError(Function,int,int,boolean)
// XXX: public final Observable concatMapIterable(Function)
// XXX: public final Observable concatMapIterable(Function,int)
// XXX: public final Observable concatMapMaybe(Function)
// XXX: public final Observable concatMapMaybe(Function,int)
// XXX: public final Observable concatMapMaybeDelayError(Function)
// XXX: public final Observable concatMapMaybeDelayError(Function,boolean)
// XXX: public final Observable concatMapMaybeDelayError(Function,boolean,int)
// XXX: public final Observable concatMapSingle(Function)
// XXX: public final Observable concatMapSingle(Function,int)
// XXX: public final Observable concatMapSingleDelayError(Function)
// XXX: public final Observable concatMapSingleDelayError(Function,boolean)
// XXX: public final Observable concatMapSingleDelayError(Function,boolean,int)
// XXX: public final Observable concatWith(CompletableSource)
// XXX: public final Observable concatWith(MaybeSource)
// XXX: public final Observable concatWith(ObservableSource)
// XXX: public final Observable concatWith(SingleSource)
// XXX: public final Single contains(Object)
// XXX: public final Single count()
// XXX: public final Observable debounce(Function)
// XXX: public final Observable debounce(long,TimeUnit)
// XXX: public final Observable debounce(long,TimeUnit,Scheduler)
// XXX: public final Observable defaultIfEmpty(Object)
// XXX: public final Observable delay(Function)
// XXX: public final Observable delay(long,TimeUnit)
// XXX: public final Observable delay(long,TimeUnit,boolean)
// XXX: public final Observable delay(long,TimeUnit,Scheduler)
// XXX: public final Observable delay(long,TimeUnit,Scheduler,boolean)
// XXX: public final Observable delay(ObservableSource,Function)
// XXX: public final Observable delaySubscription(long,TimeUnit)
// XXX: public final Observable delaySubscription(long,TimeUnit,Scheduler)
// XXX: public final Observable delaySubscription(ObservableSource)
// XXX: public final Observable dematerialize()
// XXX: public final Observable dematerialize(Function)
// XXX: public final Observable distinct()
// XXX: public final Observable distinct(Function)
// XXX: public final Observable distinct(Function,Callable)
// XXX: public final Observable distinctUntilChanged()
// XXX: public final Observable distinctUntilChanged(BiPredicate)
// XXX: public final Observable distinctUntilChanged(Function)
// XXX: public final Observable doAfterNext(Consumer)
// XXX: public final Observable doAfterTerminate(Action)
// XXX: public final Observable doFinally(Action)
// XXX: public final Observable doOnComplete(Action)
// XXX: public final Observable doOnDispose(Action)
// XXX: public final Observable doOnEach(Consumer)
// XXX: public final Observable doOnEach(Observer)
// XXX: public final Observable doOnError(Consumer)
// XXX: public final Observable doOnLifecycle(Consumer,Action)
// XXX: public final Observable doOnNext(Consumer)
// XXX: public final Observable doOnSubscribe(Consumer)
// XXX: public final Observable doOnTerminate(Action)
// XXX: public final Maybe elementAt(long)
// XXX: public final Single elementAt(long,Object)
// XXX: public final Single elementAtOrError(long)
// XXX: Default BackPressureStrategy.BUFFER is set.
static final class ObservableFilter<T> {
@BeforeTemplate
Observable<T> before(Observable<T> observable, Predicate<T> predicate) {
return observable.filter(predicate);
}
@AfterTemplate
Observable<T> after(Observable<T> observable, Predicate<T> predicate) {
return RxJava2Adapter.fluxToObservable(
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate)));
}
}
// XXX: public final Single first(Object)
// XXX: Default BUFFER is chosen here.
static final class MaybeFirstElement<T> {
@BeforeTemplate
Maybe<T> before(Observable<T> observable) {
return observable.firstElement();
}
@AfterTemplate
Maybe<T> after(Observable<T> observable) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER).next());
}
}
// XXX: public final Single firstOrError()
// XXX: public final Observable flatMap(Function)
// XXX: Add test
// XXX: Default BUFFER is set here.
static final class ObservableFlatMap<I, T extends I, O, P extends ObservableSource<O>> {
@BeforeTemplate
Observable<O> before(
Observable<T> observable,
Function<? super T, ? extends ObservableSource<? extends O>> function) {
return observable.flatMap(function);
}
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
@AfterTemplate
Observable<O> after(Observable<T> observable, Function<I, P> function) {
return RxJava2Adapter.fluxToObservable(
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.flatMap(
z ->
RxJava2Adapter.observableToFlux(
Observable.wrap(
RxJavaReactorMigrationUtil.<I, P>toJdkFunction(function).apply(z)),
BackpressureStrategy.BUFFER)));
}
}
// XXX: public final Observable flatMap(Function,BiFunction)
// XXX: public final Observable flatMap(Function,BiFunction,boolean)
// XXX: public final Observable flatMap(Function,BiFunction,boolean,int)
// XXX: public final Observable flatMap(Function,BiFunction,boolean,int,int)
// XXX: public final Observable flatMap(Function,BiFunction,int)
// XXX: public final Observable flatMap(Function,boolean)
// XXX: public final Observable flatMap(Function,boolean,int)
// XXX: public final Observable flatMap(Function,boolean,int,int)
// XXX: public final Observable flatMap(Function,Function,Callable)
// XXX: public final Observable flatMap(Function,Function,Callable,int)
// XXX: public final Observable flatMap(Function,int)
// XXX: public final Completable flatMapCompletable(Function)
// XXX: public final Completable flatMapCompletable(Function,boolean)
static final class ObservableFromIterable<T> {
@BeforeTemplate
Observable<T> before(Iterable<? extends T> iterable) {
return Observable.fromIterable(iterable);
}
@AfterTemplate
Observable<T> after(Iterable<? extends T> iterable) {
return RxJava2Adapter.fluxToObservable(Flux.fromIterable(iterable));
}
}
// XXX: public final Observable flatMapIterable(Function,BiFunction)
static final class ObservableFlatMapMaybe<T, R, O extends R, M extends MaybeSource<O>> {
Observable<O> before(
Observable<T> observable, Function<? super T, ? extends MaybeSource<? extends O>> mapper) {
return observable.flatMapMaybe(mapper);
}
Observable<O> after(Observable<T> observable, Function<T, M> mapper) {
return RxJava2Adapter.fluxToObservable(
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.flatMap(
t ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.<T, M>toJdkFunction(mapper).apply(t)))));
}
} // XXX: public final Observable flatMapMaybe(Function,boolean)
// XXX: public final Observable flatMapSingle(Function)
// XXX: public final Observable flatMapSingle(Function,boolean)
// XXX: public final Disposable forEach(Consumer)
// XXX: public final Disposable forEachWhile(Predicate)
// XXX: public final Disposable forEachWhile(Predicate,Consumer)
// XXX: public final Disposable forEachWhile(Predicate,Consumer,Action)
// XXX: public final Observable groupBy(Function)
// XXX: public final Observable groupBy(Function,boolean)
// XXX: public final Observable groupBy(Function,Function)
// XXX: public final Observable groupBy(Function,Function,boolean)
// XXX: public final Observable groupBy(Function,Function,boolean,int)
// XXX: public final Observable groupJoin(ObservableSource,Function,Function,BiFunction)
// XXX: public final Observable hide()
static final class ObservableIgnoreElements<T> {
@BeforeTemplate
Completable before(Observable<T> observable) {
return observable.ignoreElements();
}
@AfterTemplate
Completable after(Observable<T> observable) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.ignoreElements()
.then());
}
}
// XXX: public final Single isEmpty()
// XXX: public final Observable join(ObservableSource,Function,Function,BiFunction)
// XXX: public final Single last(Object)
// XXX: public final Maybe lastElement()
// XXX: public final Single lastOrError()
// XXX: public final Observable lift(ObservableOperator)
// XXX: public final Observable map(Function)
// XXX: public final Observable materialize()
// XXX: public final Observable mergeWith(CompletableSource)
// XXX: public final Observable mergeWith(MaybeSource)
// XXX: public final Observable mergeWith(ObservableSource)
// XXX: public final Observable mergeWith(SingleSource)
// XXX: public final Observable observeOn(Scheduler)
// XXX: public final Observable observeOn(Scheduler,boolean)
// XXX: public final Observable observeOn(Scheduler,boolean,int)
// XXX: public final Observable ofType(Class)
// XXX: public final Observable onErrorResumeNext(Function)
// XXX: public final Observable onErrorResumeNext(ObservableSource)
// XXX: public final Observable onErrorReturn(Function)
// XXX: public final Observable onErrorReturnItem(Object)
// XXX: public final Observable onExceptionResumeNext(ObservableSource)
// XXX: public final Observable onTerminateDetach()
// XXX: public final ConnectableObservable publish()
// XXX: public final Observable publish(Function)
// XXX: public final Maybe reduce(BiFunction)
// XXX: public final Single reduce(Object,BiFunction)
// XXX: public final Single reduceWith(Callable,BiFunction)
// XXX: public final Observable repeat()
// XXX: public final Observable repeat(long)
// XXX: public final Observable repeatUntil(BooleanSupplier)
// XXX: public final Observable repeatWhen(Function)
// XXX: public final ConnectableObservable replay()
// XXX: public final Observable replay(Function)
// XXX: public final Observable replay(Function,int)
// XXX: public final Observable replay(Function,int,long,TimeUnit)
// XXX: public final Observable replay(Function,int,long,TimeUnit,Scheduler)
// XXX: public final Observable replay(Function,int,Scheduler)
// XXX: public final Observable replay(Function,long,TimeUnit)
// XXX: public final Observable replay(Function,long,TimeUnit,Scheduler)
// XXX: public final Observable replay(Function,Scheduler)
// XXX: public final ConnectableObservable replay(int)
// XXX: public final ConnectableObservable replay(int,long,TimeUnit)
// XXX: public final ConnectableObservable replay(int,long,TimeUnit,Scheduler)
// XXX: public final ConnectableObservable replay(int,Scheduler)
// XXX: public final ConnectableObservable replay(long,TimeUnit)
// XXX: public final ConnectableObservable replay(long,TimeUnit,Scheduler)
// XXX: public final ConnectableObservable replay(Scheduler)
// XXX: public final Observable retry()
// XXX: public final Observable retry(BiPredicate)
// XXX: public final Observable retry(long)
// XXX: public final Observable retry(long,Predicate)
// XXX: public final Observable retry(Predicate)
// XXX: public final Observable retryUntil(BooleanSupplier)
// XXX: public final Observable retryWhen(Function)
// XXX: public final void safeSubscribe(Observer)
// XXX: public final Observable sample(long,TimeUnit)
// XXX: public final Observable sample(long,TimeUnit,boolean)
// XXX: public final Observable sample(long,TimeUnit,Scheduler)
// XXX: public final Observable sample(long,TimeUnit,Scheduler,boolean)
// XXX: public final Observable sample(ObservableSource)
// XXX: public final Observable sample(ObservableSource,boolean)
// XXX: public final Observable scan(BiFunction)
// XXX: public final Observable scan(Object,BiFunction)
// XXX: public final Observable scanWith(Callable,BiFunction)
// XXX: public final Observable serialize()
// XXX: public final Observable share()
// XXX: public final Single single(Object)
// XXX: public final Maybe singleElement()
// XXX: public final Single singleOrError()
// XXX: public final Observable skip(long)
// XXX: public final Observable skip(long,TimeUnit)
// XXX: public final Observable skip(long,TimeUnit,Scheduler)
// XXX: public final Observable skipLast(int)
// XXX: public final Observable skipLast(long,TimeUnit)
// XXX: public final Observable skipLast(long,TimeUnit,boolean)
// XXX: public final Observable skipLast(long,TimeUnit,Scheduler)
// XXX: public final Observable skipLast(long,TimeUnit,Scheduler,boolean)
// XXX: public final Observable skipLast(long,TimeUnit,Scheduler,boolean,int)
// XXX: public final Observable skipUntil(ObservableSource)
// XXX: public final Observable skipWhile(Predicate)
// XXX: public final Observable sorted()
// XXX: public final Observable sorted(Comparator)
// XXX: public final Observable startWith(Iterable)
// XXX: public final Observable startWith(Object)
// XXX: public final Observable startWith(ObservableSource)
// XXX: public final Observable startWithArray(Object[])
// XXX: public final Disposable subscribe()
// XXX: public final Disposable subscribe(Consumer)
// XXX: public final Disposable subscribe(Consumer,Consumer)
// XXX: public final Disposable subscribe(Consumer,Consumer,Action)
// XXX: public final Disposable subscribe(Consumer,Consumer,Action,Consumer)
// XXX: public final void subscribe(Observer)
// XXX: public final Observable subscribeOn(Scheduler)
// XXX: public final Observer subscribeWith(Observer)
// XXX: public final Observable switchIfEmpty(ObservableSource)
// XXX: public final Observable switchMap(Function)
// XXX: public final Observable switchMap(Function,int)
// XXX: public final Completable switchMapCompletable(Function)
// XXX: public final Completable switchMapCompletableDelayError(Function)
// XXX: public final Observable switchMapDelayError(Function)
// XXX: public final Observable switchMapDelayError(Function,int)
// XXX: public final Observable switchMapMaybe(Function)
// XXX: public final Observable switchMapMaybeDelayError(Function)
// XXX: public final Observable switchMapSingle(Function)
// XXX: public final Observable switchMapSingleDelayError(Function)
// XXX: public final Observable take(long)
// XXX: public final Observable take(long,TimeUnit)
// XXX: public final Observable take(long,TimeUnit,Scheduler)
// XXX: public final Observable takeLast(int)
// XXX: public final Observable takeLast(long,long,TimeUnit)
// XXX: public final Observable takeLast(long,long,TimeUnit,Scheduler)
// XXX: public final Observable takeLast(long,long,TimeUnit,Scheduler,boolean,int)
// XXX: public final Observable takeLast(long,TimeUnit)
// XXX: public final Observable takeLast(long,TimeUnit,boolean)
// XXX: public final Observable takeLast(long,TimeUnit,Scheduler)
// XXX: public final Observable takeLast(long,TimeUnit,Scheduler,boolean)
// XXX: public final Observable takeLast(long,TimeUnit,Scheduler,boolean,int)
// XXX: public final Observable takeUntil(ObservableSource)
// XXX: public final Observable takeUntil(Predicate)
// XXX: public final Observable takeWhile(Predicate)
// XXX: public final Observable throttleFirst(long,TimeUnit)
// XXX: public final Observable throttleFirst(long,TimeUnit,Scheduler)
// XXX: public final Observable throttleLast(long,TimeUnit)
// XXX: public final Observable throttleLast(long,TimeUnit,Scheduler)
// XXX: public final Observable throttleLatest(long,TimeUnit)
// XXX: public final Observable throttleLatest(long,TimeUnit,boolean)
// XXX: public final Observable throttleLatest(long,TimeUnit,Scheduler)
// XXX: public final Observable throttleLatest(long,TimeUnit,Scheduler,boolean)
// XXX: public final Observable throttleWithTimeout(long,TimeUnit)
// XXX: public final Observable throttleWithTimeout(long,TimeUnit,Scheduler)
// XXX: public final Observable timeInterval()
// XXX: public final Observable timeInterval(Scheduler)
// XXX: public final Observable timeInterval(TimeUnit)
// XXX: public final Observable timeInterval(TimeUnit,Scheduler)
// XXX: public final Observable timeout(Function)
// XXX: public final Observable timeout(Function,ObservableSource)
// XXX: public final Observable timeout(long,TimeUnit)
// XXX: public final Observable timeout(long,TimeUnit,ObservableSource)
// XXX: public final Observable timeout(long,TimeUnit,Scheduler)
// XXX: public final Observable timeout(long,TimeUnit,Scheduler,ObservableSource)
// XXX: public final Observable timeout(ObservableSource,Function)
// XXX: public final Observable timeout(ObservableSource,Function,ObservableSource)
// XXX: public final Observable timestamp()
// XXX: public final Observable timestamp(Scheduler)
// XXX: public final Observable timestamp(TimeUnit)
// XXX: public final Observable timestamp(TimeUnit,Scheduler)
// XXX: public final Object to(Function)
static final class CompletableToFlowable<T> {
@BeforeTemplate
Flowable<T> before(Observable<T> observable, BackpressureStrategy strategy) {
return observable.toFlowable(strategy);
}
@AfterTemplate
Flowable<T> after(Observable<T> observable, BackpressureStrategy strategy) {
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.observableToFlux(observable, strategy));
}
}
// XXX: public final Future toFuture()
// XXX: public final Single toList()
// XXX: public final Single toList(Callable)
// XXX: public final Single toList(int)
// XXX: public final Single toMap(Function)
// XXX: public final Single toMap(Function,Function)
// XXX: public final Single toMap(Function,Function,Callable)
// XXX: public final Single toMultimap(Function)
// XXX: public final Single toMultimap(Function,Function)
// XXX: public final Single toMultimap(Function,Function,Callable)
// XXX: public final Single toMultimap(Function,Function,Callable,Function)
// XXX: public final Single toSortedList()
// XXX: public final Single toSortedList(Comparator)
// XXX: public final Single toSortedList(Comparator,int)
// XXX: public final Single toSortedList(int)
// XXX: public final Observable unsubscribeOn(Scheduler)
// XXX: public final Observable window(Callable)
// XXX: public final Observable window(Callable,int)
// XXX: public final Observable window(long)
// XXX: public final Observable window(long,long)
// XXX: public final Observable window(long,long,int)
// XXX: public final Observable window(long,long,TimeUnit)
// XXX: public final Observable window(long,long,TimeUnit,Scheduler)
// XXX: public final Observable window(long,long,TimeUnit,Scheduler,int)
// XXX: public final Observable window(long,TimeUnit)
// XXX: public final Observable window(long,TimeUnit,long)
// XXX: public final Observable window(long,TimeUnit,long,boolean)
// XXX: public final Observable window(long,TimeUnit,Scheduler)
// XXX: public final Observable window(long,TimeUnit,Scheduler,long)
// XXX: public final Observable window(long,TimeUnit,Scheduler,long,boolean)
// XXX: public final Observable window(long,TimeUnit,Scheduler,long,boolean,int)
// XXX: public final Observable window(ObservableSource)
// XXX: public final Observable window(ObservableSource,Function)
// XXX: public final Observable window(ObservableSource,Function,int)
// XXX: public final Observable window(ObservableSource,int)
// XXX: public final Observable withLatestFrom(Iterable,Function)
// XXX: public final Observable withLatestFrom(ObservableSource,BiFunction)
// XXX: public final Observable withLatestFrom(ObservableSource[],Function)
// XXX: public final Observable withLatestFrom(ObservableSource,ObservableSource,Function3)
// XXX: public final Observable
// withLatestFrom(ObservableSource,ObservableSource,ObservableSource,Function4)
// XXX: public final Observable
// withLatestFrom(ObservableSource,ObservableSource,ObservableSource,ObservableSource,Function5)
// XXX: public final Observable zipWith(Iterable,BiFunction)
// XXX: public final Observable zipWith(ObservableSource,BiFunction)
// XXX: public final Observable zipWith(ObservableSource,BiFunction,boolean)
// XXX: public final Observable zipWith(ObservableSource,BiFunction,boolean,int)
// XXX: Default BackpressureStrategy.BUFFER is set
static final class ObservableTestAssertResultItem<T> {
@BeforeTemplate
void before(Observable<T> observable, T item) throws InterruptedException {
Refaster.anyOf(
observable.test().await().assertResult(item),
observable.test().await().assertValue(item));
}
@AfterTemplate
void after(Observable<T> observable, T item) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNext(item)
.verifyComplete();
}
}
// XXX: Default BackpressureStrategy.BUFFER is set
@SuppressWarnings("unchecked")
static final class ObservableTestAssertResult<T> {
@BeforeTemplate
void before(Observable<T> observable) throws InterruptedException {
Refaster.anyOf(observable.test().await().assertResult(), observable.test().await());
}
@AfterTemplate
void after(Observable<T> observable) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyComplete();
}
}
@SuppressWarnings("unchecked")
static final class ObservableTestAssertResultTwoItems<T> {
@BeforeTemplate
void before(Observable<T> observable, T t1, T t2) throws InterruptedException {
observable.test().await().assertResult(t1, t2);
}
@AfterTemplate
void after(Observable<T> observable, T t1, T t2) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNext(t1, t2)
.verifyComplete();
}
}
// XXX: Default BackpressureStrategy.BUFFER is set
static final class ObservableTestAssertValue<T> {
@BeforeTemplate
void before(Observable<T> observable, Predicate<T> predicate) throws InterruptedException {
Refaster.anyOf(
observable.test().await().assertValue(predicate),
observable.test().await().assertValue(predicate).assertNoErrors().assertComplete(),
observable.test().await().assertComplete().assertValue(predicate),
observable.test().await().assertValue(predicate).assertComplete());
}
@AfterTemplate
void after(Observable<T> observable, Predicate<T> predicate) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(predicate))
.verifyComplete();
}
}
// XXX: Default BackpressureStrategy.BUFFER is set
static final class ObservableTestAssertResultValues<T> {
@BeforeTemplate
void before(Observable<T> observable, @Repeated T item) throws InterruptedException {
Refaster.anyOf(
observable.test().await().assertResult(Refaster.asVarargs(item)),
observable.test().await().assertValues(Refaster.asVarargs(item)));
}
@AfterTemplate
void after(Observable<T> observable, @Repeated T item) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNext(item)
.verifyComplete();
}
}
// XXX: Default BackpressureStrategy.BUFFER is set
static final class ObservableTestAssertComplete<T> {
@BeforeTemplate
void before(Observable<T> observable) throws InterruptedException {
observable.test().await().assertComplete();
}
@AfterTemplate
void after(Observable<T> observable) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyComplete();
}
}
// XXX: Default BackpressureStrategy.BUFFER is set
static final class ObservableTestAssertErrorClass<T> {
@BeforeTemplate
void before(Observable<T> observable, Class<? extends Throwable> errorClass)
throws InterruptedException {
observable.test().await().assertError(errorClass);
}
@AfterTemplate
void after(Observable<T> observable, Class<? extends Throwable> errorClass) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyError(errorClass);
}
}
// XXX: Default BackpressureStrategy.BUFFER is set
static final class ObservableTestAssertNoErrors<T> {
@BeforeTemplate
void before(Observable<T> observable) throws InterruptedException {
observable.test().await().assertNoErrors();
}
@AfterTemplate
void after(Observable<T> observable) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyComplete();
}
}
// XXX: Default BackpressureStrategy.BUFFER is set
static final class ObservableTestAssertValueCount<T> {
@BeforeTemplate
void before(Observable<T> observable, int count) throws InterruptedException {
observable.test().await().assertValueCount(count);
}
@AfterTemplate
void after(Observable<T> observable, int count) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectNextCount(count)
.verifyComplete();
}
}
// XXX: Add test
// XXX: Default BackpressureStrategy.BUFFER is set
@SuppressWarnings("unchecked")
static final class ObservableTestAssertFailure<T> {
@BeforeTemplate
void before(Observable<T> observable, Class<? extends Throwable> error)
throws InterruptedException {
observable.test().await().assertFailure(error);
}
@AfterTemplate
void after(Observable<T> observable, Class<? extends Throwable> error) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyError(error);
}
}
// XXX: Add test
// XXX: Default BackpressureStrategy.BUFFER is set
static final class ObservableTestAssertNoValues<T> {
@BeforeTemplate
void before(Observable<T> observable) throws InterruptedException {
Refaster.anyOf(
observable.test().await().assertNoValues(),
observable.test().await().assertNoValues().assertComplete());
}
@AfterTemplate
void after(Observable<T> observable) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.verifyComplete();
}
}
// XXX: Add test
// XXX: This introduces AssertJ dependency
@SuppressWarnings("unchecked")
static final class ObservableTestAssertFailureAndMessage<T> {
@BeforeTemplate
void before(Observable<T> observable, Class<? extends Throwable> error, String message)
throws InterruptedException {
observable.test().await().assertFailureAndMessage(error, message);
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
void after(Observable<T> observable, Class<? extends Throwable> error, String message) {
RxJava2Adapter.observableToFlux(observable, BackpressureStrategy.BUFFER)
.as(StepVerifier::create)
.expectErrorSatisfies(
t -> assertThat(t).isInstanceOf(error).hasMessageContaining(message))
.verify();
}
}
// XXX: public final TestObserver test(boolean)
}

View File

@@ -0,0 +1,764 @@
package tech.picnic.errorprone.refastertemplates;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.refaster.ImportPolicy;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
import com.google.errorprone.refaster.annotation.Placeholder;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import io.reactivex.Completable;
import io.reactivex.CompletableSource;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.MaybeSource;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;
import java.util.concurrent.Callable;
import org.reactivestreams.Publisher;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
/** The Refaster templates for the migration of the RxJava Single type to Reactor */
final class RxJavaSingleToReactorTemplates {
private RxJavaSingleToReactorTemplates() {}
// XXX: public static Single amb(Iterable)
// XXX: public static Single ambArray(SingleSource[])
// XXX: public static Flowable concat(Iterable)
// XXX: public static Observable concat(ObservableSource)
// XXX: public static Flowable concat(Publisher)
// XXX: public static Flowable concat(Publisher,int)
// XXX: public static Flowable concat(SingleSource,SingleSource)
// XXX: public static Flowable concat(SingleSource,SingleSource,SingleSource)
// XXX: public static Flowable concat(SingleSource,SingleSource,SingleSource,SingleSource)
// XXX: public static Flowable concatArray(SingleSource[])
// XXX: public static Flowable concatArrayEager(SingleSource[])
// XXX: public static Flowable concatEager(Iterable)
// XXX: public static Flowable concatEager(Publisher)
// XXX: public static Single create(SingleOnSubscribe)
abstract static class SingleDeferFirst<T> {
@Placeholder
abstract Single<? extends T> singleProducer();
@BeforeTemplate
Single<T> before() {
return Single.defer(() -> singleProducer());
}
@AfterTemplate
Single<? extends T> after() {
return RxJava2Adapter.monoToSingle(
Mono.defer(() -> RxJava2Adapter.singleToMono(singleProducer())));
}
}
// XXX: public static Single equals(SingleSource,SingleSource)
static final class SingleErrorCallable<T> {
@BeforeTemplate
Single<T> before(Callable<? extends Throwable> throwable) {
return Single.error(throwable);
}
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
@AfterTemplate
Single<T> after(Callable<? extends Throwable> throwable) {
return RxJava2Adapter.monoToSingle(
Mono.error(RxJavaReactorMigrationUtil.callableAsSupplier(throwable)));
}
}
static final class SingleErrorThrowable<T> {
@BeforeTemplate
Single<T> before(Throwable throwable) {
return Single.error(throwable);
}
@AfterTemplate
Single<T> after(Throwable throwable) {
return RxJava2Adapter.monoToSingle(Mono.error(throwable));
}
}
static final class SingleFromCallable<T> {
@BeforeTemplate
Single<T> before(Callable<? extends T> callable) {
return Single.fromCallable(callable);
}
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
@AfterTemplate
Single<T> after(Callable<? extends T> callable) {
return RxJava2Adapter.monoToSingle(
Mono.fromSupplier(RxJavaReactorMigrationUtil.callableAsSupplier(callable)));
}
}
// XXX: public static Single fromFuture(Future)
// XXX: public static Single fromFuture(Future,long,TimeUnit)
// XXX: public static Single fromFuture(Future,long,TimeUnit,Scheduler)
// XXX: public static Single fromFuture(Future,Scheduler)
// XXX: public static Single fromObservable(ObservableSource)
static final class SingleFromPublisher<T> {
@BeforeTemplate
Single<T> before(Publisher<? extends T> source) {
return Single.fromPublisher(source);
}
@AfterTemplate
Single<T> after(Publisher<? extends T> source) {
return RxJava2Adapter.monoToSingle(Mono.from(source));
}
}
static final class SingleJust<T> {
@BeforeTemplate
Single<T> before(T item) {
return Single.just(item);
}
@AfterTemplate
Single<T> after(T item) {
return RxJava2Adapter.monoToSingle(Mono.just(item));
}
}
// XXX: public static Flowable merge(Iterable)
// XXX: public static Flowable merge(Publisher)
// XXX: public static Single merge(SingleSource)
// XXX: public static Flowable merge(SingleSource,SingleSource)
// XXX: public static Flowable merge(SingleSource,SingleSource,SingleSource)
// XXX: public static Flowable merge(SingleSource,SingleSource,SingleSource,SingleSource)
// XXX: public static Flowable mergeDelayError(Iterable)
// XXX: public static Flowable mergeDelayError(Publisher)
// XXX: public static Flowable mergeDelayError(SingleSource,SingleSource)
// XXX: public static Flowable mergeDelayError(SingleSource,SingleSource,SingleSource)
// XXX: public static Flowable
// mergeDelayError(SingleSource,SingleSource,SingleSource,SingleSource)
// XXX: public static Single never()
static final class SingleNever {
@BeforeTemplate
<T> Single<T> before() {
return Single.never();
}
@AfterTemplate
<T> Single<T> after() {
return RxJava2Adapter.monoToSingle(Mono.never());
}
}
// XXX: public static Single timer(long,TimeUnit)
// XXX: public static Single timer(long,TimeUnit,Scheduler)
// XXX: public static Single unsafeCreate(SingleSource)
// XXX: public static Single using(Callable,Function,Consumer)
// XXX: public static Single using(Callable,Function,Consumer,boolean)
static final class SingleWrap<T> {
@BeforeTemplate
Single<T> before(Single<T> single) {
return Single.wrap(single);
}
@AfterTemplate
Single<T> after(Single<T> single) {
return single;
}
}
// XXX: public static Single zip(Iterable,Function)
// XXX: public static Single zip(SingleSource,SingleSource,BiFunction)
// XXX: public static Single zip(SingleSource,SingleSource,SingleSource,Function3)
// XXX: public static Single zip(SingleSource,SingleSource,SingleSource,SingleSource,Function4)
// XXX: public static Single
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function5)
// XXX: public static Single
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function6)
// XXX: public static Single
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function7)
// XXX: public static Single
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function8)
// XXX: public static Single
// zip(SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,SingleSource,Function9)
// XXX: public static Single zipArray(Function,SingleSource[])
// XXX: public final Single ambWith(SingleSource)
// XXX: public final Object as(SingleConverter)
static final class SingleBlockingGet<T> {
@BeforeTemplate
Object before(Single<T> single) {
return single.blockingGet();
}
@AfterTemplate
Object after(Single<T> single) {
return RxJava2Adapter.singleToMono(single).block();
}
}
// XXX: public final Single cache()
// XXX: public final Single cast(Class)
// XXX: public final Single compose(SingleTransformer)
static final class SingleConcatWith<T> {
@BeforeTemplate
Flowable<T> before(Single<T> single, SingleSource<? extends T> source) {
return single.concatWith(source);
}
@AfterTemplate
Flowable<T> after(Single<T> single, SingleSource<? extends T> source) {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.singleToMono(single)
.concatWith(RxJava2Adapter.singleToMono(Single.wrap(source))));
}
}
// XXX: public final Single contains(Object)
// XXX: public final Single contains(Object,BiPredicate)
// XXX: public final Single delay(long,TimeUnit)
// XXX: public final Single delay(long,TimeUnit,boolean)
// XXX: public final Single delay(long,TimeUnit,Scheduler)
// XXX: public final Single delay(long,TimeUnit,Scheduler,boolean)
// XXX: public final Single delaySubscription(CompletableSource)
// XXX: public final Single delaySubscription(long,TimeUnit)
// XXX: public final Single delaySubscription(long,TimeUnit,Scheduler)
// XXX: public final Single delaySubscription(ObservableSource)
// XXX: public final Single delaySubscription(Publisher)
// XXX: public final Single delaySubscription(SingleSource)
// XXX: public final Maybe dematerialize(Function)
// XXX: public final Single doAfterSuccess(Consumer)
// XXX: public final Single doAfterTerminate(Action)
// XXX: public final Single doFinally(Action)
// XXX: public final Single doOnDispose(Action)
static final class SingleDoOnError<T> {
@BeforeTemplate
Single<T> before(Single<T> single, Consumer<? super Throwable> consumer) {
return single.doOnError(consumer);
}
@AfterTemplate
Single<T> after(Single<T> single, Consumer<? super Throwable> consumer) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.doOnError(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
}
}
// XXX: public final Single doOnEvent(BiConsumer)
// XXX: public final Single doOnSubscribe(Consumer)
static final class SingleDoOnSuccess<T> {
@BeforeTemplate
Single<T> before(Single<T> single, Consumer<T> consumer) {
return single.doOnSuccess(consumer);
}
@AfterTemplate
Single<T> after(Single<T> single, Consumer<T> consumer) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.doOnSuccess(RxJavaReactorMigrationUtil.toJdkConsumer(consumer)));
}
}
// XXX: public final Single doOnTerminate(Action)
static final class SingleFilter<S, T extends S> {
@BeforeTemplate
Maybe<T> before(Single<T> single, Predicate<S> predicate) {
return single.filter(predicate);
}
@AfterTemplate
Maybe<T> after(Single<T> single, Predicate<S> predicate) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.singleToMono(single)
.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate)));
}
}
// XXX: Add test
static final class SingleFlatMapFunction<I, T extends I, O, M extends SingleSource<O>> {
@BeforeTemplate
Single<O> before(
Single<T> single, Function<? super I, ? extends SingleSource<? extends O>> function) {
return single.flatMap(function);
}
@AfterTemplate
@UseImportPolicy(ImportPolicy.IMPORT_CLASS_DIRECTLY)
Single<O> after(Single<T> single, Function<I, M> function) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.flatMap(
v ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil.<I, M>toJdkFunction(function).apply(v)))));
}
}
abstract static class SingleFlatMapLambda<S, T> {
@Placeholder
abstract Single<T> toSingleFunction(@MayOptionallyUse S element);
@BeforeTemplate
Single<T> before(Single<S> single) {
return Refaster.anyOf(
single.flatMap(v -> toSingleFunction(v)), single.flatMap((S v) -> toSingleFunction(v)));
}
@AfterTemplate
Single<T> after(Single<S> single) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.flatMap(v -> RxJava2Adapter.singleToMono(toSingleFunction(v))));
}
}
static final class SingleFlatMapCompletable<T, R extends CompletableSource> {
@BeforeTemplate
Completable before(
Single<T> single, Function<? super T, ? extends CompletableSource> function) {
return single.flatMapCompletable(function);
}
@AfterTemplate
Completable after(Single<T> single, Function<T, R> function) {
return RxJava2Adapter.monoToCompletable(
RxJava2Adapter.singleToMono(single)
.flatMap(
z ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, R>toJdkFunction(function).apply(z))))
.then());
}
}
// XXX: Add test
static final class SingleFlatMapMaybe<T, R, M extends MaybeSource<R>> {
@BeforeTemplate
Maybe<R> before(
Single<T> single, Function<? super T, ? extends MaybeSource<? extends R>> mapper) {
return single.flatMapMaybe(mapper);
}
@AfterTemplate
Maybe<R> after(Single<T> single, Function<T, M> mapper) {
return RxJava2Adapter.monoToMaybe(
RxJava2Adapter.singleToMono(single)
.flatMap(
e ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.<T, M>toJdkFunction(mapper).apply(e)))));
}
}
// XXX: public final Observable flatMapObservable(Function)
static final class SingleFlatMapPublisher<T, R> {
@BeforeTemplate
Flowable<R> before(
Single<T> single, Function<? super T, ? extends Publisher<? extends R>> mapper) {
return single.flatMapPublisher(mapper);
}
@AfterTemplate
Flowable<R> after(
Single<T> single, Function<? super T, ? extends Publisher<? extends R>> mapper) {
return RxJava2Adapter.fluxToFlowable(
RxJava2Adapter.singleToMono(single)
.flatMapMany(RxJavaReactorMigrationUtil.toJdkFunction(mapper)));
}
}
// XXX: public final Flowable flattenAsFlowable(Function)
// XXX: public final Observable flattenAsObservable(Function)
// XXX: public final Single hide()
static final class CompletableIgnoreElement<T> {
@BeforeTemplate
Completable before(Single<T> single) {
return single.ignoreElement();
}
@AfterTemplate
Completable after(Single<T> single) {
return RxJava2Adapter.monoToCompletable(RxJava2Adapter.singleToMono(single).then());
}
}
// XXX: public final Single lift(SingleOperator)
static final class SingleMap<I, T extends I, O> {
@BeforeTemplate
Single<O> before(Single<T> single, Function<? super I, ? extends O> function) {
return single.map(function);
}
@AfterTemplate
Single<O> after(Single<T> single, Function<I, O> function) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.map(RxJavaReactorMigrationUtil.toJdkFunction(function)));
}
}
// XXX: public final Single materialize()
// XXX: public final Flowable mergeWith(SingleSource)
// XXX: public final Single observeOn(Scheduler)
static final class SingleOnErrorResumeNext<
S, T extends S, R, P extends Throwable, Q extends Single<T>> {
@BeforeTemplate
Single<T> before(
Single<T> single,
Function<? super Throwable, ? extends SingleSource<? extends T>> function) {
return single.onErrorResumeNext(function);
}
@AfterTemplate
Single<T> after(Single<T> single, Function<Throwable, Q> function) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.onErrorResume(
err ->
RxJava2Adapter.singleToMono(
RxJavaReactorMigrationUtil.<Throwable, Q>toJdkFunction(function)
.apply(err))));
}
}
// XXX: public final Single onErrorResumeNext(Single)
// XXX: public final Single onErrorReturn(Function)
// XXX: public final Single onErrorReturnItem(Object)
// XXX: public final Single onTerminateDetach()
// XXX: public final Flowable repeat()
// XXX: public final Flowable repeat(long)
// XXX: public final Flowable repeatUntil(BooleanSupplier)
// XXX: public final Flowable repeatWhen(Function)
// XXX: public final Single retry()
// XXX: public final Single retry(BiPredicate)
// XXX: public final Single retry(long)
// XXX: public final Single retry(long,Predicate)
// XXX: public final Single retry(Predicate)
// XXX: public final Single retryWhen(Function)
// XXX: Add test
static final class SingleSubscribe<T> {
@BeforeTemplate
Disposable before(Single<T> single) {
return single.subscribe();
}
@AfterTemplate
reactor.core.Disposable after(Single<T> single) {
return RxJava2Adapter.singleToMono(single).subscribe();
}
}
// XXX: public final Disposable subscribe(BiConsumer)
// XXX: Add test
static final class SingleSubscribeConsumer<T> {
@BeforeTemplate
Disposable before(Single<T> single, Consumer<? super T> consumer) {
return single.subscribe(consumer);
}
@AfterTemplate
reactor.core.Disposable after(Single<T> single, Consumer<? super T> consumer) {
return RxJava2Adapter.singleToMono(single)
.subscribe(RxJavaReactorMigrationUtil.toJdkConsumer(consumer));
}
}
// XXX: Add test
static final class SingleSubscribeTwoConsumers<T> {
@BeforeTemplate
Disposable before(
Single<T> single, Consumer<? super T> consumer1, Consumer<? super Throwable> consumer2) {
return single.subscribe(consumer1, consumer2);
}
@AfterTemplate
reactor.core.Disposable after(
Single<T> single, Consumer<? super T> consumer1, Consumer<? super Throwable> consumer2) {
return RxJava2Adapter.singleToMono(single)
.subscribe(
RxJavaReactorMigrationUtil.toJdkConsumer(consumer1),
RxJavaReactorMigrationUtil.toJdkConsumer(consumer2));
}
}
// XXX: public final void subscribe(SingleObserver)
// XXX: We are currently not accounting for the Schedulers.computation()
static final class SingleSubscribeOn<T> {
@BeforeTemplate
Single<T> before(Single<T> single) {
return single.subscribeOn(Schedulers.io());
}
@AfterTemplate
Single<T> after(Single<T> single) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.subscribeOn(reactor.core.scheduler.Schedulers.boundedElastic()));
}
}
// XXX: public final SingleObserver subscribeWith(SingleObserver)
// XXX: public final Single takeUntil(CompletableSource)
// XXX: public final Single takeUntil(Publisher)
// XXX: public final Single takeUntil(SingleSource)
// XXX: public final Single timeout(long,TimeUnit)
// XXX: public final Single timeout(long,TimeUnit,Scheduler)
// XXX: public final Single timeout(long,TimeUnit,Scheduler,SingleSource)
// XXX: public final Single timeout(long,TimeUnit,SingleSource)
// XXX: public final Object to(Function)
// XXX: public final Completable toCompletable()
static final class SingleToFlowable<T> {
@BeforeTemplate
Flowable<T> before(Single<T> single) {
return single.toFlowable();
}
@AfterTemplate
Flowable<T> after(Single<T> single) {
return RxJava2Adapter.fluxToFlowable(RxJava2Adapter.singleToMono(single).flux());
}
}
// XXX: public final Future toFuture()
static final class SingleToMaybe<T> {
@BeforeTemplate
Maybe<T> before(Single<T> single) {
return single.toMaybe();
}
@AfterTemplate
Maybe<T> after(Single<T> single) {
return RxJava2Adapter.monoToMaybe(RxJava2Adapter.singleToMono(single));
}
}
// XXX: public final Observable toObservable()
// XXX: public final Single unsubscribeOn(Scheduler)
static final class SingleZipWith<T, R, U> {
@BeforeTemplate
Single<R> before(
Single<T> single,
SingleSource<U> source,
BiFunction<? super T, ? super U, ? extends R> biFunction) {
return single.zipWith(source, biFunction);
}
@AfterTemplate
Single<R> after(
Single<T> single,
SingleSource<U> source,
BiFunction<? super T, ? super U, ? extends R> biFunction) {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.singleToMono(single)
.zipWith(
RxJava2Adapter.singleToMono(Single.wrap(source)),
RxJavaReactorMigrationUtil.toJdkBiFunction(biFunction)));
}
}
@SuppressWarnings("unchecked")
static final class SingleTestAssertResultItem<T> {
@BeforeTemplate
void before(Single<T> single, T item) throws InterruptedException {
Refaster.anyOf(
single.test().assertResult(item),
single.test().await().assertResult(item),
single.test().await().assertComplete().assertResult(item),
single.test().await().assertResult(item).assertComplete(),
single.test().await().assertValue(item),
single.test().await().assertComplete().assertValue(item),
single.test().assertValue(item),
single.test().await().assertValue(item).assertComplete());
}
@AfterTemplate
void after(Single<T> single, T item) {
RxJava2Adapter.singleToMono(single)
.as(StepVerifier::create)
.expectNext(item)
.verifyComplete();
}
}
static final class SingleAssertValueSet<T> {
@BeforeTemplate
void before(Single<T> single, ImmutableSet<? extends T> set) throws InterruptedException {
single.test().await().assertNoErrors().assertValueSet(set).assertComplete();
}
@AfterTemplate
void after(Single<T> single, ImmutableSet<? extends T> set) {
RxJava2Adapter.singleToMono(single)
.map(ImmutableSet::of)
.as(StepVerifier::create)
.expectNext(ImmutableSet.copyOf(set))
.verifyComplete();
}
}
@SuppressWarnings("unchecked")
static final class SingleTestAssertResult<T> {
@BeforeTemplate
void before(Single<T> single) throws InterruptedException {
single.test().await().assertResult();
}
@AfterTemplate
void after(Single<T> single) {
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyComplete();
}
}
static final class SingleTestAssertValue<T> {
@BeforeTemplate
void before(Single<T> single, Predicate<T> predicate) throws InterruptedException {
Refaster.anyOf(
single.test().await().assertValue(predicate),
single.test().await().assertValue(predicate).assertComplete(),
single.test().await().assertValue(predicate).assertNoErrors().assertComplete(),
single.test().await().assertComplete().assertValue(predicate));
}
@AfterTemplate
void after(Single<T> single, Predicate<T> predicate) {
RxJava2Adapter.singleToMono(single)
.as(StepVerifier::create)
.expectNextMatches(RxJavaReactorMigrationUtil.toJdkPredicate(predicate))
.verifyComplete();
}
}
static final class SingleTestAssertComplete<T> {
@BeforeTemplate
void before(Single<T> single) throws InterruptedException {
single.test().await().assertComplete();
}
@AfterTemplate
void after(Single<T> single) {
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyComplete();
}
}
static final class SingleTestAssertErrorClass<T> {
@BeforeTemplate
void before(Single<T> single, Class<? extends Throwable> errorClass)
throws InterruptedException {
single.test().await().assertError(errorClass);
}
@AfterTemplate
void after(Single<T> single, Class<? extends Throwable> errorClass) {
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyError(errorClass);
}
}
static final class SingleTestAssertNoErrors<T> {
@BeforeTemplate
void before(Single<T> single) throws InterruptedException {
single.test().await().assertNoErrors();
}
@AfterTemplate
void after(Single<T> single) {
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyComplete();
}
}
static final class SingleTestAssertValueCount<T> {
@BeforeTemplate
void before(Single<T> single, int count) throws InterruptedException {
single.test().await().assertValueCount(count);
}
@AfterTemplate
void after(Single<T> single, int count) {
RxJava2Adapter.singleToMono(single)
.as(StepVerifier::create)
.expectNextCount(count)
.verifyComplete();
}
}
// XXX: Add test
@SuppressWarnings("unchecked")
static final class SingleTestAssertFailure<T> {
@BeforeTemplate
void before(Single<T> single, Class<? extends Throwable> error) throws InterruptedException {
single.test().await().assertFailure(error);
}
@AfterTemplate
void after(Single<T> single, Class<? extends Throwable> error) {
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyError(error);
}
}
// XXX: Add test
static final class SingleTestAssertNoValues<T> {
@BeforeTemplate
void before(Single<T> single) throws InterruptedException {
Refaster.anyOf(
single.test().await().assertNoValues(),
single.test().await().assertNoValues().assertComplete());
}
@AfterTemplate
void after(Single<T> single) {
RxJava2Adapter.singleToMono(single).as(StepVerifier::create).verifyComplete();
}
}
// XXX: Add test
// XXX: This introduces AssertJ dependency
static final class SingleTestAssertFailureAndMessage<T> {
@BeforeTemplate
void before(Single<T> single, Class<? extends Throwable> error, String message)
throws InterruptedException {
single.test().await().assertFailureAndMessage(error, message);
}
@AfterTemplate
void after(Single<T> single, Class<? extends Throwable> error, String message) {
RxJava2Adapter.singleToMono(single)
.as(StepVerifier::create)
.expectErrorSatisfies(
t -> assertThat(t).isInstanceOf(error).hasMessageContaining(message))
.verify();
}
}
// XXX: public final TestObserver test(boolean)
}

View File

@@ -0,0 +1,290 @@
package tech.picnic.errorprone.refastertemplates;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.CanTransformToTargetType;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.functions.Action;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import java.util.concurrent.Callable;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
/** Assorted Refaster templates for the migration of RxJava to Reactor */
public final class RxJavaToReactorTemplates {
private RxJavaToReactorTemplates() {}
static final class FluxToFlowableToFlux<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux, BackpressureStrategy strategy) {
return Refaster.anyOf(
RxJava2Adapter.fluxToFlowable(flux).as(RxJava2Adapter::flowableToFlux),
RxJava2Adapter.flowableToFlux(RxJava2Adapter.fluxToFlowable(flux)),
RxJava2Adapter.flowableToFlux(flux.as(RxJava2Adapter::fluxToFlowable)),
RxJava2Adapter.observableToFlux(flux.as(RxJava2Adapter::fluxToObservable), strategy),
flux.as(RxJava2Adapter::fluxToObservable)
.toFlowable(strategy)
.as(RxJava2Adapter::flowableToFlux),
RxJava2Adapter.observableToFlux(RxJava2Adapter.fluxToObservable(flux), strategy),
flux.as(RxJava2Adapter::fluxToFlowable).as(RxJava2Adapter::flowableToFlux));
}
@AfterTemplate
Flux<T> after(Flux<T> flux) {
return flux;
}
}
static final class MonoToFlowableToMono<T> {
@BeforeTemplate
Mono<Void> before(Mono<Void> mono) {
return Refaster.anyOf(
RxJava2Adapter.monoToCompletable(mono).as(RxJava2Adapter::completableToMono),
mono.as(RxJava2Adapter::monoToCompletable).as(RxJava2Adapter::completableToMono),
RxJava2Adapter.completableToMono(RxJava2Adapter.monoToCompletable(mono)),
RxJava2Adapter.completableToMono(mono.as(RxJava2Adapter::monoToCompletable)));
}
@BeforeTemplate
Mono<T> before2(Mono<T> mono) {
return Refaster.anyOf(
RxJava2Adapter.monoToMaybe(mono).as(RxJava2Adapter::maybeToMono),
RxJava2Adapter.maybeToMono(RxJava2Adapter.monoToMaybe(mono)),
RxJava2Adapter.maybeToMono(mono.as(RxJava2Adapter::monoToMaybe)),
mono.as(RxJava2Adapter::monoToMaybe).as(RxJava2Adapter::maybeToMono),
RxJava2Adapter.monoToSingle(mono).as(RxJava2Adapter::singleToMono),
RxJava2Adapter.singleToMono(RxJava2Adapter.monoToSingle(mono)),
RxJava2Adapter.singleToMono(mono.as(RxJava2Adapter::monoToSingle)),
mono.as(RxJava2Adapter::monoToSingle).as(RxJava2Adapter::singleToMono));
}
@BeforeTemplate
Mono<Void> before3(Mono<T> mono) {
return Refaster.anyOf(
RxJava2Adapter.completableToMono(RxJava2Adapter.monoToCompletable(mono)),
RxJava2Adapter.completableToMono(mono.as(RxJava2Adapter::monoToCompletable)),
RxJava2Adapter.monoToCompletable(mono).as(RxJava2Adapter::completableToMono));
}
@AfterTemplate
Mono<T> after(Mono<T> mono) {
return mono;
}
}
// XXX: Add test cases
static final class MonoToFlowableToFlux<T> {
@BeforeTemplate
Flux<T> before(Mono<T> mono) {
return mono.as(RxJava2Adapter::monoToFlowable).as(RxJava2Adapter::flowableToFlux);
}
@AfterTemplate
Flux<T> after(Mono<T> mono) {
return mono.flux();
}
}
static final class MonoErrorCallableSupplierUtil<T> {
@BeforeTemplate
Mono<T> before(@CanTransformToTargetType Callable<? extends Throwable> callable) {
return Mono.error(RxJavaReactorMigrationUtil.callableAsSupplier(callable));
}
@AfterTemplate
Mono<T> after(Supplier<? extends Throwable> callable) {
return Mono.error(callable);
}
}
@SuppressWarnings({"NoFunctionalReturnType", "FunctionalInterfaceClash"})
static final class RemoveUtilCallable<T> {
@BeforeTemplate
Supplier<T> before(@CanTransformToTargetType Callable<T> callable) {
return RxJavaReactorMigrationUtil.callableAsSupplier(callable);
}
@AfterTemplate
Supplier<T> before(Supplier<T> callable) {
return callable;
}
}
@SuppressWarnings("NoFunctionalReturnType")
static final class UnnecessaryFunctionConversion<I, O> {
@BeforeTemplate
java.util.function.Function<I, O> before(@CanTransformToTargetType Function<I, O> function) {
return RxJavaReactorMigrationUtil.toJdkFunction(function);
}
@AfterTemplate
java.util.function.Function<I, O> after(java.util.function.Function<I, O> function) {
return function;
}
}
@SuppressWarnings("NoFunctionalReturnType")
static final class UnnecessaryBiFunctionConversion<T, U, R> {
@BeforeTemplate
java.util.function.BiFunction<? super T, ? super U, ? extends R> before(
@CanTransformToTargetType BiFunction<? super T, ? super U, ? extends R> zipper) {
return RxJavaReactorMigrationUtil.toJdkBiFunction(zipper);
}
@AfterTemplate
java.util.function.BiFunction<? super T, ? super U, ? extends R> after(
java.util.function.BiFunction<? super T, ? super U, ? extends R> zipper) {
return zipper;
}
}
@SuppressWarnings("NoFunctionalReturnType")
static final class UnnecessaryConsumerConversion<T> {
@BeforeTemplate
java.util.function.Consumer<? extends T> before(
@CanTransformToTargetType Consumer<? extends T> consumer) {
return RxJavaReactorMigrationUtil.toJdkConsumer(consumer);
}
@AfterTemplate
java.util.function.Consumer<? extends T> after(
java.util.function.Consumer<? extends T> consumer) {
return consumer;
}
}
static final class UnnecessaryRunnableConversion {
@BeforeTemplate
Runnable before(@CanTransformToTargetType Action action) {
return RxJavaReactorMigrationUtil.toRunnable(action);
}
@AfterTemplate
Runnable after(Runnable action) {
return action;
}
}
@SuppressWarnings("NoFunctionalReturnType")
static final class UnnecessaryPredicateConversion<T> {
@BeforeTemplate
java.util.function.Predicate<? extends T> before(
@CanTransformToTargetType Predicate<? extends T> predicate) {
return RxJavaReactorMigrationUtil.toJdkPredicate(predicate);
}
@AfterTemplate
java.util.function.Predicate<? extends T> after(
java.util.function.Predicate<? extends T> predicate) {
return predicate;
}
}
static final class FlowableBiFunctionRemoveUtil<T, U, R> {
@BeforeTemplate
Flowable<R> before(
Publisher<? extends T> source1,
Publisher<? extends U> source2,
@CanTransformToTargetType BiFunction<? super T, ? super U, ? extends R> zipper) {
return RxJava2Adapter.fluxToFlowable(
Flux.<T, U, R>zip(source1, source2, RxJavaReactorMigrationUtil.toJdkBiFunction(zipper)));
}
@AfterTemplate
Flowable<R> after(
Publisher<? extends T> source1,
Publisher<? extends U> source2,
java.util.function.BiFunction<? super T, ? super U, ? extends R> zipper) {
return RxJava2Adapter.fluxToFlowable(Flux.<T, U, R>zip(source1, source2, zipper));
}
}
///////////////////////////////////////////
//////////// ASSORTED TEMPLATES ///////////
///////////////////////////////////////////
static final class MonoFromNestedPublisher<T> {
@BeforeTemplate
Mono<T> before(Flux<T> flux) {
return Mono.from(RxJava2Adapter.fluxToFlowable(flux));
}
@AfterTemplate
Mono<T> after(Flux<T> flux) {
return Mono.from(flux);
}
}
static final class FlowableToFluxWithFilter<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux, Predicate<T> predicate) {
return RxJava2Adapter.flowableToFlux(
flux.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate))
.as(RxJava2Adapter::fluxToFlowable));
}
@AfterTemplate
Flux<T> after(Flux<T> flux, Predicate<T> predicate) {
return flux.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate));
}
}
static final class ObservableToFlux<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux, Predicate<T> predicate, BackpressureStrategy strategy) {
return RxJava2Adapter.observableToFlux(
RxJava2Adapter.fluxToObservable(flux).filter(predicate), strategy);
}
@AfterTemplate
Flux<T> after(Flux<T> flux, Predicate<T> predicate, BackpressureStrategy strategy) {
return flux.filter(RxJavaReactorMigrationUtil.toJdkPredicate(predicate));
}
}
static final class MonoFromToFlowableToFlux<T> {
@BeforeTemplate
Flux<T> before(Mono<T> mono) {
return RxJava2Adapter.flowableToFlux(mono.as(RxJava2Adapter::monoToFlowable));
}
@AfterTemplate
Flux<T> after(Mono<T> mono) {
return mono.flux();
}
}
static final class MonoThenThen<T> {
@BeforeTemplate
Mono<T> before(Mono<T> mono, Mono<T> other) {
return mono.then().then(other);
}
@AfterTemplate
Mono<T> after(Mono<T> mono, Mono<T> other) {
return mono.then(other);
}
}
// XXX: Find out how we can use this in the future.
// static final class RemoveRedundantCast<T> {
// @BeforeTemplate
// T before(T object) {
// return (T) object;
// }
//
// @AfterTemplate
// T after(T object) {
// return object;
// }
// }
}

View File

@@ -0,0 +1,404 @@
package tech.picnic.errorprone.refastertemplates;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
import com.google.errorprone.refaster.annotation.Placeholder;
import io.reactivex.Completable;
import io.reactivex.CompletableSource;
import io.reactivex.Maybe;
import io.reactivex.MaybeSource;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.functions.Function;
import org.reactivestreams.Publisher;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Mono;
import tech.picnic.errorprone.migration.util.RxJavaReactorMigrationUtil;
public final class RxJavaUnwrapTemplates {
private RxJavaUnwrapTemplates() {}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class FlowableConcatMapCompletableUnwrapLambda<T> {
@Placeholder
abstract Mono<?> placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<? super T, ? extends Publisher<?>> before() {
return e ->
RxJava2Adapter.completableToMono(
RxJavaReactorMigrationUtil.toJdkFunction(
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
.apply(e));
}
@AfterTemplate
java.util.function.Function<T, ? extends Publisher<?>> after() {
return v -> placeholder(v);
}
}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class MaybeFlatMapUnwrapLambda<I, T extends I, O> {
@Placeholder
abstract Mono<? extends O> placeholder(@MayOptionallyUse T input);
@BeforeTemplate
@SuppressWarnings("unchecked")
java.util.function.Function<? super T, ? extends Mono<? extends O>> before() {
return Refaster.anyOf(
v ->
RxJava2Adapter.maybeToMono(
(Maybe<O>)
RxJavaReactorMigrationUtil.toJdkFunction(
(T ident) -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
.apply(v)),
v ->
RxJava2Adapter.maybeToMono(
RxJavaReactorMigrationUtil.toJdkFunction(
(T ident) -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
.apply(v)));
}
@AfterTemplate
java.util.function.Function<? super T, ? extends Mono<? extends O>> after() {
return v -> placeholder(v);
}
}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class MaybeFlatMapSingleElementUnwrapLambda<T, R> {
@Placeholder
abstract Mono<R> placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<T, ? extends Mono<? extends R>> before() {
return Refaster.anyOf(
e ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<T, SingleSource<R>>)
(T ident) -> RxJava2Adapter.monoToSingle(placeholder(ident)))
.apply(e))),
e ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil.<T, SingleSource<R>>toJdkFunction(
(T ident) -> RxJava2Adapter.monoToSingle(placeholder(ident)))
.apply(e))));
}
@AfterTemplate
java.util.function.Function<T, ? extends Mono<? extends R>> after() {
return e -> placeholder(e);
}
}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class SingleFlatMapMaybeUnwrapLambda<T, R> {
@Placeholder
abstract Mono<R> placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<? super T, ? extends Mono<? extends R>> before() {
return Refaster.anyOf(
e ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<T, MaybeSource<R>>)
(T ident) -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
.apply(e))),
e ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<T, MaybeSource<R>>)
ident -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
.apply(e))),
e ->
RxJava2Adapter.maybeToMono(
Maybe.wrap(
RxJavaReactorMigrationUtil.<T, MaybeSource<R>>toJdkFunction(
ident -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
.apply(e))));
}
@AfterTemplate
java.util.function.Function<? super T, ? extends Mono<? extends R>> after() {
return e -> placeholder(e);
}
}
// XXX: Add test
@SuppressWarnings({"NoFunctionalReturnType", "unchecked"})
abstract static class SingleOnResumeUnwrapLambda<T, R> {
@Placeholder
abstract Mono<? extends R> placeholder(@MayOptionallyUse Throwable input);
@BeforeTemplate
java.util.function.Function<? extends Throwable, ? extends Mono<? extends R>> before() {
return Refaster.anyOf(
e ->
RxJava2Adapter.singleToMono(
RxJavaReactorMigrationUtil.toJdkFunction(
ident -> RxJava2Adapter.monoToSingle(placeholder(e)))
.apply(e)),
e ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<Throwable, ? extends SingleSource<? extends R>>)
placeholder(e))
.apply(e))),
e ->
RxJava2Adapter.singleToMono(
Single.wrap(
RxJavaReactorMigrationUtil.<Throwable, SingleSource<R>>toJdkFunction(
(Function<Throwable, SingleSource<R>>) placeholder(e))
.apply(e))));
}
@AfterTemplate
java.util.function.Function<Throwable, ? extends Mono<? extends R>> after() {
return v -> placeholder(v);
}
}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class FlowableConcatMapMaybeDelayErrorUnwrapLambda<T, R> {
@Placeholder
abstract Mono<R> placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<? super T, ? extends Publisher<? extends R>> after() {
return Refaster.anyOf(
e ->
Maybe.wrap(
RxJavaReactorMigrationUtil.toJdkFunction(
(Function<T, MaybeSource<R>>)
ident -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
.apply(e))
.toFlowable(),
e ->
Maybe.wrap(
RxJavaReactorMigrationUtil.<T, MaybeSource<R>>toJdkFunction(
ident -> RxJava2Adapter.monoToMaybe(placeholder(ident)))
.apply(e))
.toFlowable());
}
@AfterTemplate
java.util.function.Function<? super T, ? extends Publisher<? extends R>> before() {
return e -> placeholder(e);
}
}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class FlowableFlatMapCompletableUnwrapLambda<T> {
@Placeholder
abstract Mono<?> placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<T, ? extends Publisher<? extends Void>> before() {
return Refaster.anyOf(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
(Function<T, Completable>)
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
.apply(e))),
e ->
RxJava2Adapter.completableToMono(
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
(Function<T, Completable>)
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
.apply(e)),
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
.apply(e))),
e ->
RxJava2Adapter.completableToMono(
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
(T ident) -> RxJava2Adapter.monoToCompletable(placeholder(ident)))
.apply(e)));
}
@AfterTemplate
java.util.function.Function<T, Mono<?>> after() {
return v -> placeholder(v);
}
}
// XXX: Improve naming and add test case
@SuppressWarnings("NoFunctionalReturnType")
abstract static class FlowableUnwrapLambda<T> {
@Placeholder
abstract Completable placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<T, Publisher<? extends Void>> before() {
return Refaster.anyOf(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
(Function<T, CompletableSource>) v -> placeholder(v))
.apply(e))),
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
v -> placeholder(v))
.apply(e))));
}
@AfterTemplate
java.util.function.Function<T, Mono<? extends Void>> after() {
return v -> RxJava2Adapter.completableToMono(Completable.wrap(placeholder(v)));
}
}
@SuppressWarnings("NoFunctionalReturnType")
abstract static class FlowableFlatMapUnwrapLambda<T> {
@Placeholder
abstract CompletableSource placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<T, ? extends Publisher<? extends Void>> before() {
return e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
(Function<T, CompletableSource>) v -> placeholder(v))
.apply(e)));
}
@AfterTemplate
java.util.function.Function<T, Mono<? extends Void>> after() {
return v -> RxJava2Adapter.completableToMono(Completable.wrap(placeholder(v)));
}
}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class SingleFlatMapUnwrapLambda<T, R> {
@Placeholder
abstract Mono<? extends R> placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<T, ? extends Mono<? extends R>> before() {
return v ->
RxJava2Adapter.singleToMono(
(Single<? extends R>)
RxJavaReactorMigrationUtil.toJdkFunction(
(T ident) -> RxJava2Adapter.monoToSingle(placeholder(ident)))
.apply(v));
}
@AfterTemplate
java.util.function.Function<T, ? extends Mono<? extends R>> after() {
return v -> placeholder(v);
}
}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class SingleRemoveLambdaWithCast<T> {
@Placeholder
abstract Mono<?> placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<? super T, ? extends Publisher<? extends Void>> before() {
return Refaster.anyOf(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
(Function<T, Completable>)
v -> placeholder(v).as(RxJava2Adapter::monoToCompletable))
.apply(e))),
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
(Function<T, Completable>)
v -> RxJava2Adapter.monoToCompletable(placeholder(v)))
.apply(e))),
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, Completable>toJdkFunction(
v -> RxJava2Adapter.monoToCompletable(placeholder(v)))
.apply(e))));
}
@AfterTemplate
java.util.function.Function<? super T, ? extends Mono<?>> after() {
return v -> placeholder(v);
}
}
// XXX: Add test
@SuppressWarnings("NoFunctionalReturnType")
abstract static class SingleRemoveLambdaWithCompletable<T> {
@BeforeTemplate
java.util.function.Function<? super T, ? extends Mono<? extends Void>> before(
Completable completable) {
return Refaster.anyOf(
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
(Function<T, CompletableSource>) v -> completable)
.apply(e))),
e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
v -> completable)
.apply(e))));
}
@AfterTemplate
java.util.function.Function<? super T, ? extends Mono<? extends Void>> after(
Completable completable) {
return v -> RxJava2Adapter.completableToMono(completable);
}
}
// XXX: Verify if this template still flags other cases than the one above.
@SuppressWarnings("NoFunctionalReturnType")
abstract static class SingleRemoveLambdaWithCompletableExtra<T> {
@Placeholder
abstract Completable placeholder(@MayOptionallyUse T input);
@BeforeTemplate
java.util.function.Function<? super T, ? extends Mono<? extends Void>> before() {
return e ->
RxJava2Adapter.completableToMono(
Completable.wrap(
RxJavaReactorMigrationUtil.<T, CompletableSource>toJdkFunction(
(Function<T, CompletableSource>) v -> placeholder(v))
.apply(e)));
}
@AfterTemplate
java.util.function.Function<? super T, ? extends Mono<? extends Void>> after() {
return v -> RxJava2Adapter.completableToMono(placeholder(v));
}
}
}

View File

@@ -148,6 +148,8 @@ final class StreamTemplates {
*/
// XXX: Consider whether to have a similar rule for `.findAny()`. For parallel streams it
// wouldn't be quite the same....
// XXX: This change is not equivalent for `null`-returning functions, as the original code throws
// an NPE if the first element is `null`, while the latter yields an empty `Optional`.
static final class StreamMapFirst<T, S> {
@BeforeTemplate
Optional<S> before(Stream<T> stream, Function<? super T, S> function) {

View File

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

View File

@@ -33,6 +33,10 @@ public final class EmptyMethodCheckTest {
" interface F {",
" void fun();",
" }",
"",
" final class MyTestClass {",
" void helperMethod() {}",
" }",
"}")
.addSourceLines(
"B.java",

View File

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

View File

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

View File

@@ -13,6 +13,7 @@ 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;
@@ -64,10 +65,18 @@ public final class RefasterCheckTest {
"Primitive",
"Reactor",
"RxJava2Adapter",
"RxJavaCompletableToReactor",
"RxJavaFlowableToReactor",
"RxJavaMaybeToReactor",
"RxJavaObservableToReactor",
"RxJavaSingleToReactor",
"RxJavaToReactor",
"RxJavaUnwrap",
"Stream",
"String",
"TestNGToAssertJ",
"Time");
"Time",
"WebClient");
/**
* Matches the parts of the fully-qualified name of a template class that should be removed in
* order to produce the associated {@link #TEMPLATE_GROUPS template group name}.
@@ -87,7 +96,12 @@ public final class RefasterCheckTest {
@SuppressWarnings("UnusedMethod" /* Used as a `@MethodSource`. */)
private static Stream<Arguments> templateGroupsUnderTest() {
// XXX: Drop the filter once we have added tests for AssertJ!
return TEMPLATES_BY_GROUP.keySet().stream().filter(not("AssertJ"::equals)).map(Arguments::of);
return TEMPLATES_BY_GROUP.keySet().stream()
.filter(not("AssertJ"::equals))
.filter(not("Immutable"::equals))
.filter(not("Reactor"::equals))
.filter(not("RxJava2Adapter"::equals))
.map(Arguments::of);
}
/**
@@ -98,6 +112,9 @@ public final class RefasterCheckTest {
// XXX: Drop the filter once we have added tests for AssertJ!
return TEMPLATES_BY_GROUP.entries().stream()
.filter(e -> !"AssertJ".equals(e.getKey()))
.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()));
}
@@ -130,6 +147,7 @@ public final class RefasterCheckTest {
* com.google.errorprone.refaster.Refaster#anyOf} branches are tested. Idem for {@link
* com.google.errorprone.refaster.annotation.BeforeTemplate} methods in case there are multiple .
*/
@Disabled
@MethodSource("templatesUnderTest")
@ParameterizedTest
void coverage(String group, String template) {

View File

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

View File

@@ -26,6 +26,7 @@ public final class TimeZoneUsageCheckTest {
"import java.time.LocalDate;",
"import java.time.LocalDateTime;",
"import java.time.LocalTime;",
"import java.time.ZoneId;",
"",
"class A {",
" void m() {",
@@ -78,6 +79,24 @@ public final class TimeZoneUsageCheckTest {
" // BUG: Diagnostic matches: X",
" LocalTime.now(UTC);",
" }",
"",
" abstract class ForwardingClock extends Clock {",
" private final Clock clock;",
"",
" ForwardingClock(Clock clock) {",
" this.clock = clock;",
" }",
"",
" @Override",
" public ZoneId getZone() {",
" return clock.getZone();",
" }",
"",
" @Override",
" public Clock withZone(ZoneId zone) {",
" return clock.withZone(zone);",
" }",
" }",
"}")
.doTest();
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,6 +14,12 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
final class RxJava2AdapterTemplatesTest implements RefasterTemplateTestCase {
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

@@ -14,6 +14,10 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
final class RxJava2AdapterTemplatesTest implements RefasterTemplateTestCase {
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,137 @@
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.Arrays;
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() {
return Completable.complete().onErrorComplete(throwable -> true);
}
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,185 @@
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.util.Arrays;
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(Mono.empty()).onErrorComplete();
}
Completable testCompletableOnErrorCompletePredicate() {
return RxJava2Adapter.monoToCompletable(Mono.empty()).onErrorComplete(throwable -> true);
}
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,268 @@
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 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();
}
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();
}));
}
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();
}
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,375 @@
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 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();
}
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();
})));
}
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();
}
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,219 @@
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 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;
}
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));
}
Single<Integer> testMaybeSwitchIfEmpty() {
return Maybe.just(1)
.switchIfEmpty(
Single.<Integer>error(
() -> {
throw new IllegalStateException();
}));
}
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,303 @@
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.util.concurrent.CompletableFuture;
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;
}
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());
}
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))));
}
Single<Integer> testMaybeSwitchIfEmpty() {
return RxJava2Adapter.monoToSingle(
RxJava2Adapter.maybeToMono(Maybe.just(1))
.switchIfEmpty(
RxJava2Adapter.singleToMono(
Single.wrap(
Single.<Integer>error(
() -> {
throw new IllegalStateException();
})))));
}
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,82 @@
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;
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();
}
Flowable<Integer> testCompletableToFlowable() {
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,128 @@
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 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());
}
Flowable<Integer> testCompletableToFlowable() {
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,143 @@
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 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();
}
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,194 @@
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.util.List;
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());
}
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,103 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
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() {
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> testMonoThenThen() {
return Mono.just(1).then().then(Mono.just(2));
}
}

View File

@@ -0,0 +1,93 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableSet;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
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();
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() {
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> testMonoThenThen() {
return Mono.just(1).then(Mono.just(2));
}
}

View File

@@ -0,0 +1,67 @@
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 RxJavaUnwrapTemplatesTest 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();
}
// Many tests for the `RxJavaUnwrapTemplates` class are not written due to time constraints.
}

View File

@@ -0,0 +1,45 @@
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 RxJavaUnwrapTemplatesTest 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();
}
// Many tests for the `RxJavaUnwrapTemplates` class are not written due to time constraints.
}

View File

@@ -0,0 +1,20 @@
package tech.picnic.errorprone.bugpatterns;
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
import com.google.common.collect.ImmutableSet;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.client.WebClient;
final class WebClientTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(fromValue(""));
}
ImmutableSet<?> testBodyValue() {
return ImmutableSet.of(
WebClient.create("foo").post().body(fromValue("bar")),
WebTestClient.bindToServer().build().post().body(fromValue("bar")));
}
}

View File

@@ -0,0 +1,20 @@
package tech.picnic.errorprone.bugpatterns;
import static org.springframework.web.reactive.function.BodyInserters.fromValue;
import com.google.common.collect.ImmutableSet;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.client.WebClient;
final class WebClientTemplatesTest implements RefasterTemplateTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(fromValue(""));
}
ImmutableSet<?> testBodyValue() {
return ImmutableSet.of(
WebClient.create("foo").post().bodyValue("bar"),
WebTestClient.bindToServer().build().post().bodyValue("bar"));
}
}

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.0.1-SNAPSHOT</version>
</parent>
<artifactId>migration-util</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
</dependency>
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,365 @@
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;
public final class RxJavaReactorMigrationUtil {
private RxJavaReactorMigrationUtil() {}
/**
* Convert {@code Callable<T>} to T
*
* @param callable XXX
* @param <T> XXX
* @return XXX
*/
// XXX: Rename.
// XXX: Introduce Refaster rules to drop this wrapper when possible.
@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.
// XXX: Introduce Refaster rules to drop this wrapper when possible.
@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.
// XXX: Introduce Refaster rules to drop this wrapper when possible.
@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.
// XXX: Introduce Refaster rules to drop this wrapper when possible.
@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);
}
};
}
/**
* XXX
*
* @param action XXX
* @return XXX
*/
@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
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
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 s;
private Fuseable.QueueSubscription<T> qs;
FluxAsFlowableSubscriber(Subscriber<? super T> actual) {
this.actual = actual;
}
@Override
@SuppressWarnings("unchecked")
public void onSubscribe(Subscription s) {
if (Operators.validate(this.s, s)) {
this.s = 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) {
s.request(n);
}
@Override
public void cancel() {
s.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 s;
private QueueSubscription<T> qs;
FluxAsFlowableConditionalSubscriber(ConditionalSubscriber<? super T> actual) {
this.actual = actual;
}
@Override
@SuppressWarnings("unchecked")
public void onSubscribe(Subscription s) {
if (Operators.validate(this.s, s)) {
this.s = s;
if (s instanceof io.reactivex.internal.fuseable.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) {
s.request(n);
}
@Override
public void cancel() {
s.cancel();
}
@Override
public T poll() {
try {
return qs.poll();
} catch (Throwable 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!");
}
}
}
}

131
pom.xml
View File

@@ -34,6 +34,7 @@
<modules>
<module>error-prone-contrib</module>
<module>migration-util</module>
<module>refaster-resource-compiler</module>
<module>refaster-support</module>
</modules>
@@ -69,6 +70,21 @@
arguments. In particular, JaCoCo relies on this for the configuration
of its Java agent. -->
<argLine>
<!-- Error Prone makes extensive use of unsupported
`javac`-internal APIs, in some cases even reflectively inspecting
them. These APIs are accessed at compile time and when running
tests. The former case is covered by flags in `.mvn/jvm.config`;
the latter is covered here. -->
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
<!-- The test JVMs are short-running. By disabling certain
expensive JIT optimizations we actually speed up most tests. -->
-XX:TieredStopAtLevel=1
@@ -112,16 +128,16 @@
that need to be referenced only once should *not* be listed here. -->
<version.auto-service>1.0</version.auto-service>
<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.8.0</version.error-prone-orig>
<version.error-prone-fork>HEAD-SNAPSHOT</version.error-prone-fork>
<version.error-prone-orig>HEAD-SNAPSHOT</version.error-prone-orig>
<version.error-prone-slf4j>0.1.4</version.error-prone-slf4j>
<version.findbugs-format-string>3.0.0</version.findbugs-format-string>
<version.guava-beta-checker>1.0</version.guava-beta-checker>
<version.jdk>11</version.jdk>
<version.maven>3.6.3</version.maven>
<version.mockito>3.11.2</version.mockito>
<version.mockito>3.12.4</version.mockito>
<version.nopen-checker>1.0.1</version.nopen-checker>
<version.nullaway>0.9.1</version.nullaway>
<version.nullaway>0.9.2</version.nullaway>
<!-- XXX: Two other dependencies are potentially of interest:
`com.palantir.assertj-automation:assertj-refaster-rules` and
`com.palantir.baseline:baseline-refaster-rules` contain Refaster rules
@@ -129,8 +145,8 @@
`RefasterRuleBuilderScanner` to convert those to `.refaster` files so
that we can pick them up. (But in case of `baseline-refaster-rules`
perhaps we can simply incorporate all of them.) -->
<version.palantir-assertj-automation>0.2.1</version.palantir-assertj-automation>
<version.palantir-baseline>4.7.0</version.palantir-baseline>
<version.palantir-assertj-automation>0.3.0</version.palantir-assertj-automation>
<version.palantir-baseline>4.25.0</version.palantir-baseline>
<version.surefire>2.22.2</version.surefire>
</properties>
@@ -174,14 +190,14 @@
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>2.12.4</version>
<version>2.12.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.google.auto</groupId>
<artifactId>auto-common</artifactId>
<version>1.1</version>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
@@ -260,7 +276,7 @@
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-bom</artifactId>
<version>2020.0.9</version>
<version>2020.0.11</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -314,7 +330,7 @@
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.16.0</version>
<version>3.18.0</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
@@ -324,7 +340,7 @@
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.7.2</version>
<version>5.8.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -346,7 +362,7 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>5.3.9</version>
<version>5.3.10</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -364,7 +380,7 @@
<plugin>
<groupId>com.coveo</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<version>2.9.1</version>
<version>2.12</version>
</plugin>
<plugin>
<groupId>com.github.ekryd.sortpom</groupId>
@@ -385,6 +401,7 @@
</configuration>
<executions>
<execution>
<id>verify-pom-sorting</id>
<goals>
<goal>verify</goal>
</goals>
@@ -392,27 +409,10 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.lewisd</groupId>
<artifactId>lint-maven-plugin</artifactId>
<version>0.0.11</version>
<configuration>
<failOnViolation>false</failOnViolation>
</configuration>
<executions>
<execution>
<id>validate-pom</id>
<goals>
<goal>check</goal>
</goals>
<phase>validate</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>de.thetaphi</groupId>
<artifactId>forbiddenapis</artifactId>
<version>3.1</version>
<version>3.2</version>
<configuration>
<bundledSignatures>
<bundledSignature>jdk-internal</bundledSignature>
@@ -605,6 +605,10 @@
<!-- Instead, please use
`com.google.common.base.Preconditions`. -->
</property>
<property name="illegalClasses" value="org\.assertj\.core\.util\.Streams(\..*?)?">
<!-- Instead, please use
`com.google.common.collect.Streams`. -->
</property>
<property name="illegalClasses" value="org\.junit\.jupiter\.api\.Assertions(\..*?)?">
<!-- Instead, please use
`org.assertj.core.api.Assertions`. -->
@@ -622,7 +626,7 @@
</property>
<property name="illegalClasses" value="org\.testng\.AssertJUnit(\..*?)?">
<!-- Instead, please use
`com.google.common.base.Preconditions`. -->
`org.assertj.core.api.Assertions`. -->
</property>
<property name="regexp" value="true" />
</module>
@@ -631,6 +635,10 @@
<module name="InnerAssignment" />
<module name="InvalidJavadocPosition" />
<module name="JavadocBlockTagLocation" />
<module name="MatchXpath">
<property name="query" value="//BLOCK_COMMENT_BEGIN[./COMMENT_CONTENT[contains(@text, '@author')]]" />
<message key="matchxpath.match" value="Avoid the `@author` Javadoc tag; Git history suffices." />
</module>
<module name="MissingDeprecated" />
<module name="MutableException" />
<module name="NeedBraces" />
@@ -648,13 +656,6 @@
<module name="SimplifyBooleanReturn" />
<module name="SuppressWarningsHolder" />
<module name="TrailingComment" />
<module name="WriteTag">
<property name="tag" value="@author" />
<property name="tagFormat" value="\S" />
<property name="tagSeverity" value="error" />
<property name="severity" value="ignore" />
</module>
<module name="UnnecessaryParentheses" />
<module name="UnnecessarySemicolonAfterTypeMemberDeclaration" />
<module name="UnnecessarySemicolonInEnumeration" />
<module name="UnnecessarySemicolonInTryWithResources" />
@@ -675,7 +676,7 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.41.1</version>
<version>9.0</version>
</dependency>
</dependencies>
<executions>
@@ -736,6 +737,9 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<retryFailedDeploymentCount>3</retryFailedDeploymentCount>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -836,7 +840,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.0</version>
<version>3.3.1</version>
<configuration>
<!-- All relevant doclint checks are performed during
the compilation phase; no need to recheck during
@@ -1050,7 +1054,7 @@
<plugin>
<groupId>org.gaul</groupId>
<artifactId>modernizer-maven-plugin</artifactId>
<version>2.2.0</version>
<version>2.3.0</version>
<configuration>
<exclusionPatterns>
<!-- The plugin suggests replacing Guava's
@@ -1059,6 +1063,12 @@
methods don't allow one to convey immutability at
the type system level. -->
<exclusionPattern>com/google/common/collect/Immutable(List|Map|Set)\.(copyOf|of):.*</exclusionPattern>
<!-- The plugin suggests replacing usages of
Guava's `Iterables` class with
`java.util.stream.Stream` equivalents, but the
alternative is often more verbose, requiring
unnecessary conversions to and from streams. -->
<exclusionPattern>com/google/common/collect/Iterables\..*</exclusionPattern>
</exclusionPatterns>
<failOnViolations>false</failOnViolations>
<ignorePackages>
@@ -1071,7 +1081,7 @@
</configuration>
<executions>
<execution>
<id>modernize</id>
<id>run-modernizer</id>
<goals>
<goal>modernizer</goal>
</goals>
@@ -1087,7 +1097,7 @@
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.6.7</version>
<version>1.7.0</version>
<configuration>
<!-- Use multiple threads to speed things up. Extend
timeouts to prevent false positives as a result of
@@ -1100,7 +1110,7 @@
<dependency>
<groupId>org.pitest</groupId>
<artifactId>pitest-junit5-plugin</artifactId>
<version>0.14</version>
<version>0.15</version>
</dependency>
</dependencies>
<executions>
@@ -1143,13 +1153,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>
</profile>
<profile>
@@ -1250,10 +1260,6 @@
<groupId>com.github.ekryd.sortpom</groupId>
<artifactId>sortpom-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.lewisd</groupId>
<artifactId>lint-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>de.thetaphi</groupId>
<artifactId>forbiddenapis</artifactId>
@@ -1473,9 +1479,9 @@
</profile>
<profile>
<!-- The `build-checks` and `error-prone` profiles enable a whole
bunch of additional compile checks. This profile ensures that by
default those warnings break the build. Disabling this profile
allows one to collect all build warnings without failing the build. -->
bunch of additional compile checks. By default those warnings break
the build. This profile allows one to collect all build warnings
without failing the build. -->
<id>disallow-warnings</id>
<activation>
<property>
@@ -1492,13 +1498,6 @@
<verifyFail>stop</verifyFail>
</configuration>
</plugin>
<plugin>
<groupId>com.lewisd</groupId>
<artifactId>lint-maven-plugin</artifactId>
<configuration>
<failOnViolation>true</failOnViolation>
</configuration>
</plugin>
<plugin>
<groupId>de.thetaphi</groupId>
<artifactId>forbiddenapis</artifactId>

View File

@@ -7,7 +7,7 @@ import com.google.common.collect.Multimaps;
import com.google.errorprone.CodeTransformer;
import com.google.errorprone.CompositeCodeTransformer;
import com.google.errorprone.refaster.RefasterRuleBuilderScanner;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ClassTree;
@@ -23,6 +23,7 @@ import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Name;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.UncheckedIOException;
import java.util.List;
@@ -62,7 +63,7 @@ final class RefasterRuleResourceCompilerTaskListener implements TaskListener {
try {
outputCodeTransformers(rule.getValue(), getOutputFile(taskEvent, rule.getKey()));
} catch (IOException e) {
throw new UncheckedIOException(e);
throw new UncheckedIOException("Failed to persist compiled Refaster templates", e);
}
}
}
@@ -71,11 +72,12 @@ final class RefasterRuleResourceCompilerTaskListener implements TaskListener {
return Boolean.TRUE.equals(
new TreeScanner<Boolean, Void>() {
@Override
public Boolean visitAnnotation(AnnotationTree node, Void ctx) {
public Boolean visitAnnotation(AnnotationTree node, Void v) {
Symbol sym = ASTHelpers.getSymbol(node);
return (sym != null
&& sym.getQualifiedName().contentEquals(AfterTemplate.class.getCanonicalName()))
|| super.visitAnnotation(node, ctx);
&& sym.getQualifiedName()
.contentEquals(BeforeTemplate.class.getCanonicalName()))
|| super.visitAnnotation(node, v);
}
@Override
@@ -88,13 +90,13 @@ final class RefasterRuleResourceCompilerTaskListener implements TaskListener {
private ImmutableListMultimap<ClassTree, CodeTransformer> compileRefasterTemplates(
ClassTree tree) {
ListMultimap<ClassTree, CodeTransformer> rules = ArrayListMultimap.create();
new TreeScanner<Void, Context>() {
new TreeScanner<Void, Void>() {
@Override
public Void visitClass(ClassTree node, Context ctx) {
rules.putAll(node, RefasterRuleBuilderScanner.extractRules(node, ctx));
return super.visitClass(node, ctx);
public Void visitClass(ClassTree node, Void v) {
rules.putAll(node, RefasterRuleBuilderScanner.extractRules(node, context));
return super.visitClass(node, null);
}
}.scan(tree, context);
}.scan(tree, null);
return ImmutableListMultimap.copyOf(rules);
}
@@ -123,7 +125,7 @@ final class RefasterRuleResourceCompilerTaskListener implements TaskListener {
private static void outputCodeTransformers(List<CodeTransformer> rules, FileObject target)
throws IOException {
try (ObjectOutputStream output = new ObjectOutputStream(target.openOutputStream())) {
try (ObjectOutput output = new ObjectOutputStream(target.openOutputStream())) {
output.writeObject(CompositeCodeTransformer.compose(rules));
}
}