From cffff17c28c78bdeb20316aff146d89d478ac200 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Sun, 10 Dec 2023 11:08:02 +0100 Subject: [PATCH] WIP: Matching fails, not sure why --- .../refasterrules/ReactorRules.java | 41 +++++++++++++++++++ .../refasterrules/ReactorRulesTestInput.java | 18 ++++++++ .../refasterrules/ReactorRulesTestOutput.java | 14 +++++++ 3 files changed, 73 insertions(+) diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ReactorRules.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ReactorRules.java index 467c526f..9d1a0752 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ReactorRules.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ReactorRules.java @@ -728,6 +728,27 @@ final class ReactorRules { } } + /** + * Prefer {@link Mono#map(Function)} over alternatives that unnecessarily create and collect a + * {@link Flux}. + */ + // XXX: This rule assumes that any matched `Collector` does not filter or reorder elements after + // application of the matched `Function`. + // XXX: The `function` parameter is not matched, unless `I` is changed to `Iterable`, + // which would make the rule incorrect. + static final class MonoMapToIterable> { + @BeforeTemplate + Mono before( + Mono mono, Function function, Collector collector) { + return mono.flatMapIterable(function).collect(collector); + } + + @AfterTemplate + Mono after(Mono mono, Function function) { + return mono.map(function); + } + } + /** * Prefer {@link Flux#map(Function)} over alternatives that unnecessarily require an inner * subscription. @@ -1694,6 +1715,26 @@ final class ReactorRules { } } + /** + * Prefer {@link Flux#singleOrEmpty()} over {@link Flux#next()} when the {@link Flux} emits at + * most one element. + */ + // XXX: This is a special case of a more general rule. Consider introducing an Error Prone check + // for this. + // XXX: The `transformer` parameter isn't matched, unless the signature is changed to `? extends + // Publisher`, which would make the rule incorrect. + static final class FluxTransformToMonoSingleOrEmpty { + @BeforeTemplate + Mono before(Flux flux, Function, ? extends Mono> transformer) { + return flux.transform(transformer).next(); + } + + @AfterTemplate + Mono after(Flux flux, Function, ? extends Mono> transformer) { + return flux.transform(transformer).singleOrEmpty(); + } + } + /** Prefer {@link reactor.util.context.Context#empty()}} over more verbose alternatives. */ // XXX: Introduce Refaster rules or a `BugChecker` that maps `(Immutable)Map.of(k, v)` to // `Context.of(k, v)` and likewise for multi-pair overloads. diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ReactorRulesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ReactorRulesTestInput.java index 25e0f514..215a8ac1 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ReactorRulesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ReactorRulesTestInput.java @@ -1,6 +1,8 @@ package tech.picnic.errorprone.refasterrules; import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet; import static com.google.common.collect.MoreCollectors.toOptional; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.reverseOrder; @@ -14,8 +16,10 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -262,6 +266,16 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase { Mono.just("bar").flatMap(s -> Mono.just(s.substring(1)))); } + ImmutableSet>> testMonoMapToIterable() { + return ImmutableSet.of( + Mono.just("foo").flatMapIterable(ImmutableSet::of).collect(toImmutableSet()), + Mono.just("bar").flatMapIterable(ImmutableSortedSet::of).collect(toImmutableSet()), + Mono.just("baz") + .flatMapIterable(ImmutableSet::of) + .collect(toImmutableSortedSet(naturalOrder())), + Mono.just("qux").flatMapIterable(Arrays::asList).collect(toCollection(ArrayList::new))); + } + ImmutableSet> testFluxMap() { return ImmutableSet.of( Flux.just(1).concatMap(n -> Mono.just(n)), @@ -571,6 +585,10 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase { MathFlux.min(Flux.just(1), reverseOrder()), MathFlux.max(Flux.just(2), naturalOrder())); } + Mono testFluxTransformToMonoSingleOrEmpty() { + return Flux.just("foo").transform(Flux::next).next(); + } + ImmutableSet testContextEmpty() { return ImmutableSet.of(Context.of(ImmutableMap.of()), Context.of(ImmutableMap.of(1, 2))); } diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ReactorRulesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ReactorRulesTestOutput.java index dd25437f..4a5dd78f 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ReactorRulesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ReactorRulesTestOutput.java @@ -16,8 +16,10 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -263,6 +265,14 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase { return ImmutableSet.of(Mono.just("foo").map(s -> s), Mono.just("bar").map(s -> s.substring(1))); } + ImmutableSet>> testMonoMapToIterable() { + return ImmutableSet.of( + Mono.just("foo").map(ImmutableSet::of), + Mono.just("bar").map(ImmutableSortedSet::of), + Mono.just("baz").map(ImmutableSet::of), + Mono.just("qux").map(Arrays::asList)); + } + ImmutableSet> testFluxMap() { return ImmutableSet.of( Flux.just(1).map(n -> n), @@ -560,6 +570,10 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase { return ImmutableSet.of(MathFlux.max(Flux.just(1)), MathFlux.max(Flux.just(2))); } + Mono testFluxTransformToMonoSingleOrEmpty() { + return Flux.just("foo").transform(Flux::next).singleOrEmpty(); + } + ImmutableSet testContextEmpty() { return ImmutableSet.of(Context.empty(), Context.of(ImmutableMap.of(1, 2))); }