diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaCompletableToReactorTemplates.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaCompletableToReactorTemplates.java index 1c31580a..248f451c 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaCompletableToReactorTemplates.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaCompletableToReactorTemplates.java @@ -1,11 +1,36 @@ package tech.picnic.errorprone.refastertemplates; +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.google.common.collect.Streams; +import com.google.errorprone.refaster.annotation.AfterTemplate; +import com.google.errorprone.refaster.annotation.BeforeTemplate; +import io.reactivex.Completable; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Mono; + /** The Refaster templates for the migration of the RxJava Completable type to Reactor */ public final class RxJavaCompletableToReactorTemplates { private RxJavaCompletableToReactorTemplates() {} - // XXX: public static Completable amb(Iterable) + // XXX: Copied over from Stephan's test, to make the test run. + static final class CompletableAmb { + @BeforeTemplate + Completable before(Iterable sources) { + return Completable.amb(sources); + } + + @AfterTemplate + Completable after(Iterable sources) { + return Mono.firstWithSignal( + Streams.stream(sources) + .map(RxJava2Adapter::completableToMono) + .collect(toImmutableList())) + .as(RxJava2Adapter::monoToCompletable); + } + } + // XXX: public static Completable ambArray(CompletableSource[]) // XXX: public static Completable complete() // XXX: public static Completable concat(Iterable) diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaFlowableToReactorTemplates.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaFlowableToReactorTemplates.java index 6c3ab315..2220923f 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaFlowableToReactorTemplates.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaFlowableToReactorTemplates.java @@ -1,19 +1,76 @@ package tech.picnic.errorprone.refastertemplates; +import com.google.errorprone.refaster.annotation.AfterTemplate; +import com.google.errorprone.refaster.annotation.BeforeTemplate; +import com.google.errorprone.refaster.annotation.Repeated; +import io.reactivex.Flowable; +import io.reactivex.Maybe; +import io.reactivex.Single; +import io.reactivex.functions.BiFunction; +import io.reactivex.functions.Function; +import io.reactivex.functions.Predicate; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.function.Supplier; +import org.reactivestreams.Publisher; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Flux; + /** The Refaster templates for the migration of the RxJava Flowable type to Reactor */ public final class RxJavaFlowableToReactorTemplates { private RxJavaFlowableToReactorTemplates() {} // XXX: public static Flowable amb(Iterable) - // XXX: public static Flowable ambArray(Publisher[]) + + // XXX: Write test + static final class FlowableAmbArray { + @BeforeTemplate + Flowable before(Publisher... sources) { + return Flowable.ambArray(sources); + } + + @AfterTemplate + Flowable after(Publisher... sources) { + return RxJava2Adapter.fluxToFlowable(Flux.firstWithSignal(sources)); + } + } + // XXX: public static int bufferSize() // XXX: public static Flowable combineLatest(Function,Publisher[]) // XXX: public static Flowable combineLatest(Iterable,Function) // XXX: public static Flowable combineLatest(Iterable,Function,int) // XXX: public static Flowable combineLatest(Publisher[],Function) // XXX: public static Flowable combineLatest(Publisher[],Function,int) - // XXX: public static Flowable combineLatest(Publisher,Publisher,BiFunction) + + // XXX: This wouldn't work for this case right? + // return Flowable.combineLatest( + // getEnabledConsentRequests(requiredConsentTopics, locale), // returns Flowable + // Flowable.fromIterable(requiredConsentTopics), // returns Flowable + // this::filterByTopic) + // XXX: Add test + static final class FlowableCombineLatest { + @BeforeTemplate + Flowable before( + Publisher p1, + Publisher p2, + BiFunction combiner) { + return Flowable.combineLatest(p1, p2, combiner); + } + + @AfterTemplate + Flowable after( + Publisher p1, + Publisher p2, + BiFunction combiner) { + return RxJava2Adapter.fluxToFlowable( + Flux.combineLatest( + p1, + p2, + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.toJdkBiFunction(combiner))); + } + } + // XXX: public static Flowable combineLatest(Publisher,Publisher,Publisher,Function3) // XXX: public static Flowable combineLatest(Publisher,Publisher,Publisher,Publisher,Function4) // XXX: public static Flowable @@ -52,10 +109,57 @@ public final class RxJavaFlowableToReactorTemplates { // XXX: public static Flowable concatEager(Publisher) // XXX: public static Flowable concatEager(Publisher,int,int) // XXX: public static Flowable create(FlowableOnSubscribe,BackpressureStrategy) - // XXX: public static Flowable defer(Callable) - // XXX: public static Flowable empty() - // XXX: public static Flowable error(Callable) - // XXX: public static Flowable error(Throwable) + + static final class FlowableDefer { + @BeforeTemplate + Flowable before(Callable> supplier) { + return Flowable.defer(supplier); + } + + @AfterTemplate + Flowable after(Callable> supplier) { + return RxJava2Adapter.fluxToFlowable( + Flux.defer( + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.callableAsSupplier(supplier))); + } + } + + static final class FlowableEmpty { + @BeforeTemplate + Flowable before() { + return Flowable.empty(); + } + + @AfterTemplate + Flowable after() { + return RxJava2Adapter.fluxToFlowable(Flux.empty()); + } + } + + // XXX: Use `CanBeCoercedTo`. + static final class FlowableErrorCallable { + @BeforeTemplate + Flowable before(Callable throwable) { + return Flowable.error(throwable); + } + + @AfterTemplate + Flowable after(Supplier throwable) { + return RxJava2Adapter.fluxToFlowable(Flux.error(throwable)); + } + } + + static final class FlowableErrorThrowable { + @BeforeTemplate + Flowable before(Throwable throwable) { + return Flowable.error(throwable); + } + + @AfterTemplate + Flowable after(Throwable throwable) { + return RxJava2Adapter.fluxToFlowable(Flux.error(throwable)); + } + } // XXX: public static Flowable fromArray(Object[]) // XXX: public static Flowable fromCallable(Callable) // XXX: public static Flowable fromFuture(Future) @@ -75,8 +179,31 @@ public final class RxJavaFlowableToReactorTemplates { // XXX: public static Flowable interval(long,TimeUnit,Scheduler) // XXX: public static Flowable intervalRange(long,long,long,long,TimeUnit) // XXX: public static Flowable intervalRange(long,long,long,long,TimeUnit,Scheduler) - // XXX: public static Flowable just(Object) - // XXX: public static Flowable just(Object,Object) + + static final class FlowableJust { + @BeforeTemplate + Flowable before(T t) { + return Flowable.just(t); + } + + @AfterTemplate + Flowable after(T t) { + return RxJava2Adapter.fluxToFlowable(Flux.just(t)); + } + } + + static final class FlowableJustTwo { + @BeforeTemplate + Flowable before(T t, @Repeated T arguments) { + return Flowable.just(t, arguments); + } + + @AfterTemplate + Flowable after(T t, @Repeated T arguments) { + return RxJava2Adapter.fluxToFlowable(Flux.just(t, arguments)); + } + } + // XXX: public static Flowable just(Object,Object,Object) // XXX: public static Flowable just(Object,Object,Object,Object) // XXX: public static Flowable just(Object,Object,Object,Object,Object) @@ -219,7 +346,22 @@ public final class RxJavaFlowableToReactorTemplates { // XXX: public final Flowable concatMapSingleDelayError(Function,boolean,int) // XXX: public final Flowable concatWith(CompletableSource) // XXX: public final Flowable concatWith(MaybeSource) - // XXX: public final Flowable concatWith(Publisher) + + static final class FlowableConcatWithPublisher { + @BeforeTemplate + Flowable before(Flowable flowable, Publisher source) { + return flowable.concatWith(source); + } + + @AfterTemplate + Flowable after(Flowable flowable, Publisher source) { + return flowable + .as(RxJava2Adapter::flowableToFlux) + .concatWith(source) + .as(RxJava2Adapter::fluxToFlowable); + } + } + // XXX: public final Flowable concatWith(SingleSource) // XXX: public final Single contains(Object) // XXX: public final Single count() @@ -260,11 +402,54 @@ public final class RxJavaFlowableToReactorTemplates { // XXX: public final Maybe elementAt(long) // XXX: public final Single elementAt(long,Object) // XXX: public final Single elementAtOrError(long) - // XXX: public final Flowable filter(Predicate) + + // XXX: `Refaster.canBeCoercedTo(...)`. + static final class FlowableFilter { + @BeforeTemplate + Flowable before(Flowable flowable, Predicate predicate) { + return flowable.filter(predicate); + } + + @AfterTemplate + Flowable after(Flowable flowable, java.util.function.Predicate predicate) { + return flowable + .as(RxJava2Adapter::flowableToFlux) + .filter(predicate) + .as(RxJava2Adapter::fluxToFlowable); + } + } // XXX: public final Single first(Object) - // XXX: public final Maybe firstElement() + + static final class FlowableFirstElement { + @BeforeTemplate + Maybe before(Flowable flowable) { + return flowable.firstElement(); + } + + @AfterTemplate + Maybe after(Flowable flowable) { + return flowable.as(RxJava2Adapter::flowableToFlux).next().as(RxJava2Adapter::monoToMaybe); + } + } + // XXX: public final Single firstOrError() - // XXX: public final Flowable flatMap(Function) + + // XXX: `Refaster.canBeCoercedTo(...)`. + static final class FlowableFlatMap> { + @BeforeTemplate + Flowable before(Flowable flowable, Function function) { + return flowable.flatMap(function); + } + + @AfterTemplate + Flowable after(Flowable flowable, java.util.function.Function function) { + return flowable + .as(RxJava2Adapter::flowableToFlux) + .flatMap(function) + .as(RxJava2Adapter::fluxToFlowable); + } + } + // XXX: public final Flowable flatMap(Function,BiFunction) // XXX: public final Flowable flatMap(Function,BiFunction,boolean) // XXX: public final Flowable flatMap(Function,BiFunction,boolean,int) @@ -306,7 +491,23 @@ public final class RxJavaFlowableToReactorTemplates { // XXX: public final Single lastOrError() // XXX: public final Flowable lift(FlowableOperator) // XXX: public final Flowable limit(long) - // XXX: public final Flowable map(Function) + + // XXX: `Refaster.canBeCoercedTo(...)`. + static final class FlowableMap { + @BeforeTemplate + Flowable before(Flowable flowable, Function function) { + return flowable.map(function); + } + + @AfterTemplate + Flowable after(Flowable flowable, java.util.function.Function function) { + return flowable + .as(RxJava2Adapter::flowableToFlux) + .map(function) + .as(RxJava2Adapter::fluxToFlowable); + } + } + // XXX: public final Flowable materialize() // XXX: public final Flowable mergeWith(CompletableSource) // XXX: public final Flowable mergeWith(MaybeSource) @@ -413,7 +614,22 @@ public final class RxJavaFlowableToReactorTemplates { // XXX: public final Flowable subscribeOn(Scheduler) // XXX: public final Flowable subscribeOn(Scheduler,boolean) // XXX: public final Subscriber subscribeWith(Subscriber) - // XXX: public final Flowable switchIfEmpty(Publisher) + + static final class FlowableSwitchIfEmpty { + @BeforeTemplate + Flowable before(Flowable flowable, Publisher publisher) { + return flowable.switchIfEmpty(publisher); + } + + @AfterTemplate + Flowable after(Flowable flowable, Publisher publisher) { + return flowable + .as(RxJava2Adapter::flowableToFlux) + .switchIfEmpty(publisher) + .as(RxJava2Adapter::fluxToFlowable); + } + } + // XXX: public final Flowable switchMap(Function) // XXX: public final Flowable switchMap(Function,int) // XXX: public final Completable switchMapCompletable(Function) @@ -470,7 +686,22 @@ public final class RxJavaFlowableToReactorTemplates { // XXX: public final Single toList() // XXX: public final Single toList(Callable) // XXX: public final Single toList(int) - // XXX: public final Single toMap(Function) + + static final class FlowableToMap { + @BeforeTemplate + Single> before(Flowable flowable, Function function) { + return flowable.toMap(function); + } + + @AfterTemplate + Single> after(Flowable flowable, java.util.function.Function function) { + return flowable + .as(RxJava2Adapter::flowableToFlux) + .collectMap(function) + .as(RxJava2Adapter::monoToSingle); + } + } + // XXX: public final Single toMap(Function,Function) // XXX: public final Single toMap(Function,Function,Callable) // XXX: public final Single toMultimap(Function) diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaMaybeToReactorTemplates.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaMaybeToReactorTemplates.java index 43739a8a..d3a843bf 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaMaybeToReactorTemplates.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaMaybeToReactorTemplates.java @@ -1,19 +1,83 @@ package tech.picnic.errorprone.refastertemplates; +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.google.common.collect.Streams; +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.Flowable; +import io.reactivex.Maybe; +import io.reactivex.MaybeSource; +import io.reactivex.Single; +import io.reactivex.functions.Function; +import java.util.Arrays; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + /** The Refaster templates for the migration of the RxJava Maybe type to Reactor */ public final class RxJavaMaybeToReactorTemplates { private RxJavaMaybeToReactorTemplates() {} - // XXX: public static Maybe amb(Iterable) - // XXX: public static Maybe ambArray(MaybeSource[]) + static final class MaybeAmb { + @BeforeTemplate + Maybe before(Iterable> iterable) { + return Maybe.amb(iterable); + } + + @AfterTemplate + Maybe after(Iterable> iterable) { + return RxJava2Adapter.monoToMaybe( + Mono.firstWithSignal( + Streams.stream(iterable) + .map(RxJava2Adapter::maybeToMono) + .collect(toImmutableList()))); + } + } + + static final class MaybeAmbArray { + @BeforeTemplate + Maybe before(Maybe... sources) { + return Maybe.ambArray(sources); + } + + @AfterTemplate + Maybe after(Maybe... sources) { + return RxJava2Adapter.monoToMaybe( + Mono.firstWithSignal( + Arrays.stream(sources).map(RxJava2Adapter::maybeToMono).collect(toImmutableList()))); + } + } + // 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: public static Flowable concatArray(MaybeSource[]) + + // XXX: The test is not triggering? What did I do wrong? Perhaps it should be a MaybeSource... + static final class MaybeConcatArray { + @BeforeTemplate + Flowable before(Maybe... sources) { + return Maybe.concatArray(sources); + } + + @AfterTemplate + Flowable after(Maybe... sources) { + return RxJava2Adapter.fluxToFlowable( + Flux.concat( + Arrays.stream(sources).map(RxJava2Adapter::maybeToMono).collect(toImmutableList()))); + } + } + // XXX: public static Flowable concatArrayDelayError(MaybeSource[]) // XXX: public static Flowable concatArrayEager(MaybeSource[]) // XXX: public static Flowable concatDelayError(Iterable) @@ -21,14 +85,57 @@ public final class RxJavaMaybeToReactorTemplates { // XXX: public static Flowable concatEager(Iterable) // XXX: public static Flowable concatEager(Publisher) // XXX: public static Maybe create(MaybeOnSubscribe) - // XXX: public static Maybe defer(Callable) + + // XXX: Is this correct? + abstract static class MaybeDefer { + @Placeholder + abstract Maybe maybeProducer(); + + @BeforeTemplate + Mono before() { + return Maybe.defer(() -> maybeProducer()).as(RxJava2Adapter::maybeToMono); + } + + @AfterTemplate + Mono after() { + return Mono.defer(() -> maybeProducer().as(RxJava2Adapter::maybeToMono)); + } + } + // XXX: public static Maybe empty() // XXX: public static Maybe error(Callable) // XXX: public static Maybe error(Throwable) // XXX: public static Maybe fromAction(Action) - // XXX: public static Maybe fromCallable(Callable) + + static final class MaybeFromCallable { + @BeforeTemplate + Maybe before(Callable callable) { + return Maybe.fromCallable(callable); + } + + @AfterTemplate + Maybe after(Callable callable) { + return RxJava2Adapter.monoToMaybe( + Mono.fromSupplier( + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.callableAsSupplier(callable))); + } + } + // XXX: public static Maybe fromCompletable(CompletableSource) - // XXX: public static Maybe fromFuture(Future) + + // XXX: Also handle `Future`s that don't extend `CompletableFuture`. + static final class MaybeFromFuture { + @BeforeTemplate + Maybe before(CompletableFuture future) { + return Maybe.fromFuture(future); + } + + @AfterTemplate + Maybe after(CompletableFuture future) { + return RxJava2Adapter.monoToMaybe(Mono.fromFuture(future)); + } + } + // XXX: public static Maybe fromFuture(Future,long,TimeUnit) // XXX: public static Maybe fromRunnable(Runnable) // XXX: public static Maybe fromSingle(SingleSource) @@ -56,7 +163,19 @@ public final class RxJavaMaybeToReactorTemplates { // XXX: public static Maybe unsafeCreate(MaybeSource) // XXX: public static Maybe using(Callable,Function,Consumer) // XXX: public static Maybe using(Callable,Function,Consumer,boolean) - // XXX: public static Maybe wrap(MaybeSource) + + static final class MaybeWrap { + @BeforeTemplate + Maybe before(Maybe maybe) { + return Maybe.wrap(maybe); + } + + @AfterTemplate + Maybe after(Maybe 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) @@ -72,12 +191,39 @@ public final class RxJavaMaybeToReactorTemplates { // XXX: public static Maybe // zip(MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,MaybeSource,Function9) // XXX: public static Maybe zipArray(Function,MaybeSource[]) - // XXX: public final Maybe ambWith(MaybeSource) + + static final class MaybeAmbWith { + @BeforeTemplate + Maybe before(Maybe maybe, Maybe otherMaybe) { + return maybe.ambWith(otherMaybe); + } + + @AfterTemplate + Maybe after(Maybe maybe, Maybe otherMaybe) { + return maybe + .as(RxJava2Adapter::maybeToMono) + .or(otherMaybe.as(RxJava2Adapter::maybeToMono)) + .as(RxJava2Adapter::monoToMaybe); + } + } + // XXX: public final Object as(MaybeConverter) // XXX: public final Object blockingGet() // XXX: public final Object blockingGet(Object) // XXX: public final Maybe cache() - // XXX: public final Maybe cast(Class) + + static final class MaybeCast { + @BeforeTemplate + Maybe before(Maybe maybe) { + return maybe.cast(Refaster.clazz()); + } + + @AfterTemplate + Maybe after(Maybe maybe) { + return maybe; + } + } + // XXX: public final Maybe compose(MaybeTransformer) // XXX: public final Maybe concatMap(Function) // XXX: public final Flowable concatWith(MaybeSource) @@ -101,18 +247,99 @@ public final class RxJavaMaybeToReactorTemplates { // XXX: public final Maybe doOnSuccess(Consumer) // XXX: public final Maybe doOnTerminate(Action) // XXX: public final Maybe filter(Predicate) - // XXX: public final Maybe flatMap(Function) + + // See the MyUtil for additional explanation. + static final class MaybeFlatMapFunction> { + @BeforeTemplate + Maybe before(Maybe maybe, Function function) { + return maybe.flatMap(function); + } + + @AfterTemplate + @SuppressWarnings("unchecked") + Maybe after(Maybe maybe, Function function) { + return maybe + .as(RxJava2Adapter::maybeToMono) + .flatMap( + v -> + RxJava2Adapter.maybeToMono( + Maybe.wrap( + (Maybe) + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.toJdkFunction( + function) + .apply(v)))) + .as(RxJava2Adapter::monoToMaybe); + } + } + + // XXX: There is no link to an original public method for this, but it is important. + abstract static class MaybeFlatMapLambda { + @Placeholder + abstract Maybe toMaybeFunction(@MayOptionallyUse S element); + + @BeforeTemplate + Maybe before(Maybe maybe) { + return maybe.flatMap(v -> toMaybeFunction(v)); + } + + @AfterTemplate + Maybe after(Maybe maybe) { + return maybe + .as(RxJava2Adapter::maybeToMono) + .flatMap(v -> toMaybeFunction(v).as(RxJava2Adapter::maybeToMono)) + .as(RxJava2Adapter::monoToMaybe); + } + } + // XXX: public final Maybe flatMap(Function,BiFunction) // XXX: public final Maybe flatMap(Function,Function,Callable) // XXX: public final Completable flatMapCompletable(Function) // XXX: public final Observable flatMapObservable(Function) // XXX: public final Flowable flatMapPublisher(Function) // XXX: public final Single flatMapSingle(Function) + // XXX: public final Maybe flatMapSingleElement(Function) + // The following template is required to rewrite this code from platform: + // private Completable verifyTagExists(Optional tagId) { + // return Maybe.defer(() -> tagId.map(Maybe::just).orElseGet(Maybe::empty)) + // .flatMapSingleElement(this::getTagById) + // .ignoreElement(); + // } + // static final class MaybeFlatMapSingleElement< + // I, T extends I, O, S extends Single> { // { + // @BeforeTemplate + // Maybe before(Maybe maybe, Function function) { + // return maybe.flatMapSingleElement(function); + // } + // + // @AfterTemplate + // Maybe after(Maybe maybe, Function function) { + // return maybe + // .as(RxJava2Adapter::maybeToMono) + // .flatMap(RxJava2ReactorMigrationUtil.toJdkFunction(function)) + // .as(RxJava2Adapter::monoToMaybe); + // } + // } + // XXX: public final Flowable flattenAsFlowable(Function) // XXX: public final Observable flattenAsObservable(Function) // XXX: public final Maybe hide() - // XXX: public final Completable ignoreElement() + + static final class MaybeIgnoreElement { + @BeforeTemplate + Completable before(Maybe maybe) { + return maybe.ignoreElement(); + } + + @AfterTemplate + Completable after(Maybe maybe) { + return maybe + .as(RxJava2Adapter::maybeToMono) + .ignoreElement() + .as(RxJava2Adapter::monoToCompletable); + } + } + // XXX: public final Single isEmpty() // XXX: public final Maybe lift(MaybeOperator) // XXX: public final Maybe map(Function) @@ -147,7 +374,22 @@ public final class RxJavaMaybeToReactorTemplates { // XXX: public final Maybe subscribeOn(Scheduler) // XXX: public final MaybeObserver subscribeWith(MaybeObserver) // XXX: public final Maybe switchIfEmpty(MaybeSource) - // XXX: public final Single switchIfEmpty(SingleSource) + + static final class MaybeSwitchIfEmpty { + @BeforeTemplate + Single before(Maybe maybe, Single single) { + return maybe.switchIfEmpty(single); + } + + @AfterTemplate + Single after(Maybe maybe, Single single) { + return maybe + .as(RxJava2Adapter::maybeToMono) + .switchIfEmpty(single.as(RxJava2Adapter::singleToMono)) + .as(RxJava2Adapter::monoToSingle); + } + } + // XXX: public final Maybe takeUntil(MaybeSource) // XXX: public final Maybe takeUntil(Publisher) // XXX: public final TestObserver test() diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaObservableToReactorTemplates.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaObservableToReactorTemplates.java index 3b1bacea..db3c9daf 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaObservableToReactorTemplates.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaObservableToReactorTemplates.java @@ -1,11 +1,38 @@ package tech.picnic.errorprone.refastertemplates; +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.google.common.collect.Streams; +import com.google.errorprone.refaster.annotation.AfterTemplate; +import com.google.errorprone.refaster.annotation.BeforeTemplate; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Observable; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Flux; + /** The Refaster templates for the migration of the RxJava Observable type to Reactor */ public final class RxJavaObservableToReactorTemplates { private RxJavaObservableToReactorTemplates() {} - // XXX: public static Observable amb(Iterable) + // XXX: is the conversion sequence correct here? + static final class ObservableAmb { + @BeforeTemplate + Observable before(Iterable> sources) { + return Observable.amb(sources); + } + + @AfterTemplate + Observable after(Iterable> sources) { + return RxJava2Adapter.fluxToObservable( + Flux.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[]) diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaSingleToReactorTemplates.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaSingleToReactorTemplates.java index e7b3b39f..2f86dabd 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaSingleToReactorTemplates.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaSingleToReactorTemplates.java @@ -1,5 +1,15 @@ package tech.picnic.errorprone.refastertemplates; +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.Maybe; +import io.reactivex.Single; +import io.reactivex.functions.Function; +import io.reactivex.functions.Predicate; +import reactor.adapter.rxjava.RxJava2Adapter; + /** The Refaster templates for the migration of the RxJava Single type to Reactor */ public final class RxJavaSingleToReactorTemplates { @@ -94,8 +104,43 @@ public final class RxJavaSingleToReactorTemplates { // XXX: public final Single doOnSubscribe(Consumer) // XXX: public final Single doOnSuccess(Consumer) // XXX: public final Single doOnTerminate(Action) - // XXX: public final Maybe filter(Predicate) + + // XXX: `function` type change; look into `Refaster.canBeCoercedTo(...)`. + static final class SingleFilter { + @BeforeTemplate + Maybe before(Single single, Predicate predicate) { + return single.filter(predicate); + } + + @AfterTemplate + Maybe after(Single single, java.util.function.Predicate predicate) { + return single + .as(RxJava2Adapter::singleToMono) + .filter(predicate) + .as(RxJava2Adapter::monoToMaybe); + } + } + // XXX: public final Single flatMap(Function) + // XXX: `function` type change; look into `Refaster.canBeCoercedTo(...)`. + abstract static class SingleFlatMapLambda { + @Placeholder + abstract Single toSingleFunction(@MayOptionallyUse S element); + + @BeforeTemplate + Single before(Single single) { + return single.flatMap(v -> toSingleFunction(v)); + } + + @AfterTemplate + Single after(Single single) { + return single + .as(RxJava2Adapter::singleToMono) + .flatMap(v -> toSingleFunction(v).as(RxJava2Adapter::singleToMono)) + .as(RxJava2Adapter::monoToSingle); + } + } + // XXX: public final Completable flatMapCompletable(Function) // XXX: public final Maybe flatMapMaybe(Function) // XXX: public final Observable flatMapObservable(Function) @@ -105,7 +150,20 @@ public final class RxJavaSingleToReactorTemplates { // XXX: public final Single hide() // XXX: public final Completable ignoreElement() // XXX: public final Single lift(SingleOperator) - // XXX: public final Single map(Function) + + // XXX: `Refaster.canBeCoercedTo(...)`. + static final class SingleMap { + @BeforeTemplate + Single before(Single single, Function function) { + return single.map(function); + } + + @AfterTemplate + Single after(Single single, java.util.function.Function function) { + return single.as(RxJava2Adapter::singleToMono).map(function).as(RxJava2Adapter::monoToSingle); + } + } + // XXX: public final Single materialize() // XXX: public final Flowable mergeWith(SingleSource) // XXX: public final Single observeOn(Scheduler) diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaToReactorTemplates.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaToReactorTemplates.java index 5da27bfe..bdc137d2 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaToReactorTemplates.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refastertemplates/RxJavaToReactorTemplates.java @@ -1,35 +1,17 @@ package tech.picnic.errorprone.refastertemplates; -import static com.google.common.collect.ImmutableList.toImmutableList; - -import com.google.common.collect.Streams; 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 io.reactivex.BackpressureStrategy; -import io.reactivex.Completable; -import io.reactivex.Flowable; -import io.reactivex.Maybe; -import io.reactivex.MaybeSource; -import io.reactivex.Single; -import io.reactivex.functions.BiFunction; import io.reactivex.functions.Function; -import io.reactivex.functions.Predicate; -import java.util.Arrays; -import java.util.Map; import java.util.concurrent.Callable; -import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; -import org.reactivestreams.Publisher; import reactor.adapter.rxjava.RxJava2Adapter; -import reactor.core.Exceptions; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -/** The Refaster templates for the migration of RxJava to Reactor */ +/** Assorted Refaster templates for the migration of RxJava to Reactor */ public final class RxJavaToReactorTemplates { private RxJavaToReactorTemplates() {} @@ -49,467 +31,6 @@ public final class RxJavaToReactorTemplates { } } - // How do this? - static final class FlowableAmbArray { - // static final class ambArray(Publisher[]) - @BeforeTemplate - Flowable before(Publisher... sources) { - return Flowable.ambArray(sources); - } - - @AfterTemplate - Flowable after(Publisher... sources) { - return RxJava2Adapter.fluxToFlowable( - Flux.firstWithSignal( - sources) ); - } - } - - // XXX: This wouldn't work for this case right? - // return Flowable.combineLatest( - // getEnabledConsentRequests(requiredConsentTopics, locale), // returns Flowable - // Flowable.fromIterable(requiredConsentTopics), // returns Flowable - // this::filterByTopic) - // XXX: Add test - static final class FlowableCombineLatest { - @BeforeTemplate - Flowable before( - Publisher p1, - Publisher p2, - BiFunction combiner) { - return Flowable.combineLatest(p1, p2, combiner); - } - - @AfterTemplate - Flowable after( - Publisher p1, - Publisher p2, - BiFunction combiner) { - return RxJava2Adapter.fluxToFlowable( - Flux.combineLatest( - p1, p2, RxJava2ReactorMigrationUtil.toJdkBiFunction(combiner))); - } - } - - static final class FlowableConcatWithPublisher { - @BeforeTemplate - Flowable before(Flowable flowable, Publisher source) { - return flowable.concatWith(source); - } - - @AfterTemplate - Flowable after(Flowable flowable, Publisher source) { - return flowable - .as(RxJava2Adapter::flowableToFlux) - .concatWith(source) - .as(RxJava2Adapter::fluxToFlowable); - } - } - - // XXX: Flowable.concatWith. -> CompletableSource - // XXX: Flowable.concatWith. -> SingleSource - // XXX: Flowable.concatWith. -> MaybeSource - - static final class FlowableDeferNew { - @BeforeTemplate - Flowable before(Callable> supplier) { - return Flowable.defer(supplier); - } - - @AfterTemplate - Flowable after(Callable> supplier) { - return RxJava2Adapter.fluxToFlowable(Flux.defer(RxJava2ReactorMigrationUtil.callableAsSupplier(supplier))); - } - } - - abstract static class FlowableDefer { - @Placeholder - abstract Flowable flowableCallable(); - - @BeforeTemplate - Flowable before() { - return Flowable.defer(() -> flowableCallable()); - } - - @AfterTemplate - Flowable after() { - return RxJava2Adapter.fluxToFlowable( - Flux.defer(() -> flowableCallable().as(RxJava2Adapter::flowableToFlux))); - } - } - - static final class FlowableEmpty { - @BeforeTemplate - Flowable before() { - return Flowable.empty(); - } - - @AfterTemplate - Flowable after() { - return RxJava2Adapter.fluxToFlowable(Flux.empty()); - } - } - - static final class FlowableErrorThrowable { - @BeforeTemplate - Flowable before(Throwable throwable) { - return Flowable.error(throwable); - } - - @AfterTemplate - Flowable after(Throwable throwable) { - return RxJava2Adapter.fluxToFlowable(Flux.error(throwable)); - } - } - - // XXX: Use `CanBeCoercedTo`. - static final class FlowableErrorCallable { - @BeforeTemplate - Flowable before(Callable throwable) { - return Flowable.error(throwable); - } - - @AfterTemplate - Flowable after(Supplier throwable) { - return RxJava2Adapter.fluxToFlowable(Flux.error(throwable)); - } - } - - static final class FlowableJust { - @BeforeTemplate - Flowable before(T t, @Repeated T arguments) { - return Flowable.just(t, arguments); - } - - @AfterTemplate - Flowable after(T t, @Repeated T arguments) { - return RxJava2Adapter.fluxToFlowable(Flux.just(t, arguments)); - } - } - - // XXX: `function` type change; look into `Refaster.canBeCoercedTo(...)`. - static final class FlowableFilter { - @BeforeTemplate - Flowable before(Flowable flowable, Predicate predicate) { - return flowable.filter(predicate); - } - - @AfterTemplate - Flowable after(Flowable flowable, java.util.function.Predicate predicate) { - return flowable - .as(RxJava2Adapter::flowableToFlux) - .filter(predicate) - .as(RxJava2Adapter::fluxToFlowable); - } - } - - static final class FlowableFirstElement { - @BeforeTemplate - Maybe before(Flowable flowable) { - return flowable.firstElement(); - } - - @AfterTemplate - Maybe after(Flowable flowable) { - return flowable.as(RxJava2Adapter::flowableToFlux).next().as(RxJava2Adapter::monoToMaybe); - } - } - - // XXX: `function` type change; look into `Refaster.canBeCoercedTo(...)`. - static final class FlowableFlatMap> { - @BeforeTemplate - Flowable before(Flowable flowable, Function function) { - return flowable.flatMap(function); - } - - @AfterTemplate - Flowable after(Flowable flowable, java.util.function.Function function) { - return flowable - .as(RxJava2Adapter::flowableToFlux) - .flatMap(function) - .as(RxJava2Adapter::fluxToFlowable); - } - } - - // static final class FlowableFromArray { - // @BeforeTemplate - // - // } - - // XXX: `function` type change; look into `Refaster.canBeCoercedTo(...)`. - static final class FlowableMap { - @BeforeTemplate - Flowable before(Flowable flowable, Function function) { - return flowable.map(function); - } - - @AfterTemplate - Flowable after(Flowable flowable, java.util.function.Function function) { - return flowable - .as(RxJava2Adapter::flowableToFlux) - .map(function) - .as(RxJava2Adapter::fluxToFlowable); - } - } - - static final class FlowableToMap { - @BeforeTemplate - Single> before(Flowable flowable, Function function) { - return flowable.toMap(function); - } - - @AfterTemplate - Single> after(Flowable flowable, java.util.function.Function function) { - return flowable - .as(RxJava2Adapter::flowableToFlux) - .collectMap(function) - .as(RxJava2Adapter::monoToSingle); - } - } - - static final class FlowableSwitchIfEmptyPublisher { - @BeforeTemplate - Flowable before(Flowable flowable, Publisher publisher) { - return flowable.switchIfEmpty(publisher); - } - - @AfterTemplate - Flowable after(Flowable flowable, Publisher publisher) { - return flowable - .as(RxJava2Adapter::flowableToFlux) - .switchIfEmpty(publisher) - .as(RxJava2Adapter::fluxToFlowable); - } - } - - static final class MaybeAmb { - @BeforeTemplate - Maybe before(Iterable> iterable) { - return Maybe.amb(iterable); - } - - @AfterTemplate - Maybe after(Iterable> iterable) { - return RxJava2Adapter.monoToMaybe( - Mono.firstWithSignal( - Streams.stream(iterable) - .map(RxJava2Adapter::maybeToMono) - .collect(toImmutableList()))); - } - } - - static final class MaybeAmbWith { - @BeforeTemplate - Maybe before(Maybe maybe, Maybe otherMaybe) { - return maybe.ambWith(otherMaybe); - } - - @AfterTemplate - Maybe after(Maybe maybe, Maybe otherMaybe) { - return maybe - .as(RxJava2Adapter::maybeToMono) - .or(otherMaybe.as(RxJava2Adapter::maybeToMono)) - .as(RxJava2Adapter::monoToMaybe); - } - } - - static final class MaybeAmbArray { - @BeforeTemplate - Maybe before(Maybe... sources) { - return Maybe.ambArray(sources); - } - - @AfterTemplate - Maybe after(Maybe... sources) { - return RxJava2Adapter.monoToMaybe( - Mono.firstWithSignal( - Arrays.stream(sources).map(RxJava2Adapter::maybeToMono).collect(toImmutableList()))); - } - } - - // XXX: The test is not triggering? What did I do wrong? Perhaps it should be a MaybeSource... - static final class MaybeConcatArray { - @BeforeTemplate - Flowable before(Maybe... sources) { - return Maybe.concatArray(sources); - } - - @AfterTemplate - Flowable after(Maybe... sources) { - return RxJava2Adapter.fluxToFlowable( - Flux.concat( - Arrays.stream(sources).map(RxJava2Adapter::maybeToMono).collect(toImmutableList()))); - } - } - - // XXX: Perhaps omit this one. - abstract static class MaybeDeferToMono { - @Placeholder - abstract Maybe maybeProducer(); - - @BeforeTemplate - Mono before() { - return Maybe.defer(() -> maybeProducer()).as(RxJava2Adapter::maybeToMono); - } - - @AfterTemplate - Mono after() { - return Mono.defer(() -> maybeProducer().as(RxJava2Adapter::maybeToMono)); - } - } - - static final class MaybeCast { - @BeforeTemplate - Maybe before(Maybe maybe) { - return maybe.cast(Refaster.clazz()); - } - - @AfterTemplate - Maybe after(Maybe maybe) { - return maybe; - } - } - - static final class MaybeWrap { - @BeforeTemplate - Maybe before(Maybe maybe) { - return Maybe.wrap(maybe); - } - - @AfterTemplate - Maybe after(Maybe maybe) { - return maybe; - } - } - - // See the MyUtil for additional explanation. - static final class MaybeFlatMapFunction> { - @BeforeTemplate - Maybe before(Maybe maybe, Function function) { - return maybe.flatMap(function); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - Maybe after(Maybe maybe, Function function) { - return maybe - .as(RxJava2Adapter::maybeToMono) - .flatMap( - v -> - RxJava2Adapter.maybeToMono( - Maybe.wrap((Maybe) MyUtil.convert(function).apply(v)))) - .as(RxJava2Adapter::monoToMaybe); - } - } - - abstract static class MaybeFlatMapLambda { - @Placeholder - abstract Maybe toMaybeFunction(@MayOptionallyUse S element); - - @BeforeTemplate - Maybe before(Maybe maybe) { - return maybe.flatMap(v -> toMaybeFunction(v)); - } - - @AfterTemplate - Maybe after(Maybe maybe) { - return maybe - .as(RxJava2Adapter::maybeToMono) - .flatMap(v -> toMaybeFunction(v).as(RxJava2Adapter::maybeToMono)) - .as(RxJava2Adapter::monoToMaybe); - } - } - - static final class MaybeFromCallable { - @BeforeTemplate - Maybe before(Callable callable) { - return Maybe.fromCallable(callable); - } - - @AfterTemplate - Maybe after(Callable callable) { - return RxJava2Adapter.monoToMaybe( - Mono.fromSupplier(RxJava2ReactorMigrationUtil.callableAsSupplier(callable))); - } - } - - // XXX: Also handle `Future`s that don't extend `CompletableFuture`. - static final class MaybeFromFuture { - @BeforeTemplate - Maybe before(CompletableFuture future) { - return Maybe.fromFuture(future); - } - - @AfterTemplate - Maybe after(CompletableFuture future) { - return RxJava2Adapter.monoToMaybe(Mono.fromFuture(future)); - } - } - - // The following template is required to rewrite this code from platform: - // private Completable verifyTagExists(Optional tagId) { - // return Maybe.defer(() -> tagId.map(Maybe::just).orElseGet(Maybe::empty)) - // .flatMapSingleElement(this::getTagById) - // .ignoreElement(); - // } - // static final class MaybeFlatMapSingleElement< - // I, T extends I, O, S extends Single> { // { - // @BeforeTemplate - // Maybe before(Maybe maybe, Function function) { - // return maybe.flatMapSingleElement(function); - // } - // - // @AfterTemplate - // Maybe after(Maybe maybe, Function function) { - // return maybe - // .as(RxJava2Adapter::maybeToMono) - // .flatMap(RxJava2ReactorMigrationUtil.toJdkFunction(function)) - // .as(RxJava2Adapter::monoToMaybe); - // } - // } - - static final class MaybeIgnoreElement { - @BeforeTemplate - Completable before(Maybe maybe) { - return maybe.ignoreElement(); - } - - @AfterTemplate - Completable after(Maybe maybe) { - return maybe - .as(RxJava2Adapter::maybeToMono) - .ignoreElement() - .as(RxJava2Adapter::monoToCompletable); - } - } - - static final class MaybeSwitchIfEmpty { - @BeforeTemplate - Single before(Maybe maybe, Single single) { - return maybe.switchIfEmpty(single); - } - - @AfterTemplate - Single after(Maybe maybe, Single single) { - return maybe - .as(RxJava2Adapter::maybeToMono) - .switchIfEmpty(single.as(RxJava2Adapter::singleToMono)) - .as(RxJava2Adapter::monoToSingle); - } - } - - static final class RemoveRedundantCast { - @BeforeTemplate - T before(T object) { - return (T) object; - } - - @AfterTemplate - T after(T object) { - return object; - } - } - // XXX: What should we do with the naming here? Since it is not entirely correct now. static final class MonoToFlowableToMono { @BeforeTemplate @@ -530,51 +51,29 @@ public final class RxJavaToReactorTemplates { } } - // XXX: `function` type change; look into `Refaster.canBeCoercedTo(...)`. - static final class SingleFilter { + static final class RemoveRedundantCast { @BeforeTemplate - Maybe before(Single single, Predicate predicate) { - return single.filter(predicate); + T before(T object) { + return (T) object; } @AfterTemplate - Maybe after(Single single, java.util.function.Predicate predicate) { - return single - .as(RxJava2Adapter::singleToMono) - .filter(predicate) - .as(RxJava2Adapter::monoToMaybe); + T after(T object) { + return object; } } - // XXX: `function` type change; look into `Refaster.canBeCoercedTo(...)`. - abstract static class SingleFlatMapLambda { - @Placeholder - abstract Single toSingleFunction(@MayOptionallyUse S element); - + // XXX: Use `CanBeCoercedTo` + @SuppressWarnings("NoFunctionalReturnType") + static final class UnnecessaryConversion { @BeforeTemplate - Single before(Single single) { - return single.flatMap(v -> toSingleFunction(v)); + java.util.function.Function before(Function function) { + return RxJava2ReactorMigrationUtil.toJdkFunction(function); } @AfterTemplate - Single after(Single single) { - return single - .as(RxJava2Adapter::singleToMono) - .flatMap(v -> toSingleFunction(v).as(RxJava2Adapter::singleToMono)) - .as(RxJava2Adapter::monoToSingle); - } - } - - // XXX: `function` type change; look into `Refaster.canBeCoercedTo(...)`. - static final class SingleMap { - @BeforeTemplate - Single before(Single single, Function function) { - return single.map(function); - } - - @AfterTemplate - Single after(Single single, java.util.function.Function function) { - return single.as(RxJava2Adapter::singleToMono).map(function).as(RxJava2Adapter::monoToSingle); + java.util.function.Function after(java.util.function.Function function) { + return function; } } @@ -625,41 +124,40 @@ public final class RxJavaToReactorTemplates { // } // } - /** - * XXX: Temporary solution, this could be fixed when we know whether the function throws an - * Exception. - */ - public static final class MyUtil { - - private MyUtil() {} - - /** - * Temporary construct to convert functions that do not throw an exception - * - *

The idea is to convert a io.reactivex.functions.Function to a java.util.function.Function. - * - * @param function The function to convert - * @param The input type - * @param The output type - * @return the java.util.function.Function - */ - @SuppressWarnings({"IllegalCatch", "NoFunctionalReturnType"}) - public static java.util.function.Function convert( - Function function) { - return input -> { - try { - return function.apply(input); - } catch (Exception e) { - throw Exceptions.propagate(e); - } - }; - } - } + // /** + // * XXX: Temporary solution, this could be fixed when we know whether the function throws an + // * Exception. + // */ + // public static final class MyUtil { + // + // private MyUtil() {} + // + // /** Temporary construct to convert functions that do not throw an exception */ + // @SuppressWarnings({"IllegalCatch", "NoFunctionalReturnType"}) + // public static java.util.function.Function convert( + // Function function) { + // return input -> { + // try { + // return function.apply(input); + // } catch (Exception e) { + // throw Exceptions.propagate(e); + // } + // }; + // } + // } // XXX: Move to a separate Maven module. + /** Util for the conversion of types */ public static final class RxJava2ReactorMigrationUtil { private RxJava2ReactorMigrationUtil() {} + /** + * Convert {@code Callable} to T + * + * @param callable XXX + * @param XXX + * @return XXX + */ // XXX: Rename. // XXX: Introduce Refaster rules to drop this wrapper when possible. @SuppressWarnings("IllegalCatch") @@ -671,20 +169,37 @@ public final class RxJavaToReactorTemplates { } } + /** + * Convert {@link io.reactivex.functions.Function} to {@link java.util.function.Function} + * + * @param function XXX + * @param XXX + * @param XXX + * @return XXX + */ // XXX: Rename. // XXX: Introduce Refaster rules to drop this wrapper when possible. @SuppressWarnings("IllegalCatch") - public static java.util.function.Function> toJdkFunction( - io.reactivex.functions.Function> function) { + public static java.util.function.Function toJdkFunction( + io.reactivex.functions.Function function) { return (t) -> { try { - return function.apply(t).as(RxJava2Adapter::singleToMono); + 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 XXX + * @param XXX + * @param XXX + * @return XXX + */ @SuppressWarnings("IllegalCatch") public static java.util.function.BiFunction toJdkBiFunction( @@ -698,37 +213,30 @@ public final class RxJavaToReactorTemplates { }; } - - @SuppressWarnings("IllegalCatch") - public static Supplier callableAsSupplier(Callable callable) { - return () -> { - try { - return callable.call(); - } catch (Exception e) { - throw new IllegalArgumentException("Callable 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 - - // @CheckParameterCoersion - @SuppressWarnings("NoFunctionalReturnType") - static final class UnnecessaryConversion { - @BeforeTemplate - java.util.function.Function before(Function function) { - return MyUtil.convert(function); + /** + * Convert {@link io.reactivex.functions.BiFunction} to {@link java.util.function.BiFunction} + * + * @param callable XXX + * @param XXX + * @return XXX + */ + @SuppressWarnings("IllegalCatch") + public static Supplier callableAsSupplier(Callable callable) { + return () -> { + try { + return callable.call(); + } catch (Exception e) { + throw new IllegalArgumentException("Callable threw checked exception", e); + } + }; } - @AfterTemplate - java.util.function.Function after(java.util.function.Function function) { - return function; - } + // "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 } } diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaCompletableToReactorTemplatesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaCompletableToReactorTemplatesTestInput.java index 87302793..6151a863 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaCompletableToReactorTemplatesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaCompletableToReactorTemplatesTestInput.java @@ -1,3 +1,10 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaCompletableReactorTemplatesTest implements RefasterTemplateTestCase {} +import io.reactivex.Completable; + +final class RxJavaCompletableReactorTemplatesTest implements RefasterTemplateTestCase { + + Completable testCompletableAmb() { + return Completable.amb(Arrays.asList(Completable.complete(), Completable.complete())); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaCompletableToReactorTemplatesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaCompletableToReactorTemplatesTestOutput.java index 87302793..db6f4551 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaCompletableToReactorTemplatesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaCompletableToReactorTemplatesTestOutput.java @@ -1,3 +1,20 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaCompletableReactorTemplatesTest implements RefasterTemplateTestCase {} +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.google.common.collect.Streams; +import io.reactivex.Completable; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Mono; + +final class RxJavaCompletableReactorTemplatesTest implements RefasterTemplateTestCase { + + Completable testCompletableAmb() { + return Mono.firstWithSignal( + Streams.stream( + Completable.amb(Arrays.asList(Completable.complete(), Completable.complete()))) + .map(RxJava2Adapter::completableToMono) + .collect(toImmutableList())) + .as(RxJava2Adapter::monoToCompletable); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaFlowableToReactorTemplatesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaFlowableToReactorTemplatesTestInput.java index d2bda991..181f1d1d 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaFlowableToReactorTemplatesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaFlowableToReactorTemplatesTestInput.java @@ -1,3 +1,80 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaFlowableToReactorTemplatesTest implements RefasterTemplateTestCase {} +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import io.reactivex.Flowable; +import io.reactivex.Maybe; +import io.reactivex.Single; +import java.util.Map; + +final class RxJavaFlowableToReactorTemplatesTest implements RefasterTemplateTestCase { + + Flowable testFlowableCombineLatest() { + return Flowable.combineLatest(Flowable.just(1), Flowable.just(2), Integer::sum); + } + + Flowable testFlowableConcatWithPublisher() { + return Flowable.just(1).concatWith(Flowable.just(2)); + } + + Flowable testFlowableDefer() { + return Flowable.defer(() -> Flowable.just(1)); + } + + Flowable testFlowableEmpty() { + return Flowable.empty(); + } + + Flowable testFlowableErrorThrowable() { + return Flowable.error(new IllegalStateException()); + } + + Flowable testFlowableErrorCallable() { + return Flowable.error( + () -> { + throw new IllegalStateException(); + }); + } + + Flowable testFlowableFilter() { + return Flowable.just(1).filter(i -> i > 2); + } + + Maybe testFlowableFirstElement() { + return Flowable.just(1).firstElement(); + } + + Flowable testFlowableFlatMap() { + Flowable.just(1).flatMap(this::exampleMethod2); + return Flowable.just(1).flatMap(i -> ImmutableSet::of); + } + + private Maybe exampleMethod(Integer x) { + return null; + } + + private Flowable exampleMethod2(Integer x) { + return null; + } + + ImmutableList> testFlowableJust() { + return ImmutableList.of(Flowable.just(1), Flowable.just(1, 2)); + } + + Flowable testFlowableMap() { + return Flowable.just(1).map(i -> i + 1); + } + + Flowable testFlowableSwitchIfEmptyPublisher() { + return Flowable.just(1) + .switchIfEmpty( + Flowable.error( + () -> { + throw new IllegalStateException(); + })); + } + + Single> testFlowableToMap() { + return Flowable.just(1).toMap(i -> i > 1); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaFlowableToReactorTemplatesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaFlowableToReactorTemplatesTestOutput.java index d2bda991..3d867aaf 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaFlowableToReactorTemplatesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaFlowableToReactorTemplatesTestOutput.java @@ -1,3 +1,115 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaFlowableToReactorTemplatesTest implements RefasterTemplateTestCase {} +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import io.reactivex.Flowable; +import io.reactivex.Maybe; +import io.reactivex.Single; +import java.util.Map; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Flux; +import tech.picnic.errorprone.refastertemplates.RxJavaToReactorTemplates; + +final class RxJavaFlowableToReactorTemplatesTest implements RefasterTemplateTestCase { + + Flowable testFlowableCombineLatest() { + return RxJava2Adapter.fluxToFlowable( + Flux.combineLatest( + Flowable.just(1), + Flowable.just(2), + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.toJdkBiFunction(Integer::sum))); + } + + Flowable testFlowableConcatWithPublisher() { + return Flowable.just(1) + .as(RxJava2Adapter::flowableToFlux) + .concatWith(Flowable.just(2)) + .as(RxJava2Adapter::fluxToFlowable); + } + + Flowable testFlowableDefer() { + return RxJava2Adapter.fluxToFlowable( + Flux.defer(() -> Flowable.just(1).as(RxJava2Adapter::flowableToFlux))); + } + + Flowable testFlowableEmpty() { + return RxJava2Adapter.fluxToFlowable(Flux.empty()); + } + + Flowable testFlowableErrorThrowable() { + return RxJava2Adapter.fluxToFlowable(Flux.error(new IllegalStateException())); + } + + Flowable testFlowableErrorCallable() { + return RxJava2Adapter.fluxToFlowable( + Flux.error( + () -> { + throw new IllegalStateException(); + })); + } + + Flowable testFlowableFilter() { + return Flowable.just(1) + .as(RxJava2Adapter::flowableToFlux) + .filter(i -> i > 2) + .as(RxJava2Adapter::fluxToFlowable); + } + + Maybe testFlowableFirstElement() { + return Flowable.just(1) + .as(RxJava2Adapter::flowableToFlux) + .next() + .as(RxJava2Adapter::monoToMaybe); + } + + Flowable testFlowableFlatMap() { + Flowable.just(1) + .as(RxJava2Adapter::flowableToFlux) + .flatMap(this::exampleMethod2) + .as(RxJava2Adapter::fluxToFlowable); + + return Flowable.just(1) + .as(RxJava2Adapter::flowableToFlux) + .flatMap(i -> ImmutableSet::of) + .as(RxJava2Adapter::fluxToFlowable); + } + + private Maybe exampleMethod(Integer x) { + return null; + } + + private Flowable exampleMethod2(Integer x) { + return null; + } + + ImmutableList> testFlowableJust() { + return ImmutableList.of( + RxJava2Adapter.fluxToFlowable(Flux.just(1)), + RxJava2Adapter.fluxToFlowable(Flux.just(1, 2))); + } + + Flowable testFlowableMap() { + return Flowable.just(1) + .as(RxJava2Adapter::flowableToFlux) + .map(i -> i + 1) + .as(RxJava2Adapter::fluxToFlowable); + } + + Flowable testFlowableSwitchIfEmptyPublisher() { + return Flowable.just(1) + .as(RxJava2Adapter::flowableToFlux) + .switchIfEmpty( + Flowable.error( + () -> { + throw new IllegalStateException(); + })) + .as(RxJava2Adapter::fluxToFlowable); + } + + Single> testFlowableToMap() { + return Flowable.just(1) + .as(RxJava2Adapter::flowableToFlux) + .collectMap(i -> i > 1) + .as(RxJava2Adapter::monoToSingle); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaMaybeToReactorTemplatesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaMaybeToReactorTemplatesTestInput.java index 5944d9f2..87ccc6e1 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaMaybeToReactorTemplatesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaMaybeToReactorTemplatesTestInput.java @@ -1,3 +1,89 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaMaybeToReactorTemplatesTest implements RefasterTemplateTestCase {} +import com.google.common.collect.ImmutableList; +import io.reactivex.Completable; +import io.reactivex.Flowable; +import io.reactivex.Maybe; +import io.reactivex.Single; +import java.util.concurrent.CompletableFuture; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Mono; + +final class RxJavaMaybeToReactorTemplatesTest implements RefasterTemplateTestCase { + + Maybe testMaybeAmb() { + return Maybe.amb(ImmutableList.of(Maybe.just("foo"), Maybe.just("bar"))); + } + + Maybe testMaybeAmbArray() { + return Maybe.ambArray(Maybe.just("foo"), Maybe.just("bar")); + } + + Flowable testMaybeConcatArray() { + return Maybe.concatArray(Maybe.just(1), Maybe.just(2), Maybe.empty()); + } + + Mono testMaybeDefer() { + return Maybe.defer(() -> Maybe.just("test")).as(RxJava2Adapter::maybeToMono); + } + + Maybe testMaybeFromCallable() { + return Maybe.fromCallable( + () -> { + String s = "foo"; + return null; + }); + } + + Maybe testMaybeFromFuture() { + return Maybe.fromFuture(new CompletableFuture<>()); + } + + Maybe testMaybeWrap() { + return Maybe.wrap(Maybe.just(1)); + } + + Maybe testMaybeAmbWith() { + return Maybe.just("foo").ambWith(Maybe.just("bar")); + } + + Maybe testMaybeCastPositive() { + return Maybe.just("string").cast(String.class); + } + + Maybe testMaybeCastNegative() { + return Maybe.just("string").cast(Object.class); + } + + // XXX: This should be fixed later with `Refaster.canBeCoercedTo(...)` + Maybe testMaybeFlatMapFunction() { + Maybe.just(1).flatMap(this::exampleMethod); + + return Maybe.just(1).flatMap(exampleFunction()); + } + + private io.reactivex.functions.Function> exampleFunction() { + return null; + } + + Maybe testMaybeFlatMapLambda() { + return Maybe.just(1).flatMap(i -> Maybe.just(i * 2)); + } + + Maybe testMaybeFlatMapMethodReference() { + return Maybe.just(1).flatMap(this::exampleMethod); + } + + Completable testMaybeIgnoreElement() { + return Maybe.just(1).ignoreElement(); + } + + Single testMaybeSwitchIfEmpty() { + return Maybe.just(1) + .switchIfEmpty( + Single.error( + () -> { + throw new IllegalStateException(); + })); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaMaybeToReactorTemplatesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaMaybeToReactorTemplatesTestOutput.java index 5944d9f2..7c797a5f 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaMaybeToReactorTemplatesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaMaybeToReactorTemplatesTestOutput.java @@ -1,3 +1,139 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaMaybeToReactorTemplatesTest implements RefasterTemplateTestCase {} +import com.google.common.collect.ImmutableList; +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.concurrent.CompletableFuture; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Mono; +import tech.picnic.errorprone.refastertemplates.RxJavaToReactorTemplates; + +final class RxJavaMaybeToReactorTemplatesTest implements RefasterTemplateTestCase { + + Maybe testMaybeAmb() { + return RxJava2Adapter.monoToMaybe( + Mono.firstWithSignal( + Streams.stream(ImmutableList.of(Maybe.just("foo"), Maybe.just("bar"))) + .map(RxJava2Adapter::maybeToMono) + .collect(ImmutableList.toImmutableList()))); + } + + Maybe testMaybeAmbArray() { + return Maybe.ambArray(Maybe.just("foo"), Maybe.just("bar")); + } + + Flowable testMaybeConcatArray() { + return Maybe.concatArray(Maybe.just(1), Maybe.just(2), Maybe.empty()); + } + + Mono testMaybeDefer() { + return Mono.defer(() -> Maybe.just("test").as(RxJava2Adapter::maybeToMono)); + } + + Maybe testMaybeWrap() { + return Maybe.just(1); + } + + Maybe testMaybeFromCallable() { + return RxJava2Adapter.monoToMaybe( + Mono.fromSupplier( + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.callableAsSupplier( + () -> { + String s = "foo"; + return null; + }))); + } + + Maybe testMaybeFromFuture() { + return RxJava2Adapter.monoToMaybe(Mono.fromFuture(new CompletableFuture<>())); + } + + Maybe testMaybeAmbWith() { + return Maybe.just("foo") + .as(RxJava2Adapter::maybeToMono) + .or(Maybe.just("bar").as(RxJava2Adapter::maybeToMono)) + .as(RxJava2Adapter::monoToMaybe); + } + + Maybe testMaybeCastPositive() { + return Maybe.just("string"); + } + + Maybe testMaybeCastNegative() { + return Maybe.just("string").cast(Object.class); + } + + // XXX: This should be fixed later with `Refaster.canBeCoercedTo(...)` + Maybe testMaybeFlatMapFunction() { + Maybe.just(1) + .as(RxJava2Adapter::maybeToMono) + .flatMap( + v -> + RxJava2Adapter.maybeToMono( + Maybe.wrap( + (Maybe) + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.toJdkFunction( + this::exampleMethod) + .apply(v)))) + .as(RxJava2Adapter::monoToMaybe); + + return Maybe.just(1) + .as(RxJava2Adapter::maybeToMono) + .flatMap( + v -> + RxJava2Adapter.maybeToMono( + Maybe.wrap( + (Maybe) + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.toJdkFunction( + exampleFunction()) + .apply(v)))) + .as(RxJava2Adapter::monoToMaybe); + } + + private io.reactivex.functions.Function> exampleFunction() { + return null; + } + + Maybe testMaybeFlatMapLambda() { + return Maybe.just(1) + .as(RxJava2Adapter::maybeToMono) + .flatMap(i -> Maybe.just(i * 2).as(RxJava2Adapter::maybeToMono)) + .as(RxJava2Adapter::monoToMaybe); + } + + Maybe testMaybeFlatMapMethodReference() { + return Maybe.just(1) + .as(RxJava2Adapter::maybeToMono) + .flatMap( + v -> + RxJava2Adapter.maybeToMono( + Maybe.wrap( + (Maybe) + RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.toJdkFunction( + this::exampleMethod) + .apply(v)))) + .as(RxJava2Adapter::monoToMaybe); + } + + Completable testMaybeIgnoreElement() { + return Maybe.just(1) + .as(RxJava2Adapter::maybeToMono) + .ignoreElement() + .as(RxJava2Adapter::monoToCompletable); + } + + Single testMaybeSwitchIfEmpty() { + return Maybe.just(1) + .as(RxJava2Adapter::maybeToMono) + .switchIfEmpty( + Single.error( + () -> { + throw new IllegalStateException(); + }) + .as(RxJava2Adapter::singleToMono)) + .as(RxJava2Adapter::monoToSingle); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaObservableToReactorTemplatesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaObservableToReactorTemplatesTestInput.java index a82ee95b..75788415 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaObservableToReactorTemplatesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaObservableToReactorTemplatesTestInput.java @@ -1,3 +1,11 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaObservableToReactorTemplatesTest implements RefasterTemplateTestCase {} +import io.reactivex.Observable; +import java.util.concurrent.TimeUnit; + +final class RxJavaObservableToReactorTemplatesTest implements RefasterTemplateTestCase { + + Completable testObservableAmb() { + return Observable.amb(Observable.timer(100, TimeUnit.NANOSECONDS).map(i -> 1)); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaObservableToReactorTemplatesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaObservableToReactorTemplatesTestOutput.java index a82ee95b..131a9dbe 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaObservableToReactorTemplatesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaObservableToReactorTemplatesTestOutput.java @@ -1,3 +1,22 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaObservableToReactorTemplatesTest implements RefasterTemplateTestCase {} +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.google.common.collect.Streams; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Observable; +import java.util.concurrent.TimeUnit; +import reactor.adapter.rxjava.RxJava2Adapter; +import reactor.core.publisher.Flux; + +final class RxJavaObservableToReactorTemplatesTest implements RefasterTemplateTestCase { + + Completable testObservableAmb() { + return RxJava2Adapter.fluxToObservable( + Flux.firstWithSignal( + Streams.stream(Observable.timer(100, TimeUnit.NANOSECONDS).map(i -> 1)) + .map(e -> e.toFlowable(BackpressureStrategy.BUFFER)) + .map(RxJava2Adapter::flowableToFlux) + .collect(toImmutableList()))); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaSingleToReactorTemplatesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaSingleToReactorTemplatesTestInput.java index a82ee95b..cb4eb4fa 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaSingleToReactorTemplatesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaSingleToReactorTemplatesTestInput.java @@ -1,3 +1,19 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaObservableToReactorTemplatesTest implements RefasterTemplateTestCase {} +import io.reactivex.Maybe; +import io.reactivex.Single; + +final class RxJavaObservableToReactorTemplatesTest implements RefasterTemplateTestCase { + + Maybe testSingleFilter() { + return Single.just(1).filter(i -> i > 2); + } + + Single testSingleFlatMapLambda() { + return Single.just(1).flatMap(i -> Single.just(i * 2)); + } + + Single testSingleMap() { + return Single.just(1).map(i -> i + 1); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaSingleToReactorTemplatesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaSingleToReactorTemplatesTestOutput.java index 8c0891bd..bc6e3e24 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaSingleToReactorTemplatesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaSingleToReactorTemplatesTestOutput.java @@ -1,3 +1,29 @@ package tech.picnic.errorprone.bugpatterns; -final class RxJavaSingleToReactorTemplatesTest implements RefasterTemplateTestCase {} +import io.reactivex.Maybe; +import io.reactivex.Single; +import reactor.adapter.rxjava.RxJava2Adapter; + +final class RxJavaSingleToReactorTemplatesTest implements RefasterTemplateTestCase { + + Maybe testSingleFilter() { + return Single.just(1) + .as(RxJava2Adapter::singleToMono) + .filter(i -> i > 2) + .as(RxJava2Adapter::monoToMaybe); + } + + Single testSingleFlatMapLambda() { + return Single.just(1) + .as(RxJava2Adapter::singleToMono) + .flatMap(i -> Single.just(i * 2).as(RxJava2Adapter::singleToMono)) + .as(RxJava2Adapter::monoToSingle); + } + + Single testSingleMap() { + return Single.just(1) + .as(RxJava2Adapter::singleToMono) + .map(i -> i + 1) + .as(RxJava2Adapter::monoToSingle); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaToReactorTemplatesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaToReactorTemplatesTestInput.java index ea3d576d..d4a36b1c 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaToReactorTemplatesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaToReactorTemplatesTestInput.java @@ -1,17 +1,9 @@ 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.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; import reactor.adapter.rxjava.RxJava2Adapter; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -30,156 +22,6 @@ final class RxJavaToReactorTemplatesTest implements RefasterTemplateTestCase { return Flux.just(2).as(RxJava2Adapter::fluxToFlowable).as(RxJava2Adapter::flowableToFlux); } - // XXX: Can this be done with Flowable instead of Flowable - Flowable testFlowableCombineLatest() { - return Flowable.combineLatest(Flowable.just(1), Flowable.just(2), Integer::sum); - } - - // XXX: Discuss with Stephan, look at the Publisher which is of type Flowable, that won't work... - Flowable testFlowableConcatWithPublisher() { - return Flowable.just(1).concatWith(Flowable.just(2)); - } - - Flowable testFlowableDefer() { - return Flowable.defer(() -> Flowable.just(1)); - } - - Flowable testFlowableEmpty() { - return Flowable.empty(); - } - - Flowable testFlowableErrorThrowable() { - return Flowable.error(new IllegalStateException()); - } - - Flowable testFlowableErrorCallable() { - return Flowable.error( - () -> { - throw new IllegalStateException(); - }); - } - - ImmutableList> testFlowableJust() { - return ImmutableList.of( - // RxJava2Adapter.fluxToFlowable(Flux.just(1)), - Flowable.just(1, 2)); - // RxJava2Adapter.fluxToFlowable(Flux.just(1, 2, 3))); - } - - Flowable testFlowableFilter() { - return Flowable.just(1).filter(i -> i > 2); - } - - Maybe testFlowableFirstElement() { - return Flowable.just(1).firstElement(); - } - - Flowable testFlowableFlatMap() { - Flowable.just(1).flatMap(this::exampleMethod2); - return Flowable.just(1).flatMap(i -> ImmutableSet::of); - } - - Flowable testFlowableMap() { - return Flowable.just(1).map(i -> i + 1); - } - - Single> testFlowableToMap() { - return Flowable.just(1).toMap(i -> i > 1); - } - - Flowable testFlowableSwitchIfEmptyPublisher() { - return Flowable.just(1) - .switchIfEmpty( - Flowable.error( - () -> { - throw new IllegalStateException(); - })); - } - - Maybe testMaybeAmb() { - return Maybe.amb(ImmutableList.of(Maybe.just("foo"), Maybe.just("bar"))); - } - - Maybe testMaybeAmbWith() { - return Maybe.just("foo").ambWith(Maybe.just("bar")); - } - - Maybe testMaybeAmbArray() { - return Maybe.ambArray(Maybe.just("foo"), Maybe.just("bar")); - } - - Flowable testMaybeConcatArray() { - return Maybe.concatArray(Maybe.just(1), Maybe.just(2), Maybe.empty()); - } - - Mono testMaybeDeferToMono() { - return Maybe.defer(() -> Maybe.just("test")).as(RxJava2Adapter::maybeToMono); - } - - Maybe testMaybeCastPositive() { - return Maybe.just("string").cast(String.class); - } - - Maybe testMaybeCastNegative() { - return Maybe.just("string").cast(Object.class); - } - - Maybe testMaybeWrap() { - return Maybe.wrap(Maybe.just(1)); - } - - // XXX: This should be fixed later with `Refaster.canBeCoercedTo(...)` - Maybe testMaybeFlatMapFunction() { - Maybe.just(1).flatMap(this::exampleMethod); - - return Maybe.just(1).flatMap(exampleFunction()); - } - - private io.reactivex.functions.Function> exampleFunction() { - return null; - } - - Maybe testMaybeFlatMapLambda() { - return Maybe.just(1).flatMap(i -> Maybe.just(i * 2)); - } - - Maybe testMaybeFromCallable() { - return Maybe.fromCallable( - () -> { - String s = "foo"; - return null; - }); - } - - Maybe testMaybeFromFuture() { - return Maybe.fromFuture(new CompletableFuture<>()); - } - - Maybe testMaybeFlatMapMethodReference() { - return Maybe.just(1).flatMap(this::exampleMethod); - } - - private Maybe exampleMethod(Integer x) { - return null; - } - - private Flowable exampleMethod2(Integer x) { - return null; - } - - Completable testMaybeIgnoreElement() { - return Maybe.just(1).ignoreElement(); - } - - Single testMaybeSwitchIfEmpty() { - return Maybe.just(1) - .switchIfEmpty( - Single.error( - () -> { - throw new IllegalStateException(); - })); - } - Maybe testRemoveRedundantCast() { return (Maybe) Maybe.just("foo"); } @@ -197,16 +39,4 @@ final class RxJavaToReactorTemplatesTest implements RefasterTemplateTestCase { return Mono.just(3).as(RxJava2Adapter::monoToMaybe).as(RxJava2Adapter::maybeToMono); } - - Maybe testSingleFilter() { - return Single.just(1).filter(i -> i > 2); - } - - Single testSingleFlatMapLambda() { - return Single.just(1).flatMap(i -> Single.just(i * 2)); - } - - Single testSingleMap() { - return Single.just(1).map(i -> i + 1); - } } diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaToReactorTemplatesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaToReactorTemplatesTestOutput.java index 661861b6..bea73130 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaToReactorTemplatesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/bugpatterns/RxJavaToReactorTemplatesTestOutput.java @@ -1,19 +1,12 @@ 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.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; import reactor.adapter.rxjava.RxJava2Adapter; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import tech.picnic.errorprone.refastertemplates.RxJavaToReactorTemplates; final class RxJavaToReactorTemplatesTest implements RefasterTemplateTestCase { @@ -27,227 +20,6 @@ final class RxJavaToReactorTemplatesTest implements RefasterTemplateTestCase { return Flux.just(2); } - // XXX: Can this be done with Flowable instead of Flowable - Flowable testFlowableCombineLatest() { - return RxJava2Adapter.fluxToFlowable( - Flux.combineLatest( - Flowable.just(1), - Flowable.just(2), - RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.toJdkBiFunction(Integer::sum))); - } - - // XXX: Discuss with Stephan, look at the Publisher which is of type Flowable, that won't work... - Flowable testFlowableConcatWithPublisher() { - return Flowable.just(1) - .as(RxJava2Adapter::flowableToFlux) - .concatWith(Flowable.just(2)) - .as(RxJava2Adapter::fluxToFlowable); - } - - Flowable testFlowableDefer() { - return RxJava2Adapter.fluxToFlowable( - Flux.defer(() -> Flowable.just(1).as(RxJava2Adapter::flowableToFlux))); - } - - Flowable testFlowableEmpty() { - return RxJava2Adapter.fluxToFlowable(Flux.empty()); - } - - Flowable testFlowableErrorThrowable() { - return RxJava2Adapter.fluxToFlowable(Flux.error(new IllegalStateException())); - } - - Flowable testFlowableErrorCallable() { - return RxJava2Adapter.fluxToFlowable( - Flux.error( - () -> { - throw new IllegalStateException(); - })); - } - - ImmutableList> testFlowableJust() { - return ImmutableList.of( - // RxJava2Adapter.fluxToFlowable(Flux.just(1)), - RxJava2Adapter.fluxToFlowable(Flux.just(1, 2))); - // RxJava2Adapter.fluxToFlowable(Flux.just(1, 2, 3))); - } - - Flowable testFlowableFilter() { - return Flowable.just(1) - .as(RxJava2Adapter::flowableToFlux) - .filter(i -> i > 2) - .as(RxJava2Adapter::fluxToFlowable); - } - - Maybe testFlowableFirstElement() { - return Flowable.just(1) - .as(RxJava2Adapter::flowableToFlux) - .next() - .as(RxJava2Adapter::monoToMaybe); - } - - Flowable testFlowableFlatMap() { - Flowable.just(1) - .as(RxJava2Adapter::flowableToFlux) - .flatMap(this::exampleMethod2) - .as(RxJava2Adapter::fluxToFlowable); - return Flowable.just(1) - .as(RxJava2Adapter::flowableToFlux) - .flatMap(i -> ImmutableSet::of) - .as(RxJava2Adapter::fluxToFlowable); - } - - Flowable testFlowableMap() { - return Flowable.just(1) - .as(RxJava2Adapter::flowableToFlux) - .map(i -> i + 1) - .as(RxJava2Adapter::fluxToFlowable); - } - - Single> testFlowableToMap() { - return Flowable.just(1) - .as(RxJava2Adapter::flowableToFlux) - .collectMap(i -> i > 1) - .as(RxJava2Adapter::monoToSingle); - } - - Flowable testFlowableSwitchIfEmptyPublisher() { - return Flowable.just(1) - .as(RxJava2Adapter::flowableToFlux) - .switchIfEmpty( - Flowable.error( - () -> { - throw new IllegalStateException(); - })) - .as(RxJava2Adapter::fluxToFlowable); - } - - Maybe testMaybeAmb() { - return RxJava2Adapter.monoToMaybe( - Mono.firstWithSignal( - Streams.stream(ImmutableList.of(Maybe.just("foo"), Maybe.just("bar"))) - .map(RxJava2Adapter::maybeToMono) - .collect(ImmutableList.toImmutableList()))); - } - - Maybe testMaybeAmbWith() { - return Maybe.just("foo") - .as(RxJava2Adapter::maybeToMono) - .or(Maybe.just("bar").as(RxJava2Adapter::maybeToMono)) - .as(RxJava2Adapter::monoToMaybe); - } - - Maybe testMaybeAmbArray() { - return Maybe.ambArray(Maybe.just("foo"), Maybe.just("bar")); - } - - Flowable testMaybeConcatArray() { - return Maybe.concatArray(Maybe.just(1), Maybe.just(2), Maybe.empty()); - } - - Mono testMaybeDeferToMono() { - return Mono.defer(() -> Maybe.just("test").as(RxJava2Adapter::maybeToMono)); - } - - Maybe testMaybeCastPositive() { - return Maybe.just("string"); - } - - Maybe testMaybeCastNegative() { - return Maybe.just("string").cast(Object.class); - } - - Maybe testMaybeWrap() { - return Maybe.just(1); - } - - // XXX: This should be fixed later with `Refaster.canBeCoercedTo(...)` - Maybe testMaybeFlatMapFunction() { - Maybe.just(1) - .as(RxJava2Adapter::maybeToMono) - .flatMap( - v -> - RxJava2Adapter.maybeToMono( - Maybe.wrap( - (Maybe) - RxJavaToReactorTemplates.MyUtil.convert(this::exampleMethod).apply(v)))) - .as(RxJava2Adapter::monoToMaybe); - - return Maybe.just(1) - .as(RxJava2Adapter::maybeToMono) - .flatMap( - v -> - RxJava2Adapter.maybeToMono( - Maybe.wrap( - (Maybe) - RxJavaToReactorTemplates.MyUtil.convert(exampleFunction()).apply(v)))) - .as(RxJava2Adapter::monoToMaybe); - } - - private io.reactivex.functions.Function> exampleFunction() { - return null; - } - - Maybe testMaybeFlatMapLambda() { - return Maybe.just(1) - .as(RxJava2Adapter::maybeToMono) - .flatMap(i -> Maybe.just(i * 2).as(RxJava2Adapter::maybeToMono)) - .as(RxJava2Adapter::monoToMaybe); - } - - Maybe testMaybeFromCallable() { - return RxJava2Adapter.monoToMaybe( - Mono.fromSupplier( - RxJavaToReactorTemplates.RxJava2ReactorMigrationUtil.callableAsSupplier( - () -> { - String s = "foo"; - return null; - }))); - } - - Maybe testMaybeFromFuture() { - return RxJava2Adapter.monoToMaybe(Mono.fromFuture(new CompletableFuture<>())); - } - - Maybe testMaybeFlatMapMethodReference() { - return Maybe.just(1) - .as(RxJava2Adapter::maybeToMono) - .flatMap( - v -> - RxJava2Adapter.maybeToMono( - Maybe.wrap( - (Maybe) - RxJavaToReactorTemplates.MyUtil.convert(this::exampleMethod).apply(v)))) - .as(RxJava2Adapter::monoToMaybe); - } - - private Maybe exampleMethod(Integer x) { - return null; - } - - private Flowable exampleMethod2(Integer x) { - return null; - } - - Completable testMaybeIgnoreElement() { - return Maybe.just(1) - .as(RxJava2Adapter::maybeToMono) - .ignoreElement() - .as(RxJava2Adapter::monoToCompletable); - } - - Single testMaybeSwitchIfEmpty() { - return Maybe.just(1) - .as(RxJava2Adapter::maybeToMono) - .switchIfEmpty( - Single.error( - () -> { - throw new IllegalStateException(); - }) - .as(RxJava2Adapter::singleToMono)) - .as(RxJava2Adapter::monoToSingle); - } - Maybe testRemoveRedundantCast() { return Maybe.just("foo"); } @@ -263,25 +35,4 @@ final class RxJavaToReactorTemplatesTest implements RefasterTemplateTestCase { return Mono.just(3); } - - Maybe testSingleFilter() { - return Single.just(1) - .as(RxJava2Adapter::singleToMono) - .filter(i -> i > 2) - .as(RxJava2Adapter::monoToMaybe); - } - - Single testSingleFlatMapLambda() { - return Single.just(1) - .as(RxJava2Adapter::singleToMono) - .flatMap(i -> Single.just(i * 2).as(RxJava2Adapter::singleToMono)) - .as(RxJava2Adapter::monoToSingle); - } - - Single testSingleMap() { - return Single.just(1) - .as(RxJava2Adapter::singleToMono) - .map(i -> i + 1) - .as(RxJava2Adapter::monoToSingle); - } }