Compare commits

..

1 Commits

Author SHA1 Message Date
Stephan Schroevers
6c8f11fbdc Introduce SpringTestRules Refaster rule collection 2025-03-29 21:25:16 +01:00
39 changed files with 180 additions and 232 deletions

View File

@@ -1,12 +0,0 @@
{
"name": "Java",
"image": "mcr.microsoft.com/devcontainers/java:1-21",
"features": {
"ghcr.io/devcontainers/features/java:1": {
"version": "none",
"installMaven": "true",
"mavenVersion": "3.8.6",
"installGradle": "true"
}
}
}

View File

@@ -26,7 +26,7 @@ jobs:
continue-on-error: ${{ matrix.experimental }}
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block

View File

@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block
@@ -75,7 +75,7 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block

View File

@@ -1,22 +0,0 @@
name: Junie
run-name: Junie run ${{ inputs.run_id }}
permissions:
contents: write
pull-requests: write
on:
workflow_dispatch:
inputs:
run_id:
description: "id of workflow process"
required: true
workflow_params:
description: "stringified params"
required: true
jobs:
call-workflow-passing-data:
uses: jetbrains-junie/junie-workflows/.github/workflows/ej-issue.yml@main
with:
workflow_params: ${{ inputs.workflow_params }}

View File

@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block

View File

@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block

View File

@@ -22,7 +22,7 @@ jobs:
integration-test: [ "checkstyle", "metrics", "prometheus-java-client" ]
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
with:
disable-sudo: true
egress-policy: block

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>documentation-support</artifactId>

View File

@@ -2,7 +2,6 @@ package tech.picnic.errorprone.documentation;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
import static java.util.Objects.requireNonNull;
import static java.util.function.Predicate.not;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@@ -168,10 +167,7 @@ public final class BugPatternTestExtractor implements Extractor<BugPatternTestCa
* is safe, because this code is guarded by an earlier call to `#getClassUnderTest(..)`,
* which ensures that `tree` is part of a longer method invocation chain.
*/
MethodInvocationTree inputTree =
(MethodInvocationTree)
requireNonNull(
ASTHelpers.getReceiver(tree), "Instance method invocation must have receiver");
MethodInvocationTree inputTree = (MethodInvocationTree) ASTHelpers.getReceiver(tree);
String path = ASTHelpers.constValue(inputTree.getArguments().get(0), String.class);
Optional<String> inputCode = getSourceCode(inputTree);

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>error-prone-contrib</artifactId>
@@ -62,16 +62,6 @@
<artifactId>auto-value-annotations</artifactId>
<scope>provided</scope>
</dependency>
<!-- XXX: JSR-305 (meta-)annotation usage by some dependencies triggers
NullAway to attempt to load said annotations. As such some modules
require these annotations to be on the classpath. Periodically review
whether we can drop this dependeny declaration. See
https://github.com/uber/NullAway/issues/1171. -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotation</artifactId>

View File

@@ -11,7 +11,6 @@ import static com.google.errorprone.matchers.Matchers.not;
import static com.google.errorprone.matchers.Matchers.returnStatement;
import static com.google.errorprone.matchers.Matchers.staticMethod;
import static com.google.errorprone.matchers.Matchers.toType;
import static java.util.Objects.requireNonNull;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
@@ -80,10 +79,7 @@ public final class DirectReturn extends BugChecker implements BlockTreeMatcher {
return Description.NO_MATCH;
}
Symbol variableSymbol =
requireNonNull(
ASTHelpers.getSymbol(((ReturnTree) finalStatement).getExpression()),
"Missing symbol for returned variable");
Symbol variableSymbol = ASTHelpers.getSymbol(((ReturnTree) finalStatement).getExpression());
StatementTree precedingStatement = statements.get(statements.size() - 2);
return tryMatchAssignment(variableSymbol, precedingStatement)

View File

@@ -18,7 +18,6 @@ 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.common.collect.Iterables;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
@@ -34,8 +33,6 @@ import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -181,45 +178,30 @@ public final class ExplicitArgumentEnumeration extends BugChecker
state.getTypes())
.collect(toImmutableList());
return hasLikelySuitableVarargsOverload(method, overloads, state)
/*
* 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();
}
/**
* Tells whether it is likely that, if the argument to the given method is unwrapped, a suitable
* varargs overload will be invoked instead.
*
* <p>If all overloads have a single parameter, and at least one of them is a suitably-typed
* 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 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.)
*
* <p>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 validate that eligible overloads have compatible return types.
private static boolean hasLikelySuitableVarargsOverload(
MethodSymbol method, ImmutableList<MethodSymbol> overloads, VisitorState state) {
Types types = state.getTypes();
// XXX: This logic is fragile, as it assumes that the method parameter's type is of the form
// `X<T>`, where `T` is the type of the explicitly enumerated values passed to the expression to
// be unwrapped. This should generally hold, given the types returned by the
// `EXPLICIT_ITERABLE_CREATOR` expressions: `Iterable<T>`, `List<T>`, `Set<T>`, etc.
Type parameterType =
Iterables.getOnlyElement(
Iterables.getOnlyElement(method.getParameters()).type.getTypeArguments());
return overloads.stream().allMatch(m -> m.params().size() == 1)
&& overloads.stream()
.filter(MethodSymbol::isVarArgs)
.map(m -> types.elemtype(Iterables.getOnlyElement(m.getParameters()).type))
.anyMatch(varArgsType -> types.containsType(parameterType, varArgsType));
}
private static Optional<SuggestedFix> trySuggestCallingCustomAlternative(
MethodInvocationTree tree, MethodInvocationTree argument, VisitorState state) {
return ALTERNATIVE_METHODS.rowMap().entrySet().stream()

View File

@@ -17,7 +17,6 @@ import static com.google.errorprone.matchers.Matchers.isSameType;
import static com.google.errorprone.matchers.Matchers.methodHasParameters;
import static com.google.errorprone.matchers.Matchers.staticMethod;
import static com.google.errorprone.matchers.Matchers.toType;
import static java.util.Objects.requireNonNull;
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.joining;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
@@ -130,10 +129,7 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
return Description.NO_MATCH;
}
Type parameterType =
requireNonNull(
ASTHelpers.getType(Iterables.getOnlyElement(tree.getParameters())),
"Missing type for method parameter");
Type parameterType = ASTHelpers.getType(Iterables.getOnlyElement(tree.getParameters()));
return findMethodSourceAnnotation(tree, state)
.flatMap(
@@ -177,9 +173,7 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
private static Optional<MethodTree> findMatchingSibling(
MethodTree tree, Predicate<? super MethodTree> predicate, VisitorState state) {
return requireNonNull(state.findEnclosing(ClassTree.class), "No class enclosing method")
.getMembers()
.stream()
return state.findEnclosing(ClassTree.class).getMembers().stream()
.filter(MethodTree.class::isInstance)
.map(MethodTree.class::cast)
.filter(not(tree::equals))

View File

@@ -5,7 +5,6 @@ import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
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 java.util.Objects.requireNonNull;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
@@ -87,9 +86,7 @@ public final class NonEmptyMono extends BugChecker implements MethodInvocationTr
return Description.NO_MATCH;
}
ExpressionTree receiver =
requireNonNull(
ASTHelpers.getReceiver(tree), "Instance method invocation must have receiver");
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
if (!NON_EMPTY_MONO.matches(receiver, state)) {
return Description.NO_MATCH;
}

View File

@@ -204,11 +204,6 @@ final class AssertJEnumerableRules {
return enumAssert.hasSize(iterable.length);
}
@BeforeTemplate
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, CharSequence iterable) {
return enumAssert.hasSize(iterable.length());
}
@AfterTemplate
EnumerableAssert<?, S> after(EnumerableAssert<?, S> enumAssert, Iterable<E> iterable) {
return enumAssert.hasSameSizeAs(iterable);

View File

@@ -515,14 +515,8 @@ final class ReactorRules {
mono.switchIfEmpty(Mono.empty()), mono.flux().next(), mono.flux().singleOrEmpty());
}
// XXX: Consider filing a SonarCloud issue for the S2637 false positive.
@BeforeTemplate
@SuppressWarnings({
"java:S2637" /* False positive: result is never `null`. */,
"java:S4968" /* Result may be `Mono<Void>`. */,
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
})
Mono<? extends @Nullable Void> before2(Mono<@Nullable Void> mono) {
Mono<@Nullable Void> before2(Mono<@Nullable Void> mono) {
return Refaster.anyOf(mono.ignoreElement(), mono.then());
}
@@ -951,8 +945,7 @@ final class ReactorRules {
/** Prefer direct invocation of {@link Mono#then()}} over more contrived alternatives. */
static final class MonoThen<T> {
@BeforeTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> before(Mono<T> mono) {
Mono<@Nullable Void> before(Mono<T> mono) {
return Refaster.anyOf(
mono.ignoreElement().then(),
mono.flux().then(),
@@ -961,8 +954,7 @@ final class ReactorRules {
}
@AfterTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> after(Mono<T> mono) {
Mono<@Nullable Void> after(Mono<T> mono) {
return mono.then();
}
}
@@ -970,25 +962,17 @@ final class ReactorRules {
/** Avoid vacuous invocations of {@link Flux#ignoreElements()}. */
static final class FluxThen<T> {
@BeforeTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> before(Flux<T> flux) {
Mono<@Nullable Void> before(Flux<T> flux) {
return flux.ignoreElements().then();
}
// XXX: Consider filing a SonarCloud issue for the S2637 false positive.
@BeforeTemplate
@SuppressWarnings({
"java:S2637" /* False positive: result is never `null`. */,
"java:S4968" /* Result may be `Mono<Void>`. */,
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
})
Mono<? extends @Nullable Void> before2(Flux<@Nullable Void> flux) {
Mono<@Nullable Void> before2(Flux<@Nullable Void> flux) {
return flux.ignoreElements();
}
@AfterTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> after(Flux<T> flux) {
Mono<@Nullable Void> after(Flux<T> flux) {
return flux.then();
}
}
@@ -996,14 +980,12 @@ final class ReactorRules {
/** Avoid vacuous invocations of {@link Mono#ignoreElement()}. */
static final class MonoThenEmpty<T> {
@BeforeTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> before(Mono<T> mono, Publisher<@Nullable Void> publisher) {
Mono<@Nullable Void> before(Mono<T> mono, Publisher<@Nullable Void> publisher) {
return mono.ignoreElement().thenEmpty(publisher);
}
@AfterTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> after(Mono<T> mono, Publisher<@Nullable Void> publisher) {
Mono<@Nullable Void> after(Mono<T> mono, Publisher<@Nullable Void> publisher) {
return mono.thenEmpty(publisher);
}
}
@@ -1011,14 +993,12 @@ final class ReactorRules {
/** Avoid vacuous invocations of {@link Flux#ignoreElements()}. */
static final class FluxThenEmpty<T> {
@BeforeTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> before(Flux<T> flux, Publisher<@Nullable Void> publisher) {
Mono<@Nullable Void> before(Flux<T> flux, Publisher<@Nullable Void> publisher) {
return flux.ignoreElements().thenEmpty(publisher);
}
@AfterTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> after(Flux<T> flux, Publisher<@Nullable Void> publisher) {
Mono<@Nullable Void> after(Flux<T> flux, Publisher<@Nullable Void> publisher) {
return flux.thenEmpty(publisher);
}
}
@@ -1074,8 +1054,7 @@ final class ReactorRules {
}
@BeforeTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> before2(Mono<T> mono1, Mono<@Nullable Void> mono2) {
Mono<@Nullable Void> before2(Mono<T> mono1, Mono<@Nullable Void> mono2) {
return mono1.thenEmpty(mono2);
}
@@ -1093,8 +1072,7 @@ final class ReactorRules {
}
@BeforeTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> before2(Flux<T> flux, Mono<@Nullable Void> mono) {
Mono<@Nullable Void> before2(Flux<T> flux, Mono<@Nullable Void> mono) {
return flux.thenEmpty(mono);
}

View File

@@ -23,16 +23,14 @@ final class RxJava2AdapterRules {
/** Use the fluent API style when using {@link RxJava2Adapter#completableToMono}. */
static final class CompletableToMono {
@BeforeTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> before(Completable completable) {
Mono<@Nullable Void> before(Completable completable) {
return Refaster.anyOf(
RxJava2Adapter.completableToMono(completable),
completable.to(RxJava2Adapter::completableToMono));
}
@AfterTemplate
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
Mono<? extends @Nullable Void> after(Completable completable) {
Mono<@Nullable Void> after(Completable completable) {
return completable.as(RxJava2Adapter::completableToMono);
}
}

View File

@@ -0,0 +1,47 @@
package tech.picnic.errorprone.refasterrules;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import org.springframework.test.json.JsonCompareMode;
import org.springframework.test.web.reactive.server.WebTestClient.BodyContentSpec;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
/** Refaster rules related to Spring Test expressions and statements. */
@OnlineDocumentation
final class SpringTestRules {
private SpringTestRules() {}
/**
* Prefer {@link BodyContentSpec#json(String, JsonCompareMode)} over alternatives that implicitly
* perform a {@link JsonCompareMode#LENIENT lenient} comparison or are deprecated.
*/
static final class BodyContentSpecJsonLenient {
@BeforeTemplate
@SuppressWarnings("deprecation" /* This deprecated method invocation will be rewritten. */)
BodyContentSpec before(BodyContentSpec spec, String expectedJson) {
return Refaster.anyOf(spec.json(expectedJson), spec.json(expectedJson, /* strict= */ false));
}
@AfterTemplate
BodyContentSpec after(BodyContentSpec spec, String expectedJson) {
return spec.json(expectedJson, JsonCompareMode.LENIENT);
}
}
/**
* Prefer {@link BodyContentSpec#json(String, JsonCompareMode)} over the deprecated alternative.
*/
static final class BodyContentSpecJsonStrict {
@BeforeTemplate
@SuppressWarnings("deprecation" /* This deprecated method invocation will be rewritten. */)
BodyContentSpec before(BodyContentSpec spec, String expectedJson) {
return spec.json(expectedJson, /* strict= */ true);
}
@AfterTemplate
BodyContentSpec after(BodyContentSpec spec, String expectedJson) {
return spec.json(expectedJson, JsonCompareMode.STRICT);
}
}
}

View File

@@ -16,8 +16,6 @@ final class ExplicitArgumentEnumerationTest {
"import com.google.common.collect.ImmutableList;",
"import com.google.errorprone.CompilationTestHelper;",
"import com.google.errorprone.bugpatterns.BugChecker;",
"import io.micrometer.core.instrument.Counter;",
"import io.micrometer.core.instrument.Tag;",
"import org.jooq.impl.DSL;",
"import reactor.core.publisher.Flux;",
"import reactor.test.StepVerifier;",
@@ -34,8 +32,6 @@ final class ExplicitArgumentEnumerationTest {
"",
" DSL.row(ImmutableList.of(1, 2));",
"",
" Counter.builder(\"foo\").tags(ImmutableList.of(Tag.of(\"bar\", \"baz\")));",
"",
" // BUG: Diagnostic contains:",
" unaryMethod(ImmutableList.of(1, 2));",
" unaryMethodWithLessVisibleOverload(ImmutableList.of(1, 2));",

View File

@@ -73,6 +73,7 @@ final class RefasterRulesTest {
PrimitiveRules.class,
ReactorRules.class,
RxJava2AdapterRules.class,
SpringTestRules.class,
StreamRules.class,
StringRules.class,
SuggestedFixRules.class,

View File

@@ -67,11 +67,10 @@ final class AssertJEnumerableRulesTest implements RefasterRuleCollectionTestCase
assertThat(ImmutableSet.of(4)).size().isBetween(5, 6));
}
ImmutableSet<EnumerableAssert<?, Character>> testEnumerableAssertHasSameSizeAs() {
ImmutableSet<EnumerableAssert<?, Integer>> testEnumerableAssertHasSameSizeAs() {
return ImmutableSet.of(
assertThat("foo").hasSize(Iterables.size(ImmutableSet.of(1))),
assertThat("bar").hasSize(ImmutableSet.of(2).size()),
assertThat("baz").hasSize(new Integer[0].length),
assertThat("qux").hasSize("quux".length()));
assertThat(ImmutableSet.of(1)).hasSize(Iterables.size(ImmutableSet.of(2))),
assertThat(ImmutableSet.of(3)).hasSize(ImmutableSet.of(4).size()),
assertThat(ImmutableSet.of(5)).hasSize(new Integer[0].length));
}
}

View File

@@ -66,11 +66,10 @@ final class AssertJEnumerableRulesTest implements RefasterRuleCollectionTestCase
assertThat(ImmutableSet.of(4)).hasSizeBetween(5, 6));
}
ImmutableSet<EnumerableAssert<?, Character>> testEnumerableAssertHasSameSizeAs() {
ImmutableSet<EnumerableAssert<?, Integer>> testEnumerableAssertHasSameSizeAs() {
return ImmutableSet.of(
assertThat("foo").hasSameSizeAs(ImmutableSet.of(1)),
assertThat("bar").hasSameSizeAs(ImmutableSet.of(2)),
assertThat("baz").hasSameSizeAs(new Integer[0]),
assertThat("qux").hasSameSizeAs("quux"));
assertThat(ImmutableSet.of(1)).hasSameSizeAs(ImmutableSet.of(2)),
assertThat(ImmutableSet.of(3)).hasSameSizeAs(ImmutableSet.of(4)),
assertThat(ImmutableSet.of(5)).hasSameSizeAs(new Integer[0]));
}
}

View File

@@ -0,0 +1,18 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableSet;
import org.springframework.test.web.reactive.server.WebTestClient.BodyContentSpec;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class SpringTestRulesTest implements RefasterRuleCollectionTestCase {
@SuppressWarnings("deprecation" /* Rule rewrites deprecated method invocation. */)
ImmutableSet<BodyContentSpec> testBodyContentSpecJsonLenient() {
return ImmutableSet.of(
((BodyContentSpec) null).json("foo"), ((BodyContentSpec) null).json("bar", false));
}
@SuppressWarnings("deprecation" /* Rule rewrites deprecated method invocation. */)
BodyContentSpec testBodyContentSpecJsonStrict() {
return ((BodyContentSpec) null).json("foo", true);
}
}

View File

@@ -0,0 +1,20 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableSet;
import org.springframework.test.json.JsonCompareMode;
import org.springframework.test.web.reactive.server.WebTestClient.BodyContentSpec;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class SpringTestRulesTest implements RefasterRuleCollectionTestCase {
@SuppressWarnings("deprecation" /* Rule rewrites deprecated method invocation. */)
ImmutableSet<BodyContentSpec> testBodyContentSpecJsonLenient() {
return ImmutableSet.of(
((BodyContentSpec) null).json("foo", JsonCompareMode.LENIENT),
((BodyContentSpec) null).json("bar", JsonCompareMode.LENIENT));
}
@SuppressWarnings("deprecation" /* Rule rewrites deprecated method invocation. */)
BodyContentSpec testBodyContentSpecJsonStrict() {
return ((BodyContentSpec) null).json("foo", JsonCompareMode.STRICT);
}
}

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>error-prone-experimental</artifactId>

View File

@@ -29,7 +29,6 @@ import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Type;
import java.util.List;
import java.util.Optional;
@@ -127,7 +126,7 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
return Optional.empty();
}
Symbol sym = ASTHelpers.getSymbol(subTree);
Symbol sym = ASTHelpers.getSymbol(methodSelect);
return ASTHelpers.isStatic(sym)
? constructFix(lambdaExpr, sym.owner, methodSelect)
: constructFix(lambdaExpr, "this", methodSelect);
@@ -201,8 +200,7 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
Name sName = target.getSimpleName();
Optional<SuggestedFix.Builder> fix = constructFix(lambdaExpr, sName, methodName);
PackageSymbol pkg = ASTHelpers.enclosingPackage(target);
if (pkg != null && !"java.lang".equals(pkg.toString())) {
if (!"java.lang".equals(ASTHelpers.enclosingPackage(target).toString())) {
Name fqName = target.getQualifiedName();
if (!sName.equals(fqName)) {
return fix.map(b -> b.addImport(fqName.toString()));

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>error-prone-guidelines</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>error-prone-utils</artifactId>

View File

@@ -1,7 +1,5 @@
package tech.picnic.errorprone.utils;
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
@@ -117,15 +115,9 @@ public final class AnnotationAttributeMatcher implements Serializable {
}
private static String extractAttributeName(ExpressionTree expr) {
if (!(expr instanceof AssignmentTree assignment)) {
return "value";
}
return requireNonNull(
ASTHelpers.getSymbol(assignment.getVariable()),
"Missing symbol for annotation attribute")
.getSimpleName()
.toString();
return (expr instanceof AssignmentTree assignment)
? ASTHelpers.getSymbol(assignment.getVariable()).getSimpleName().toString()
: "value";
}
// XXX: The caller of this method can be implemented more efficiently in case of a "wholeTypes"

View File

@@ -38,7 +38,7 @@
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>33.4.7-jre<!-- Renovate: com.google.guava:guava-bom --></version>
+ <version>33.4.0-jre<!-- Renovate: com.google.guava:guava-bom --></version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>

57
pom.xml
View File

@@ -4,7 +4,7 @@
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Picnic :: Error Prone Support</name>
@@ -146,7 +146,7 @@
<error-prone.self-check-args />
<!-- The build timestamp is derived from the most recent commit
timestamp in support of reproducible builds. -->
<project.build.outputTimestamp>2025-04-14T09:36:15Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2025-03-24T10:41:07Z</project.build.outputTimestamp>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Glob pattern identifying Refaster rule definition files. These
Java classes don't contain "regular" code, and thus require special
@@ -211,11 +211,11 @@
<version.guava-beta-checker>1.0</version.guava-beta-checker>
<version.jdk>17</version.jdk>
<version.maven>3.9.9</version.maven>
<version.mockito>5.17.0</version.mockito>
<version.mockito>5.16.1</version.mockito>
<version.nopen-checker>1.0.1</version.nopen-checker>
<version.nullaway>0.12.6</version.nullaway>
<version.pitest-git>2.2.1</version.pitest-git>
<version.rewrite-templating>1.25.1</version.rewrite-templating>
<version.nullaway>0.12.5</version.nullaway>
<version.pitest-git>2.2.0</version.pitest-git>
<version.rewrite-templating>1.24.1</version.rewrite-templating>
<version.surefire>3.2.3</version.surefire>
</properties>
@@ -303,16 +303,6 @@
<artifactId>auto-value-annotations</artifactId>
<version>${version.auto-value}</version>
</dependency>
<!-- XXX: JSR-305 (meta-)annotation usage by some dependencies
triggers NullAway to attempt to load said annotations. As such
some modules require these annotations to be on the classpath.
Periodically review whether we can drop this dependeny version
declaration. See https://github.com/uber/NullAway/issues/1171. -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotation</artifactId>
@@ -341,7 +331,7 @@
<dependency>
<groupId>com.google.googlejavaformat</groupId>
<artifactId>google-java-format</artifactId>
<version>1.26.0</version>
<version>1.25.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
@@ -351,7 +341,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-bom</artifactId>
<version>33.4.7-jre</version>
<version>33.4.0-jre</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -373,14 +363,14 @@
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-bom</artifactId>
<version>1.14.6</version>
<version>1.14.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-bom</artifactId>
<version>2024.0.5</version>
<version>2024.0.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -397,7 +387,7 @@
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.2.30</version>
<version>2.2.29</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
@@ -432,7 +422,7 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.17.5</version>
<version>1.17.4</version>
</dependency>
<!-- Specified so that Renovate will file Maven upgrade PRs, which
subsequently will cause `maven-enforcer-plugin` to require that
@@ -445,7 +435,7 @@
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.24</version>
<version>1.9.23</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
@@ -457,7 +447,7 @@
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.49.2</version>
<version>3.49.1</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
@@ -482,7 +472,7 @@
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.12.2</version>
<version>5.12.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -508,7 +498,7 @@
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-recipe-bom</artifactId>
<version>3.6.1</version>
<version>3.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -620,7 +610,7 @@
<plugin>
<groupId>de.thetaphi</groupId>
<artifactId>forbiddenapis</artifactId>
<version>3.9</version>
<version>3.8</version>
<configuration>
<bundledSignatures>
<bundledSignature>jdk-internal</bundledSignature>
@@ -935,7 +925,7 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.23.0</version>
<version>10.21.4</version>
</dependency>
<dependency>
<groupId>io.spring.nohttp</groupId>
@@ -1146,7 +1136,7 @@
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.10.0</version>
<version>1.9.0</version>
</dependency>
</dependencies>
<executions>
@@ -1310,7 +1300,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.3</version>
<version>3.5.2</version>
<configuration>
<includes>
<include>**/*Test.java</include>
@@ -1507,7 +1497,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.13</version>
<version>0.8.12</version>
<configuration>
<excludes>
<!-- Refaster rules are tested using a custom method
@@ -1537,7 +1527,7 @@
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.19.1</version>
<version>1.19.0</version>
<configuration>
<excludedClasses>
<!-- AutoValue generated classes. -->
@@ -1591,7 +1581,7 @@
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>5.1.0.4751</version>
<version>5.0.0.4389</version>
</plugin>
</plugins>
</pluginManagement>
@@ -1950,7 +1940,6 @@
-XepOpt:NullAway:AnnotatedPackages=tech.picnic
-XepOpt:NullAway:AssertsEnabled=true
-XepOpt:NullAway:CheckOptionalEmptiness=true
-XepOpt:NullAway:JSpecifyMode=true
-XepOpt:Nullness:Conservative=false
-XepOpt:StatementSwitchToExpressionSwitch:EnableDirectConversion=true
<!-- Append additional custom arguments. -->

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>refaster-compiler</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>refaster-runner</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>refaster-support</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.22.1-SNAPSHOT</version>
<version>0.21.1-SNAPSHOT</version>
</parent>
<artifactId>refaster-test-support</artifactId>

View File

@@ -1,9 +1,6 @@
# An overview of Error Prone Support releases, along with compatible Error
# Prone releases. This data was generated by `generate-version-compatibility-overview.sh`.
releases:
- version: 0.22.0
compatible:
- "2.37.0"
- version: 0.21.0
compatible:
- "2.37.0"