Skip to content

Commit

Permalink
Introduce Flux and Stream Refaster rules to suggest filtering bef…
Browse files Browse the repository at this point in the history
…ore sorting (#393)

Fixes #386.
  • Loading branch information
CoolTomatos authored Dec 9, 2022
1 parent 3ee527f commit 17bcdb6
Show file tree
Hide file tree
Showing 15 changed files with 175 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,22 @@ DoubleStream after(Stream<T> stream, DoubleFunction<? extends DoubleStream> func
}
}

/**
* Apply {@link DoubleStream#filter(DoublePredicate)} before {@link DoubleStream#sorted()} to
* reduce the number of elements to sort.
*/
static final class DoubleStreamFilterSorted {
@BeforeTemplate
DoubleStream before(DoubleStream stream, DoublePredicate predicate) {
return stream.sorted().filter(predicate);
}

@AfterTemplate
DoubleStream after(DoubleStream stream, DoublePredicate predicate) {
return stream.filter(predicate).sorted();
}
}

/** In order to test whether a stream has any element, simply try to find one. */
static final class DoubleStreamIsEmpty {
@BeforeTemplate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ IntStream after(Stream<T> stream, IntFunction<? extends IntStream> function) {
}
}

/**
* Apply {@link IntStream#filter(IntPredicate)} before {@link IntStream#sorted()} to reduce the
* number of elements to sort.
*/
static final class IntStreamFilterSorted {
@BeforeTemplate
IntStream before(IntStream stream, IntPredicate predicate) {
return stream.sorted().filter(predicate);
}

@AfterTemplate
IntStream after(IntStream stream, IntPredicate predicate) {
return stream.filter(predicate).sorted();
}
}

/** In order to test whether a stream has any element, simply try to find one. */
static final class IntStreamIsEmpty {
@BeforeTemplate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ LongStream after(Stream<T> stream, LongFunction<? extends LongStream> function)
}
}

/**
* Apply {@link LongStream#filter(LongPredicate)} before {@link LongStream#sorted()} to reduce the
* number of elements to sort.
*/
static final class LongStreamFilterSorted {
@BeforeTemplate
LongStream before(LongStream stream, LongPredicate predicate) {
return stream.sorted().filter(predicate);
}

@AfterTemplate
LongStream after(LongStream stream, LongPredicate predicate) {
return stream.filter(predicate).sorted();
}
}

/** In order to test whether a stream has any element, simply try to find one. */
static final class LongStreamIsEmpty {
@BeforeTemplate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.google.errorprone.refaster.annotation.Placeholder;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import java.time.Duration;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.Callable;
Expand Down Expand Up @@ -1062,6 +1063,38 @@ Flux<T> after(Flux<T> flux, Class<? extends Throwable> clazz, T fallbackValue) {
}
}

/**
* Apply {@link Flux#filter(Predicate)} before {@link Flux#sort()} to reduce the number of
* elements to sort.
*/
static final class FluxFilterSort<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux, Predicate<? super T> predicate) {
return flux.sort().filter(predicate);
}

@AfterTemplate
Flux<T> after(Flux<T> flux, Predicate<? super T> predicate) {
return flux.filter(predicate).sort();
}
}

/**
* Apply {@link Flux#filter(Predicate)} before {@link Flux#sort(Comparator)} to reduce the number
* of elements to sort.
*/
static final class FluxFilterSortWithComparator<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux, Predicate<? super T> predicate, Comparator<? super T> comparator) {
return flux.sort(comparator).filter(predicate);
}

@AfterTemplate
Flux<T> after(Flux<T> flux, Predicate<? super T> predicate, Comparator<? super T> comparator) {
return flux.filter(predicate).sort(comparator);
}
}

/** Prefer {@link reactor.util.context.Context#empty()}} over more verbose alternatives. */
// XXX: Consider introducing an `IsEmpty` matcher that identifies a wide range of guaranteed-empty
// `Collection` and `Map` expressions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,40 @@ Stream<R> after(Stream<T> stream, Function<? super S, ? extends Stream<? extends
}
}

/**
* Apply {@link Stream#filter(Predicate)} before {@link Stream#sorted()} to reduce the number of
* elements to sort.
*/
static final class StreamFilterSorted<T> {
@BeforeTemplate
Stream<T> before(Stream<T> stream, Predicate<? super T> predicate) {
return stream.sorted().filter(predicate);
}

@AfterTemplate
Stream<T> after(Stream<T> stream, Predicate<? super T> predicate) {
return stream.filter(predicate).sorted();
}
}

/**
* Apply {@link Stream#filter(Predicate)} before {@link Stream#sorted(Comparator)} to reduce the
* number of elements to sort.
*/
static final class StreamFilterSortedWithComparator<T> {
@BeforeTemplate
Stream<T> before(
Stream<T> stream, Predicate<? super T> predicate, Comparator<? super T> comparator) {
return stream.sorted(comparator).filter(predicate);
}

@AfterTemplate
Stream<T> after(
Stream<T> stream, Predicate<? super T> predicate, Comparator<? super T> comparator) {
return stream.filter(predicate).sorted(comparator);
}
}

/**
* Where possible, clarify that a mapping operation will be applied only to a single stream
* element.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ DoubleStream testFlatMapOuterStreamAfterFlatMapToDouble() {
return Stream.of(1).flatMapToDouble(v -> DoubleStream.of(v * v).flatMap(DoubleStream::of));
}

DoubleStream testDoubleStreamFilterSorted() {
return DoubleStream.of(1, 4, 3, 2).sorted().filter(d -> d % 2 == 0);
}

ImmutableSet<Boolean> testDoubleStreamIsEmpty() {
return ImmutableSet.of(
DoubleStream.of(1).count() == 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ DoubleStream testFlatMapOuterStreamAfterFlatMapToDouble() {
return Stream.of(1).flatMapToDouble(v -> DoubleStream.of(v * v)).flatMap(DoubleStream::of);
}

DoubleStream testDoubleStreamFilterSorted() {
return DoubleStream.of(1, 4, 3, 2).filter(d -> d % 2 == 0).sorted();
}

ImmutableSet<Boolean> testDoubleStreamIsEmpty() {
return ImmutableSet.of(
DoubleStream.of(1).findAny().isEmpty(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ IntStream testFlatMapOuterStreamAfterFlatMapToInt() {
return Stream.of(1).flatMapToInt(v -> IntStream.of(v * v).flatMap(IntStream::of));
}

IntStream testIntStreamFilterSorted() {
return IntStream.of(1, 4, 3, 2).sorted().filter(i -> i % 2 == 0);
}

ImmutableSet<Boolean> testIntStreamIsEmpty() {
return ImmutableSet.of(
IntStream.of(1).count() == 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ IntStream testFlatMapOuterStreamAfterFlatMapToInt() {
return Stream.of(1).flatMapToInt(v -> IntStream.of(v * v)).flatMap(IntStream::of);
}

IntStream testIntStreamFilterSorted() {
return IntStream.of(1, 4, 3, 2).filter(i -> i % 2 == 0).sorted();
}

ImmutableSet<Boolean> testIntStreamIsEmpty() {
return ImmutableSet.of(
IntStream.of(1).findAny().isEmpty(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ LongStream testFlatMapOuterStreamAfterFlatMapToLong() {
return Stream.of(1).flatMapToLong(v -> LongStream.of(v * v).flatMap(LongStream::of));
}

LongStream testLongStreamFilterSorted() {
return LongStream.of(1, 4, 3, 2).sorted().filter(l -> l % 2 == 0);
}

ImmutableSet<Boolean> testLongStreamIsEmpty() {
return ImmutableSet.of(
LongStream.of(1).count() == 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ LongStream testFlatMapOuterStreamAfterFlatMapToLong() {
return Stream.of(1).flatMapToLong(v -> LongStream.of(v * v)).flatMap(LongStream::of);
}

LongStream testLongStreamFilterSorted() {
return LongStream.of(1, 4, 3, 2).filter(l -> l % 2 == 0).sorted();
}

ImmutableSet<Boolean> testLongStreamIsEmpty() {
return ImmutableSet.of(
LongStream.of(1).findAny().isEmpty(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tech.picnic.errorprone.refasterrules;

import static java.util.Comparator.reverseOrder;
import static java.util.function.Function.identity;
import static org.assertj.core.api.Assertions.assertThat;

Expand Down Expand Up @@ -327,6 +328,14 @@ Flux<Integer> testFluxOnErrorReturn() {
return Flux.just(1).onErrorReturn(IllegalArgumentException.class::isInstance, 2);
}

Flux<Integer> testFluxFilterSort() {
return Flux.just(1, 4, 3, 2).sort().filter(i -> i % 2 == 0);
}

Flux<Integer> testFluxFilterSortWithComparator() {
return Flux.just(1, 4, 3, 2).sort(reverseOrder()).filter(i -> i % 2 == 0);
}

ImmutableSet<Context> testContextEmpty() {
return ImmutableSet.of(Context.of(new HashMap<>()), Context.of(ImmutableMap.of()));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tech.picnic.errorprone.refasterrules;

import static com.google.common.collect.MoreCollectors.toOptional;
import static java.util.Comparator.reverseOrder;
import static java.util.function.Function.identity;
import static org.assertj.core.api.Assertions.assertThat;
import static reactor.function.TupleUtils.function;
Expand Down Expand Up @@ -322,6 +323,14 @@ Flux<Integer> testFluxOnErrorReturn() {
return Flux.just(1).onErrorReturn(IllegalArgumentException.class, 2);
}

Flux<Integer> testFluxFilterSort() {
return Flux.just(1, 4, 3, 2).filter(i -> i % 2 == 0).sort();
}

Flux<Integer> testFluxFilterSortWithComparator() {
return Flux.just(1, 4, 3, 2).filter(i -> i % 2 == 0).sort(reverseOrder());
}

ImmutableSet<Context> testContextEmpty() {
return ImmutableSet.of(Context.empty(), Context.empty());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
final class StreamRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(Objects.class, Streams.class, not(null), reverseOrder());
return ImmutableSet.of(Objects.class, Streams.class, not(null));
}

String testJoining() {
Expand Down Expand Up @@ -56,6 +56,14 @@ Stream<Integer> testFlatMapOuterStreamAfterFlatMap() {
return Stream.of("foo").flatMap(v -> Stream.of(v.length()).flatMap(Stream::of));
}

Stream<Integer> testStreamFilterSorted() {
return Stream.of(1, 4, 3, 2).sorted().filter(i -> i % 2 == 0);
}

Stream<Integer> testStreamFilterSortedWithComparator() {
return Stream.of(1, 4, 3, 2).sorted(reverseOrder()).filter(i -> i % 2 == 0);
}

ImmutableSet<Optional<Integer>> testStreamMapFirst() {
return ImmutableSet.of(
Stream.of("foo").map(s -> s.length()).findFirst(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
final class StreamRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<?> elidedTypesAndStaticImports() {
return ImmutableSet.of(Objects.class, Streams.class, not(null), reverseOrder());
return ImmutableSet.of(Objects.class, Streams.class, not(null));
}

String testJoining() {
Expand Down Expand Up @@ -57,6 +57,14 @@ Stream<Integer> testFlatMapOuterStreamAfterFlatMap() {
return Stream.of("foo").flatMap(v -> Stream.of(v.length())).flatMap(Stream::of);
}

Stream<Integer> testStreamFilterSorted() {
return Stream.of(1, 4, 3, 2).filter(i -> i % 2 == 0).sorted();
}

Stream<Integer> testStreamFilterSortedWithComparator() {
return Stream.of(1, 4, 3, 2).filter(i -> i % 2 == 0).sorted(reverseOrder());
}

ImmutableSet<Optional<Integer>> testStreamMapFirst() {
return ImmutableSet.of(
Stream.of("foo").findFirst().map(s -> s.length()),
Expand Down

0 comments on commit 17bcdb6

Please sign in to comment.