From 8ebd7531d49852c526c8a966b27a9da13a2214ba Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Sat, 1 Apr 2023 17:06:48 +0200 Subject: [PATCH 1/7] Introduce `ExplicitArgumentEnumeration` check --- error-prone-contrib/pom.xml | 5 + .../ExplicitArgumentEnumeration.java | 193 ++++ .../refasterrules/AssertJRules.java | 917 +----------------- .../ExplicitArgumentEnumerationTest.java | 142 +++ ...aphicalAnnotationAttributeListingTest.java | 6 +- .../RedundantStringConversionTest.java | 4 +- pom.xml | 7 + 7 files changed, 352 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..3a7da08040 100644 --- a/error-prone-contrib/pom.xml +++ b/error-prone-contrib/pom.xml @@ -167,6 +167,11 @@ value-annotations test + + org.jooq + jooq + provided + 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..fbc0c7a097 --- /dev/null +++ b/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumeration.java @@ -0,0 +1,193 @@ +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.bugpatterns.util.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.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 tech.picnic.errorprone.bugpatterns.util.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, "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) { + return Description.NO_MATCH; + } + + MethodSymbol method = ASTHelpers.getSymbol(tree); + if (!isUnaryIterableAcceptingMethod(method, state)) { + return Description.NO_MATCH; + } + + ExpressionTree argument = tree.getArguments().get(0); + if (!(argument instanceof MethodInvocationTree) + || !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) { + ImmutableList overloads = + ASTHelpers.matchingMethods( + method.getSimpleName(), + m -> m.isPublic() && !m.equals(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 is 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) { + String name = ASTHelpers.getSymbol(tree).getSimpleName().toString(); + String alternative = alternatives.get(name); + + if (alternative == null) { + return Optional.empty(); + } + + SuggestedFix fix = SourceCode.unwrapMethodInvocation(argument, state); + return Optional.of( + alternative.equals(name) + ? fix + : SuggestedFix.builder() + .merge(SuggestedFixes.renameMethodInvocation(tree, alternative, state)) + .merge(fix) + .build()); + } +} 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..8108422b69 --- /dev/null +++ b/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumerationTest.java @@ -0,0 +1,142 @@ +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));", + "", + " ImmutableList.builder()", + " // BUG: Diagnostic contains:", + " .addAll(ImmutableList.of())", + " .build();", + "", + " assertThat(ImmutableList.of(1))", + " // BUG: Diagnostic contains:", + " .containsAnyElementsOf(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();", + " }", + "}") + .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(1));", + " assertThat(ImmutableList.of()).doesNotContainSequence(ImmutableSet.of(1));", + " assertThat(ImmutableList.of()).doesNotContainSubsequence(List.of(1));", + " assertThat(ImmutableList.of()).hasSameElementsAs(Set.of(1));", + " assertThat(ImmutableList.of()).isSubsetOf(Arrays.asList(1));", + "", + " 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(1);", + " assertThat(ImmutableList.of()).doesNotContainSequence(1);", + " assertThat(ImmutableList.of()).doesNotContainSubsequence(1);", + " assertThat(ImmutableList.of()).containsOnly(1);", + " assertThat(ImmutableList.of()).isSubsetOf(1);", + "", + " 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..d02f49a69b 100644 --- a/pom.xml +++ b/pom.xml @@ -464,6 +464,11 @@ value-annotations 2.10.1 + + org.jooq + jooq + 3.16.23 + 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 From 11c21e501971e8d5de4a4ac32748ad055e4c56d4 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Sun, 21 Jan 2024 20:04:46 +0100 Subject: [PATCH 2/7] Fix JDK 11 compatibility --- .../bugpatterns/ExplicitArgumentEnumeration.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 index fbc0c7a097..965e8d8af2 100644 --- 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 @@ -27,6 +27,7 @@ import com.google.errorprone.util.ASTHelpers; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.MethodInvocationTree; +import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import java.util.Arrays; @@ -34,6 +35,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import javax.lang.model.element.Modifier; import tech.picnic.errorprone.bugpatterns.util.SourceCode; /** @@ -132,7 +134,7 @@ private static Optional trySuggestCallingVarargsOverload( ImmutableList overloads = ASTHelpers.matchingMethods( method.getSimpleName(), - m -> m.isPublic() && !m.equals(method), + m -> isPublic(m) && !m.equals(method), method.enclClass().type, state.getTypes()) .collect(toImmutableList()); @@ -190,4 +192,9 @@ private static Optional trySuggestCallingCustomAlternative( .merge(fix) .build()); } + + // XXX: Once we target JDK 14+, drop this method in favour of `Symbol#isPublic()`. + private static boolean isPublic(Symbol symbol) { + return symbol.getModifiers().contains(Modifier.PUBLIC); + } } From 1a93edb0f07b6af1872e350741b801470a32b843 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Sat, 10 Feb 2024 16:25:42 +0100 Subject: [PATCH 3/7] Post-rebase fix --- .../errorprone/bugpatterns/ExplicitArgumentEnumeration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index 965e8d8af2..a71abc13d5 100644 --- 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 @@ -8,7 +8,7 @@ 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.bugpatterns.util.Documentation.BUG_PATTERNS_BASE_URL; +import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL; import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableCollection; @@ -36,7 +36,7 @@ import java.util.Optional; import java.util.Set; import javax.lang.model.element.Modifier; -import tech.picnic.errorprone.bugpatterns.util.SourceCode; +import tech.picnic.errorprone.utils.SourceCode; /** * A {@link BugChecker} that flags single-argument method invocations with an iterable of explicitly From 284023f5112dde25d324fa429276fdc086437678 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Sun, 11 Feb 2024 20:57:24 +0100 Subject: [PATCH 4/7] Tweaks --- .../ExplicitArgumentEnumeration.java | 46 +++++++++---------- .../ExplicitArgumentEnumerationTest.java | 21 ++++++++- 2 files changed, 43 insertions(+), 24 deletions(-) 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 index a71abc13d5..49dc17b1f9 100644 --- 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 @@ -25,9 +25,9 @@ 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; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import java.util.Arrays; @@ -35,7 +35,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import javax.lang.model.element.Modifier; +import javax.lang.model.element.Element; import tech.picnic.errorprone.utils.SourceCode; /** @@ -91,6 +91,8 @@ public final class ExplicitArgumentEnumeration extends BugChecker 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") @@ -102,6 +104,7 @@ 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; } @@ -111,8 +114,7 @@ public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState } ExpressionTree argument = tree.getArguments().get(0); - if (!(argument instanceof MethodInvocationTree) - || !EXPLICIT_ITERABLE_CREATOR.matches(argument, state)) { + if (!EXPLICIT_ITERABLE_CREATOR.matches(argument, state)) { return Description.NO_MATCH; } @@ -131,10 +133,14 @@ private static boolean isUnaryIterableAcceptingMethod(MethodSymbol method, Visit 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 -> isPublic(m) && !m.equals(method), + m -> isAtLeastAsVisible(m, method), method.enclClass().type, state.getTypes()) .collect(toImmutableList()); @@ -176,25 +182,19 @@ private static Optional trySuggestCallingCustomAlternative( MethodInvocationTree argument, VisitorState state, Map alternatives) { - String name = ASTHelpers.getSymbol(tree).getSimpleName().toString(); - String alternative = alternatives.get(name); - - if (alternative == null) { - return Optional.empty(); - } - - SuggestedFix fix = SourceCode.unwrapMethodInvocation(argument, state); - return Optional.of( - alternative.equals(name) - ? fix - : SuggestedFix.builder() - .merge(SuggestedFixes.renameMethodInvocation(tree, alternative, state)) - .merge(fix) - .build()); + 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()); } - // XXX: Once we target JDK 14+, drop this method in favour of `Symbol#isPublic()`. - private static boolean isPublic(Symbol symbol) { - return symbol.getModifiers().contains(Modifier.PUBLIC); + 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/test/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumerationTest.java b/error-prone-contrib/src/test/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumerationTest.java index 8108422b69..7cade5422a 100644 --- 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 @@ -29,6 +29,11 @@ void identification() { "", " 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())", @@ -36,7 +41,9 @@ void identification() { "", " assertThat(ImmutableList.of(1))", " // BUG: Diagnostic contains:", - " .containsAnyElementsOf(ImmutableList.of(1));", + " .containsAnyElementsOf(ImmutableList.of(1))", + " // BUG: Diagnostic contains:", + " .isSubsetOf(ImmutableList.of(1));", "", " Flux.just(1, 2)", " .as(StepVerifier::create)", @@ -49,6 +56,18 @@ void identification() { " .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(); } From 0796c8561c8a1b89a8550e374c4bb1d18fc29ef1 Mon Sep 17 00:00:00 2001 From: Rick Ossendrijver Date: Thu, 12 Dec 2024 09:44:23 +0100 Subject: [PATCH 5/7] Typo --- .../errorprone/bugpatterns/ExplicitArgumentEnumeration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 49dc17b1f9..625f52bdf4 100644 --- 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 @@ -149,7 +149,7 @@ private static Optional trySuggestCallingVarargsOverload( * 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 is does not attempt to determine which exact method 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. From d602a2bf20c7835f7b86babe5b8a34ad630fe88b Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Sat, 14 Dec 2024 14:53:48 +0100 Subject: [PATCH 6/7] Address PR feedback --- .../ExplicitArgumentEnumerationTest.java | 20 +++++++++---------- pom.xml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) 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 index 7cade5422a..3366248f70 100644 --- 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 @@ -101,11 +101,11 @@ void replacement() { " 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(1));", - " assertThat(ImmutableList.of()).doesNotContainSequence(ImmutableSet.of(1));", - " assertThat(ImmutableList.of()).doesNotContainSubsequence(List.of(1));", - " assertThat(ImmutableList.of()).hasSameElementsAs(Set.of(1));", - " assertThat(ImmutableList.of()).isSubsetOf(Arrays.asList(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)", @@ -144,11 +144,11 @@ void replacement() { " assertThat(ImmutableList.of()).containsExactlyInAnyOrder();", " assertThat(ImmutableList.of()).containsSequence();", " assertThat(ImmutableList.of()).containsSubsequence(1);", - " assertThat(ImmutableList.of()).doesNotContain(1);", - " assertThat(ImmutableList.of()).doesNotContainSequence(1);", - " assertThat(ImmutableList.of()).doesNotContainSubsequence(1);", - " assertThat(ImmutableList.of()).containsOnly(1);", - " assertThat(ImmutableList.of()).isSubsetOf(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();", "", diff --git a/pom.xml b/pom.xml index d02f49a69b..fd24dd441e 100644 --- a/pom.xml +++ b/pom.xml @@ -467,7 +467,7 @@ org.jooq jooq - 3.16.23 + 3.19.16 org.jspecify From 6f0de3a296b0c67f49f6095d5da72cb2a97f3e33 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Sat, 14 Dec 2024 18:59:34 +0100 Subject: [PATCH 7/7] Tweak --- error-prone-contrib/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/error-prone-contrib/pom.xml b/error-prone-contrib/pom.xml index 3a7da08040..9912be1a42 100644 --- a/error-prone-contrib/pom.xml +++ b/error-prone-contrib/pom.xml @@ -170,7 +170,7 @@ org.jooq jooq - provided + test org.jspecify