From 1f71ccccf7af27862072b01e48e8db64a7d2791e Mon Sep 17 00:00:00 2001 From: Giovanni Zotta Date: Sun, 11 Feb 2024 12:01:33 +0100 Subject: [PATCH] Extend `StreamIsEmpty` Refaster rule (#1025) --- .../errorprone/refasterrules/StreamRules.java | 14 ++++++++++--- .../refasterrules/StreamRulesTestInput.java | 21 +++++++++++++++++-- .../refasterrules/StreamRulesTestOutput.java | 20 ++++++++++++++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/StreamRules.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/StreamRules.java index be5a2b4709..5ab7f9de53 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/StreamRules.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/StreamRules.java @@ -4,6 +4,7 @@ import static java.util.Comparator.naturalOrder; import static java.util.Comparator.reverseOrder; import static java.util.function.Predicate.not; +import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.filtering; import static java.util.stream.Collectors.flatMapping; @@ -37,6 +38,7 @@ import java.util.DoubleSummaryStatistics; import java.util.IntSummaryStatistics; import java.util.LongSummaryStatistics; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.BinaryOperator; @@ -254,15 +256,21 @@ Optional after(Stream stream, Function function) { // XXX: This rule assumes that any matched `Collector` does not perform any filtering. // (Perhaps we could add a `@Matches` guard that validates that the collector expression does not // contain a `Collectors#filtering` call. That'd still not be 100% accurate, though.) - static final class StreamIsEmpty { + static final class StreamIsEmpty, M extends Map> { @BeforeTemplate - boolean before(Stream stream, Collector> collector) { + boolean before(Stream stream, Collector collector) { return Refaster.anyOf( stream.count() == 0, stream.count() <= 0, stream.count() < 1, stream.findFirst().isEmpty(), - stream.collect(collector).isEmpty()); + stream.collect(collector).isEmpty(), + stream.collect(collectingAndThen(collector, C::isEmpty))); + } + + @BeforeTemplate + boolean before2(Stream stream, Collector collector) { + return stream.collect(collectingAndThen(collector, M::isEmpty)); } @AfterTemplate diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StreamRulesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StreamRulesTestInput.java index ed6bbc3c19..01cd245601 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StreamRulesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StreamRulesTestInput.java @@ -1,10 +1,13 @@ package tech.picnic.errorprone.refasterrules; +import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static java.util.Comparator.comparingInt; import static java.util.Comparator.reverseOrder; import static java.util.function.Function.identity; import static java.util.function.Predicate.not; +import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.filtering; import static java.util.stream.Collectors.flatMapping; @@ -21,11 +24,14 @@ import static java.util.stream.Collectors.summingLong; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Streams; import java.util.DoubleSummaryStatistics; import java.util.IntSummaryStatistics; +import java.util.List; import java.util.LongSummaryStatistics; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.Function; @@ -38,8 +44,12 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase { public ImmutableSet elidedTypesAndStaticImports() { return ImmutableSet.of( ImmutableList.class, + ImmutableMap.class, + List.class, + Map.class, Objects.class, Streams.class, + collectingAndThen(null, null), counting(), filtering(null, null), flatMapping(null, null), @@ -54,7 +64,9 @@ public ImmutableSet elidedTypesAndStaticImports() { summarizingLong(null), summingDouble(null), summingInt(null), - summingLong(null)); + summingLong(null), + toImmutableList(), + toImmutableMap(null, null)); } String testJoining() { @@ -114,7 +126,12 @@ ImmutableSet testStreamIsEmpty() { Stream.of(2).count() <= 0, Stream.of(3).count() < 1, Stream.of(4).findFirst().isEmpty(), - Stream.of(5).collect(toImmutableSet()).isEmpty()); + Stream.of(5).collect(toImmutableSet()).isEmpty(), + Stream.of(6).collect(collectingAndThen(toImmutableList(), List::isEmpty)), + Stream.of(7).collect(collectingAndThen(toImmutableList(), ImmutableList::isEmpty)), + Stream.of(8).collect(collectingAndThen(toImmutableMap(k -> k, v -> v), Map::isEmpty)), + Stream.of(9) + .collect(collectingAndThen(toImmutableMap(k -> k, v -> v), ImmutableMap::isEmpty))); } ImmutableSet testStreamIsNotEmpty() { diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StreamRulesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StreamRulesTestOutput.java index 9ced3b0dcf..0d865cba59 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StreamRulesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/StreamRulesTestOutput.java @@ -1,11 +1,14 @@ package tech.picnic.errorprone.refasterrules; +import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static java.util.Comparator.comparingInt; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.reverseOrder; import static java.util.function.Function.identity; import static java.util.function.Predicate.not; +import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.filtering; import static java.util.stream.Collectors.flatMapping; @@ -22,12 +25,15 @@ import static java.util.stream.Collectors.summingLong; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Streams; import java.util.Arrays; import java.util.DoubleSummaryStatistics; import java.util.IntSummaryStatistics; +import java.util.List; import java.util.LongSummaryStatistics; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.Function; @@ -40,8 +46,12 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase { public ImmutableSet elidedTypesAndStaticImports() { return ImmutableSet.of( ImmutableList.class, + ImmutableMap.class, + List.class, + Map.class, Objects.class, Streams.class, + collectingAndThen(null, null), counting(), filtering(null, null), flatMapping(null, null), @@ -56,7 +66,9 @@ public ImmutableSet elidedTypesAndStaticImports() { summarizingLong(null), summingDouble(null), summingInt(null), - summingLong(null)); + summingLong(null), + toImmutableList(), + toImmutableMap(null, null)); } String testJoining() { @@ -115,7 +127,11 @@ ImmutableSet testStreamIsEmpty() { Stream.of(2).findAny().isEmpty(), Stream.of(3).findAny().isEmpty(), Stream.of(4).findAny().isEmpty(), - Stream.of(5).findAny().isEmpty()); + Stream.of(5).findAny().isEmpty(), + Stream.of(6).findAny().isEmpty(), + Stream.of(7).findAny().isEmpty(), + Stream.of(8).findAny().isEmpty(), + Stream.of(9).findAny().isEmpty()); } ImmutableSet testStreamIsNotEmpty() {