Compare commits

...

41 Commits

Author SHA1 Message Date
Stephan Schroevers
728814aa6a WIP (Use new SuggestedFix.mergeFixes()) 2024-12-01 15:53:55 +01:00
Rick Ossendrijver
b3d391c80d Introduce Dropwizard Metrics integration test (#1426) 2024-11-28 15:05:35 +01:00
Picnic-DevPla-Bot
43a1ea1d6c Upgrade Spring 6.1.14 -> 6.2.0 (#1422)
See:
- https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-6.2-Release-Notes
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.15
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-M1
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-M2
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-M3
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-M4
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-M5
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-M6
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-M7
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-RC1
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-RC2
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0-RC3
- https://github.com/spring-projects/spring-framework/releases/tag/v6.2.0
- https://github.com/spring-projects/spring-framework/compare/v6.1.14...v6.2.0
2024-11-27 23:04:26 +01:00
Picnic-DevPla-Bot
c4fd4871fc Replace deprecated Renovate configuration (#1438) 2024-11-27 18:24:54 +01:00
Picnic-DevPla-Bot
23bbb34fb7 Upgrade Spring Boot 3.3.5 -> 3.4.0 (#1435)
See:
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.6
- https://github.com/spring-projects/spring-boot/releases/tag/v3.4.0-M1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.4.0-M2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.4.0-M3
- https://github.com/spring-projects/spring-boot/releases/tag/v3.4.0-RC1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.4.0
- https://github.com/spring-projects/spring-boot/compare/v3.3.5...v3.4.0
2024-11-27 15:42:03 +01:00
Picnic-DevPla-Bot
56a82e56c0 Upgrade Micrometer 1.13.6 -> 1.14.0 (#1415)
While there, use the provided BOM.

See:
- https://github.com/micrometer-metrics/micrometer/releases/tag/v1.14.0
- https://github.com/micrometer-metrics/micrometer/releases/tag/v1.13.7
- https://github.com/micrometer-metrics/micrometer/compare/v1.13.6...v1.14.0
2024-11-27 14:50:05 +01:00
Picnic-DevPla-Bot
8f0d870fff Upgrade Spring Security 6.3.4 -> 6.4.1 (#1433)
See:
- https://docs.spring.io/spring-security/reference/6.4/whats-new.html
- https://github.com/spring-projects/spring-security/releases/tag/6.3.5
- https://github.com/spring-projects/spring-security/releases/tag/6.4.0-M1
- https://github.com/spring-projects/spring-security/releases/tag/6.4.0-M2
- https://github.com/spring-projects/spring-security/releases/tag/6.4.0-M3
- https://github.com/spring-projects/spring-security/releases/tag/6.4.0-M4
- https://github.com/spring-projects/spring-security/releases/tag/6.4.0-RC1
- https://github.com/spring-projects/spring-security/releases/tag/6.4.0
- https://github.com/spring-projects/spring-security/releases/tag/6.4.1
- https://github.com/spring-projects/spring-security/compare/6.3.4...6.4.1
2024-11-27 14:38:11 +01:00
Stephan Schroevers
d531ceb9c6 Fix Slf4jLoggerDeclaration flag name (#1436) 2024-11-25 09:07:04 +01:00
Stephan Schroevers
dc87aeda6c Improve integration test setup (#1427)
Summary of changes:
- Configure Renovate to update AssertJ and fmt-maven-plugin version
  references in patch files and shell scripts any time those
  dependencies are updated in the top-level `pom.xml`.
- Enhance the `--sync` flag such that it also updates the initial patch
  file, avoiding drift due to line shifts.
2024-11-20 13:58:28 +01:00
Picnic-DevPla-Bot
1668546450 Upgrade Swagger 2.2.25 -> 2.2.26 (#1432)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.26
- https://github.com/swagger-api/swagger-core/compare/v2.2.25...v2.2.26
2024-11-20 09:04:42 +01:00
Stephan Schroevers
fc9c20062a Introduce RedundantStringEscape check (#1138)
This check aims to simplify string constants by dropping redundant
single quote escape sequences. The check is optimized for performance.

While there, update existing checks such that they do not introduce
violations of the type flagged by this new check.
2024-11-18 20:33:08 +01:00
Rick Ossendrijver
27e9fe79a5 Upgrade Checkstyle integration test target 10.14.0 -> 10.21.1 (#1425) 2024-11-18 18:00:39 +01:00
Picnic-DevPla-Bot
e37280b752 Upgrade MongoDB driver 5.2.0 -> 5.2.1 (#1408)
See:
- https://jira.mongodb.org/issues/?jql=project%20%3D%20JAVA%20AND%20fixVersion%20%3E%205.2.0%20AND%20fixVersion%20%3C%3D%205.2.1
- https://github.com/mongodb/mongo-java-driver/releases/tag/r5.2.1
- https://github.com/mongodb/mongo-java-driver/compare/r5.2.0...r5.2.1
2024-11-18 09:03:57 +01:00
Stephan Schroevers
fff368c80a Update Checkstyle integration test (#1424)
Summary of changes:
- Move Checkstyle-specific build parameters out of
  `run-integration-test.sh`.
- Build with `-Dmaven.compiler.failOnError=true` to compensate for
  `<failOnError>false</failOnError>` configured by the enabled Maven
  profiles.
- Tweak `XdocGenerator.java` logic prior to integration test execution,
  to work around a subtle semantic difference introduced by the
  `FilesCreateTempFileToFile` Refaster rule.
- Document this difference on the relevant Refaster rules.
- To aid debugging, run Maven commands with `set -x`, such that the
  exact command executed is logged.
- Update the patch file containing the expected changes.
2024-11-18 06:32:51 +01:00
Picnic-DevPla-Bot
37cbee0f0a Upgrade OpenRewrite Templating 1.17.0 -> 1.17.1 (#1418)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.17.1
- https://github.com/openrewrite/rewrite-templating/compare/v1.17.0...v1.17.1
2024-11-15 13:49:51 +01:00
Picnic-DevPla-Bot
141822b614 Upgrade OpenRewrite 2.21.1 -> 2.22.0 (#1419)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.22.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.21.1...v2.22.0
2024-11-15 13:19:35 +01:00
Picnic-DevPla-Bot
b1bfc1fd36 Upgrade versions-maven-plugin 2.17.1 -> 2.18.0 (#1420)
See:
- https://github.com/mojohaus/versions/releases/tag/2.18.0
- https://github.com/mojohaus/versions-maven-plugin/compare/2.17.1...2.18.0
2024-11-15 08:59:27 +01:00
Stephan Schroevers
13684ec59d Replace deprecated build-helper:remove-project-artifact goal (#1413) 2024-11-13 18:27:41 +01:00
Picnic-DevPla-Bot
a51ff4de4e Upgrade actions/checkout v4.1.6 -> v4.2.2 (#1401)
See:
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v422
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v421
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v420
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v417
2024-11-12 11:11:52 +01:00
Phil Werli
da9b313ff7 Introduce assorted Reactor StepVerifier Refaster rules (#1132) 2024-11-11 14:08:05 +01:00
Phil Werli
6a50fe2d9c Introduce Instant{Identity,TruncatedTo{Milliseconds,Seconds}} Refaster rules (#1395)
While there, have `IdentityConversion` support `Instant#from`.
2024-11-11 10:42:05 +01:00
Stephan Schroevers
ed32cbae06 Update step-security/harden-runner configuration (#1412)
By allowing access to Open Source Insights.
2024-11-11 08:46:49 +01:00
Picnic-DevPla-Bot
00549a3ba6 Upgrade org.openrewrite:rewrite-java-17 8.38.1 -> 8.40.0 (#1390)
See:
- https://github.com/openrewrite/rewrite/releases/tag/v8.40.0
- https://github.com/openrewrite/rewrite/releases/tag/v8.39.0
- https://github.com/openrewrite/rewrite/releases/tag/v8.38.3
- https://github.com/openrewrite/rewrite/releases/tag/v8.38.2
- https://github.com/openrewrite/rewrite/compare/v8.38.1...v8.40.0
2024-11-11 07:54:49 +01:00
Picnic-DevPla-Bot
13f1fa3167 Upgrade ossf/scorecard-action v2.3.3 -> v2.4.0 (#1403)
See:
- https://github.com/ossf/scorecard-action/releases/tag/v2.4.0
- https://github.com/ossf/scorecard-action/compare/v2.3.3...v2.4.0
2024-11-11 07:44:12 +01:00
Picnic-DevPla-Bot
6396def588 Upgrade sonar-maven-plugin 4.0.0.4121 -> 5.0.0.4389 (#1405)
See:
- https://github.com/SonarSource/sonar-scanner-maven/releases/tag/5.0.0.4389
- https://github.com/SonarSource/sonar-scanner-maven/compare/4.0.0.4121...5.0.0.4389
2024-11-10 22:04:47 +01:00
Picnic-DevPla-Bot
7599b0f22f Upgrade step-security/harden-runner v2.8.0 -> v2.10.1 (#1404)
See:
- https://github.com/step-security/harden-runner/releases/tag/v2.10.1
- https://github.com/step-security/harden-runner/releases/tag/v2.10.0
- https://github.com/step-security/harden-runner/releases/tag/v2.9.1
- https://github.com/step-security/harden-runner/releases/tag/v2.9.0
- https://github.com/step-security/harden-runner/releases/tag/v2.8.1
2024-11-10 21:33:56 +01:00
Picnic-DevPla-Bot
08eb7e7699 Upgrade OpenRewrite Templating 1.16.3 -> 1.17.0 (#1409)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.17.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.16.3...v1.17.0
2024-11-10 18:38:30 +01:00
Stephan Schroevers
89f918c23e Update step-security/harden-runner configuration (#1411)
By allowing Docker Hub and Maven Central access.
2024-11-10 18:26:40 +01:00
Stephan Schroevers
f08fc344f5 Track StreamFlatMapOptional Refaster rule caveat (#1410) 2024-11-10 15:14:08 +01:00
Picnic-DevPla-Bot
99aa656a1e Upgrade s4u/setup-maven-action v1.13.0 -> v1.16.0 (#1400)
See:
- https://github.com/s4u/setup-maven-action/releases/tag/v1.16.0
- https://github.com/s4u/setup-maven-action/releases/tag/v1.15.0
- https://github.com/s4u/setup-maven-action/releases/tag/v1.14.0
2024-11-09 10:27:57 +01:00
Picnic-DevPla-Bot
86fbaf7403 Upgrade Checkstyle 10.20.0 -> 10.20.1 (#1407)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.20.1
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.20.0...checkstyle-10.20.1
2024-11-08 19:37:12 +01:00
Picnic-DevPla-Bot
563012549a Upgrade pitest-maven-plugin 1.17.0 -> 1.17.1 (#1397)
See:
- https://github.com/hcoles/pitest/releases/tag/1.17.1
- https://github.com/hcoles/pitest/compare/1.17.0...1.17.1
2024-11-07 21:29:39 +01:00
Picnic-DevPla-Bot
4f46eb30d2 Upgrade actions/upload-artifact v4.3.3 -> v4.4.3 (#1402)
See:
- https://github.com/actions/upload-artifact/releases/tag/v4.4.3
- https://github.com/actions/upload-artifact/releases/tag/v4.4.2
- https://github.com/actions/upload-artifact/releases/tag/v4.4.1
- https://github.com/actions/upload-artifact/releases/tag/v4.4.0
- https://github.com/actions/upload-artifact/releases/tag/v4.3.6
- https://github.com/actions/upload-artifact/releases/tag/v4.3.5
- https://github.com/actions/upload-artifact/releases/tag/v4.3.4
2024-11-07 16:39:05 +01:00
Picnic-DevPla-Bot
2f30082127 Upgrade maven-javadoc-plugin 3.10.1 -> 3.11.1 (#1398)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MJAVADOC%20AND%20fixVersion%20%3E%203.10.1%20AND%20fixVersion%20%3C%3D%203.11.1
- https://github.com/apache/maven-javadoc-plugin/releases/tag/maven-javadoc-plugin-3.11.0
- https://github.com/apache/maven-javadoc-plugin/releases/tag/maven-javadoc-plugin-3.11.1
- https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.1...maven-javadoc-plugin-3.11.1
2024-11-07 12:48:15 +01:00
Stephan Schroevers
548506fbbb Update Error Prone compatibility matrix (#1406) 2024-11-07 10:54:08 +01:00
Picnic-DevPla-Bot
bdef83bce5 Upgrade Byte Buddy 1.15.7 -> 1.15.10 (#1388)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.8
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.9
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.10
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.15.7...byte-buddy-1.15.10
2024-11-06 09:03:44 +01:00
Picnic-DevPla-Bot
f7f665681d Upgrade Surefire 3.5.1 -> 3.5.2 (#1396)
See:
- https://github.com/apache/maven-surefire/releases/tag/surefire-3.5.2
- https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.2
2024-11-05 11:36:11 +01:00
Picnic-DevPla-Bot
7c0d544cf8 Upgrade Checker Framework Annotations 3.48.1 -> 3.48.2 (#1389)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.48.2
- https://github.com/typetools/checker-framework/compare/checker-framework-3.48.1...checker-framework-3.48.2
2024-11-04 14:51:00 +01:00
Stephan Schroevers
9390b6f571 Run GitHub Actions workflows on ubuntu-24.04 (#1391)
See https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
2024-11-03 18:36:54 +01:00
Stephan Schroevers
176a833d89 Upgrade ruby/setup-ruby v1.174.0 -> v1.199.0 (#1392)
See:
- https://github.com/ruby/setup-ruby/releases/tag/v1.175.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.176.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.177.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.178.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.179.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.180.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.181.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.182.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.183.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.184.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.185.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.186.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.187.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.188.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.189.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.190.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.191.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.192.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.193.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.194.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.195.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.196.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.197.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.198.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.199.0
- https://github.com/ruby/setup-ruby/compare/v1.174.0...v1.199.0
2024-11-03 18:17:38 +01:00
Stephan Schroevers
3cacd27248 [maven-release-plugin] prepare for next development iteration 2024-11-03 16:58:19 +01:00
62 changed files with 20578 additions and 5003 deletions

View File

@@ -9,7 +9,7 @@ jobs:
build:
strategy:
matrix:
os: [ ubuntu-22.04 ]
os: [ ubuntu-24.04 ]
jdk: [ 17.0.13, 21.0.5, 23.0.1 ]
distribution: [ temurin ]
experimental: [ false ]
@@ -26,7 +26,7 @@ jobs:
continue-on-error: ${{ matrix.experimental }}
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
@@ -42,7 +42,7 @@ jobs:
# additionally enabling all checks defined in this project and any Error
# Prone checks available only from other artifact repositories.
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
uses: s4u/setup-maven-action@382542f77617f34e56bf83868920a4d45b7451e7 # v1.16.0
with:
java-version: ${{ matrix.jdk }}
java-distribution: ${{ matrix.distribution }}
@@ -54,6 +54,6 @@ jobs:
- name: Build project with self-check against Error Prone fork
run: mvn -T1C clean verify -Perror-prone-fork -Pnon-maven-central -Pself-check -s settings.xml
- name: Remove installed project artifacts
run: mvn build-helper:remove-project-artifact
run: mvn dependency:purge-local-repository -DmanualInclude='${project.groupId}' -DresolutionFuzziness=groupId
# XXX: Enable Codecov once we "go public".

View File

@@ -19,10 +19,10 @@ jobs:
permissions:
contents: read
security-events: write
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
@@ -34,7 +34,7 @@ jobs:
repo.maven.apache.org:443
uploads.github.com:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
uses: s4u/setup-maven-action@382542f77617f34e56bf83868920a4d45b7451e7 # v1.16.0
with:
java-version: 17.0.13
java-distribution: temurin

View File

@@ -9,10 +9,10 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
@@ -39,10 +39,10 @@ jobs:
www.youtube.com:443
youtrack.jetbrains.com:443
- name: Check out code
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0
- uses: ruby/setup-ruby@7d3497fd78c07c0d84ebafa58d8dac60cd1f0763 # v1.199.0
with:
working-directory: ./website
bundler-cache: true
@@ -68,13 +68,13 @@ jobs:
permissions:
id-token: write
pages: write
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block

View File

@@ -18,28 +18,31 @@ jobs:
contents: read
security-events: write
id-token: write
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.deps.dev:443
api.github.com:443
api.osv.dev:443
api.scorecard.dev:443
api.securityscorecards.dev:443
github.com:443
index.docker.io:443
oss-fuzz-build-logs.storage.googleapis.com:443
repo.maven.apache.org:443
*.sigstore.dev:443
www.bestpractices.dev:443
- name: Check out code
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Run OpenSSF Scorecard analysis
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with:
results_file: results.sarif
results_format: sarif

View File

@@ -9,10 +9,10 @@ permissions:
contents: read
jobs:
analyze-pr:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
@@ -22,7 +22,7 @@ jobs:
objects.githubusercontent.com:443
repo.maven.apache.org:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
uses: s4u/setup-maven-action@382542f77617f34e56bf83868920a4d45b7451e7 # v1.16.0
with:
checkout-fetch-depth: 2
java-version: 17.0.13
@@ -38,7 +38,7 @@ jobs:
- name: Aggregate Pitest reports
run: mvn pitest-git:aggregate -DkilledEmoji=":tada:" -DmutantEmoji=":zombie:" -DtrailingText="Mutation testing report by [Pitest](https://pitest.org/). Review any surviving mutants by inspecting the line comments under [_Files changed_](${{ github.event.number }}/files)."
- name: Upload Pitest reports as artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: pitest-reports
path: ./target/pit-reports-ci

View File

@@ -17,10 +17,10 @@ jobs:
checks: write
contents: read
pull-requests: write
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
@@ -31,7 +31,7 @@ jobs:
objects.githubusercontent.com:443
repo.maven.apache.org:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
uses: s4u/setup-maven-action@382542f77617f34e56bf83868920a4d45b7451e7 # v1.16.0
with:
java-version: 17.0.13
java-distribution: temurin

View File

@@ -1,9 +1,9 @@
# If requested by means of a pull request comment, runs integration tests
# against the project, using the code found on the pull request branch.
# XXX: Generalize this to a matrix build of multiple integration tests,
# possibly using multiple JDK or OS versions.
# XXX: Investigate whether the comment can specify which integration tests run
# run. See this example of a dynamic build matrix:
# XXX: Review whether then build matrix should also vary JDK or OS versions.
# XXX: Support `/integration-test [name...]` comment syntax to specify the
# subset of integration tests to run.
# See this example of a dynamic build matrix:
# https://docs.github.com/en/actions/learn-github-actions/expressions#example-returning-a-json-object
name: "Integration tests"
on:
@@ -16,16 +16,20 @@ jobs:
name: On-demand integration test
if: |
github.event.issue.pull_request && contains(github.event.comment.body, '/integration-test')
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
strategy:
matrix:
integration-test: [ "checkstyle", "metrics" ]
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.adoptium.net:443
checkstyle.org:443
example.com:80
github.com:443
objects.githubusercontent.com:443
oss.sonatype.org:443
@@ -33,7 +37,7 @@ jobs:
repo.maven.apache.org:443
repository.sonatype.org:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
uses: s4u/setup-maven-action@382542f77617f34e56bf83868920a4d45b7451e7 # v1.16.0
with:
checkout-ref: "refs/pull/${{ github.event.issue.number }}/head"
java-version: 17.0.13
@@ -42,12 +46,12 @@ jobs:
- name: Install project to local Maven repository
run: mvn -T1C install -DskipTests -Dverification.skip
- name: Run integration test
run: xvfb-run ./integration-tests/checkstyle.sh "${{ runner.temp }}/artifacts"
run: xvfb-run "./integration-tests/${{ matrix.integration-test }}.sh" "${{ runner.temp }}/artifacts"
- name: Upload artifacts on failure
if: ${{ failure() }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: integration-test-checkstyle
name: "integration-test-${{ matrix.integration-test }}"
path: "${{ runner.temp }}/artifacts"
- name: Remove installed project artifacts
run: mvn build-helper:remove-project-artifact
run: mvn dependency:purge-local-repository -DmanualInclude='${project.groupId}' -DresolutionFuzziness=groupId

View File

@@ -16,10 +16,10 @@ jobs:
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
permissions:
contents: read
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
@@ -35,7 +35,7 @@ jobs:
*.sonarcloud.io:443
sonarcloud.io:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
uses: s4u/setup-maven-action@382542f77617f34e56bf83868920a4d45b7451e7 # v1.16.0
with:
checkout-fetch-depth: 0
java-version: 17.0.13

View File

@@ -3,11 +3,24 @@
"extends": [
"helpers:pinGitHubActionDigests"
],
"customManagers": [
{
"customType": "regex",
"fileMatch": [
"^integration-tests/.*(-init\\.patch|\\.sh)$"
],
"matchStrings": [
"\\b(?<packageName>[a-z0-9_.-]+?:[a-z0-9_.-]+?):(?<currentValue>[^:]+?):[a-zA-Z0-9_-]+\\b",
"<version>(?<currentValue>.*?)<!-- Renovate: (?<packageName>.*?) --></version>"
],
"datasourceTemplate": "maven"
}
],
"packageRules": [
{
"matchPackagePatterns": [
"^org\\.springframework:spring-framework-bom$",
"^org\\.springframework\\.boot:spring-boot[a-z-]*$"
"matchPackageNames": [
"/^org\\.springframework:spring-framework-bom$/",
"/^org\\.springframework\\.boot:spring-boot[a-z-]*$/"
],
"separateMinorPatch": true
},

View File

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

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.19.1</version>
<version>0.19.2-SNAPSHOT</version>
</parent>
<artifactId>error-prone-contrib</artifactId>

View File

@@ -3,6 +3,7 @@ package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
import static java.util.function.Predicate.not;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
@@ -19,7 +20,6 @@ import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.NewArrayTree;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
@@ -38,12 +38,11 @@ import tech.picnic.errorprone.utils.SourceCode;
public final class CanonicalAnnotationSyntax extends BugChecker implements AnnotationTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Pattern TRAILING_ARRAY_COMMA = Pattern.compile(",\\s*}$");
private static final ImmutableSet<BiFunction<AnnotationTree, VisitorState, Optional<Fix>>>
FIX_FACTORIES =
ImmutableSet.of(
CanonicalAnnotationSyntax::dropRedundantParentheses,
CanonicalAnnotationSyntax::dropRedundantValueAttribute,
CanonicalAnnotationSyntax::dropRedundantCurlies);
private static final ImmutableSet<BiFunction<AnnotationTree, VisitorState, Fix>> FIX_FACTORIES =
ImmutableSet.of(
CanonicalAnnotationSyntax::dropRedundantParentheses,
CanonicalAnnotationSyntax::dropRedundantValueAttribute,
CanonicalAnnotationSyntax::dropRedundantCurlies);
/** Instantiates a new {@link CanonicalAnnotationSyntax} instance. */
public CanonicalAnnotationSyntax() {}
@@ -52,39 +51,38 @@ public final class CanonicalAnnotationSyntax extends BugChecker implements Annot
public Description matchAnnotation(AnnotationTree tree, VisitorState state) {
return FIX_FACTORIES.stream()
.map(op -> op.apply(tree, state))
.flatMap(Optional::stream)
.filter(not(Fix::isEmpty))
.findFirst()
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
}
private static Optional<Fix> dropRedundantParentheses(AnnotationTree tree, VisitorState state) {
private static Fix dropRedundantParentheses(AnnotationTree tree, VisitorState state) {
if (!tree.getArguments().isEmpty()) {
/* Parentheses are necessary. */
return Optional.empty();
return SuggestedFix.emptyFix();
}
String src = state.getSourceForNode(tree);
if (src == null) {
/* Without the source code there's not much we can do. */
return Optional.empty();
return SuggestedFix.emptyFix();
}
int parenIndex = src.indexOf('(');
if (parenIndex < 0) {
/* There are no redundant parentheses. */
return Optional.empty();
return SuggestedFix.emptyFix();
}
return Optional.of(SuggestedFix.replace(tree, src.substring(0, parenIndex)));
return SuggestedFix.replace(tree, src.substring(0, parenIndex));
}
private static Optional<Fix> dropRedundantValueAttribute(
AnnotationTree tree, VisitorState state) {
private static Fix dropRedundantValueAttribute(AnnotationTree tree, VisitorState state) {
List<? extends ExpressionTree> args = tree.getArguments();
if (args.size() != 1) {
/* The `value` attribute, if specified, cannot be dropped. */
return Optional.empty();
return SuggestedFix.emptyFix();
}
ExpressionTree arg = args.get(0);
@@ -93,25 +91,23 @@ public final class CanonicalAnnotationSyntax extends BugChecker implements Annot
* The annotation argument doesn't have a source representation, e.g. because `value` isn't
* assigned explicitly.
*/
return Optional.empty();
return SuggestedFix.emptyFix();
}
ExpressionTree expr = AnnotationMatcherUtils.getArgument(tree, "value");
if (expr == null) {
/* This is not an explicit assignment to the `value` attribute. */
return Optional.empty();
return SuggestedFix.emptyFix();
}
/* Replace the assignment with (the simplified representation of) just its value. */
return Optional.of(
SuggestedFix.replace(
arg,
simplifyAttributeValue(expr, state)
.orElseGet(() -> SourceCode.treeToString(expr, state))));
return SuggestedFix.replace(
arg,
simplifyAttributeValue(expr, state).orElseGet(() -> SourceCode.treeToString(expr, state)));
}
private static Optional<Fix> dropRedundantCurlies(AnnotationTree tree, VisitorState state) {
List<SuggestedFix.Builder> fixes = new ArrayList<>();
private static Fix dropRedundantCurlies(AnnotationTree tree, VisitorState state) {
SuggestedFix.Builder fix = SuggestedFix.builder();
for (ExpressionTree arg : tree.getArguments()) {
/*
* We'll try to simplify each assignment's RHS; for non-assignment we'll try to simplify
@@ -122,10 +118,10 @@ public final class CanonicalAnnotationSyntax extends BugChecker implements Annot
/* Store a fix for each expression that was successfully simplified. */
simplifyAttributeValue(value, state)
.ifPresent(expr -> fixes.add(SuggestedFix.builder().replace(value, expr)));
.ifPresent(expr -> fix.merge(SuggestedFix.replace(value, expr)));
}
return fixes.stream().reduce(SuggestedFix.Builder::merge).map(SuggestedFix.Builder::build);
return fix.build();
}
private static Optional<String> simplifyAttributeValue(ExpressionTree expr, VisitorState state) {

View File

@@ -39,6 +39,7 @@ import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import tech.picnic.errorprone.utils.SourceCode;
@@ -84,6 +85,7 @@ public final class IdentityConversion extends BugChecker implements MethodInvoca
ImmutableSetMultimap.class.getCanonicalName(),
ImmutableTable.class.getCanonicalName())
.named("copyOf"),
staticMethod().onClass(Instant.class.getCanonicalName()).namedAnyOf("from"),
staticMethod().onClass(Matchers.class.getCanonicalName()).namedAnyOf("allOf", "anyOf"),
staticMethod().onClass("reactor.adapter.rxjava.RxJava2Adapter"),
staticMethod()

View File

@@ -105,22 +105,19 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
@Override
public Description matchAnnotation(AnnotationTree tree, VisitorState state) {
return sortArrayElements(tree, state)
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
Fix fix = sortArrayElements(tree, state);
return fix.isEmpty() ? Description.NO_MATCH : describeMatch(tree, fix);
}
private Optional<Fix> sortArrayElements(AnnotationTree tree, VisitorState state) {
private Fix sortArrayElements(AnnotationTree tree, VisitorState state) {
/*
* We loop over the array's attributes, trying to sort each array associated with a
* non-blacklisted attribute. A single compound fix, if any, is returned.
*/
return matcher
.extractMatchingArguments(tree)
.map(expr -> extractArray(expr).flatMap(arr -> suggestSorting(arr, state)))
.flatMap(Optional::stream)
.reduce(SuggestedFix.Builder::merge)
.map(SuggestedFix.Builder::build);
.flatMap(expr -> extractArray(expr).map(arr -> suggestSorting(arr, state)).stream())
.collect(SuggestedFix.mergeFixes());
}
private static Optional<NewArrayTree> extractArray(ExpressionTree expr) {
@@ -129,18 +126,17 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
: Optional.of(expr).filter(NewArrayTree.class::isInstance).map(NewArrayTree.class::cast);
}
private static Optional<SuggestedFix.Builder> suggestSorting(
NewArrayTree array, VisitorState state) {
private static SuggestedFix suggestSorting(NewArrayTree array, VisitorState state) {
if (array.getInitializers().size() < 2 || !canSort(array, state)) {
/* There's nothing to sort, or we don't want to sort. */
return Optional.empty();
return SuggestedFix.emptyFix();
}
List<? extends ExpressionTree> actualOrdering = array.getInitializers();
ImmutableList<? extends ExpressionTree> desiredOrdering = doSort(actualOrdering);
if (actualOrdering.equals(desiredOrdering)) {
/* In the (presumably) common case the elements are already sorted. */
return Optional.empty();
return SuggestedFix.emptyFix();
}
/* The elements aren't sorted. Suggest the sorted alternative. */
@@ -148,7 +144,7 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
desiredOrdering.stream()
.map(expr -> SourceCode.treeToString(expr, state))
.collect(joining(", ", "{", "}"));
return Optional.of(SuggestedFix.builder().replace(array, suggestion));
return SuggestedFix.replace(array, suggestion);
}
private static boolean canSort(Tree array, VisitorState state) {

View File

@@ -10,7 +10,6 @@ import static java.util.Comparator.comparing;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import com.google.errorprone.BugPattern;
@@ -105,10 +104,7 @@ public final class LexicographicalAnnotationListing extends BugChecker
originalAnnotations.stream(),
sortedAnnotations.stream(),
(original, replacement) ->
SuggestedFix.builder()
.replace(original, SourceCode.treeToString(replacement, state)))
.reduce(SuggestedFix.Builder::merge)
.map(SuggestedFix.Builder::build)
.orElseThrow(() -> new VerifyException("No annotations were provided"));
SuggestedFix.replace(original, SourceCode.treeToString(replacement, state)))
.collect(SuggestedFix.mergeFixes());
}
}

View File

@@ -6,6 +6,7 @@ import static com.google.errorprone.BugPattern.StandardTags.PERFORMANCE;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.method.MethodMatchers.instanceMethod;
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
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;
@@ -85,22 +86,22 @@ public final class PrimitiveComparison extends BugChecker implements MethodInvoc
}
return getPotentiallyBoxedReturnType(tree.getArguments().get(0))
.flatMap(cmpType -> attemptMethodInvocationReplacement(tree, cmpType, isStatic, state))
.map(cmpType -> attemptMethodInvocationReplacement(tree, cmpType, isStatic, state))
.filter(not(SuggestedFix::isEmpty))
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
}
private static Optional<Fix> attemptMethodInvocationReplacement(
private static SuggestedFix attemptMethodInvocationReplacement(
MethodInvocationTree tree, Type cmpType, boolean isStatic, VisitorState state) {
String actualMethodName = ASTHelpers.getSymbol(tree).getSimpleName().toString();
String preferredMethodName = getPreferredMethod(cmpType, isStatic, state);
if (actualMethodName.equals(preferredMethodName)) {
return Optional.empty();
return SuggestedFix.emptyFix();
}
return Optional.of(
suggestFix(
tree, prefixTypeArgumentsIfRelevant(preferredMethodName, tree, cmpType, state), state));
return suggestFix(
tree, prefixTypeArgumentsIfRelevant(preferredMethodName, tree, cmpType, state), state);
}
/**
@@ -169,7 +170,7 @@ public final class PrimitiveComparison extends BugChecker implements MethodInvoc
}
// XXX: Use switch pattern matching once the targeted JDK supports this.
private static Fix suggestFix(
private static SuggestedFix suggestFix(
MethodInvocationTree tree, String preferredMethodName, VisitorState state) {
ExpressionTree expr = tree.getMethodSelect();

View File

@@ -44,7 +44,6 @@ import com.sun.source.tree.Tree.Kind;
import java.io.Console;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Formattable;
import java.util.Formatter;
import java.util.List;
@@ -177,18 +176,18 @@ public final class RedundantStringConversion extends BugChecker
return createDescription(tree, tryFix(rhs, state, STRING));
}
List<SuggestedFix.Builder> fixes = new ArrayList<>();
SuggestedFix.Builder fix = SuggestedFix.builder();
// XXX: Avoid trying to simplify the RHS twice.
ExpressionTree preferredRhs = trySimplify(rhs, state).orElse(rhs);
if (STRING.matches(preferredRhs, state)) {
tryFix(lhs, state, ANY_EXPR).ifPresent(fixes::add);
fix.merge(tryFix(lhs, state, ANY_EXPR));
} else {
tryFix(lhs, state, STRING).ifPresent(fixes::add);
fix.merge(tryFix(lhs, state, STRING));
}
tryFix(rhs, state, ANY_EXPR).ifPresent(fixes::add);
fix.merge(tryFix(rhs, state, ANY_EXPR));
return createDescription(tree, fixes.stream().reduce(SuggestedFix.Builder::merge));
return createDescription(tree, fix.build());
}
@Override
@@ -229,17 +228,18 @@ public final class RedundantStringConversion extends BugChecker
return createDescription(tree, tryFix(tree, state, NON_NULL_STRING));
}
private Optional<SuggestedFix.Builder> tryFixPositionalConverter(
private SuggestedFix tryFixPositionalConverter(
List<? extends ExpressionTree> arguments, VisitorState state, int index) {
return Optional.of(arguments)
.filter(args -> args.size() > index)
.flatMap(args -> tryFix(args.get(index), state, ANY_EXPR));
.map(args -> tryFix(args.get(index), state, ANY_EXPR))
.orElseGet(SuggestedFix::emptyFix);
}
// XXX: Write another check that checks that Formatter patterns don't use `{}` and have a
// matching number of arguments of the appropriate type. Also flag explicit conversions from
// `Formattable` to string.
private Optional<SuggestedFix.Builder> tryFixFormatter(
private SuggestedFix tryFixFormatter(
List<? extends ExpressionTree> arguments, VisitorState state) {
/*
* Formatter methods have an optional first `Locale` parameter; if present, it must be
@@ -258,7 +258,7 @@ public final class RedundantStringConversion extends BugChecker
return tryFixFormatterArguments(arguments, state, LOCALE, NOT_FORMATTABLE);
}
private Optional<SuggestedFix.Builder> tryFixGuavaGuard(
private SuggestedFix tryFixGuavaGuard(
List<? extends ExpressionTree> arguments, VisitorState state) {
/*
* All Guava guard methods accept a value to be checked, a format string and zero or more
@@ -271,7 +271,7 @@ public final class RedundantStringConversion extends BugChecker
// number of arguments of the appropriate type. Also flag explicit conversions from `Throwable` to
// string as the last logger argument. Suggests either dropping the conversion or going with
// `Throwable#getMessage()` instead.
private Optional<SuggestedFix.Builder> tryFixSlf4jLogger(
private SuggestedFix tryFixSlf4jLogger(
List<? extends ExpressionTree> arguments, VisitorState state) {
/*
* SLF4J treats the final argument to a log statement specially if it is a `Throwable`: it
@@ -291,36 +291,34 @@ public final class RedundantStringConversion extends BugChecker
omitLast ? arguments.subList(0, arguments.size() - 1) : arguments, state, MARKER, ANY_EXPR);
}
private Optional<SuggestedFix.Builder> tryFixFormatterArguments(
private SuggestedFix tryFixFormatterArguments(
List<? extends ExpressionTree> arguments,
VisitorState state,
Matcher<ExpressionTree> firstArgFilter,
Matcher<ExpressionTree> remainingArgFilter) {
if (arguments.isEmpty()) {
/* This format method accepts no arguments. Some odd overload? */
return Optional.empty();
return SuggestedFix.emptyFix();
}
int patternIndex = firstArgFilter.matches(arguments.get(0), state) ? 1 : 0;
if (arguments.size() <= patternIndex) {
/* This format method accepts only an ignored parameter. Some odd overload? */
return Optional.empty();
return SuggestedFix.emptyFix();
}
/* Simplify the values to be plugged into the format pattern, if possible. */
return arguments.stream()
.skip(patternIndex + 1L)
.map(arg -> tryFix(arg, state, remainingArgFilter))
.flatMap(Optional::stream)
.reduce(SuggestedFix.Builder::merge);
.collect(SuggestedFix.mergeFixes());
}
private Optional<SuggestedFix.Builder> tryFix(
private SuggestedFix tryFix(
ExpressionTree tree, VisitorState state, Matcher<ExpressionTree> filter) {
return trySimplify(tree, state, filter)
.map(
replacement ->
SuggestedFix.builder().replace(tree, SourceCode.treeToString(replacement, state)));
.map(replacement -> SuggestedFix.replace(tree, SourceCode.treeToString(replacement, state)))
.orElseGet(SuggestedFix::emptyFix);
}
private Optional<ExpressionTree> trySimplify(
@@ -369,11 +367,8 @@ public final class RedundantStringConversion extends BugChecker
return Optional.of(Iterables.getOnlyElement(methodInvocation.getArguments()));
}
private Description createDescription(Tree tree, Optional<SuggestedFix.Builder> fixes) {
return fixes
.map(SuggestedFix.Builder::build)
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
private Description createDescription(Tree tree, SuggestedFix fix) {
return fix.isEmpty() ? Description.NO_MATCH : describeMatch(tree, fix);
}
private static Matcher<MethodInvocationTree> createConversionMethodMatcher(

View File

@@ -0,0 +1,95 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.LiteralTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.LiteralTree;
import tech.picnic.errorprone.utils.SourceCode;
/** A {@link BugChecker} that flags string constants with extraneous escaping. */
// XXX: Also cover `\"` sequences inside text blocks. Note that this requires a more subtle
// approach, as double-quote characters will need to remain escaped if removing the backslash would
// create a new sequence of three or more double-quotes. (TBD whether we'd like to enforce a
// "preferred" approach to escaping, e.g. by always escaping the last of a triplet, such that the
// over-all number of escaped characters is minimized.)
// XXX: Also flag `'\"'` char literals.
@AutoService(BugChecker.class)
@BugPattern(
summary = "Inside string expressions single quotes do not need to be escaped",
link = BUG_PATTERNS_BASE_URL + "RedundantStringEscape",
linkType = CUSTOM,
severity = SUGGESTION,
tags = SIMPLIFICATION)
public final class RedundantStringEscape extends BugChecker implements LiteralTreeMatcher {
private static final long serialVersionUID = 1L;
/** Instantiates a new {@link RedundantStringEscape} instance. */
public RedundantStringEscape() {}
@Override
public Description matchLiteral(LiteralTree tree, VisitorState state) {
String constant = ASTHelpers.constValue(tree, String.class);
if (constant == null || constant.indexOf('\'') < 0) {
/* Fast path: this isn't a string constant with a single quote. */
return Description.NO_MATCH;
}
String source = SourceCode.treeToString(tree, state);
if (!containsBannedEscapeSequence(source)) {
/* Semi-fast path: this expression doesn't contain an escaped single quote. */
return Description.NO_MATCH;
}
/* Slow path: suggest dropping the escape characters. */
return describeMatch(tree, SuggestedFix.replace(tree, dropRedundantEscapeSequences(source)));
}
/**
* Tells whether the given string constant source expression contains an escaped single quote.
*
* @implNote As the input is a literal Java string expression, it will start and end with a double
* quote; as such any found backslash will not be the string's final character.
*/
private static boolean containsBannedEscapeSequence(String source) {
for (int p = source.indexOf('\\'); p != -1; p = source.indexOf('\\', p + 2)) {
if (source.charAt(p + 1) == '\'') {
return true;
}
}
return false;
}
/**
* Simplifies the given string constant source expression by dropping the backslash preceding an
* escaped single quote.
*
* @implNote Note that this method does not delegate to {@link
* SourceCode#toStringConstantExpression}, as that operation may replace other Unicode
* characters with their associated escape sequence.
* @implNote As the input is a literal Java string expression, it will start and end with a double
* quote; as such any found backslash will not be the string's final character.
*/
private static String dropRedundantEscapeSequences(String source) {
StringBuilder result = new StringBuilder();
for (int p = 0; p < source.length(); p++) {
char c = source.charAt(p);
if (c != '\\' || source.charAt(p + 1) != '\'') {
result.append(c);
}
}
return result.toString();
}
}

View File

@@ -41,7 +41,7 @@ import tech.picnic.errorprone.utils.SourceCode;
tags = LIKELY_ERROR)
public final class Slf4jLogStatement extends BugChecker implements MethodInvocationTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> MARKER = isSubtypeOf("org.slf4j.Marker");
private static final Matcher<ExpressionTree> SLF4J_MARKER = isSubtypeOf("org.slf4j.Marker");
private static final Matcher<ExpressionTree> THROWABLE = isSubtypeOf(Throwable.class);
private static final Matcher<ExpressionTree> SLF4J_LOGGER_INVOCATION =
instanceMethod()
@@ -71,7 +71,7 @@ public final class Slf4jLogStatement extends BugChecker implements MethodInvocat
* SLF4J log statements may accept a "marker" as a first argument, before the format string.
* We ignore such markers.
*/
int lTrim = MARKER.matches(args.get(0), state) ? 1 : 0;
int lTrim = SLF4J_MARKER.matches(args.get(0), state) ? 1 : 0;
/*
* SLF4J treats the final argument to a log statement specially if it is a `Throwabe`: it
* will always choose to render the associated stacktrace, even if the argument has a

View File

@@ -53,7 +53,7 @@ public final class Slf4jLoggerDeclaration extends BugChecker implements Variable
private static final Matcher<ExpressionTree> IS_GET_LOGGER =
staticMethod().onDescendantOf("org.slf4j.LoggerFactory").named("getLogger");
private static final String CANONICAL_STATIC_LOGGER_NAME_FLAG =
"Slf4jLogDeclaration:CanonicalStaticLoggerName";
"Slf4jLoggerDeclaration:CanonicalStaticLoggerName";
private static final String DEFAULT_CANONICAL_LOGGER_NAME = "LOG";
private static final Matcher<ExpressionTree> IS_STATIC_ENCLOSING_CLASS_REFERENCE =
classLiteral(Slf4jLoggerDeclaration::isEnclosingClassReference);

View File

@@ -15,7 +15,6 @@ import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher;
import com.google.errorprone.fixes.Fix;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
@@ -65,16 +64,18 @@ public final class SpringMvcAnnotation extends BugChecker implements AnnotationT
return ARGUMENT_SELECTOR
.extractMatchingArguments(tree)
.findFirst()
.flatMap(arg -> trySimplification(tree, arg, state))
.map(arg -> trySimplification(tree, arg, state))
.filter(not(SuggestedFix::isEmpty))
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
}
private static Optional<Fix> trySimplification(
private static SuggestedFix trySimplification(
AnnotationTree tree, ExpressionTree arg, VisitorState state) {
return extractUniqueMethod(arg, state)
.map(REPLACEMENTS::get)
.map(newAnnotation -> replaceAnnotation(tree, arg, newAnnotation, state));
.map(newAnnotation -> replaceAnnotation(tree, arg, newAnnotation, state))
.orElseGet(SuggestedFix::emptyFix);
}
private static Optional<String> extractUniqueMethod(ExpressionTree arg, VisitorState state) {
@@ -99,7 +100,7 @@ public final class SpringMvcAnnotation extends BugChecker implements AnnotationT
};
}
private static Fix replaceAnnotation(
private static SuggestedFix replaceAnnotation(
AnnotationTree tree, ExpressionTree argToRemove, String newAnnotation, VisitorState state) {
String newArguments =
tree.getArguments().stream()

View File

@@ -4,6 +4,7 @@ import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
import static com.google.errorprone.BugPattern.StandardTags.STYLE;
import static java.util.Objects.requireNonNull;
import static java.util.function.Predicate.not;
import static tech.picnic.errorprone.bugpatterns.NonStaticImport.NON_STATIC_IMPORT_CANDIDATE_IDENTIFIERS;
import static tech.picnic.errorprone.bugpatterns.NonStaticImport.NON_STATIC_IMPORT_CANDIDATE_MEMBERS;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
@@ -34,7 +35,6 @@ import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.MemberSelectTreeMatcher;
import com.google.errorprone.bugpatterns.StaticImports;
import com.google.errorprone.bugpatterns.StaticImports.StaticImportInfo;
import com.google.errorprone.fixes.Fix;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
@@ -203,7 +203,8 @@ public final class StaticImport extends BugChecker implements MemberSelectTreeMa
}
return getCandidateSimpleName(importInfo)
.flatMap(n -> tryStaticImport(tree, importInfo.canonicalName() + '.' + n, n, state))
.map(n -> tryStaticImport(tree, importInfo.canonicalName() + '.' + n, n, state))
.filter(not(SuggestedFix::isEmpty))
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
}
@@ -240,15 +241,15 @@ public final class StaticImport extends BugChecker implements MemberSelectTreeMa
|| STATIC_IMPORT_CANDIDATE_MEMBERS.containsEntry(canonicalName, name));
}
private static Optional<Fix> tryStaticImport(
private static SuggestedFix tryStaticImport(
MemberSelectTree tree, String fullyQualifiedName, String simpleName, VisitorState state) {
SuggestedFix.Builder fix = SuggestedFix.builder().replace(tree, simpleName);
if (!simpleName.equals(SuggestedFixes.qualifyStaticImport(fullyQualifiedName, fix, state))) {
/* Statically importing this symbol would clash with an existing import. */
return Optional.empty();
return SuggestedFix.emptyFix();
}
return Optional.of(fix.build());
return fix.build();
}
}

View File

@@ -23,7 +23,6 @@ import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.util.Constants;
import java.util.Formattable;
import java.util.Iterator;
import java.util.List;
@@ -150,7 +149,7 @@ public final class StringJoin extends BugChecker implements MethodInvocationTree
SuggestedFix.Builder fix =
SuggestedFix.builder()
.replace(tree.getMethodSelect(), "String.join")
.replace(arguments.next(), Constants.format(separator));
.replace(arguments.next(), SourceCode.toStringConstantExpression(separator, state));
while (arguments.hasNext()) {
ExpressionTree argument = arguments.next();

View File

@@ -11,6 +11,7 @@ import com.sun.tools.javac.util.Constants;
import com.sun.tools.javac.util.Convert;
import javax.lang.model.element.Name;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
import tech.picnic.errorprone.utils.SourceCode;
/** Refaster rules related to {@link com.google.errorprone.bugpatterns.BugChecker} classes. */
@OnlineDocumentation
@@ -56,16 +57,26 @@ final class BugCheckerRules {
}
}
/** Prefer using the {@link Constants} API over more verbose alternatives. */
/**
* Prefer {@link SourceCode#toStringConstantExpression(Object,
* com.google.errorprone.VisitorState)} over alternatives that unnecessarily escape single quote
* characters.
*/
static final class ConstantsFormat {
@BeforeTemplate
String before(CharSequence value) {
return Constants.format(value);
}
@BeforeTemplate
String before(String value) {
return String.format("\"%s\"", Convert.quote(value));
}
@AfterTemplate
String after(String value) {
return Constants.format(value);
String after(CharSequence value) {
return SourceCode.toStringConstantExpression(
value, Refaster.emitCommentBefore("REPLACEME", null));
}
}

View File

@@ -93,6 +93,12 @@ final class FileRules {
/**
* Prefer {@link Files#createTempFile(String, String, FileAttribute[])} over alternatives that
* create files with more liberal permissions.
*
* <p>Note that {@link File#createTempFile} treats the given prefix as a path, and ignores all but
* its file name. That is, the actual prefix used is derived from all characters following the
* final file separator (if any). This is not the case with {@link Files#createTempFile}, which
* will instead throw an {@link IllegalArgumentException} if the prefix contains any file
* separators.
*/
static final class FilesCreateTempFileToFile {
@BeforeTemplate
@@ -117,6 +123,12 @@ final class FileRules {
/**
* Prefer {@link Files#createTempFile(Path, String, String, FileAttribute[])} over alternatives
* that create files with more liberal permissions.
*
* <p>Note that {@link File#createTempFile} treats the given prefix as a path, and ignores all but
* its file name. That is, the actual prefix used is derived from all characters following the
* final file separator (if any). This is not the case with {@link Files#createTempFile}, which
* will instead throw an {@link IllegalArgumentException} if the prefix contains any file
* separators.
*/
static final class FilesCreateTempFileInCustomDirectoryToFile {
@BeforeTemplate

View File

@@ -279,6 +279,9 @@ final class OptionalRules {
*/
// XXX: Do we need the `.filter(Optional::isPresent)`? If it's absent the caller probably assumed
// that the values are present. (If we drop it, we should rewrite vacuous filter steps.)
// XXX: The rewritten `filter`/`map` expression may be more performant than its replacement. See
// https://github.com/palantir/gradle-baseline/pull/2946. (There are plans to pair Refaster rules
// with JMH benchmarks; this would be a great use case.)
static final class StreamFlatMapOptional<T> {
@BeforeTemplate
Stream<T> before(Stream<Optional<T>> stream) {
@@ -395,10 +398,7 @@ final class OptionalRules {
}
}
/**
* Avoid unnecessary operations on an {@link Optional} that ultimately result in that very same
* {@link Optional}.
*/
/** Don't unnecessarily transform an {@link Optional} to an equivalent instance. */
static final class OptionalIdentity<T> {
@BeforeTemplate
@SuppressWarnings("NestedOptionals")

View File

@@ -1768,6 +1768,60 @@ final class ReactorRules {
}
}
/**
* Prefer {@link StepVerifier#verify()} over a dangling {@link
* StepVerifier#verifyThenAssertThat()}.
*/
// XXX: Application of this rule (and several others in this class) will cause invalid code if the
// result of the rewritten expression is dereferenced. Consider introducing a bug checker that
// identifies rules that change the return type of an expression and annotates them accordingly.
// The associated annotation can then be used to instruct an annotation processor to generate
// corresponding `void` rules that match only statements. This would allow the `Refaster` check to
// conditionally skip "not fully safe" rules. This allows conditionally flagging more dubious
// code, at the risk of compilation failures. With this rule, for example, we want to explicitly
// nudge users towards `StepVerifier.Step#assertNext(Consumer)` or
// `StepVerifier.Step#expectNext(Object)`, together with `Step#verifyComplete()`.
static final class StepVerifierVerify {
@BeforeTemplate
StepVerifier.Assertions before(StepVerifier stepVerifier) {
return stepVerifier.verifyThenAssertThat();
}
@AfterTemplate
Duration after(StepVerifier stepVerifier) {
return stepVerifier.verify();
}
}
/**
* Prefer {@link StepVerifier#verify(Duration)} over a dangling {@link
* StepVerifier#verifyThenAssertThat(Duration)}.
*/
static final class StepVerifierVerifyDuration {
@BeforeTemplate
StepVerifier.Assertions before(StepVerifier stepVerifier, Duration duration) {
return stepVerifier.verifyThenAssertThat(duration);
}
@AfterTemplate
Duration after(StepVerifier stepVerifier, Duration duration) {
return stepVerifier.verify(duration);
}
}
/** Don't unnecessarily invoke {@link StepVerifier#verifyLater()} multiple times. */
static final class StepVerifierVerifyLater {
@BeforeTemplate
StepVerifier before(StepVerifier stepVerifier) {
return stepVerifier.verifyLater().verifyLater();
}
@AfterTemplate
StepVerifier after(StepVerifier stepVerifier) {
return stepVerifier.verifyLater();
}
}
/** Don't unnecessarily have {@link StepVerifier.Step} expect no elements. */
static final class StepVerifierStepIdentity<T> {
@BeforeTemplate
@@ -1868,6 +1922,12 @@ final class ReactorRules {
return step.expectErrorMatches(predicate).verify();
}
@BeforeTemplate
@SuppressWarnings("StepVerifierVerify" /* This is a more specific template. */)
StepVerifier.Assertions before2(StepVerifier.LastStep step, Predicate<Throwable> predicate) {
return step.expectError().verifyThenAssertThat().hasOperatorErrorMatching(predicate);
}
@AfterTemplate
Duration after(StepVerifier.LastStep step, Predicate<Throwable> predicate) {
return step.verifyErrorMatches(predicate);
@@ -1890,6 +1950,30 @@ final class ReactorRules {
}
}
/**
* Prefer {@link StepVerifier.LastStep#verifyErrorSatisfies(Consumer)} with AssertJ over more
* contrived alternatives.
*/
static final class StepVerifierLastStepVerifyErrorSatisfiesAssertJ<T extends Throwable> {
@BeforeTemplate
@SuppressWarnings("StepVerifierVerify" /* This is a more specific template. */)
StepVerifier.Assertions before(StepVerifier.LastStep step, Class<T> clazz, String message) {
return Refaster.anyOf(
step.expectError()
.verifyThenAssertThat()
.hasOperatorErrorOfType(clazz)
.hasOperatorErrorWithMessage(message),
step.expectError(clazz).verifyThenAssertThat().hasOperatorErrorWithMessage(message),
step.expectErrorMessage(message).verifyThenAssertThat().hasOperatorErrorOfType(clazz));
}
@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
Duration after(StepVerifier.LastStep step, Class<T> clazz, String message) {
return step.verifyErrorSatisfies(t -> assertThat(t).isInstanceOf(clazz).hasMessage(message));
}
}
/**
* Prefer {@link StepVerifier.LastStep#verifyErrorMessage(String)} over more verbose alternatives.
*/

View File

@@ -142,6 +142,63 @@ final class TimeRules {
}
}
/** Don't unnecessarily transform an {@link Instant} to an equivalent instance. */
static final class InstantIdentity {
@BeforeTemplate
Instant before(Instant instant, TemporalUnit temporalUnit) {
return Refaster.anyOf(
instant.plus(Duration.ZERO),
instant.plus(0, temporalUnit),
instant.plusNanos(0),
instant.plusMillis(0),
instant.plusSeconds(0),
instant.minus(Duration.ZERO),
instant.minus(0, temporalUnit),
instant.minusNanos(0),
instant.minusMillis(0),
instant.minusSeconds(0),
Instant.parse(instant.toString()),
instant.truncatedTo(ChronoUnit.NANOS),
Instant.ofEpochSecond(instant.getEpochSecond(), instant.getNano()));
}
@AfterTemplate
Instant after(Instant instant) {
return instant;
}
}
/**
* Prefer {@link Instant#truncatedTo(TemporalUnit)} over less obvious alternatives.
*
* <p>Note that {@link Instant#toEpochMilli()} throws an {@link ArithmeticException} for dates
* very far in the past or future, while the suggested alternative doesn't.
*/
static final class InstantTruncatedToMilliseconds {
@BeforeTemplate
Instant before(Instant instant) {
return Instant.ofEpochMilli(instant.toEpochMilli());
}
@AfterTemplate
Instant after(Instant instant) {
return instant.truncatedTo(ChronoUnit.MILLIS);
}
}
/** Prefer {@link Instant#truncatedTo(TemporalUnit)} over less obvious alternatives. */
static final class InstantTruncatedToSeconds {
@BeforeTemplate
Instant before(Instant instant) {
return Instant.ofEpochSecond(instant.getEpochSecond());
}
@AfterTemplate
Instant after(Instant instant) {
return instant.truncatedTo(ChronoUnit.SECONDS);
}
}
/** Prefer {@link Instant#atOffset(ZoneOffset)} over more verbose alternatives. */
static final class InstantAtOffset {
@BeforeTemplate

View File

@@ -28,6 +28,8 @@ final class IdentityConversionTest {
"import com.google.common.collect.ImmutableTable;",
"import com.google.errorprone.matchers.Matcher;",
"import com.google.errorprone.matchers.Matchers;",
"import java.time.Instant;",
"import java.time.ZonedDateTime;",
"import reactor.adapter.rxjava.RxJava2Adapter;",
"import reactor.core.publisher.Flux;",
"import reactor.core.publisher.Mono;",
@@ -149,6 +151,10 @@ final class IdentityConversionTest {
" // BUG: Diagnostic contains:",
" ImmutableTable<Object, Object, Object> o11 = ImmutableTable.copyOf(ImmutableTable.of());",
"",
" Instant instant1 = Instant.from(ZonedDateTime.now());",
" // BUG: Diagnostic contains:",
" Instant instant2 = Instant.from(Instant.now());",
"",
" // BUG: Diagnostic contains:",
" Matcher allOf1 = Matchers.allOf(instanceMethod());",
" Matcher allOf2 = Matchers.allOf(instanceMethod(), staticMethod());",

View File

@@ -0,0 +1,90 @@
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 RedundantStringEscapeTest {
@Test
void identification() {
CompilationTestHelper.newInstance(RedundantStringEscape.class, getClass())
.addSourceLines(
"A.java",
"import java.util.Arrays;",
"import java.util.List;",
"",
"class A {",
" List<String> m() {",
" return Arrays.asList(",
" \"foo\",",
" \"ß\",",
" \"'\",",
" \"\\\"\",",
" \"\\\\\",",
" \"\\\\'\",",
" \"'\\\\\",",
" // BUG: Diagnostic contains:",
" \"\\\\\\'\",",
" // BUG: Diagnostic contains:",
" \"\\'\\\\\",",
" // BUG: Diagnostic contains:",
" \"\\'\",",
" // BUG: Diagnostic contains:",
" \"'\\'\",",
" // BUG: Diagnostic contains:",
" \"\\''\",",
" // BUG: Diagnostic contains:",
" \"\\'\\'\",",
" (",
" // BUG: Diagnostic contains:",
" /* Leading comment. */ \"\\'\" /* Trailing comment. */),",
" // BUG: Diagnostic contains:",
" \"\\'foo\\\"bar\\'baz\\\"qux\\'\");",
" }",
"}")
.doTest();
}
@Test
void replacement() {
BugCheckerRefactoringTestHelper.newInstance(RedundantStringEscape.class, getClass())
.addInputLines(
"A.java",
"import java.util.Arrays;",
"import java.util.List;",
"",
"class A {",
" List<String> m() {",
" return Arrays.asList(",
" \"\\'\",",
" \"'\\'\",",
" \"\\''\",",
" \"\\'\\'\",",
" \"\\\\'\",",
" (",
" /* Leading comment. */ \"\\'\" /* Trailing comment. */),",
" \"\\'foo\\\"bar\\'baz\\\"qux\\'\");",
" }",
"}")
.addOutputLines(
"A.java",
"import java.util.Arrays;",
"import java.util.List;",
"",
"class A {",
" List<String> m() {",
" return Arrays.asList(",
" \"'\",",
" \"''\",",
" \"''\",",
" \"''\",",
" \"'ß'\",",
" (",
" /* Leading comment. */ \"'\" /* Trailing comment. */),",
" \"'foo\\\"bar'baz\\\"qux'\");",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -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;
@@ -189,7 +188,7 @@ final class Slf4jLoggerDeclarationTest {
@Test
void replacementWithCustomLoggerName() {
BugCheckerRefactoringTestHelper.newInstance(Slf4jLoggerDeclaration.class, getClass())
.setArgs(ImmutableList.of("-XepOpt:Slf4jLogDeclaration:CanonicalStaticLoggerName=FOO_BAR"))
.setArgs("-XepOpt:Slf4jLoggerDeclaration:CanonicalStaticLoggerName=FOO_BAR")
.addInputLines(
"A.java",
"import org.slf4j.Logger;",

View File

@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;
import com.google.errorprone.bugpatterns.BugChecker;
import com.sun.tools.javac.util.Constants;
import com.sun.tools.javac.util.Convert;
import javax.lang.model.element.Name;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
@@ -11,7 +12,7 @@ import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(Convert.class, FixChoosers.class);
return ImmutableSet.of(Constants.class, Convert.class, FixChoosers.class);
}
ImmutableSet<BugCheckerRefactoringTestHelper> testBugCheckerRefactoringTestHelperIdentity() {
@@ -29,8 +30,8 @@ final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
.addOutputLines("A.java", "class A {}");
}
String testConstantsFormat() {
return String.format("\"%s\"", Convert.quote("foo"));
ImmutableSet<String> testConstantsFormat() {
return ImmutableSet.of(Constants.format("foo"), String.format("\"%s\"", Convert.quote("bar")));
}
ImmutableSet<Boolean> testNameContentEquals() {

View File

@@ -8,11 +8,12 @@ import com.sun.tools.javac.util.Constants;
import com.sun.tools.javac.util.Convert;
import javax.lang.model.element.Name;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
import tech.picnic.errorprone.utils.SourceCode;
final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(Convert.class, FixChoosers.class);
return ImmutableSet.of(Constants.class, Convert.class, FixChoosers.class);
}
ImmutableSet<BugCheckerRefactoringTestHelper> testBugCheckerRefactoringTestHelperIdentity() {
@@ -28,8 +29,10 @@ final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
.expectUnchanged();
}
String testConstantsFormat() {
return Constants.format("foo");
ImmutableSet<String> testConstantsFormat() {
return ImmutableSet.of(
SourceCode.toStringConstantExpression("foo", /* REPLACEME */ null),
SourceCode.toStringConstantExpression("bar", /* REPLACEME */ null));
}
ImmutableSet<Boolean> testNameContentEquals() {

View File

@@ -598,6 +598,18 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
return StepVerifier.create(Flux.just(1));
}
Object testStepVerifierVerify() {
return Mono.empty().as(StepVerifier::create).expectError().verifyThenAssertThat();
}
Object testStepVerifierVerifyDuration() {
return Mono.empty().as(StepVerifier::create).expectError().verifyThenAssertThat(Duration.ZERO);
}
StepVerifier testStepVerifierVerifyLater() {
return Mono.empty().as(StepVerifier::create).expectError().verifyLater().verifyLater();
}
ImmutableSet<StepVerifier.Step<Integer>> testStepVerifierStepIdentity() {
return ImmutableSet.of(
Mono.just(1).as(StepVerifier::create).expectNext(),
@@ -638,17 +650,43 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
.verifyErrorSatisfies(t -> assertThat(t).isInstanceOf(AssertionError.class)));
}
Duration testStepVerifierLastStepVerifyErrorMatches() {
return Mono.empty()
.as(StepVerifier::create)
.expectErrorMatches(IllegalArgumentException.class::equals)
.verify();
ImmutableSet<?> testStepVerifierLastStepVerifyErrorMatches() {
return ImmutableSet.of(
Mono.empty()
.as(StepVerifier::create)
.expectErrorMatches(IllegalArgumentException.class::equals)
.verify(),
Mono.empty()
.as(StepVerifier::create)
.expectError()
.verifyThenAssertThat()
.hasOperatorErrorMatching(IllegalStateException.class::equals));
}
Duration testStepVerifierLastStepVerifyErrorSatisfies() {
return Mono.empty().as(StepVerifier::create).expectErrorSatisfies(t -> {}).verify();
}
ImmutableSet<?> testStepVerifierLastStepVerifyErrorSatisfiesAssertJ() {
return ImmutableSet.of(
Mono.empty()
.as(StepVerifier::create)
.expectError()
.verifyThenAssertThat()
.hasOperatorErrorOfType(IllegalArgumentException.class)
.hasOperatorErrorWithMessage("foo"),
Mono.empty()
.as(StepVerifier::create)
.expectError(IllegalStateException.class)
.verifyThenAssertThat()
.hasOperatorErrorWithMessage("bar"),
Mono.empty()
.as(StepVerifier::create)
.expectErrorMessage("baz")
.verifyThenAssertThat()
.hasOperatorErrorOfType(AssertionError.class));
}
Duration testStepVerifierLastStepVerifyErrorMessage() {
return Mono.empty().as(StepVerifier::create).expectErrorMessage("foo").verify();
}

View File

@@ -586,6 +586,18 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
return Flux.just(1).as(StepVerifier::create);
}
Object testStepVerifierVerify() {
return Mono.empty().as(StepVerifier::create).expectError().verify();
}
Object testStepVerifierVerifyDuration() {
return Mono.empty().as(StepVerifier::create).expectError().verify(Duration.ZERO);
}
StepVerifier testStepVerifierVerifyLater() {
return Mono.empty().as(StepVerifier::create).expectError().verifyLater();
}
ImmutableSet<StepVerifier.Step<Integer>> testStepVerifierStepIdentity() {
return ImmutableSet.of(
Mono.just(1).as(StepVerifier::create),
@@ -619,16 +631,36 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Mono.empty().as(StepVerifier::create).verifyError(AssertionError.class));
}
Duration testStepVerifierLastStepVerifyErrorMatches() {
return Mono.empty()
.as(StepVerifier::create)
.verifyErrorMatches(IllegalArgumentException.class::equals);
ImmutableSet<?> testStepVerifierLastStepVerifyErrorMatches() {
return ImmutableSet.of(
Mono.empty()
.as(StepVerifier::create)
.verifyErrorMatches(IllegalArgumentException.class::equals),
Mono.empty()
.as(StepVerifier::create)
.verifyErrorMatches(IllegalStateException.class::equals));
}
Duration testStepVerifierLastStepVerifyErrorSatisfies() {
return Mono.empty().as(StepVerifier::create).verifyErrorSatisfies(t -> {});
}
ImmutableSet<?> testStepVerifierLastStepVerifyErrorSatisfiesAssertJ() {
return ImmutableSet.of(
Mono.empty()
.as(StepVerifier::create)
.verifyErrorSatisfies(
t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("foo")),
Mono.empty()
.as(StepVerifier::create)
.verifyErrorSatisfies(
t -> assertThat(t).isInstanceOf(IllegalStateException.class).hasMessage("bar")),
Mono.empty()
.as(StepVerifier::create)
.verifyErrorSatisfies(
t -> assertThat(t).isInstanceOf(AssertionError.class).hasMessage("baz")));
}
Duration testStepVerifierLastStepVerifyErrorMessage() {
return Mono.empty().as(StepVerifier::create).verifyErrorMessage("foo");
}

View File

@@ -66,6 +66,32 @@ final class TimeRulesTest implements RefasterRuleCollectionTestCase {
return Instant.EPOCH.atZone(ZoneOffset.UTC).toOffsetDateTime();
}
ImmutableSet<Instant> testInstantIdentity() {
return ImmutableSet.of(
Instant.EPOCH.plusMillis(1).plus(Duration.ZERO),
Instant.EPOCH.plusMillis(2).plus(0, ChronoUnit.MILLIS),
Instant.EPOCH.plusMillis(3).plusNanos(0L),
Instant.EPOCH.plusMillis(4).plusMillis(0),
Instant.EPOCH.plusMillis(5).plusSeconds(0L),
Instant.EPOCH.plusMillis(6).minus(Duration.ZERO),
Instant.EPOCH.plusMillis(7).minus(0, ChronoUnit.SECONDS),
Instant.EPOCH.plusMillis(8).minusNanos(0L),
Instant.EPOCH.plusMillis(9).minusMillis(0),
Instant.EPOCH.plusMillis(10).minusSeconds(0L),
Instant.parse(Instant.EPOCH.plusMillis(11).toString()),
Instant.EPOCH.plusMillis(12).truncatedTo(ChronoUnit.NANOS),
Instant.ofEpochSecond(
Instant.EPOCH.plusMillis(13).getEpochSecond(), Instant.EPOCH.plusMillis(13).getNano()));
}
Instant testInstantTruncatedToMilliseconds() {
return Instant.ofEpochMilli(Instant.EPOCH.toEpochMilli());
}
Instant testInstantTruncatedToSeconds() {
return Instant.ofEpochSecond(Instant.EPOCH.getEpochSecond());
}
OffsetDateTime testInstantAtOffset() {
return OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
}

View File

@@ -66,6 +66,31 @@ final class TimeRulesTest implements RefasterRuleCollectionTestCase {
return OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
}
ImmutableSet<Instant> testInstantIdentity() {
return ImmutableSet.of(
Instant.EPOCH.plusMillis(1),
Instant.EPOCH.plusMillis(2),
Instant.EPOCH.plusMillis(3),
Instant.EPOCH.plusMillis(4),
Instant.EPOCH.plusMillis(5),
Instant.EPOCH.plusMillis(6),
Instant.EPOCH.plusMillis(7),
Instant.EPOCH.plusMillis(8),
Instant.EPOCH.plusMillis(9),
Instant.EPOCH.plusMillis(10),
Instant.EPOCH.plusMillis(11),
Instant.EPOCH.plusMillis(12),
Instant.EPOCH.plusMillis(13));
}
Instant testInstantTruncatedToMilliseconds() {
return Instant.EPOCH.truncatedTo(ChronoUnit.MILLIS);
}
Instant testInstantTruncatedToSeconds() {
return Instant.EPOCH.truncatedTo(ChronoUnit.SECONDS);
}
OffsetDateTime testInstantAtOffset() {
return Instant.EPOCH.atOffset(ZoneOffset.UTC);
}

View File

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

View File

@@ -73,19 +73,18 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
* because the latter are not syntactically valid or ambiguous. Rather than encoding all these
* edge cases we try to compile the code with the suggested fix, to see whether this works.
*/
return constructMethodRef(tree, tree.getBody())
.map(SuggestedFix.Builder::build)
.filter(
fix ->
SuggestedFixes.compilesWithFix(
fix, state, ImmutableList.of(), /* onlyInSameCompilationUnit= */ true))
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
SuggestedFix fix = constructMethodRef(tree, tree.getBody());
if (fix.isEmpty()
|| !SuggestedFixes.compilesWithFix(
fix, state, ImmutableList.of(), /* onlyInSameCompilationUnit= */ true)) {
return Description.NO_MATCH;
}
return describeMatch(tree, fix);
}
// XXX: Use switch pattern matching once the targeted JDK supports this.
private static Optional<SuggestedFix.Builder> constructMethodRef(
LambdaExpressionTree lambdaExpr, Tree subTree) {
private static SuggestedFix constructMethodRef(LambdaExpressionTree lambdaExpr, Tree subTree) {
return switch (subTree.getKind()) {
case BLOCK -> constructMethodRef(lambdaExpr, (BlockTree) subTree);
case EXPRESSION_STATEMENT ->
@@ -94,27 +93,28 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
case PARENTHESIZED ->
constructMethodRef(lambdaExpr, ((ParenthesizedTree) subTree).getExpression());
case RETURN -> constructMethodRef(lambdaExpr, ((ReturnTree) subTree).getExpression());
default -> Optional.empty();
default -> SuggestedFix.emptyFix();
};
}
private static Optional<SuggestedFix.Builder> constructMethodRef(
private static SuggestedFix constructMethodRef(
LambdaExpressionTree lambdaExpr, BlockTree subTree) {
return Optional.of(subTree.getStatements())
.filter(statements -> statements.size() == 1)
.flatMap(statements -> constructMethodRef(lambdaExpr, statements.get(0)));
.map(statements -> constructMethodRef(lambdaExpr, statements.get(0)))
.orElseGet(SuggestedFix::emptyFix);
}
// XXX: Replace nested `Optional` usage.
@SuppressWarnings("NestedOptionals")
private static Optional<SuggestedFix.Builder> constructMethodRef(
private static SuggestedFix constructMethodRef(
LambdaExpressionTree lambdaExpr, MethodInvocationTree subTree) {
return matchArguments(lambdaExpr, subTree)
.flatMap(expectedInstance -> constructMethodRef(lambdaExpr, subTree, expectedInstance));
.map(expectedInstance -> constructMethodRef(lambdaExpr, subTree, expectedInstance))
.orElseGet(SuggestedFix::emptyFix);
}
// XXX: Review whether to use switch pattern matching once the targeted JDK supports this.
private static Optional<SuggestedFix.Builder> constructMethodRef(
private static SuggestedFix constructMethodRef(
LambdaExpressionTree lambdaExpr,
MethodInvocationTree subTree,
Optional<Name> expectedInstance) {
@@ -123,7 +123,7 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
if (methodSelect instanceof IdentifierTree) {
if (expectedInstance.isPresent()) {
/* Direct method call; there is no matching "implicit parameter". */
return Optional.empty();
return SuggestedFix.emptyFix();
}
Symbol sym = ASTHelpers.getSymbol(methodSelect);
@@ -139,7 +139,7 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
throw new VerifyException("Unexpected type of expression: " + methodSelect.getKind());
}
private static Optional<SuggestedFix.Builder> constructMethodRef(
private static SuggestedFix constructMethodRef(
LambdaExpressionTree lambdaExpr, MemberSelectTree subTree, Optional<Name> expectedInstance) {
if (!(subTree.getExpression() instanceof IdentifierTree identifier)) {
// XXX: Could be parenthesized. Handle. Also in other classes.
@@ -147,7 +147,7 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
* Only suggest a replacement if the method select's expression provably doesn't have
* side-effects. Otherwise the replacement may not be behavior preserving.
*/
return Optional.empty();
return SuggestedFix.emptyFix();
}
Name lhs = identifier.getName();
@@ -157,7 +157,7 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
Type lhsType = ASTHelpers.getType(identifier);
if (lhsType == null || !expectedInstance.orElseThrow().equals(lhs)) {
return Optional.empty();
return SuggestedFix.emptyFix();
}
// XXX: Dropping generic type information is in most cases fine or even more likely to yield a
@@ -195,23 +195,23 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
// XXX: Resolve this suppression.
@SuppressWarnings("UnqualifiedSuggestedFixImport")
private static Optional<SuggestedFix.Builder> constructFix(
private static SuggestedFix constructFix(
LambdaExpressionTree lambdaExpr, Symbol target, Object methodName) {
Name sName = target.getSimpleName();
Optional<SuggestedFix.Builder> fix = constructFix(lambdaExpr, sName, methodName);
SuggestedFix fix = constructFix(lambdaExpr, sName, methodName);
if (!"java.lang".equals(ASTHelpers.enclosingPackage(target).toString())) {
Name fqName = target.getQualifiedName();
if (!sName.equals(fqName)) {
return fix.map(b -> b.addImport(fqName.toString()));
return fix.toBuilder().addImport(fqName.toString()).build();
}
}
return fix;
}
private static Optional<SuggestedFix.Builder> constructFix(
private static SuggestedFix constructFix(
LambdaExpressionTree lambdaExpr, Object target, Object methodName) {
return Optional.of(SuggestedFix.builder().replace(lambdaExpr, target + "::" + methodName));
return SuggestedFix.replace(lambdaExpr, target + "::" + methodName);
}
}

View File

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

View File

@@ -30,8 +30,8 @@ import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.util.Constants;
import javax.lang.model.element.Name;
import tech.picnic.errorprone.utils.SourceCode;
/**
* A {@link BugChecker} that flags {@link BugChecker} declarations inside {@code
@@ -126,7 +126,9 @@ public final class BugPatternLink extends BugChecker implements ClassTreeMatcher
state,
"link",
ImmutableList.of(
linkPrefix + " + " + Constants.format(tree.getSimpleName().toString()))));
linkPrefix
+ " + "
+ SourceCode.toStringConstantExpression(tree.getSimpleName(), state))));
String linkType =
SuggestedFixes.qualifyStaticImport(

View File

@@ -26,8 +26,8 @@ import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.util.Constants;
import java.util.regex.Pattern;
import tech.picnic.errorprone.utils.SourceCode;
import tech.picnic.errorprone.utils.ThirdPartyLibrary;
/**
@@ -123,7 +123,8 @@ public final class ErrorProneRuntimeClasspath extends BugChecker
.setMessage("This type may not be on the runtime classpath; use a string literal instead")
.addFix(
SuggestedFix.replace(
tree, Constants.format(receiver.owner.getQualifiedName().toString())))
tree,
SourceCode.toStringConstantExpression(receiver.owner.getQualifiedName(), state)))
.build();
}
@@ -150,7 +151,9 @@ public final class ErrorProneRuntimeClasspath extends BugChecker
original,
identifier
+ ".class.getCanonicalName()"
+ (suffix.isEmpty() ? "" : (" + " + Constants.format(suffix))))
+ (suffix.isEmpty()
? ""
: (" + " + SourceCode.toStringConstantExpression(suffix, state))))
.build();
}

View File

@@ -38,7 +38,6 @@ import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.util.Constants;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@@ -49,6 +48,7 @@ import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Modifier;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.utils.SourceCode;
/**
* A {@link BugChecker} that validates the claim made by {@link
@@ -129,7 +129,9 @@ public final class ExhaustiveRefasterTypeMigration extends BugChecker implements
migrationAnnotation,
state,
TYPE_MIGRATION_UNMIGRATED_METHODS_ELEMENT,
unmigratedMethods.stream().map(Constants::format).collect(toImmutableList()))
unmigratedMethods.stream()
.map(m -> SourceCode.toStringConstantExpression(m, state))
.collect(toImmutableList()))
.build());
}

View File

@@ -35,7 +35,6 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import javax.lang.model.element.Name;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.utils.SourceCode;
@@ -74,12 +73,11 @@ public final class RefasterMethodParameterOrder extends BugChecker implements Cl
Comparator<VariableTree> canonicalOrder = determineCanonicalParameterOrder(methods);
return methods.stream()
.flatMap(m -> tryReorderParameters(m, canonicalOrder, state))
.reduce(SuggestedFix.Builder::merge)
.map(SuggestedFix.Builder::build)
.map(fix -> describeMatch(tree, fix))
.orElse(Description.NO_MATCH);
SuggestedFix fix =
methods.stream()
.map(m -> tryReorderParameters(m, canonicalOrder, state))
.collect(SuggestedFix.mergeFixes());
return fix.isEmpty() ? Description.NO_MATCH : describeMatch(tree, fix);
}
private static ImmutableList<MethodTree> getMethodsByPriority(
@@ -123,17 +121,18 @@ public final class RefasterMethodParameterOrder extends BugChecker implements Cl
}.scan(method, null);
}
private static Stream<SuggestedFix.Builder> tryReorderParameters(
private static SuggestedFix tryReorderParameters(
MethodTree method, Comparator<VariableTree> canonicalOrder, VisitorState state) {
List<? extends VariableTree> originalOrder = method.getParameters();
ImmutableList<? extends VariableTree> orderedParams =
ImmutableList.sortedCopyOf(canonicalOrder, originalOrder);
return originalOrder.equals(orderedParams)
? Stream.empty()
? SuggestedFix.emptyFix()
: Streams.zip(
originalOrder.stream(),
orderedParams.stream().map(p -> SourceCode.treeToString(p, state)),
SuggestedFix.builder()::replace);
originalOrder.stream(),
orderedParams.stream().map(p -> SourceCode.treeToString(p, state)),
SuggestedFix::replace)
.collect(SuggestedFix.mergeFixes());
}
}

View File

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

View File

@@ -42,6 +42,24 @@ public final class SourceCode {
return src != null ? src : tree.toString();
}
/**
* Returns a Java string constant expression (i.e., a quoted string) representing the given input.
*
* @param value The value of interest.
* @param state A {@link VisitorState} describing the context in which the given {@link Tree} is
* found.
* @return A non-{@code null} string.
* @apiNote This method differs from {@link com.sun.tools.javac.util.Constants#format(Object)} in
* that it does not superfluously escape single quote characters. It is different from {@link
* VisitorState#getConstantExpression(Object)} in that it is more performant and accepts any
* {@link CharSequence} instance.
*/
// XXX: Drop this method if https://github.com/google/error-prone/pull/4586 is merged and released
// with the proposed `CharSequence` compatibility change.
public static String toStringConstantExpression(Object value, VisitorState state) {
return state.getConstantExpression(value instanceof CharSequence ? value.toString() : value);
}
/**
* Creates a {@link SuggestedFix} for the deletion of the given {@link Tree}, including any
* whitespace that follows it.

View File

@@ -8,18 +8,49 @@ import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.LiteralTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import java.util.Optional;
import javax.lang.model.element.Name;
import org.junit.jupiter.api.Test;
final class SourceCodeTest {
@Test
void toStringConstantExpression() {
BugCheckerRefactoringTestHelper.newInstance(
ToStringConstantExpressionTestChecker.class, getClass())
.addInputLines(
"A.java",
"class A {",
" String m() {",
" char a = 'c';",
" char b = '\\'';",
" return \"foo\\\"bar\\'baz\\bqux\";",
" }",
"}")
.addOutputLines(
"A.java",
"class A {",
" String m() {",
" char a = 'c' /* 'c' */; /* \"a\" */",
" char b = '\\'' /* '\\'' */; /* \"b\" */",
" return \"foo\\\"bar\\'baz\\bqux\" /* \"foo\\\"bar'baz\\bqux\" */;",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
@Test
void deleteWithTrailingWhitespaceAnnotations() {
BugCheckerRefactoringTestHelper.newInstance(
@@ -228,6 +259,41 @@ final class SourceCodeTest {
.doTest(TestMode.TEXT_MATCH);
}
/**
* A {@link BugChecker} that applies {@link SourceCode#toStringConstantExpression(Object,
* VisitorState)} to string literals.
*/
@BugPattern(severity = ERROR, summary = "Interacts with `SourceCode` for testing purposes")
public static final class ToStringConstantExpressionTestChecker extends BugChecker
implements LiteralTreeMatcher, VariableTreeMatcher {
private static final long serialVersionUID = 1L;
@Override
public Description matchLiteral(LiteralTree tree, VisitorState state) {
// XXX: The character conversion is a workaround for the fact that `ASTHelpers#constValue`
// returns an `Integer` value for `char` constants.
return Optional.ofNullable(ASTHelpers.constValue(tree))
.map(
constant ->
ASTHelpers.isSubtype(ASTHelpers.getType(tree), state.getSymtab().charType, state)
? (char) (int) constant
: constant)
.map(constant -> describeMatch(tree, addComment(tree, constant, state)))
.orElse(Description.NO_MATCH);
}
@Override
public Description matchVariable(VariableTree tree, VisitorState state) {
return describeMatch(
tree, addComment(tree, ASTHelpers.getSymbol(tree).getSimpleName(), state));
}
private static SuggestedFix addComment(Tree tree, Object value, VisitorState state) {
return SuggestedFix.postfixWith(
tree, "/* %s */".formatted(SourceCode.toStringConstantExpression(value, state)));
}
}
/**
* A {@link BugChecker} that uses {@link SourceCode#deleteWithTrailingWhitespace(Tree,
* VisitorState)} to suggest the deletion of annotations and methods with a name containing

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,59 @@
src/it/java/com/google/checkstyle/test/chapter7javadoc/rule711generalform/InvalidJavadocPositionTest.java:[35,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/com/google/checkstyle/test/chapter7javadoc/rule734nonrequiredjavadoc/InvalidJavadocPositionTest.java:[35,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/com/google/checkstyle/test/chapter7javadoc/rule734nonrequiredjavadoc/NonRequiredJavadocTest.java:[33,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/com/sun/checkstyle/test/chapter5comments/rule52documentationcomments/InvalidJavadocPositionTest.java:[35,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[117,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[169,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[116,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[166,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[91,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[104,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[101,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[71,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[69,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnonInnerLengthTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAvoidEscapedUnicodeCharactersTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAvoidNoArgumentSuperConstructorCallTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionCatchParameterNameTest.java:[166,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionCatchParameterNameTest.java:[193,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionCatchParameterNameTest.java:[161,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionCatchParameterNameTest.java:[187,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionClassMemberImpliedModifierTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionClassMemberImpliedModifierTest.java:[71,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionClassTypeParameterNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionClassTypeParameterNameTest.java:[69,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionConstructorsDeclarationGroupingTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionConstructorsDeclarationGroupingTest.java:[70,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionDeclarationOrderTest.java:[64,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `static` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionEqualsAvoidNullTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `equals` is already defined in this class or a supertype)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionFinalClassTest.java:[38,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalImportTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalImportTest.java:[53,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `static` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalInstantiationTest.java:[91,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionLambdaBodyLengthTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalTokenTest.java:[56,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `native` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalTokenTextTest.java:[91,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIndentationTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionLambdaParameterNameTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMemberNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[109,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `protected` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[134,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `public` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[61,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `private` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[85,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `package` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMissingJavadocTypeTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMissingOverrideTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMissingOverrideTest.java:[67,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMissingOverrideTest.java:[66,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMultipleStringLiteralsTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMutableExceptionTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionNeedBracesTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `do` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionNoLineWrapTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionOuterTypeNumberTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionOverloadMethodsDeclarationOrderTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionParameterNumberTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionRecordComponentNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionRecordComponentNumberTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionReturnCountTest.java:[38,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `void` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionSimplifyBooleanExpressionTest.java:[90,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionThrowsCountTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionTypeNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionUncommentedMainTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionUnnecessarySemicolonAfterTypeMemberDeclarationTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionUnnecessarySemicolonInTryWithResourcesTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionUnusedImportsTest.java:[57,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `static` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/DetailAstImplTest.java:[595,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
src/test/java/com/puppycrawl/tools/checkstyle/PackageNamesLoaderTest.java:[58,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/api/FilterSetTest.java:[49,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
@@ -46,6 +75,7 @@ src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/ArrayTrailingCommaCh
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/AvoidDoubleBraceInitializationCheckTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/AvoidInlineConditionalsCheckTest.java:[36,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/AvoidNoArgumentSuperConstructorCallCheckTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheckTest.java:[35,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/CovariantEqualsCheckTest.java:[36,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/DeclarationOrderCheckTest.java:[44,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheckTest.java:[55,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
@@ -70,8 +100,7 @@ src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessarySemicolon
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessarySemicolonInTryWithResourcesCheckTest.java:[38,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/design/InterfaceIsTypeCheckTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/design/MutableExceptionCheckTest.java:[54,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/design/ThrowsCountCheckTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheckTest.java:[99,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `null` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheckTest.java:[100,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `null` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheckTest.java:[81,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/InvalidJavadocPositionCheckTest.java:[59,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocContentLocationCheckTest.java:[57,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
@@ -133,7 +162,7 @@ src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithNearbyCommentF
src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilterTest.java:[151,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionSingleFilterTest.java:[42,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/grammar/antlr4/Antlr4AstRegressionTest.java:[34,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `package` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/grammar/comments/CommentsTest.java:[53,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
src/test/java/com/puppycrawl/tools/checkstyle/grammar/comments/CommentsTest.java:[69,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
src/test/java/com/puppycrawl/tools/checkstyle/grammar/java8/DefaultMethodsTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `switch` is not a valid identifier)
src/test/java/com/puppycrawl/tools/checkstyle/gui/BaseCellEditorTest.java:[31,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
src/test/java/com/puppycrawl/tools/checkstyle/utils/CheckUtilTest.java:[71,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `equals` is already defined in this class or a supertype)

View File

@@ -1,19 +1,19 @@
--- a/pom.xml
+++ b/pom.xml
@@ -366,6 +366,12 @@
<version>1.4.1</version>
@@ -368,6 +368,12 @@
<version>1.4.4</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj.version}</version>
+ <version>3.26.3<!-- Renovate: org.assertj:assertj-bom --></version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId>
@@ -2422,6 +2428,8 @@
@@ -2420,6 +2426,8 @@
<arg>
-Xplugin:ErrorProne ${error-prone.configuration-args}
</arg>
@@ -22,7 +22,7 @@
</compilerArgs>
<annotationProcessorPaths>
<path>
@@ -2434,6 +2442,11 @@
@@ -2432,6 +2440,11 @@
<artifactId>error-prone-contrib</artifactId>
<version>${error-prone-support.version}</version>
</path>
@@ -34,7 +34,7 @@
</annotationProcessorPaths>
</configuration>
</execution>
@@ -2476,9 +2489,10 @@
@@ -2474,9 +2487,10 @@
<arg>-XDcompilePolicy=simple</arg>
<arg>
-Xplugin:ErrorProne \
@@ -46,7 +46,7 @@
</compilerArgs>
<annotationProcessorPaths>
<path>
@@ -2491,6 +2505,11 @@
@@ -2489,6 +2503,11 @@
<artifactId>error-prone-contrib</artifactId>
<version>${error-prone-support.version}</version>
</path>
@@ -58,6 +58,39 @@
</annotationProcessorPaths>
</configuration>
</execution>
--- a/src/it/java/com/google/checkstyle/test/chapter2filebasic/rule21filename/FileNameTest.java
+++ b/src/it/java/com/google/checkstyle/test/chapter2filebasic/rule21filename/FileNameTest.java
@@ -23,6 +23,8 @@ import org.junit.jupiter.api.Test;
import com.google.checkstyle.test.base.AbstractGoogleModuleTestSupport;
+// This class is referenced from another package.
+@SuppressWarnings("JUnitClassModifiers")
public class FileNameTest extends AbstractGoogleModuleTestSupport {
@Override
--- a/src/it/java/com/google/checkstyle/test/chapter3filestructure/rule3sourcefile/SourceFileStructureTest.java
+++ b/src/it/java/com/google/checkstyle/test/chapter3filestructure/rule3sourcefile/SourceFileStructureTest.java
@@ -23,6 +23,8 @@ import org.junit.jupiter.api.Test;
import com.google.checkstyle.test.base.AbstractGoogleModuleTestSupport;
+// This class is referenced from another package.
+@SuppressWarnings("JUnitClassModifiers")
public class SourceFileStructureTest extends AbstractGoogleModuleTestSupport {
@Override
--- a/src/it/java/com/google/checkstyle/test/chapter3filestructure/toolongpackagetotestcoveragegooglesjavastylerule/PackageStatementTest.java
+++ b/src/it/java/com/google/checkstyle/test/chapter3filestructure/toolongpackagetotestcoveragegooglesjavastylerule/PackageStatementTest.java
@@ -23,6 +23,8 @@ import org.junit.jupiter.api.Test;
import com.google.checkstyle.test.base.AbstractGoogleModuleTestSupport;
+// This class is referenced from another package.
+@SuppressWarnings("JUnitClassModifiers")
public class PackageStatementTest extends AbstractGoogleModuleTestSupport {
@Override
--- a/src/main/java/com/puppycrawl/tools/checkstyle/DetailNodeTreeStringPrinter.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/DetailNodeTreeStringPrinter.java
@@ -63,6 +63,8 @@ public final class DetailNodeTreeStringPrinter {
@@ -71,7 +104,7 @@
final ParseStatus status = parser.parseJavadocAsDetailNode(blockComment);
--- a/src/main/java/com/puppycrawl/tools/checkstyle/SarifLogger.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/SarifLogger.java
@@ -139,6 +139,9 @@ public class SarifLogger extends AbstractAutomaticBean implements AuditListener
@@ -157,6 +157,9 @@ public class SarifLogger extends AbstractAutomaticBean implements AuditListener
@Override
public void auditFinished(AuditEvent event) {
final String version = SarifLogger.class.getPackage().getImplementationVersion();
@@ -83,7 +116,7 @@
.replace(RESULTS_PLACEHOLDER, String.join(",\n", results));
--- a/src/test/java/com/puppycrawl/tools/checkstyle/CheckerTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/CheckerTest.java
@@ -93,6 +93,8 @@ import de.thetaphi.forbiddenapis.SuppressForbidden;
@@ -97,6 +97,8 @@ import de.thetaphi.forbiddenapis.SuppressForbidden;
* @noinspectionreason ClassWithTooManyDependencies - complex tests require a large number
* of imports
*/
@@ -125,7 +158,7 @@
assertWithMessage("Exception is expected but got " + test).fail();
--- a/src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java
@@ -80,6 +80,8 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
@@ -84,6 +84,8 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
* @noinspectionreason ClassWithTooManyDependencies - complex tests require a
* large number of imports
*/
@@ -134,6 +167,26 @@
public class TreeWalkerTest extends AbstractModuleTestSupport {
@TempDir
--- a/src/test/java/com/puppycrawl/tools/checkstyle/internal/utils/XdocGenerator.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/internal/utils/XdocGenerator.java
@@ -55,7 +55,8 @@ public final class XdocGenerator {
for (Path path : templatesFilePaths) {
final String pathToFile = path.toString();
final File inputFile = new File(pathToFile);
- final File tempFile = File.createTempFile(pathToFile.replace(".template", ""), "");
+ final File outputFile = new File(pathToFile.replace(".template", ""));
+ final File tempFile = File.createTempFile(outputFile.getName(), "");
tempFile.deleteOnExit();
final XdocsTemplateSinkFactory sinkFactory = (XdocsTemplateSinkFactory)
plexus.lookup(SinkFactory.ROLE, XDOCS_TEMPLATE_HINT);
@@ -70,7 +71,6 @@ public final class XdocGenerator {
finally {
sink.close();
}
- final File outputFile = new File(pathToFile.replace(".template", ""));
final StandardCopyOption copyOption = StandardCopyOption.REPLACE_EXISTING;
Files.copy(tempFile.toPath(), outputFile.toPath(), copyOption);
}
--- a/src/test/java/com/puppycrawl/tools/checkstyle/utils/CheckUtilTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/utils/CheckUtilTest.java
@@ -47,6 +47,8 @@ import com.puppycrawl.tools.checkstyle.checks.coding.NestedIfDepthCheck;

View File

@@ -5,10 +5,10 @@ set -e -u -o pipefail
test_name="$(basename "${0}" .sh)"
project='checkstyle'
repository='https://github.com/checkstyle/checkstyle.git'
revision='checkstyle-10.14.0'
# XXX: Configure Renovate to manage the AssertJ version declared here.
additional_build_flags='-Dassertj.version=3.24.2'
revision='checkstyle-10.20.1'
additional_build_flags='-Perror-prone-compile,error-prone-test-compile -Dmaven.compiler.failOnError=true'
additional_source_directories='${project.basedir}${file.separator}src${file.separator}it${file.separator}java,${project.basedir}${file.separator}src${file.separator}xdocs-examples${file.separator}java'
shared_error_prone_flags='-XepExcludedPaths:(\Q${project.basedir}${file.separator}src${file.separator}\E(it|test|xdocs-examples)\Q${file.separator}resources\E|\Q${project.build.directory}${file.separator}\E).*'
patch_error_prone_flags=''
validation_error_prone_flags=''
# Validation skips some tests:
@@ -30,6 +30,7 @@ fi
"${revision}" \
"${additional_build_flags}" \
"${additional_source_directories}" \
"${shared_error_prone_flags}" \
"${patch_error_prone_flags}" \
"${validation_error_prone_flags}" \
"${validation_build_flags}" \

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/CollectdReporter.java:[306,57] [rawtypes] found raw type: Gauge
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[164,12] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[169,11] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[175,17] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[200,8] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[203,21] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[206,11] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[250,36] [cast] redundant cast to ByteBuffer
metrics-core/src/main/java/io/dropwizard/metrics5/CsvReporter.java:[390,35] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-core/src/main/java/io/dropwizard/metrics5/InstrumentedExecutorService.java:[244,25] [try] auto-closeable resource durationContext is never referenced in body of corresponding try statement
metrics-core/src/main/java/io/dropwizard/metrics5/InstrumentedExecutorService.java:[266,25] [try] auto-closeable resource context is never referenced in body of corresponding try statement
metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[431,14] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[436,16] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[449,17] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
metrics-healthchecks/src/test/java/io/dropwizard/metrics5/health/HealthCheckTest.java:[189,46] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone
metrics-healthchecks/src/test/java/io/dropwizard/metrics5/health/HealthCheckTest.java:[203,46] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone
metrics-httpclient/src/test/java/io/dropwizard/metrics5/httpclient/HttpClientMetricNameStrategiesTest.java:[124,22] [deprecation] rewriteURI(URI,HttpHost,boolean) in URIUtils has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedAsyncClientConnectionManager.java:[29,62] [deprecation] getDefault() in DefaultClientTlsStrategy has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[116,50] [deprecation] ConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[160,12] [deprecation] DefaultHttpClientConnectionOperator(Lookup<ConnectionSocketFactory>,SchemePortResolver,DnsResolver) in DefaultHttpClientConnectionOperator has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[30,28] [deprecation] ConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[31,28] [deprecation] ConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[32,37] [deprecation] PlainConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[33,38] [deprecation] SSLConnectionSocketFactory in org.apache.hc.client5.http.ssl has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[96,21] [deprecation] ConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpRequestExecutor.java:[49,4] [deprecation] HttpRequestExecutor(Timeout,ConnectionReuseStrategy,Http1StreamListener) in HttpRequestExecutor has been deprecated
metrics-httpclient5/src/test/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientsTest.java:[46,10] [deprecation] execute(ClassicHttpRequest) in HttpClient has been deprecated
metrics-httpclient5/src/test/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientsTest.java:[68,12] [deprecation] execute(ClassicHttpRequest) in HttpClient has been deprecated
metrics-influxdb/src/main/java/io/dropwizard/metrics5/influxdb/InfluxDbReporter.java:[282,14] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
metrics-influxdb/src/main/java/io/dropwizard/metrics5/influxdb/InfluxDbReporter.java:[287,16] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
metrics-jakarta-servlets/src/test/java/io/dropwizard/metrics5/servlets/HealthCheckServletTest.java:[31,67] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone
metrics-jdbi3/src/test/java/io/dropwizard/metrics5/jdbi3/strategies/SmartNameStrategyTest.java:[18,10] [deprecation] InstrumentedTimingCollector in io.dropwizard.metrics5.jdbi3 has been deprecated
metrics-jdbi3/src/test/java/io/dropwizard/metrics5/jdbi3/strategies/SmartNameStrategyTest.java:[24,20] [deprecation] InstrumentedTimingCollector in io.dropwizard.metrics5.jdbi3 has been deprecated
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[101,74] [unchecked] unchecked cast
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[56,74] [unchecked] unchecked cast
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[65,74] [unchecked] unchecked cast
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[74,74] [unchecked] unchecked cast
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[83,74] [unchecked] unchecked cast
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[92,74] [unchecked] unchecked cast
metrics-legacy-adapter/src/main/java/com/codahale/metrics/MetricRegistry.java:[108,27] [rawtypes] found raw type: Gauge
metrics-legacy-adapter/src/main/java/com/codahale/metrics/MetricRegistry.java:[112,27] [rawtypes] found raw type: Gauge
metrics-legacy-adapter/src/main/java/com/codahale/metrics/MetricRegistry.java:[51,49] [rawtypes] found raw type: Gauge
metrics-legacy-adapter/src/main/java/com/codahale/metrics/MetricRegistry.java:[51,9] [rawtypes] found raw type: Gauge
metrics-legacy-adapter/src/test/java/com/codahale/metrics/MetricRegistryTest.java:[367,22] [rawtypes] found raw type: Gauge
metrics-legacy-adapter/src/test/java/com/codahale/metrics/MetricRegistryTest.java:[50,4] [rawtypes] found raw type: Gauge
metrics-log4j2/src/main/java/io/dropwizard/metrics5/log4j2/InstrumentedAppender.java:[85,4] [deprecation] AbstractAppender(String,Filter,Layout<? extends Serializable>,boolean) in AbstractAppender has been deprecated
metrics-log4j2/src/main/java/io/dropwizard/metrics5/log4j2/InstrumentedAppender.java:[96,4] [deprecation] AbstractAppender(String,Filter,Layout<? extends Serializable>,boolean) in AbstractAppender has been deprecated
metrics-servlets/src/test/java/io/dropwizard/metrics5/servlets/HealthCheckServletTest.java:[31,67] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone

View File

@@ -0,0 +1,98 @@
--- a/metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics5/servlets/MetricsServlet.java
+++ b/metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics5/servlets/MetricsServlet.java
@@ -188,6 +188,9 @@ public class MetricsServlet extends HttpServlet {
return mapper.writer();
}
+ // Here `value` may be `null`, while `TimeUnit#valueOf` requires a non-`null` argument.
+ // XXX: Investigate better nullness handling by `IdentityConversion`.
+ @SuppressWarnings("IdentityConversion")
protected TimeUnit parseTimeUnit(String value, TimeUnit defaultValue) {
try {
return TimeUnit.valueOf(String.valueOf(value).toUpperCase(Locale.US));
--- a/metrics-servlets/src/main/java/io/dropwizard/metrics5/servlets/MetricsServlet.java
+++ b/metrics-servlets/src/main/java/io/dropwizard/metrics5/servlets/MetricsServlet.java
@@ -188,6 +188,9 @@ public class MetricsServlet extends HttpServlet {
return mapper.writer();
}
+ // Here `value` may be `null`, while `TimeUnit#valueOf` requires a non-`null` argument.
+ // XXX: Investigate better nullness handling by `IdentityConversion`.
+ @SuppressWarnings("IdentityConversion")
protected TimeUnit parseTimeUnit(String value, TimeUnit defaultValue) {
try {
return TimeUnit.valueOf(String.valueOf(value).toUpperCase(Locale.US));
--- a/pom.xml
+++ b/pom.xml
@@ -136,6 +136,27 @@
</repository>
</distributionManagement>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_annotations</artifactId>
+ <version>${error-prone.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>33.3.1-jre<!-- Renovate: com.google.guava:guava-bom --></version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ </dependencies>
+
<profiles>
<profile>
<id>jdk8</id>
@@ -218,7 +239,7 @@
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-XDcompilePolicy=simple</arg>
- <arg>-Xplugin:ErrorProne -XepExcludedPaths:.*/target/generated-sources/.*</arg>
+ <arg>-Xplugin:ErrorProne ${error-prone.configuration-args}</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
@@ -229,12 +250,24 @@
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
+ <arg>-Xmaxwarns</arg>
+ <arg>1000000</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
- <version>${errorprone.version}</version>
+ <version>${error-prone.version}</version>
+ </path>
+ <path>
+ <groupId>tech.picnic.error-prone-support</groupId>
+ <artifactId>error-prone-contrib</artifactId>
+ <version>${error-prone-support.version}</version>
+ </path>
+ <path>
+ <groupId>tech.picnic.error-prone-support</groupId>
+ <artifactId>refaster-runner</artifactId>
+ <version>${error-prone-support.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
@@ -364,7 +397,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <release>8</release>
+ <release>11</release>
<fork>true</fork>
<parameters>true</parameters>
<showWarnings>true</showWarnings>

36
integration-tests/metrics.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -e -u -o pipefail
test_name="$(basename "${0}" .sh)"
project='metrics'
repository='https://github.com/dropwizard/metrics.git'
revision='v5.0.0-rc22'
additional_build_flags=''
additional_source_directories=''
# XXX: Minimize the diff by including
# `-XepOpt:Slf4jLoggerDeclaration:CanonicalStaticLoggerName=LOGGER` once such
# flags are supported in patch mode. See
# https://github.com/google/error-prone/pull/4699.
shared_error_prone_flags='-XepExcludedPaths:.*/target/generated-sources/.*'
patch_error_prone_flags=''
validation_error_prone_flags=''
validation_build_flags=''
if [ "${#}" -gt 2 ] || ([ "${#}" = 2 ] && [ "${1:---sync}" != '--sync' ]); then
>&2 echo "Usage: ${0} [--sync] [<report_directory>]"
exit 1
fi
"$(dirname "${0}")/run-integration-test.sh" \
"${test_name}" \
"${project}" \
"${repository}" \
"${revision}" \
"${additional_build_flags}" \
"${additional_source_directories}" \
"${shared_error_prone_flags}" \
"${patch_error_prone_flags}" \
"${validation_error_prone_flags}" \
"${validation_build_flags}" \
$@

View File

@@ -12,8 +12,8 @@ integration_test_root="$(cd "$(dirname -- "${0}")" && pwd)"
error_prone_support_root="${integration_test_root}/.."
repos_root="${integration_test_root}/.repos"
if [ "${#}" -lt 9 ] || [ "${#}" -gt 11 ] || ([ "${#}" = 11 ] && [ "${10:---sync}" != '--sync' ]); then
>&2 echo "Usage: $(basename "${0}") <test_name> <project> <repository> <revision> <additional_build_flags> <additional_source_directories> <patch_error_prone_flags> <validation_error_prone_flags> <validation_build_flags> [--sync] [<report_directory>]"
if [ "${#}" -lt 10 ] || [ "${#}" -gt 12 ] || ([ "${#}" = 12 ] && [ "${11:---sync}" != '--sync' ]); then
>&2 echo "Usage: $(basename "${0}") <test_name> <project> <repository> <revision> <additional_build_flags> <additional_source_directories> <shared_error_prone_flags> <patch_error_prone_flags> <validation_error_prone_flags> <validation_build_flags> [--sync] [<report_directory>]"
exit 1
fi
@@ -23,11 +23,12 @@ repository="${3}"
revision="${4}"
additional_build_flags="${5}"
additional_source_directories="${6}"
patch_error_prone_flags="${7}"
validation_error_prone_flags="${8}"
validation_build_flags="${9}"
do_sync="$([ "${#}" = 9 ] || [ "${10:-}" != '--sync' ] || echo 1)"
report_directory="$([ "${#}" = 9 ] || ([ -z "${do_sync}" ] && echo "${10}") || ([ "${#}" = 10 ] || echo "${11}"))"
shared_error_prone_flags="${7}"
patch_error_prone_flags="${8}"
validation_error_prone_flags="${9}"
validation_build_flags="${10}"
do_sync="$([ "${#}" = 10 ] || [ "${11:-}" != '--sync' ] || echo 1)"
report_directory="$([ "${#}" = 10 ] || ([ -z "${do_sync}" ] && echo "${11}") || ([ "${#}" = 11 ] || echo "${12}"))"
if [ -n "${report_directory}" ]; then
mkdir -p "${report_directory}"
@@ -52,7 +53,6 @@ case "$(uname -s)" in
esac
shared_build_flags="
-Perror-prone-compile,error-prone-test-compile
-Derror-prone.version=$(
mvn -f "${error_prone_support_root}" help:evaluate -Dexpression=version.error-prone -q -DforceStdout
)
@@ -63,15 +63,9 @@ shared_build_flags="
${additional_build_flags}
"
# XXX: Configure Renovate to manage the fmt-maven-plugin version declared here.
# XXX: Once GitHub actions uses Maven 3.9.2+, we can inline this variable with
# version reference `${fmt.version}`, and `-Dfmt.version=2.21.1` added to
# `shared_build_flags`.
format_goal='com.spotify.fmt:fmt-maven-plugin:2.21.1:format'
format_goal='com.spotify.fmt:fmt-maven-plugin:2.25:format'
error_prone_shared_flags='-XepExcludedPaths:(\Q${project.basedir}${file.separator}src${file.separator}\E(it|test|xdocs-examples)\Q${file.separator}resources\E|\Q${project.build.directory}${file.separator}\E).*'
error_prone_patch_flags="${error_prone_shared_flags} -XepPatchLocation:IN_PLACE -XepPatchChecks:$(
error_prone_patch_flags="${shared_error_prone_flags} -XepPatchLocation:IN_PLACE -XepPatchChecks:$(
find "${error_prone_support_root}" \
-path "*/META-INF/services/com.google.errorprone.bugpatterns.BugChecker" \
-not -path "*/error-prone-experimental/*" \
@@ -81,7 +75,7 @@ error_prone_patch_flags="${error_prone_shared_flags} -XepPatchLocation:IN_PLACE
| paste -s -d ',' -
) ${patch_error_prone_flags}"
error_prone_validation_flags="${error_prone_shared_flags} -XepDisableAllChecks $(
error_prone_validation_flags="${shared_error_prone_flags} -XepDisableAllChecks $(
find "${error_prone_support_root}" \
-path "*/META-INF/services/com.google.errorprone.bugpatterns.BugChecker" \
-not -path "*/error-prone-experimental/*" \
@@ -125,14 +119,22 @@ pushd "${project_root}"
git config user.email || git config user.email 'integration-test@example.com'
git config user.name || git config user.name 'Integration Test'
# Prepare the code for analysis by (a) applying the minimal set of changes
# required to run Error Prone with Error Prone Support and (b) formatting the
# code using the same method by which it will be formatted after each
# compilation round. The initial formatting operation ensures that subsequent
# modifications can be rendered in a clean manner.
# Prepare the code for analysis by applying the minimal set of changes required
# to run Error Prone with Error Prone Support.
initial_patch="${integration_test_root}/${test_name}-init.patch"
git clean -fdx
git apply < "${integration_test_root}/${test_name}-init.patch"
git apply < "${initial_patch}"
git commit -m 'dependency: Introduce Error Prone Support' .
if [ -n "${do_sync}" ]; then
# The initial patch applied successfully, but if it was created against a
# different version, then offsets may have changed. Here we update the patch
# to exactly match the new state.
git diff HEAD~1 | "${grep_command}" -vP '^(diff|index)' > "${initial_patch}"
fi
# Format the patched code using the same method by which it will be formatted
# after each compilation round. This initial formatting operation ensures that
# subsequent modifications can be rendered in a clean manner.
mvn ${shared_build_flags} "${format_goal}"
git commit -m 'minor: Reformat using Google Java Format' .
diff_base="$(git rev-parse HEAD)"
@@ -141,10 +143,13 @@ diff_base="$(git rev-parse HEAD)"
function apply_patch() {
local extra_build_args="${1}"
mvn ${shared_build_flags} ${extra_build_args} \
package "${format_goal}" \
-Derror-prone.configuration-args="${error_prone_patch_flags}" \
-DskipTests
(
set -x \
&& mvn ${shared_build_flags} ${extra_build_args} \
package "${format_goal}" \
-Derror-prone.configuration-args="${error_prone_patch_flags}" \
-DskipTests
)
if ! git diff --exit-code; then
git commit -m 'minor: Apply patches' .
@@ -168,12 +173,13 @@ apply_patch ''
# By also running the tests, we validate that the (majority of) applied changes
# are behavior preserving.
validation_build_log="${report_directory}/${test_name}-validation-build-log.txt"
mvn ${shared_build_flags} \
clean package \
-Derror-prone.configuration-args="${error_prone_validation_flags}" \
${validation_build_flags} \
| tee "${validation_build_log}" \
|| failure=1
(
set -x \
&& mvn ${shared_build_flags} \
clean package \
-Derror-prone.configuration-args="${error_prone_validation_flags}" \
${validation_build_flags}
) | tee "${validation_build_log}" || failure=1
# Collect the applied changes.
expected_changes="${integration_test_root}/${test_name}-expected-changes.patch"

56
pom.xml
View File

@@ -4,7 +4,7 @@
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.19.1</version>
<version>0.19.2-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Picnic :: Error Prone Support</name>
@@ -52,7 +52,7 @@
<scm child.scm.developerConnection.inherit.append.path="false" child.scm.url.inherit.append.path="false">
<developerConnection>scm:git:git@github.com:PicnicSupermarket/error-prone-support.git</developerConnection>
<tag>v0.19.1</tag>
<tag>HEAD</tag>
<url>https://github.com/PicnicSupermarket/error-prone-support</url>
</scm>
<issueManagement>
@@ -151,7 +151,7 @@
<groupId.error-prone>com.google.errorprone</groupId.error-prone>
<!-- The build timestamp is derived from the most recent commit
timestamp in support of reproducible builds. -->
<project.build.outputTimestamp>2024-11-03T15:57:02Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2024-11-03T15:58:19Z</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,7 +211,7 @@
<version.auto-value>1.11.0</version.auto-value>
<version.error-prone>${version.error-prone-orig}</version.error-prone>
<version.error-prone-fork>v${version.error-prone-orig}-picnic-1</version.error-prone-fork>
<version.error-prone-orig>2.35.1</version.error-prone-orig>
<version.error-prone-orig>1.0-HEAD-SNAPSHOT</version.error-prone-orig>
<version.error-prone-slf4j>0.1.28</version.error-prone-slf4j>
<version.guava-beta-checker>1.0</version.guava-beta-checker>
<version.jdk>17</version.jdk>
@@ -220,7 +220,7 @@
<version.nopen-checker>1.0.1</version.nopen-checker>
<version.nullaway>0.12.1</version.nullaway>
<version.pitest-git>1.1.4</version.pitest-git>
<version.rewrite-templating>1.16.3</version.rewrite-templating>
<version.rewrite-templating>1.17.1</version.rewrite-templating>
<version.surefire>3.2.3</version.surefire>
</properties>
@@ -367,8 +367,10 @@
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.13.6</version>
<artifactId>micrometer-bom</artifactId>
<version>1.14.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
@@ -390,7 +392,7 @@
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.2.25</version>
<version>2.2.26</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
@@ -425,7 +427,7 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.15.7</version>
<version>1.15.10</version>
</dependency>
<!-- Specified so that Renovate will file Maven upgrade PRs, which
subsequently will cause `maven-enforcer-plugin` to require that
@@ -450,7 +452,7 @@
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.48.1</version>
<version>3.48.2</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
@@ -484,14 +486,7 @@
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-core</artifactId>
<version>5.2.0</version>
</dependency>
<!-- XXX: Drop this `rewrite-java-17` version declaration once
`rewrite-recipe-bom` pulls in version 8.39.1 or greater. -->
<dependency>
<groupId>org.openrewrite</groupId>
<artifactId>rewrite-java-17</artifactId>
<version>8.38.1</version>
<version>5.2.1</version>
</dependency>
<dependency>
<groupId>org.openrewrite</groupId>
@@ -501,7 +496,7 @@
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-recipe-bom</artifactId>
<version>2.21.1</version>
<version>2.22.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -515,19 +510,19 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>6.1.14</version>
<version>6.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>3.3.5</version>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-bom</artifactId>
<version>6.3.4</version>
<version>6.4.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -928,7 +923,7 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.20.0</version>
<version>10.20.1</version>
</dependency>
<dependency>
<groupId>io.spring.nohttp</groupId>
@@ -1227,7 +1222,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.10.1</version>
<version>3.11.1</version>
<configuration>
<additionalJOptions>
<additionalJOption>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</additionalJOption>
@@ -1297,7 +1292,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.1</version>
<version>3.5.2</version>
<configuration>
<includes>
<include>**/*Test.java</include>
@@ -1310,11 +1305,6 @@
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.6.0</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
@@ -1457,7 +1447,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.17.1</version>
<version>2.18.0</version>
<configuration>
<updateBuildOutputTimestampPolicy>never</updateBuildOutputTimestampPolicy>
</configuration>
@@ -1526,7 +1516,7 @@
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.17.0</version>
<version>1.17.1</version>
<configuration>
<excludedClasses>
<!-- AutoValue generated classes. -->
@@ -1580,7 +1570,7 @@
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
<version>5.0.0.4389</version>
</plugin>
</plugins>
</pluginManagement>

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.19.1</version>
<version>0.19.2-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.19.1</version>
<version>0.19.2-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.19.1</version>
<version>0.19.2-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.19.1</version>
<version>0.19.2-SNAPSHOT</version>
</parent>
<artifactId>refaster-test-support</artifactId>

View File

@@ -1,8 +1,29 @@
# 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.19.1
compatible:
- "2.35.1"
- "2.35.0"
- "2.34.0"
- "2.33.0"
- "2.32.0"
- "2.31.0"
- "2.30.0"
- version: 0.19.0
compatible:
- "2.35.1"
- "2.35.0"
- "2.34.0"
- "2.33.0"
- "2.32.0"
- "2.31.0"
- "2.30.0"
- version: 0.18.0
compatible:
- "2.35.1"
- "2.35.0"
- "2.34.0"
- "2.33.0"
- "2.32.0"
- "2.31.0"