Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ Please replace this sentence with log output, if applicable.

<!-- Please complete the following information: -->

- Operating system (e.g. MacOS Monterey).
- Java version (i.e. `java --version`, e.g. `17.0.16`).
- Error Prone version (e.g. `2.41.0`).
- Error Prone Support version (e.g. `0.24.0`).
- Operating system (e.g. MacOS Tahoe).
- Java version (i.e. `java --version`, e.g. `21.0.8`).
- Error Prone version (e.g. `2.43.0`).
- Error Prone Support version (e.g. `0.26.0`).

### Additional context

Expand Down
10 changes: 3 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,8 @@ jobs:
strategy:
matrix:
os: [ ubuntu-24.04, macos-15, windows-2025 ]
build-jdk: [ 21.0.8 ]
target-jdk: [ 17.0.16 ]
include:
- os: ubuntu-24.04
build-jdk: 25
target-jdk: 17.0.16
build-jdk: [ 25 ]
target-jdk: [ 21.0.8 ]
runs-on: ${{ matrix.os }}
steps:
- name: Install Harden-Runner
Expand Down Expand Up @@ -84,7 +80,7 @@ jobs:
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@6c4e9964d4ecb8f1026310cd8618791fd51a8016 # v1.19.0
with:
java-version: 21.0.8
java-version: 25
java-distribution: temurin
maven-version: 3.9.11
- name: Build and deploy
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@6c4e9964d4ecb8f1026310cd8618791fd51a8016 # v1.19.0
with:
java-version: 21.0.8
java-version: 25
java-distribution: temurin
maven-version: 3.9.11
- name: Initialize CodeQL
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/error-prone-compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@6c4e9964d4ecb8f1026310cd8618791fd51a8016 # v1.19.0
with:
java-version: 21.0.8
java-version: 25
java-distribution: temurin
maven-version: 3.9.11
- name: Quickly build and install project
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
uses: s4u/setup-maven-action@6c4e9964d4ecb8f1026310cd8618791fd51a8016 # v1.19.0
with:
checkout-ref: ${{ github.event.issue.pull_request && format('refs/pull/{0}/head', github.event.issue.number) || github.ref }}
java-version: 21.0.8
java-version: 25
java-distribution: temurin
maven-version: 3.9.11
- name: Install project to local Maven repository
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pitest-analyze-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
uses: s4u/setup-maven-action@6c4e9964d4ecb8f1026310cd8618791fd51a8016 # v1.19.0
with:
checkout-fetch-depth: 2
java-version: 21.0.8
java-version: 25
java-distribution: temurin
maven-version: 3.9.11
- name: Run Pitest
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pitest-update-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@6c4e9964d4ecb8f1026310cd8618791fd51a8016 # v1.19.0
with:
java-version: 21.0.8
java-version: 25
java-distribution: temurin
maven-version: 3.9.11
- name: Download Pitest analysis artifact
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/reviewdog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@6c4e9964d4ecb8f1026310cd8618791fd51a8016 # v1.19.0
with:
java-version: 21.0.8
java-version: 25
java-distribution: temurin
maven-version: 3.9.11
- name: Set up Reviewdog
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
uses: s4u/setup-maven-action@6c4e9964d4ecb8f1026310cd8618791fd51a8016 # v1.19.0
with:
checkout-fetch-depth: 0
java-version: 21.0.8
java-version: 25
java-distribution: temurin
maven-version: 3.9.11
- name: Create missing `test` directory
Expand Down
2 changes: 0 additions & 2 deletions .mvn/jvm.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
-XX:ReservedCodeCacheSize=512m
-XX:SoftRefLRUPolicyMSPerMB=10
-XX:+UseParallelGC
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
Expand Down
3 changes: 3 additions & 0 deletions .sdkmanrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
java=25-tem
maven=3.9.11
mvnd=1.0.3
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ high-quality and consistent Java code_][picnic-blog-ep-post].

This library is built on top of [Error Prone][error-prone-orig-repo]. To use
it, read the installation guide for Maven or Gradle below. The library requires
that your build is executed using JDK 17 or above, but supports builds that
that your build is executed using JDK 21 or above, but supports builds that
[target][baeldung-java-source-target-options] older versions of Java.

#### Maven
Expand Down Expand Up @@ -188,7 +188,8 @@ rules][refaster-rules].

This is a [Maven][maven] project, so running `mvn clean install` performs a
full clean build and installs the library to your local Maven repository. While
the project targets JDK 17, building it requires JDK 21.
the project targets JDK 21, building it requires JDK 25. If you use
[SDKMAN!][sdmkan], simply run `sdk env` to configure the current shell.

Once you've made changes, the build may fail due to a warning or error emitted
by static code analysis. The flags and commands listed below allow you to
Expand Down Expand Up @@ -322,6 +323,7 @@ OSS license generously provided by [Arcmutate][arcmutate]. Check them out!
[script-run-branch-mutation-tests]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/run-branch-mutation-tests.sh
[script-run-full-build]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/run-full-build.sh
[script-run-mutation-tests]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/run-mutation-tests.sh
[sdkman]: https://sdkman.io
[security]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/SECURITY.md
[sonarcloud-coverage-badge]: https://sonarcloud.io/api/project_badges/measure?project=PicnicSupermarket_error-prone-support&metric=coverage
[sonarcloud-coverage-master]: https://sonarcloud.io/component_measures?id=PicnicSupermarket_error-prone-support&metric=coverage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ private ImmutableList<BugPatternTestCase> getCollectedTests() {
private static Optional<String> getClassUnderTest(
MethodInvocationTree tree, VisitorState state) {
if (TEST_HELPER_NEW_INSTANCE.matches(tree, state)) {
return Optional.ofNullable(ASTHelpers.getSymbol(tree.getArguments().get(0)))
return Optional.ofNullable(ASTHelpers.getSymbol(tree.getArguments().getFirst()))
.filter(s -> !s.type.allparams().isEmpty())
.map(s -> s.type.allparams().get(0).tsym.getQualifiedName().toString());
.map(s -> s.type.allparams().getFirst().tsym.getQualifiedName().toString());
}

ExpressionTree receiver = ASTHelpers.getReceiver(tree);
Expand All @@ -142,7 +142,7 @@ private static Optional<String> getClassUnderTest(
private static void extractIdentificationBugPatternTestCases(
MethodInvocationTree tree, List<TestEntry> sink, VisitorState state) {
if (IDENTIFICATION_SOURCE_LINES.matches(tree, state)) {
String path = ASTHelpers.constValue(tree.getArguments().get(0), String.class);
String path = ASTHelpers.constValue(tree.getArguments().getFirst(), String.class);
Optional<String> sourceCode =
getSourceCode(tree).filter(s -> s.contains("// BUG: Diagnostic"));
if (path != null && sourceCode.isPresent()) {
Expand All @@ -169,7 +169,7 @@ private static void extractReplacementBugPatternTestCases(
requireNonNull(
ASTHelpers.getReceiver(tree), "Instance method invocation must have receiver");

String path = ASTHelpers.constValue(inputTree.getArguments().get(0), String.class);
String path = ASTHelpers.constValue(inputTree.getArguments().getFirst(), String.class);
Optional<String> inputCode = getSourceCode(inputTree);
if (path != null && inputCode.isPresent()) {
Optional<String> outputCode =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ public static void compileWithDocumentationGenerator(
String outputDirectory, String path, String... lines) {
/*
* The compiler options specified here largely match those used by Error Prone's
* `CompilationTestHelper`. A key difference is the stricter linting configuration. When
* compiling using JDK 21+, these lint options also require that certain JDK modules are
* explicitly exported.
* `CompilationTestHelper`. A key difference is the stricter linting configuration, which in
* turn also requires that certain JDK modules are explicitly exported.
*/
compile(
ImmutableList.of(
Expand Down
5 changes: 0 additions & 5 deletions error-prone-contrib/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,6 @@
<artifactId>rewrite-java</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openrewrite</groupId>
<artifactId>rewrite-java-17</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openrewrite</groupId>
<artifactId>rewrite-java-21</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private static Optional<Fix> dropRedundantValueAttribute(
return Optional.empty();
}

ExpressionTree arg = args.get(0);
ExpressionTree arg = args.getFirst();
if (state.getSourceForNode(arg) == null) {
/*
* The annotation argument doesn't have a source representation, e.g. because `value` isn't
Expand Down Expand Up @@ -139,7 +139,7 @@ private static Optional<String> simplifyAttributeValue(ExpressionTree expr, Visi
private static Optional<String> simplifySingletonArray(NewArrayTree array, VisitorState state) {
return Optional.of(array.getInitializers())
.filter(initializers -> initializers.size() == 1)
.map(initializers -> SourceCode.treeToString(initializers.get(0), state));
.map(initializers -> SourceCode.treeToString(initializers.getFirst(), state));
}

private static Optional<String> dropTrailingComma(NewArrayTree array, VisitorState state) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public Description matchBlock(BlockTree tree, VisitorState state) {
return Description.NO_MATCH;
}

StatementTree finalStatement = statements.get(statements.size() - 1);
StatementTree finalStatement = statements.getLast();
if (!VARIABLE_RETURN.matches(finalStatement, state)) {
return Description.NO_MATCH;
}
Expand Down Expand Up @@ -105,24 +105,20 @@ public Description matchBlock(BlockTree tree, VisitorState state) {
}

private static Optional<ExpressionTree> tryMatchAssignment(Symbol targetSymbol, Tree tree) {
if (tree instanceof ExpressionStatementTree expressionStatement) {
return tryMatchAssignment(targetSymbol, expressionStatement.getExpression());
}

if (tree instanceof AssignmentTree assignment) {
return targetSymbol.equals(ASTHelpers.getSymbol(assignment.getVariable()))
? Optional.of(assignment.getExpression())
: Optional.empty();
}

if (tree instanceof VariableTree declaration) {
return declaration.getModifiers().getAnnotations().isEmpty()
&& targetSymbol.equals(ASTHelpers.getSymbol(declaration))
? Optional.ofNullable(declaration.getInitializer())
: Optional.empty();
}

return Optional.empty();
return switch (tree) {
case ExpressionStatementTree expressionStatement ->
tryMatchAssignment(targetSymbol, expressionStatement.getExpression());
case AssignmentTree assignment ->
targetSymbol.equals(ASTHelpers.getSymbol(assignment.getVariable()))
? Optional.of(assignment.getExpression())
: Optional.empty();
case VariableTree declaration ->
declaration.getModifiers().getAnnotations().isEmpty()
&& targetSymbol.equals(ASTHelpers.getSymbol(declaration))
? Optional.ofNullable(declaration.getInitializer())
: Optional.empty();
default -> Optional.empty();
};
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private Description analyzeFormatStringContext(
private Description analyzeRequireNonNullStringFormatContext(
StringFormatExpression stringFormat, MethodInvocationTree context) {
List<? extends ExpressionTree> arguments = context.getArguments();
if (arguments.size() != 2 || arguments.get(0).equals(stringFormat.expression())) {
if (arguments.size() != 2 || arguments.getFirst().equals(stringFormat.expression())) {
/* Vacuous validation that string formatting doesn't yield `null`. */
return buildDescription(context).setMessage(MESSAGE_NEVER_NULL_ARGUMENT).build();
}
Expand All @@ -157,7 +157,7 @@ private Description analyzeRequireNonNullStringFormatContext(
private Description analyzeGuavaGuardStringFormatContext(
StringFormatExpression stringFormat, MethodInvocationTree context, VisitorState state) {
List<? extends ExpressionTree> arguments = context.getArguments();
if (arguments.get(0).equals(stringFormat.expression())) {
if (arguments.getFirst().equals(stringFormat.expression())) {
/*
* Vacuous `checkNotNull` or `verifyNotNull` validation that string formatting doesn't yield
* `null`.
Expand Down Expand Up @@ -185,8 +185,8 @@ private Description analyzeSlf4jLoggerStringFormatContext(
}

List<? extends ExpressionTree> arguments = context.getArguments();
int leftOffset = SLF4J_MARKER.matches(arguments.get(0), state) ? 1 : 0;
int rightOffset = THROWABLE.matches(arguments.get(arguments.size() - 1), state) ? 1 : 0;
int leftOffset = SLF4J_MARKER.matches(arguments.getFirst(), state) ? 1 : 0;
int rightOffset = THROWABLE.matches(arguments.getLast(), state) ? 1 : 0;
if (arguments.size() != leftOffset + 1 + rightOffset) {
/*
* The format string produces a format string itself, or its result is the input to another
Expand Down Expand Up @@ -258,7 +258,7 @@ private static Optional<StringFormatExpression> tryCreate(

if (STATIC_FORMAT_STRING.matches(tree, state)) {
List<? extends ExpressionTree> arguments = tree.getArguments();
int argOffset = LOCALE.matches(arguments.get(0), state) ? 1 : 0;
int argOffset = LOCALE.matches(arguments.getFirst(), state) ? 1 : 0;
return Optional.of(
create(
tree,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
.named("copyOf"),
symbolMatcher(
(symbol, state) ->
state.getTypes().isArray(((MethodSymbol) symbol).params().get(0).type))),
state.getTypes().isArray(((MethodSymbol) symbol).params().getFirst().type))),
staticMethod().onClass(Arrays.class.getCanonicalName()).named("asList"));
private static final Matcher<ExpressionTree> FLUX =
staticMethod().onDescendantOf("reactor.core.publisher.Flux");
Expand Down Expand Up @@ -141,7 +141,7 @@
return Description.NO_MATCH;
}

ExpressionTree argument = tree.getArguments().get(0);
ExpressionTree argument = tree.getArguments().getFirst();
if (!EXPLICIT_ITERABLE_CREATOR.matches(argument, state)) {
return Description.NO_MATCH;
}
Expand All @@ -156,7 +156,7 @@
List<VarSymbol> params = method.params();
return !method.isVarArgs()
&& params.size() == 1
&& ASTHelpers.isSubtype(params.get(0).type, state.getSymtab().iterableType, state);
&& ASTHelpers.isSubtype(params.getFirst().type, state.getSymtab().iterableType, state);

Check warning on line 159 in error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/ExplicitArgumentEnumeration.java

View workflow job for this annotation

GitHub Actions / pitest

A change can be made to line 159 without causing a test to fail

removed conditional - replaced equality check with true (covered by 3 tests RemoveConditionalMutator_EQUAL_IF)
}

private static boolean isLocalOverload(MethodSymbol calledMethod, VisitorState state) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState
return Description.NO_MATCH;
}

ExpressionTree sourceTree = arguments.get(0);
ExpressionTree sourceTree = arguments.getFirst();
Type sourceType = ASTHelpers.getType(sourceTree);
Type resultType = ASTHelpers.getType(tree);
TargetType targetType = TargetType.targetType(state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public Description matchModifiers(ModifiersTree tree, VisitorState state) {
}

return describeMatch(
originalOrdering.get(0), fixOrdering(originalOrdering, sortedAnnotations, state));
originalOrdering.getFirst(), fixOrdering(originalOrdering, sortedAnnotations, state));
}

private static ImmutableList<? extends AnnotationTree> sort(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import java.util.List;
Expand Down Expand Up @@ -64,18 +66,18 @@ public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState
}

List<? extends ExpressionTree> arguments = tree.getArguments();
return describeMatch(tree, SuggestedFixes.removeElement(arguments.get(0), arguments, state));
return describeMatch(
tree, SuggestedFixes.removeElement(arguments.getFirst(), arguments, state));
}

// XXX: Use switch pattern matching once the targeted JDK supports this.
private static boolean isTypeDerivableFromContext(MethodInvocationTree tree, VisitorState state) {
Tree parent = state.getPath().getParentPath().getLeaf();
return switch (parent.getKind()) {
case VARIABLE ->
!ASTHelpers.hasImplicitType((VariableTree) parent, state)
&& MoreASTHelpers.areSameType(tree, parent, state);
case ASSIGNMENT -> MoreASTHelpers.areSameType(tree, parent, state);
case RETURN ->
return switch (parent) {
case VariableTree variable ->
!ASTHelpers.hasImplicitType(variable, state)
&& MoreASTHelpers.areSameType(tree, variable, state);
case AssignmentTree assignment -> MoreASTHelpers.areSameType(tree, assignment, state);
case ReturnTree returnTree ->
MoreASTHelpers.findMethodExitedOnReturn(state)
.filter(m -> MoreASTHelpers.areSameType(tree, m.getReturnType(), state))
.isPresent();
Expand Down
Loading