tech.picnic.errorprone.refasterrules.ImmutableSetRules Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of error-prone-contrib Show documentation
Show all versions of error-prone-contrib Show documentation
Extra Error Prone plugins by Picnic.
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
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;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
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;
/** Refaster rules related to expressions dealing with {@link ImmutableSet}s. */
@OnlineDocumentation
final class ImmutableSetRules {
private ImmutableSetRules() {}
/** Prefer {@link ImmutableSet#builder()} over the associated constructor. */
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
// https://github.com/google/error-prone/pull/2706.
static final class ImmutableSetBuilder {
@BeforeTemplate
ImmutableSet.Builder before() {
return new ImmutableSet.Builder<>();
}
@AfterTemplate
ImmutableSet.Builder after() {
return ImmutableSet.builder();
}
}
/** Prefer {@link ImmutableSet#copyOf(Iterable)} and variants over more contrived alternatives. */
static final class IterableToImmutableSet {
@BeforeTemplate
ImmutableSet before(T[] iterable) {
return Refaster.anyOf(
ImmutableSet.builder().add(iterable).build(),
Arrays.stream(iterable).collect(toImmutableSet()));
}
@BeforeTemplate
ImmutableSet before(Iterator iterable) {
return Refaster.anyOf(
ImmutableSet.builder().addAll(iterable).build(),
Streams.stream(iterable).collect(toImmutableSet()));
}
@BeforeTemplate
ImmutableSet before(Iterable iterable) {
return Refaster.anyOf(
ImmutableSet.builder().addAll(iterable).build(),
Streams.stream(iterable).collect(toImmutableSet()));
}
@BeforeTemplate
ImmutableSet before(Collection iterable) {
return iterable.stream().collect(toImmutableSet());
}
@AfterTemplate
ImmutableSet after(Iterable iterable) {
return ImmutableSet.copyOf(iterable);
}
}
/** Prefer {@link ImmutableSet#toImmutableSet()} over less idiomatic alternatives. */
static final class StreamToImmutableSet {
@BeforeTemplate
ImmutableSet before(Stream stream) {
return Refaster.anyOf(
ImmutableSet.copyOf(stream.iterator()), stream.distinct().collect(toImmutableSet()));
}
@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
ImmutableSet after(Stream stream) {
return stream.collect(toImmutableSet());
}
}
/** Prefer {@link SetView#immutableCopy()} over the more verbose alternative. */
static final class ImmutableSetCopyOfSetView {
@BeforeTemplate
ImmutableSet before(SetView set) {
return ImmutableSet.copyOf(set);
}
@AfterTemplate
ImmutableSet after(SetView set) {
return set.immutableCopy();
}
}
/**
* Prefer {@link ImmutableSet#of()} over more contrived alternatives or alternatives that don't
* communicate the immutability of the resulting set at the type level.
*/
// XXX: The `Stream` variant may be too contrived to warrant inclusion. Review its usage if/when
// this and similar Refaster rules are replaced with an Error Prone check.
static final class ImmutableSetOf {
@BeforeTemplate
Set before() {
return Refaster.anyOf(
ImmutableSet.builder().build(),
Stream.empty().collect(toImmutableSet()),
emptySet(),
Set.of());
}
@AfterTemplate
ImmutableSet after() {
return ImmutableSet.of();
}
}
/**
* Prefer {@link ImmutableSet#of(Object)} over more contrived alternatives or alternatives that
* don't communicate the immutability of the resulting set at the type level.
*/
// XXX: Note that the replacement of `Collections#singleton` is incorrect for nullable elements.
static final class ImmutableSetOf1 {
@BeforeTemplate
Set before(T e1) {
return Refaster.anyOf(ImmutableSet.builder().add(e1).build(), singleton(e1), Set.of(e1));
}
@AfterTemplate
ImmutableSet after(T e1) {
return ImmutableSet.of(e1);
}
}
/**
* Prefer {@link ImmutableSet#of(Object, Object)} over alternatives that don't communicate the
* immutability of the resulting set at the type level.
*/
// XXX: Consider writing an Error Prone check that also flags straightforward
// `ImmutableSet.builder()` usages.
static final class ImmutableSetOf2 {
@BeforeTemplate
Set before(T e1, T e2) {
return Set.of(e1, e2);
}
@AfterTemplate
ImmutableSet after(T e1, T e2) {
return ImmutableSet.of(e1, e2);
}
}
/**
* Prefer {@link ImmutableSet#of(Object, Object, Object)} over alternatives that don't communicate
* the immutability of the resulting set at the type level.
*/
// XXX: Consider writing an Error Prone check that also flags straightforward
// `ImmutableSet.builder()` usages.
static final class ImmutableSetOf3 {
@BeforeTemplate
Set before(T e1, T e2, T e3) {
return Set.of(e1, e2, e3);
}
@AfterTemplate
ImmutableSet after(T e1, T e2, T e3) {
return ImmutableSet.of(e1, e2, e3);
}
}
/**
* Prefer {@link ImmutableSet#of(Object, Object, Object, Object)} over alternatives that don't
* communicate the immutability of the resulting set at the type level.
*/
// XXX: Consider writing an Error Prone check that also flags straightforward
// `ImmutableSet.builder()` usages.
static final class ImmutableSetOf4 {
@BeforeTemplate
Set before(T e1, T e2, T e3, T e4) {
return Set.of(e1, e2, e3, e4);
}
@AfterTemplate
ImmutableSet after(T e1, T e2, T e3, T e4) {
return ImmutableSet.of(e1, e2, e3, e4);
}
}
/**
* Prefer {@link ImmutableSet#of(Object, Object, Object, Object, Object)} over alternatives that
* don't communicate the immutability of the resulting set at the type level.
*/
// XXX: Consider writing an Error Prone check that also flags straightforward
// `ImmutableSet.builder()` usages.
static final class ImmutableSetOf5 {
@BeforeTemplate
Set before(T e1, T e2, T e3, T e4, T e5) {
return Set.of(e1, e2, e3, e4, e5);
}
@AfterTemplate
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();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy