From 1b8ffd86b954fbeaebb1f9669c73684b9dbd1826 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Mon, 16 Dec 2024 09:15:30 +0100 Subject: [PATCH] Introduce `ExplicitArgumentEnumeration` check (#985) --- error-prone-contrib/pom.xml | 5 + .../ExplicitArgumentEnumeration.java | 200 ++++ .../refasterrules/AssertJRules.java | 917 +----------------- .../ExplicitArgumentEnumerationTest.java | 161 +++ ...aphicalAnnotationAttributeListingTest.java | 6 +- .../RedundantStringConversionTest.java | 4 +- pom.xml | 7 + 7 files changed, 378 insertions(+), 922 deletions(-) create mode 100644 error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumeration.java create mode 100644 error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumerationTest.java diff --git a/error-prone-contrib/pom.xml b/error-prone-contrib/pom.xml index 5c9d56336b..9912be1a42 100644 --- a/error-prone-contrib/pom.xml +++ b/error-prone-contrib/pom.xml @@ -167,6 +167,11 @@ value-annotations test + + org.jooq + jooq + test + org.jspecify jspecify diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumeration.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumeration.java new file mode 100644 index 0000000000..625f52bdf4 --- /dev/null +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumeration.java @@ -0,0 +1,200 @@ +package tech.picnic.errorprone.bugpatterns; + +import static com.google.common.collect.ImmutableList.toImmutableList; +import static com.google.errorprone.BugPattern.LinkType.CUSTOM; +import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION; +import static com.google.errorprone.BugPattern.StandardTags.PERFORMANCE; +import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION; +import static com.google.errorprone.matchers.Matchers.anyOf; +import static com.google.errorprone.matchers.Matchers.instanceMethod; +import static com.google.errorprone.matchers.Matchers.staticMethod; +import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL; + +import com.google.auto.service.AutoService; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableTable; +import com.google.errorprone.BugPattern; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher; +import com.google.errorprone.fixes.SuggestedFix; +import com.google.errorprone.fixes.SuggestedFixes; +import com.google.errorprone.matchers.Description; +import com.google.errorprone.matchers.Matcher; +import com.google.errorprone.util.ASTHelpers; +import com.google.errorprone.util.Visibility; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symbol.VarSymbol; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import javax.lang.model.element.Element; +import tech.picnic.errorprone.utils.SourceCode; + +/** + * A {@link BugChecker} that flags single-argument method invocations with an iterable of explicitly + * enumerated values, for which a semantically equivalent varargs variant (appears to) exists as + * well. + * + *

This check drops selected {@link ImmutableSet#of} and {@link Set#of} invocations, with the + * assumption that these operations do not deduplicate the collection of explicitly enumerated + * values. It also drops {@link ImmutableMultiset#of} and {@link Set#of} invocations, with the + * assumption that these do not materially impact iteration order. + * + *

This checker attempts to identify {@link Iterable}-accepting methods for which a varargs + * overload exists, and suggests calling the varargs overload instead. This is an imperfect + * heuristic, but it e.g. allows invocations of Immutables-generated {@code + * with*} methods to be simplified. + */ +@AutoService(BugChecker.class) +@BugPattern( + summary = "Iterable creation can be avoided by using a varargs alternative method", + link = BUG_PATTERNS_BASE_URL + "ExplicitArgumentEnumeration", + linkType = CUSTOM, + severity = SUGGESTION, + tags = {PERFORMANCE, SIMPLIFICATION}) +public final class ExplicitArgumentEnumeration extends BugChecker + implements MethodInvocationTreeMatcher { + private static final long serialVersionUID = 1L; + private static final Matcher EXPLICIT_ITERABLE_CREATOR = + anyOf( + staticMethod() + .onClassAny( + ImmutableList.class.getCanonicalName(), + ImmutableMultiset.class.getCanonicalName(), + ImmutableSet.class.getCanonicalName(), + List.class.getCanonicalName(), + Set.class.getCanonicalName()) + .named("of"), + staticMethod().onClass(Arrays.class.getCanonicalName()).named("asList")); + private static final Matcher IMMUTABLE_COLLECTION_BUILDER = + instanceMethod().onDescendantOf(ImmutableCollection.Builder.class.getCanonicalName()); + private static final Matcher OBJECT_ENUMERABLE_ASSERT = + instanceMethod().onDescendantOf("org.assertj.core.api.ObjectEnumerableAssert"); + private static final Matcher STEP_VERIFIER_STEP = + instanceMethod().onDescendantOf("reactor.test.StepVerifier.Step"); + private static final ImmutableTable, String, String> ALTERNATIVE_METHODS = + ImmutableTable., String, String>builder() + .put(IMMUTABLE_COLLECTION_BUILDER, "addAll", "add") + .put(OBJECT_ENUMERABLE_ASSERT, "containsAnyElementsOf", "containsAnyOf") + .put(OBJECT_ENUMERABLE_ASSERT, "containsAll", "contains") + .put(OBJECT_ENUMERABLE_ASSERT, "containsExactlyElementsOf", "containsExactly") + .put( + OBJECT_ENUMERABLE_ASSERT, + "containsExactlyInAnyOrderElementsOf", + "containsExactlyInAnyOrder") + .put(OBJECT_ENUMERABLE_ASSERT, "containsOnlyElementsOf", "containsOnly") + .put(OBJECT_ENUMERABLE_ASSERT, "containsOnlyOnceElementsOf", "containsOnlyOnce") + .put(OBJECT_ENUMERABLE_ASSERT, "doesNotContainAnyElementsOf", "doesNotContain") + .put(OBJECT_ENUMERABLE_ASSERT, "hasSameElementsAs", "containsOnly") + .put(STEP_VERIFIER_STEP, "expectNextSequence", "expectNext") + .build(); + + /** Instantiates a new {@link ExplicitArgumentEnumeration} instance. */ + public ExplicitArgumentEnumeration() {} + + @Override + public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { + if (tree.getArguments().size() != 1) { + /* Performance optimization: non-unary method invocations cannot be simplified. */ + return Description.NO_MATCH; + } + + MethodSymbol method = ASTHelpers.getSymbol(tree); + if (!isUnaryIterableAcceptingMethod(method, state)) { + return Description.NO_MATCH; + } + + ExpressionTree argument = tree.getArguments().get(0); + if (!EXPLICIT_ITERABLE_CREATOR.matches(argument, state)) { + return Description.NO_MATCH; + } + + return trySuggestCallingVarargsOverload(method, (MethodInvocationTree) argument, state) + .or(() -> trySuggestCallingCustomAlternative(tree, (MethodInvocationTree) argument, state)) + .map(fix -> describeMatch(tree, fix)) + .orElse(Description.NO_MATCH); + } + + private static boolean isUnaryIterableAcceptingMethod(MethodSymbol method, VisitorState state) { + List params = method.params(); + return !method.isVarArgs() + && params.size() == 1 + && ASTHelpers.isSubtype(params.get(0).type, state.getSymtab().iterableType, state); + } + + private static Optional trySuggestCallingVarargsOverload( + MethodSymbol method, MethodInvocationTree argument, VisitorState state) { + /* + * Collect all overloads of the given method that we are sure to be able to call. Note that the + * `isAtLeastAsVisible` check is conservative heuristic. + */ + ImmutableList overloads = + ASTHelpers.matchingMethods( + method.getSimpleName(), + m -> isAtLeastAsVisible(m, method), + method.enclClass().type, + state.getTypes()) + .collect(toImmutableList()); + + /* + * If all overloads have a single parameter, and at least one of them is a varargs method, then + * we assume that unwrapping the iterable argument will cause a suitable overload to be invoked. + * (Note that there may be multiple varargs overloads, either with different parameter types, or + * due to method overriding; this check does not attempt to determine which exact method or + * overload will be invoked as a result of the suggested simplification.) + * + * Note that this is a (highly!) imperfect heuristic, but it is sufficient to prevent e.g. + * unwrapping of arguments to `org.jooq.impl.DSL#row`, which can cause the expression's return + * type to change from `RowN` to (e.g.) `Row2`. + */ + // XXX: There are certainly cases where it _would_ be nice to unwrap the arguments to + // `org.jooq.impl.DSL#row(Collection)`. Look into this. + // XXX: Ideally we do check that one of the overloads accepts the unwrapped arguments. + // XXX: Ideally we validate that eligible overloads have compatible return types. + boolean hasLikelySuitableVarargsOverload = + overloads.stream().allMatch(m -> m.params().size() == 1) + && overloads.stream().anyMatch(MethodSymbol::isVarArgs); + + return hasLikelySuitableVarargsOverload + ? Optional.of(SourceCode.unwrapMethodInvocation(argument, state)) + : Optional.empty(); + } + + private static Optional trySuggestCallingCustomAlternative( + MethodInvocationTree tree, MethodInvocationTree argument, VisitorState state) { + return ALTERNATIVE_METHODS.rowMap().entrySet().stream() + .filter(e -> e.getKey().matches(tree, state)) + .findFirst() + .flatMap(e -> trySuggestCallingCustomAlternative(tree, argument, state, e.getValue())); + } + + private static Optional trySuggestCallingCustomAlternative( + MethodInvocationTree tree, + MethodInvocationTree argument, + VisitorState state, + Map alternatives) { + return Optional.ofNullable( + alternatives.get(ASTHelpers.getSymbol(tree).getSimpleName().toString())) + .map( + replacement -> + SuggestedFix.builder() + .merge(SuggestedFixes.renameMethodInvocation(tree, replacement, state)) + .merge(SourceCode.unwrapMethodInvocation(argument, state)) + .build()); + } + + private static boolean isAtLeastAsVisible(Element symbol, Element reference) { + return Visibility.fromModifiers(symbol.getModifiers()) + .compareTo(Visibility.fromModifiers(reference.getModifiers())) + >= 0; + } +} diff --git a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/AssertJRules.java b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/AssertJRules.java index c1b73ecf01..c2e2f1415c 100644 --- a/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/AssertJRules.java +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/AssertJRules.java @@ -3,9 +3,6 @@ import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS; import static org.assertj.core.api.Assertions.assertThat; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMultiset; -import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Multiset; import com.google.errorprone.refaster.Refaster; @@ -15,7 +12,6 @@ import com.google.errorprone.refaster.annotation.NotMatches; import com.google.errorprone.refaster.annotation.Repeated; import com.google.errorprone.refaster.annotation.UseImportPolicy; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; @@ -204,32 +200,8 @@ static final class ObjectEnumerableContainsOneElement { @SuppressWarnings("unchecked") ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T element) { return Refaster.anyOf( - iterAssert.containsAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))), iterAssert.containsAnyOf(element), - iterAssert.containsAll( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))), - iterAssert.containsSequence( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))), iterAssert.containsSequence(element), - iterAssert.containsSubsequence( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))), iterAssert.containsSubsequence(element)); } @@ -244,20 +216,7 @@ static final class ObjectEnumerableDoesNotContainOneElement { @BeforeTemplate @SuppressWarnings("unchecked") ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T element) { - return Refaster.anyOf( - iterAssert.doesNotContainAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))), - iterAssert.doesNotContainSequence( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))), - iterAssert.doesNotContainSequence(element)); + return iterAssert.doesNotContainSequence(element); } @AfterTemplate @@ -270,25 +229,7 @@ ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T el static final class ObjectEnumerableContainsExactlyOneElement { @BeforeTemplate @SuppressWarnings("unchecked") - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T element) { - return Refaster.anyOf( - iterAssert.containsExactlyElementsOf( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))), - iterAssert.containsExactlyInAnyOrderElementsOf( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element)))); - } - - @BeforeTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert before2( + ObjectEnumerableAssert before( ObjectEnumerableAssert iterAssert, @NotMatches(IsArray.class) T element) { return iterAssert.containsExactlyInAnyOrder(element); } @@ -313,42 +254,6 @@ ObjectEnumerableAssert after(Set set, T element) { } } - static final class ObjectEnumerableContainsOneDistinctElement { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T element) { - return iterAssert.hasSameElementsAs( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T element) { - return iterAssert.containsOnly(element); - } - } - - static final class ObjectEnumerableIsSubsetOfOneElement { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T element) { - return iterAssert.isSubsetOf( - Refaster.anyOf( - ImmutableList.of(element), - Arrays.asList(element), - ImmutableSet.of(element), - ImmutableMultiset.of(element))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T element) { - return iterAssert.isSubsetOf(element); - } - } - // // Iterable // @@ -1155,824 +1060,6 @@ void after(Predicate predicate, T object) { } } - //////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////// - // BELOW: Generated code. - - // - // ObjectEnumerableAssert: containsAnyOf - // - - static final class ObjectEnumerableContainsAnyOfTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsAnyOf(e1, e2); - } - } - - static final class ObjectEnumerableContainsAnyOfThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsAnyOf(e1, e2, e3); - } - } - - static final class ObjectEnumerableContainsAnyOfFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsAnyOf(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableContainsAnyOfFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsAnyOf(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: contains - // - - static final class ObjectEnumerableContainsTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsAll( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.contains(e1, e2); - } - } - - static final class ObjectEnumerableContainsThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsAll( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.contains(e1, e2, e3); - } - } - - static final class ObjectEnumerableContainsFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsAll( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.contains(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableContainsFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsAll( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.contains(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: containsExactly - // - - static final class ObjectEnumerableContainsExactlyTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsExactlyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsExactly(e1, e2); - } - } - - static final class ObjectEnumerableContainsExactlyThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsExactlyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsExactly(e1, e2, e3); - } - } - - static final class ObjectEnumerableContainsExactlyFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsExactlyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsExactly(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableContainsExactlyFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsExactlyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsExactly(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: containsExactlyInAnyOrder - // - - static final class ObjectEnumerableContainsExactlyInAnyOrderTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsExactlyInAnyOrderElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsExactlyInAnyOrder(e1, e2); - } - } - - static final class ObjectEnumerableContainsExactlyInAnyOrderThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsExactlyInAnyOrderElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsExactlyInAnyOrder(e1, e2, e3); - } - } - - static final class ObjectEnumerableContainsExactlyInAnyOrderFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsExactlyInAnyOrderElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsExactlyInAnyOrder(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableContainsExactlyInAnyOrderFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsExactlyInAnyOrderElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsExactlyInAnyOrder(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: containsSequence - // - - static final class ObjectEnumerableContainsSequenceTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsSequence( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsSequence(e1, e2); - } - } - - static final class ObjectEnumerableContainsSequenceThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsSequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsSequence(e1, e2, e3); - } - } - - static final class ObjectEnumerableContainsSequenceFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsSequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsSequence(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableContainsSequenceFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsSequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsSequence(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: containsSubsequence - // - - static final class ObjectEnumerableContainsSubsequenceTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsSubsequence( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsSubsequence(e1, e2); - } - } - - static final class ObjectEnumerableContainsSubsequenceThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsSubsequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsSubsequence(e1, e2, e3); - } - } - - static final class ObjectEnumerableContainsSubsequenceFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsSubsequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsSubsequence(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableContainsSubsequenceFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsSubsequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsSubsequence(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: doesNotContain - // - - static final class ObjectEnumerableDoesNotContainTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.doesNotContainAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.doesNotContain(e1, e2); - } - } - - static final class ObjectEnumerableDoesNotContainThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.doesNotContainAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.doesNotContain(e1, e2, e3); - } - } - - static final class ObjectEnumerableDoesNotContainFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.doesNotContainAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.doesNotContain(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableDoesNotContainFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.doesNotContainAnyElementsOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.doesNotContain(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: doesNotContainSequence - // - - static final class ObjectEnumerableDoesNotContainSequenceTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.doesNotContainSequence( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.doesNotContainSequence(e1, e2); - } - } - - static final class ObjectEnumerableDoesNotContainSequenceThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.doesNotContainSequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.doesNotContainSequence(e1, e2, e3); - } - } - - static final class ObjectEnumerableDoesNotContainSequenceFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.doesNotContainSequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.doesNotContainSequence(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableDoesNotContainSequenceFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.doesNotContainSequence( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.doesNotContainSequence(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: containsOnly - // - - static final class ObjectEnumerableContainsOnlyTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.hasSameElementsAs( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.containsOnly(e1, e2); - } - } - - static final class ObjectEnumerableContainsOnlyThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.hasSameElementsAs( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.containsOnly(e1, e2, e3); - } - } - - static final class ObjectEnumerableContainsOnlyFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.hasSameElementsAs( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.containsOnly(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableContainsOnlyFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.hasSameElementsAs( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.containsOnly(e1, e2, e3, e4, e5); - } - } - - // - // ObjectEnumerableAssert: isSubsetOf - // - - static final class ObjectEnumerableIsSubsetOfTwoElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.isSubsetOf( - Refaster.anyOf( - ImmutableList.of(e1, e2), - Arrays.asList(e1, e2), - ImmutableSet.of(e1, e2), - ImmutableMultiset.of(e1, e2))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2) { - return iterAssert.isSubsetOf(e1, e2); - } - } - - static final class ObjectEnumerableIsSubsetOfThreeElements { - @BeforeTemplate - ObjectEnumerableAssert before(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.isSubsetOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3), - Arrays.asList(e1, e2, e3), - ImmutableSet.of(e1, e2, e3), - ImmutableMultiset.of(e1, e2, e3))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after(ObjectEnumerableAssert iterAssert, T e1, T e2, T e3) { - return iterAssert.isSubsetOf(e1, e2, e3); - } - } - - static final class ObjectEnumerableIsSubsetOfFourElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.isSubsetOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4), - Arrays.asList(e1, e2, e3, e4), - ImmutableSet.of(e1, e2, e3, e4), - ImmutableMultiset.of(e1, e2, e3, e4))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4) { - return iterAssert.isSubsetOf(e1, e2, e3, e4); - } - } - - // XXX: Add variants for 6+ elements? - static final class ObjectEnumerableIsSubsetOfFiveElements { - @BeforeTemplate - ObjectEnumerableAssert before( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.isSubsetOf( - Refaster.anyOf( - ImmutableList.of(e1, e2, e3, e4, e5), - Arrays.asList(e1, e2, e3, e4, e5), - ImmutableSet.of(e1, e2, e3, e4, e5), - ImmutableMultiset.of(e1, e2, e3, e4, e5))); - } - - @AfterTemplate - @SuppressWarnings("unchecked") - ObjectEnumerableAssert after( - ObjectEnumerableAssert iterAssert, T e1, T e2, T e3, T e4, T e5) { - return iterAssert.isSubsetOf(e1, e2, e3, e4, e5); - } - } - - //////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////// - // Above: Generated code. - //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Organize the code below. diff --git a/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumerationTest.java b/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumerationTest.java new file mode 100644 index 0000000000..3366248f70 --- /dev/null +++ b/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumerationTest.java @@ -0,0 +1,161 @@ +package tech.picnic.errorprone.bugpatterns; + +import com.google.errorprone.BugCheckerRefactoringTestHelper; +import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode; +import com.google.errorprone.CompilationTestHelper; +import org.junit.jupiter.api.Test; + +final class ExplicitArgumentEnumerationTest { + @Test + void identification() { + CompilationTestHelper.newInstance(ExplicitArgumentEnumeration.class, getClass()) + .addSourceLines( + "A.java", + "import static org.assertj.core.api.Assertions.assertThat;", + "", + "import com.google.common.collect.ImmutableList;", + "import com.google.errorprone.CompilationTestHelper;", + "import com.google.errorprone.bugpatterns.BugChecker;", + "import org.jooq.impl.DSL;", + "import reactor.core.publisher.Flux;", + "import reactor.test.StepVerifier;", + "", + "class A {", + " void m() {", + " ImmutableList list = ImmutableList.of();", + " assertThat(ImmutableList.of()).containsAnyElementsOf(list);", + "", + " ImmutableList.>builder().add(ImmutableList.of());", + "", + " DSL.row(ImmutableList.of(1, 2));", + "", + " // BUG: Diagnostic contains:", + " unaryMethod(ImmutableList.of(1, 2));", + " unaryMethodWithLessVisibleOverload(ImmutableList.of(1, 2));", + " binaryMethod(ImmutableList.of(1, 2), 3);", + "", + " ImmutableList.builder()", + " // BUG: Diagnostic contains:", + " .addAll(ImmutableList.of())", + " .build();", + "", + " assertThat(ImmutableList.of(1))", + " // BUG: Diagnostic contains:", + " .containsAnyElementsOf(ImmutableList.of(1))", + " // BUG: Diagnostic contains:", + " .isSubsetOf(ImmutableList.of(1));", + "", + " Flux.just(1, 2)", + " .as(StepVerifier::create)", + " // BUG: Diagnostic contains:", + " .expectNextSequence(ImmutableList.of(1, 2))", + " .verifyComplete();", + "", + " CompilationTestHelper.newInstance(BugChecker.class, getClass())", + " // BUG: Diagnostic contains:", + " .setArgs(ImmutableList.of(\"foo\"))", + " .withClasspath();", + " }", + "", + " private void unaryMethod(ImmutableList args) {}", + "", + " private void unaryMethod(Integer... args) {}", + "", + " void unaryMethodWithLessVisibleOverload(ImmutableList args) {}", + "", + " private void unaryMethodWithLessVisibleOverload(Integer... args) {}", + "", + " private void binaryMethod(ImmutableList args, int extraArg) {}", + "", + " private void binaryMethod(Integer... args) {}", + "}") + .doTest(); + } + + @Test + void replacement() { + BugCheckerRefactoringTestHelper.newInstance(ExplicitArgumentEnumeration.class, getClass()) + .addInputLines( + "A.java", + "import static org.assertj.core.api.Assertions.assertThat;", + "", + "import com.google.common.collect.ImmutableList;", + "import com.google.common.collect.ImmutableMultiset;", + "import com.google.common.collect.ImmutableSet;", + "import com.google.errorprone.BugCheckerRefactoringTestHelper;", + "import com.google.errorprone.CompilationTestHelper;", + "import com.google.errorprone.bugpatterns.BugChecker;", + "import java.util.Arrays;", + "import java.util.List;", + "import java.util.Set;", + "import reactor.core.publisher.Flux;", + "import reactor.test.StepVerifier;", + "", + "class A {", + " void m() {", + " ImmutableList.builder().addAll(ImmutableList.of()).build();", + "", + " assertThat(ImmutableList.of()).containsAnyElementsOf(ImmutableMultiset.of());", + " assertThat(ImmutableList.of()).containsAll(ImmutableSet.of());", + " assertThat(ImmutableList.of()).containsExactlyElementsOf(List.of());", + " assertThat(ImmutableList.of()).containsExactlyInAnyOrderElementsOf(Set.of());", + " assertThat(ImmutableList.of()).containsSequence(Arrays.asList());", + " assertThat(ImmutableList.of()).containsSubsequence(ImmutableList.of(1));", + " assertThat(ImmutableList.of()).doesNotContainAnyElementsOf(ImmutableMultiset.of(2));", + " assertThat(ImmutableList.of()).doesNotContainSequence(ImmutableSet.of(3));", + " assertThat(ImmutableList.of()).doesNotContainSubsequence(List.of(4));", + " assertThat(ImmutableList.of()).hasSameElementsAs(Set.of(5));", + " assertThat(ImmutableList.of()).isSubsetOf(Arrays.asList(6));", + "", + " Flux.empty()", + " .as(StepVerifier::create)", + " .expectNextSequence(ImmutableList.of(1, 2))", + " .verifyComplete();", + "", + " BugCheckerRefactoringTestHelper.newInstance(BugChecker.class, getClass())", + " .setArgs(ImmutableList.of(\"foo\", \"bar\"));", + " CompilationTestHelper.newInstance(BugChecker.class, getClass())", + " .setArgs(ImmutableList.of(\"foo\", \"bar\"));", + " }", + "}") + .addOutputLines( + "A.java", + "import static org.assertj.core.api.Assertions.assertThat;", + "", + "import com.google.common.collect.ImmutableList;", + "import com.google.common.collect.ImmutableMultiset;", + "import com.google.common.collect.ImmutableSet;", + "import com.google.errorprone.BugCheckerRefactoringTestHelper;", + "import com.google.errorprone.CompilationTestHelper;", + "import com.google.errorprone.bugpatterns.BugChecker;", + "import java.util.Arrays;", + "import java.util.List;", + "import java.util.Set;", + "import reactor.core.publisher.Flux;", + "import reactor.test.StepVerifier;", + "", + "class A {", + " void m() {", + " ImmutableList.builder().add().build();", + "", + " assertThat(ImmutableList.of()).containsAnyOf();", + " assertThat(ImmutableList.of()).contains();", + " assertThat(ImmutableList.of()).containsExactly();", + " assertThat(ImmutableList.of()).containsExactlyInAnyOrder();", + " assertThat(ImmutableList.of()).containsSequence();", + " assertThat(ImmutableList.of()).containsSubsequence(1);", + " assertThat(ImmutableList.of()).doesNotContain(2);", + " assertThat(ImmutableList.of()).doesNotContainSequence(3);", + " assertThat(ImmutableList.of()).doesNotContainSubsequence(4);", + " assertThat(ImmutableList.of()).containsOnly(5);", + " assertThat(ImmutableList.of()).isSubsetOf(6);", + "", + " Flux.empty().as(StepVerifier::create).expectNext(1, 2).verifyComplete();", + "", + " BugCheckerRefactoringTestHelper.newInstance(BugChecker.class, getClass()).setArgs(\"foo\", \"bar\");", + " CompilationTestHelper.newInstance(BugChecker.class, getClass()).setArgs(\"foo\", \"bar\");", + " }", + "}") + .doTest(TestMode.TEXT_MATCH); + } +} diff --git a/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/LexicographicalAnnotationAttributeListingTest.java b/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/LexicographicalAnnotationAttributeListingTest.java index b73458a5e3..a193656626 100644 --- a/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/LexicographicalAnnotationAttributeListingTest.java +++ b/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/LexicographicalAnnotationAttributeListingTest.java @@ -1,6 +1,5 @@ package tech.picnic.errorprone.bugpatterns; -import com.google.common.collect.ImmutableList; import com.google.errorprone.BugCheckerRefactoringTestHelper; import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode; import com.google.errorprone.CompilationTestHelper; @@ -294,9 +293,8 @@ void filtering() { /* Some violations are not flagged because they are not in- or excluded. */ CompilationTestHelper.newInstance(LexicographicalAnnotationAttributeListing.class, getClass()) .setArgs( - ImmutableList.of( - "-XepOpt:LexicographicalAnnotationAttributeListing:Includes=pkg.A.Foo,pkg.A.Bar", - "-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value")) + "-XepOpt:LexicographicalAnnotationAttributeListing:Includes=pkg.A.Foo,pkg.A.Bar", + "-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value") .addSourceLines( "pkg/A.java", "package pkg;", diff --git a/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/RedundantStringConversionTest.java b/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/RedundantStringConversionTest.java index 906a16229b..0a60e14881 100644 --- a/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/RedundantStringConversionTest.java +++ b/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/RedundantStringConversionTest.java @@ -1,6 +1,5 @@ package tech.picnic.errorprone.bugpatterns; -import com.google.common.collect.ImmutableList; import com.google.errorprone.BugCheckerRefactoringTestHelper; import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode; import com.google.errorprone.CompilationTestHelper; @@ -408,8 +407,7 @@ void identificationWithinSlf4jLoggerMethod() { void identificationOfCustomConversionMethod() { CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass()) .setArgs( - ImmutableList.of( - "-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)")) + "-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)") .addSourceLines( "A.java", "import java.math.RoundingMode;", diff --git a/pom.xml b/pom.xml index 82cdc9b625..fd24dd441e 100644 --- a/pom.xml +++ b/pom.xml @@ -464,6 +464,11 @@ value-annotations 2.10.1 + + org.jooq + jooq + 3.19.16 + org.jspecify jspecify @@ -1363,6 +1368,8 @@ | BSD licence | BSD License 3 | Eclipse Distribution License (New BSD License) + | Eclipse Distribution License - v 1.0 + | EDL 1.0 | New BSD License