diff --git a/documentation-support/src/test/java/tech/picnic/errorprone/documentation/DocumentationGeneratorTaskListenerTest.java b/documentation-support/src/test/java/tech/picnic/errorprone/documentation/DocumentationGeneratorTaskListenerTest.java index 685c7cd6f2..4e9d175a47 100644 --- a/documentation-support/src/test/java/tech/picnic/errorprone/documentation/DocumentationGeneratorTaskListenerTest.java +++ b/documentation-support/src/test/java/tech/picnic/errorprone/documentation/DocumentationGeneratorTaskListenerTest.java @@ -10,7 +10,6 @@ import com.google.auto.service.AutoService; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.google.common.collect.Streams; import com.google.errorprone.VisitorState; @@ -41,7 +40,8 @@ void readOnlyFileSystemWindows(@TempDir Path outputDirectory) throws IOException entry -> AclEntry.newBuilder(entry) .setPermissions( - Sets.difference(entry.permissions(), ImmutableSet.of(ADD_SUBDIRECTORY))) + Sets.difference( + entry.permissions(), Sets.immutableEnumSet(ADD_SUBDIRECTORY))) .build()) .collect(toImmutableList())); diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/JUnitClassModifiers.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/JUnitClassModifiers.java index 8cfd59cd2a..372adebb71 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/JUnitClassModifiers.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/JUnitClassModifiers.java @@ -16,7 +16,7 @@ import static tech.picnic.errorprone.utils.MoreMatchers.hasMetaAnnotation; import com.google.auto.service.AutoService; -import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; import com.google.errorprone.BugPattern; import com.google.errorprone.VisitorState; import com.google.errorprone.bugpatterns.BugChecker; @@ -70,7 +70,7 @@ public Description matchClass(ClassTree tree, VisitorState state) { SuggestedFixes.removeModifiers( tree.getModifiers(), state, - ImmutableSet.of(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC)) + Sets.immutableEnumSet(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC)) .ifPresent(fixBuilder::merge); if (!HAS_SPRING_CONFIGURATION_ANNOTATION.matches(tree, state)) { diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRules.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRules.java new file mode 100644 index 0000000000..b513725c2b --- /dev/null +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRules.java @@ -0,0 +1,177 @@ +package tech.picnic.errorprone.refasterrules; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +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.Repeated; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation; + +/** Refaster rules related to expressions dealing with immutable {@link Enum} collections. */ +@OnlineDocumentation +final class ImmutableEnumSetRules { + private ImmutableEnumSetRules() {} + + /** + * Prefer {@link Sets#immutableEnumSet(Iterable)} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetIterable> { + @BeforeTemplate + ImmutableSet before(Collection elements) { + return ImmutableSet.copyOf(elements); + } + + @AfterTemplate + ImmutableSet after(Collection elements) { + return Sets.immutableEnumSet(elements); + } + } + + /** + * Prefer {@link Sets#immutableEnumSet(Iterable)} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetIterable1> { + @BeforeTemplate + ImmutableSet before(T[] elements) { + return ImmutableSet.copyOf(elements); + } + + @AfterTemplate + ImmutableSet after(T[] elements) { + return Sets.immutableEnumSet(Arrays.asList(elements)); + } + } + + /** + * Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetOneElement> { + @BeforeTemplate + @SuppressWarnings("ImmutableEnumSetIterable" /* This is a more specific template. */) + ImmutableSet before(T e1) { + return Refaster.anyOf(ImmutableSet.of(e1), ImmutableSet.copyOf(EnumSet.of(e1))); + } + + @AfterTemplate + @SuppressWarnings("unchecked") + ImmutableSet after(T e1) { + return Sets.immutableEnumSet(e1); + } + } + + /** + * Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetTwoElements> { + @BeforeTemplate + @SuppressWarnings("ImmutableEnumSetIterable" /* This is a more specific template. */) + ImmutableSet before(T e1, T e2) { + return Refaster.anyOf(ImmutableSet.of(e1, e2), ImmutableSet.copyOf(EnumSet.of(e1, e2))); + } + + @AfterTemplate + @SuppressWarnings("unchecked") + ImmutableSet after(T e1, T e2) { + return Sets.immutableEnumSet(e1, e2); + } + } + + /** + * Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetThreeElements> { + @BeforeTemplate + @SuppressWarnings("ImmutableEnumSetIterable" /* This is a more specific template. */) + ImmutableSet before(T e1, T e2, T e3) { + return Refaster.anyOf( + ImmutableSet.of(e1, e2, e3), ImmutableSet.copyOf(EnumSet.of(e1, e2, e3))); + } + + @AfterTemplate + @SuppressWarnings("unchecked") + ImmutableSet after(T e1, T e2, T e3) { + return Sets.immutableEnumSet(e1, e2, e3); + } + } + + /** + * Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetFourElements> { + @BeforeTemplate + @SuppressWarnings("ImmutableEnumSetIterable" /* This is a more specific template. */) + ImmutableSet before(T e1, T e2, T e3, T e4) { + return Refaster.anyOf( + ImmutableSet.of(e1, e2, e3, e4), ImmutableSet.copyOf(EnumSet.of(e1, e2, e3, e4))); + } + + @AfterTemplate + @SuppressWarnings("unchecked") + ImmutableSet after(T e1, T e2, T e3, T e4) { + return Sets.immutableEnumSet(e1, e2, e3, e4); + } + } + + /** + * Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetFiveElements> { + @BeforeTemplate + @SuppressWarnings("ImmutableEnumSetIterable" /* This is a more specific template. */) + ImmutableSet before(T e1, T e2, T e3, T e4, T e5) { + return Refaster.anyOf( + ImmutableSet.of(e1, e2, e3, e4, e5), ImmutableSet.copyOf(EnumSet.of(e1, e2, e3, e4, e5))); + } + + @AfterTemplate + @SuppressWarnings("unchecked") + ImmutableSet after(T e1, T e2, T e3, T e4, T e5) { + return Sets.immutableEnumSet(e1, e2, e3, e4, e5); + } + } + + /** + * Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetSixElements> { + @BeforeTemplate + ImmutableSet before(T e1, T e2, T e3, T e4, T e5, T e6) { + return ImmutableSet.of(e1, e2, e3, e4, e5, e6); + } + + @AfterTemplate + @SuppressWarnings("unchecked") + ImmutableSet after(T e1, T e2, T e3, T e4, T e5, T e6) { + return Sets.immutableEnumSet(e1, e2, e3, e4, e5, e6); + } + } + + /** + * Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of + * internally used {@link EnumSet}. + */ + static final class ImmutableEnumSetVarArgs> { + @BeforeTemplate + @SuppressWarnings("ImmutableEnumSetIterable" /* This is a more specific template. */) + ImmutableSet before(T e1, @Repeated T elements) { + return ImmutableSet.copyOf(EnumSet.of(e1, Refaster.asVarargs(elements))); + } + + @AfterTemplate + ImmutableSet after(T e1, @Repeated T elements) { + return Sets.immutableEnumSet(e1, Refaster.asVarargs(elements)); + } + } +} diff --git a/error-prone-contrib/src/test/java/tech/picnic/errorprone/refasterrules/RefasterRulesTest.java b/error-prone-contrib/src/test/java/tech/picnic/errorprone/refasterrules/RefasterRulesTest.java index a7c35621a8..30839af965 100644 --- a/error-prone-contrib/src/test/java/tech/picnic/errorprone/refasterrules/RefasterRulesTest.java +++ b/error-prone-contrib/src/test/java/tech/picnic/errorprone/refasterrules/RefasterRulesTest.java @@ -43,6 +43,7 @@ final class RefasterRulesTest { EqualityRules.class, FileRules.class, InputStreamRules.class, + ImmutableEnumSetRules.class, ImmutableListRules.class, ImmutableListMultimapRules.class, ImmutableMapRules.class, diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRulesTestInput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRulesTestInput.java new file mode 100644 index 0000000000..c693d024ae --- /dev/null +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRulesTestInput.java @@ -0,0 +1,89 @@ +package tech.picnic.errorprone.refasterrules; + +import com.google.common.collect.ImmutableSet; +import java.math.RoundingMode; +import java.util.EnumSet; +import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase; + +final class ImmutableEnumSetRulesTest implements RefasterRuleCollectionTestCase { + @Override + public ImmutableSet elidedTypesAndStaticImports() { + return ImmutableSet.of(EnumSet.class); + } + + ImmutableSet> testImmutableEnumSetIterable() { + return ImmutableSet.of( + ImmutableSet.copyOf(EnumSet.range(RoundingMode.UP, RoundingMode.UNNECESSARY)), + ImmutableSet.copyOf(EnumSet.allOf(RoundingMode.class))); + } + + ImmutableSet> testImmutableEnumSetIterable1() { + return ImmutableSet.of( + ImmutableSet.copyOf(RoundingMode.values()), + ImmutableSet.copyOf(RoundingMode.class.getEnumConstants())); + } + + ImmutableSet> testImmutableEnumSetOneElement() { + return ImmutableSet.of( + ImmutableSet.of(RoundingMode.UP), ImmutableSet.copyOf(EnumSet.of(RoundingMode.UP))); + } + + ImmutableSet> testImmutableEnumSetTwoElements() { + return ImmutableSet.of( + ImmutableSet.of(RoundingMode.UP, RoundingMode.DOWN), + ImmutableSet.copyOf(EnumSet.of(RoundingMode.UP, RoundingMode.DOWN))); + } + + ImmutableSet> testImmutableEnumSetThreeElements() { + return ImmutableSet.of( + ImmutableSet.of(RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING), + ImmutableSet.copyOf(EnumSet.of(RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING))); + } + + ImmutableSet> testImmutableEnumSetFourElements() { + return ImmutableSet.of( + ImmutableSet.of( + RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR), + ImmutableSet.copyOf( + EnumSet.of( + RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR))); + } + + ImmutableSet> testImmutableEnumSetFiveElements() { + return ImmutableSet.of( + ImmutableSet.of( + RoundingMode.UP, + RoundingMode.DOWN, + RoundingMode.CEILING, + RoundingMode.FLOOR, + RoundingMode.UNNECESSARY), + ImmutableSet.copyOf( + EnumSet.of( + RoundingMode.UP, + RoundingMode.DOWN, + RoundingMode.CEILING, + RoundingMode.FLOOR, + RoundingMode.UNNECESSARY))); + } + + ImmutableSet testImmutableEnumSetSixElements() { + return ImmutableSet.of( + RoundingMode.UP, + RoundingMode.DOWN, + RoundingMode.CEILING, + RoundingMode.FLOOR, + RoundingMode.UNNECESSARY, + RoundingMode.HALF_EVEN); + } + + ImmutableSet testImmutableEnumSetVarArgs() { + return ImmutableSet.copyOf( + EnumSet.of( + RoundingMode.UP, + RoundingMode.DOWN, + RoundingMode.CEILING, + RoundingMode.FLOOR, + RoundingMode.UNNECESSARY, + RoundingMode.HALF_EVEN)); + } +} diff --git a/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRulesTestOutput.java b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRulesTestOutput.java new file mode 100644 index 0000000000..11b22b26c1 --- /dev/null +++ b/error-prone-contrib/src/test/resources/tech/picnic/errorprone/refasterrules/ImmutableEnumSetRulesTestOutput.java @@ -0,0 +1,88 @@ +package tech.picnic.errorprone.refasterrules; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import java.math.RoundingMode; +import java.util.Arrays; +import java.util.EnumSet; +import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase; + +final class ImmutableEnumSetRulesTest implements RefasterRuleCollectionTestCase { + @Override + public ImmutableSet elidedTypesAndStaticImports() { + return ImmutableSet.of(EnumSet.class); + } + + ImmutableSet> testImmutableEnumSetIterable() { + return ImmutableSet.of( + Sets.immutableEnumSet(EnumSet.range(RoundingMode.UP, RoundingMode.UNNECESSARY)), + Sets.immutableEnumSet(EnumSet.allOf(RoundingMode.class))); + } + + ImmutableSet> testImmutableEnumSetIterable1() { + return ImmutableSet.of( + Sets.immutableEnumSet(Arrays.asList(RoundingMode.values())), + Sets.immutableEnumSet(Arrays.asList(RoundingMode.class.getEnumConstants()))); + } + + ImmutableSet> testImmutableEnumSetOneElement() { + return ImmutableSet.of( + Sets.immutableEnumSet(RoundingMode.UP), Sets.immutableEnumSet(RoundingMode.UP)); + } + + ImmutableSet> testImmutableEnumSetTwoElements() { + return ImmutableSet.of( + Sets.immutableEnumSet(RoundingMode.UP, RoundingMode.DOWN), + Sets.immutableEnumSet(RoundingMode.UP, RoundingMode.DOWN)); + } + + ImmutableSet> testImmutableEnumSetThreeElements() { + return ImmutableSet.of( + Sets.immutableEnumSet(RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING), + Sets.immutableEnumSet(RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING)); + } + + ImmutableSet> testImmutableEnumSetFourElements() { + return ImmutableSet.of( + Sets.immutableEnumSet( + RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR), + Sets.immutableEnumSet( + RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR)); + } + + ImmutableSet> testImmutableEnumSetFiveElements() { + return ImmutableSet.of( + Sets.immutableEnumSet( + RoundingMode.UP, + RoundingMode.DOWN, + RoundingMode.CEILING, + RoundingMode.FLOOR, + RoundingMode.UNNECESSARY), + Sets.immutableEnumSet( + RoundingMode.UP, + RoundingMode.DOWN, + RoundingMode.CEILING, + RoundingMode.FLOOR, + RoundingMode.UNNECESSARY)); + } + + ImmutableSet testImmutableEnumSetSixElements() { + return Sets.immutableEnumSet( + RoundingMode.UP, + RoundingMode.DOWN, + RoundingMode.CEILING, + RoundingMode.FLOOR, + RoundingMode.UNNECESSARY, + RoundingMode.HALF_EVEN); + } + + ImmutableSet testImmutableEnumSetVarArgs() { + return Sets.immutableEnumSet( + RoundingMode.UP, + RoundingMode.DOWN, + RoundingMode.CEILING, + RoundingMode.FLOOR, + RoundingMode.UNNECESSARY, + RoundingMode.HALF_EVEN); + } +}