diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ImmutableSetRules.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ImmutableSetRules.java index f4d5ba78b7..628bb1cf6b 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ImmutableSetRules.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ImmutableSetRules.java @@ -4,8 +4,11 @@ import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; +import static java.util.function.Predicate.not; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; import com.google.common.collect.Sets.SetView; import com.google.common.collect.Streams; import com.google.errorprone.refaster.Refaster; @@ -15,6 +18,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; +import java.util.Map; import java.util.Set; import java.util.stream.Stream; import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation; @@ -211,4 +215,116 @@ ImmutableSet after(T e1, T e2, T e3, T e4, T e5) { return ImmutableSet.of(e1, e2, e3, e4, e5); } } + + /** + * Prefer an immutable copy of {@link Sets#difference(Set, Set)} over more contrived alternatives. + */ + static final class SetsDifference { + @BeforeTemplate + ImmutableSet before(Set set1, Set set2) { + return set1.stream() + .filter(Refaster.anyOf(not(set2::contains), e -> !set2.contains(e))) + .collect(toImmutableSet()); + } + + @AfterTemplate + ImmutableSet after(Set set1, Set set2) { + return Sets.difference(set1, set2).immutableCopy(); + } + } + + /** + * Prefer an immutable copy of {@link Sets#difference(Set, Set)} over more contrived alternatives. + */ + static final class SetsDifferenceMap { + @BeforeTemplate + ImmutableSet before(Set set, Map map) { + return set.stream() + .filter(Refaster.anyOf(not(map::containsKey), e -> !map.containsKey(e))) + .collect(toImmutableSet()); + } + + @AfterTemplate + ImmutableSet after(Set set, Map map) { + return Sets.difference(set, map.keySet()).immutableCopy(); + } + } + + /** + * Prefer an immutable copy of {@link Sets#difference(Set, Set)} over more contrived alternatives. + */ + static final class SetsDifferenceMultimap { + @BeforeTemplate + ImmutableSet before(Set set, Multimap multimap) { + return set.stream() + .filter(Refaster.anyOf(not(multimap::containsKey), e -> !multimap.containsKey(e))) + .collect(toImmutableSet()); + } + + @AfterTemplate + ImmutableSet after(Set set, Multimap multimap) { + return Sets.difference(set, multimap.keySet()).immutableCopy(); + } + } + + /** + * Prefer an immutable copy of {@link Sets#intersection(Set, Set)} over more contrived + * alternatives. + */ + static final class SetsIntersection { + @BeforeTemplate + ImmutableSet before(Set set1, Set set2) { + return set1.stream().filter(set2::contains).collect(toImmutableSet()); + } + + @AfterTemplate + ImmutableSet after(Set set1, Set set2) { + return Sets.intersection(set1, set2).immutableCopy(); + } + } + + /** + * Prefer an immutable copy of {@link Sets#intersection(Set, Set)} over more contrived + * alternatives. + */ + static final class SetsIntersectionMap { + @BeforeTemplate + ImmutableSet before(Set set, Map map) { + return set.stream().filter(map::containsKey).collect(toImmutableSet()); + } + + @AfterTemplate + ImmutableSet after(Set set, Map map) { + return Sets.intersection(set, map.keySet()).immutableCopy(); + } + } + + /** + * Prefer an immutable copy of {@link Sets#intersection(Set, Set)} over more contrived + * alternatives. + */ + static final class SetsIntersectionMultimap { + @BeforeTemplate + ImmutableSet before(Set set, Multimap multimap) { + return set.stream().filter(multimap::containsKey).collect(toImmutableSet()); + } + + @AfterTemplate + ImmutableSet after(Set set, Multimap multimap) { + return Sets.intersection(set, multimap.keySet()).immutableCopy(); + } + } + + /** Prefer an immutable copy of {@link Sets#union(Set, Set)} over more contrived alternatives. */ + static final class SetsUnion { + @BeforeTemplate + ImmutableSet before(Set set1, Set set2) { + return Stream.concat(set1.stream(), set2.stream()).collect(toImmutableSet()); + } + + @AfterTemplate + ImmutableSet after(Set set1, Set set2) { + return Sets.union(set1, set2).immutableCopy(); + } + } } diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableSetRulesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableSetRulesTestInput.java index 9512cdea64..53e7c41556 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableSetRulesTestInput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableSetRulesTestInput.java @@ -1,9 +1,12 @@ package tech.picnic.errorprone.refasterrules; import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static java.util.function.Predicate.not; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Sets; import com.google.common.collect.Streams; import java.util.Arrays; @@ -15,7 +18,7 @@ final class ImmutableSetRulesTest implements RefasterRuleCollectionTestCase { @Override public ImmutableSet elidedTypesAndStaticImports() { - return ImmutableSet.of(Arrays.class, Collections.class, Streams.class); + return ImmutableSet.of(Arrays.class, Collections.class, Streams.class, not(null)); } ImmutableSet.Builder testImmutableSetBuilder() { @@ -72,4 +75,57 @@ Set testImmutableSetOf4() { Set testImmutableSetOf5() { return Set.of(1, 2, 3, 4, 5); } + + ImmutableSet> testSetsDifference() { + return ImmutableSet.of( + ImmutableSet.of(1).stream() + .filter(not(ImmutableSet.of(2)::contains)) + .collect(toImmutableSet()), + ImmutableSet.of(3).stream() + .filter(v -> !ImmutableSet.of(4).contains(v)) + .collect(toImmutableSet())); + } + + ImmutableSet> testSetsDifferenceMap() { + return ImmutableSet.of( + ImmutableSet.of(1).stream() + .filter(not(ImmutableMap.of(2, 3)::containsKey)) + .collect(toImmutableSet()), + ImmutableSet.of(4).stream() + .filter(v -> !ImmutableMap.of(5, 6).containsKey(v)) + .collect(toImmutableSet())); + } + + ImmutableSet> testSetsDifferenceMultimap() { + return ImmutableSet.of( + ImmutableSet.of(1).stream() + .filter(not(ImmutableSetMultimap.of(2, 3)::containsKey)) + .collect(toImmutableSet()), + ImmutableSet.of(4).stream() + .filter(v -> !ImmutableSetMultimap.of(5, 6).containsKey(v)) + .collect(toImmutableSet())); + } + + ImmutableSet testSetsIntersection() { + return ImmutableSet.of(1).stream() + .filter(ImmutableSet.of(2)::contains) + .collect(toImmutableSet()); + } + + ImmutableSet testSetsIntersectionMap() { + return ImmutableSet.of(1).stream() + .filter(ImmutableMap.of(2, 3)::containsKey) + .collect(toImmutableSet()); + } + + ImmutableSet testSetsIntersectionMultimap() { + return ImmutableSet.of(1).stream() + .filter(ImmutableSetMultimap.of(2, 3)::containsKey) + .collect(toImmutableSet()); + } + + ImmutableSet testSetsUnion() { + return Stream.concat(ImmutableSet.of(1).stream(), ImmutableSet.of(2).stream()) + .collect(toImmutableSet()); + } } diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableSetRulesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableSetRulesTestOutput.java index b081feee13..74a6c9d67e 100644 --- a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableSetRulesTestOutput.java +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableSetRulesTestOutput.java @@ -1,9 +1,12 @@ package tech.picnic.errorprone.refasterrules; import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static java.util.function.Predicate.not; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Sets; import com.google.common.collect.Streams; import java.util.Arrays; @@ -15,7 +18,7 @@ final class ImmutableSetRulesTest implements RefasterRuleCollectionTestCase { @Override public ImmutableSet elidedTypesAndStaticImports() { - return ImmutableSet.of(Arrays.class, Collections.class, Streams.class); + return ImmutableSet.of(Arrays.class, Collections.class, Streams.class, not(null)); } ImmutableSet.Builder testImmutableSetBuilder() { @@ -67,4 +70,40 @@ Set testImmutableSetOf4() { Set testImmutableSetOf5() { return ImmutableSet.of(1, 2, 3, 4, 5); } + + ImmutableSet> testSetsDifference() { + return ImmutableSet.of( + Sets.difference(ImmutableSet.of(1), ImmutableSet.of(2)).immutableCopy(), + Sets.difference(ImmutableSet.of(3), ImmutableSet.of(4)).immutableCopy()); + } + + ImmutableSet> testSetsDifferenceMap() { + return ImmutableSet.of( + Sets.difference(ImmutableSet.of(1), ImmutableMap.of(2, 3).keySet()).immutableCopy(), + Sets.difference(ImmutableSet.of(4), ImmutableMap.of(5, 6).keySet()).immutableCopy()); + } + + ImmutableSet> testSetsDifferenceMultimap() { + return ImmutableSet.of( + Sets.difference(ImmutableSet.of(1), ImmutableSetMultimap.of(2, 3).keySet()).immutableCopy(), + Sets.difference(ImmutableSet.of(4), ImmutableSetMultimap.of(5, 6).keySet()) + .immutableCopy()); + } + + ImmutableSet testSetsIntersection() { + return Sets.intersection(ImmutableSet.of(1), ImmutableSet.of(2)).immutableCopy(); + } + + ImmutableSet testSetsIntersectionMap() { + return Sets.intersection(ImmutableSet.of(1), ImmutableMap.of(2, 3).keySet()).immutableCopy(); + } + + ImmutableSet testSetsIntersectionMultimap() { + return Sets.intersection(ImmutableSet.of(1), ImmutableSetMultimap.of(2, 3).keySet()) + .immutableCopy(); + } + + ImmutableSet testSetsUnion() { + return Sets.union(ImmutableSet.of(1), ImmutableSet.of(2)).immutableCopy(); + } }