mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 08:11:25 +00:00
Compare commits
160 Commits
rossendrij
...
v0.22.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c429f0d1c | ||
|
|
ac6ffc72e9 | ||
|
|
07399bb4ef | ||
|
|
aa988ef2b0 | ||
|
|
b58be2b89b | ||
|
|
8fa90f6121 | ||
|
|
6ba03c6352 | ||
|
|
912e06885d | ||
|
|
e803a5d333 | ||
|
|
4a1ad1b991 | ||
|
|
80d433f051 | ||
|
|
afd9703ce6 | ||
|
|
f9d310bc4b | ||
|
|
a3a9ca0bf0 | ||
|
|
0e609aeb1c | ||
|
|
e9dae1d66c | ||
|
|
f0ad9d21e6 | ||
|
|
7138aa2100 | ||
|
|
de4667628f | ||
|
|
5e958fe20b | ||
|
|
baa921caac | ||
|
|
ba040bd191 | ||
|
|
a3a20b52e5 | ||
|
|
5d8d27176b | ||
|
|
d878a57a8e | ||
|
|
eaec12f460 | ||
|
|
da7dafb6e7 | ||
|
|
5a7aaf12d6 | ||
|
|
92e4d74e4b | ||
|
|
4a0bc0c210 | ||
|
|
53152499d6 | ||
|
|
61d92fb33f | ||
|
|
8690f49c35 | ||
|
|
d808f664ec | ||
|
|
7f5f4820e9 | ||
|
|
f7a4427852 | ||
|
|
0e956bcd44 | ||
|
|
5395fc60e1 | ||
|
|
d8cae04a98 | ||
|
|
7b14711ecf | ||
|
|
c3351b9ee1 | ||
|
|
40b3c87b72 | ||
|
|
726db5ce5b | ||
|
|
99d359c548 | ||
|
|
4744113411 | ||
|
|
ae8f940f55 | ||
|
|
8d7633df2d | ||
|
|
4a351cfbe3 | ||
|
|
bb01447760 | ||
|
|
f12ed17b96 | ||
|
|
854e05f044 | ||
|
|
82c22682c0 | ||
|
|
25b3817876 | ||
|
|
e2a2b086ad | ||
|
|
5f9a0c5e17 | ||
|
|
2a0ae0af13 | ||
|
|
7a051146b6 | ||
|
|
d9398001cb | ||
|
|
0be99cb12a | ||
|
|
70e2d3d43f | ||
|
|
441258f9f2 | ||
|
|
b96efb533c | ||
|
|
5af067cc23 | ||
|
|
0c84665e38 | ||
|
|
9316d81fe3 | ||
|
|
ec96c044d5 | ||
|
|
ae4ed9273f | ||
|
|
0ec882e62e | ||
|
|
fef9ba23f4 | ||
|
|
3bd415b910 | ||
|
|
2128624261 | ||
|
|
c53fcace76 | ||
|
|
ff3759984c | ||
|
|
6358d1e2e1 | ||
|
|
db53631e76 | ||
|
|
86b2d929ab | ||
|
|
0db4462a64 | ||
|
|
f8667fc655 | ||
|
|
d91f94e879 | ||
|
|
ad6c8593f2 | ||
|
|
873ee47e8d | ||
|
|
fed281dc2b | ||
|
|
277d30467d | ||
|
|
064e0bbc8c | ||
|
|
3beadeec50 | ||
|
|
c2a26ed12f | ||
|
|
2419dad433 | ||
|
|
900d6eaf78 | ||
|
|
33d205e11f | ||
|
|
ee0651d9d3 | ||
|
|
fb22039fd3 | ||
|
|
cf294b8964 | ||
|
|
0004c8bc44 | ||
|
|
aedeeb0943 | ||
|
|
a68e5ae150 | ||
|
|
6a6354eb55 | ||
|
|
ab0a844f26 | ||
|
|
5105cb684f | ||
|
|
f128a7975f | ||
|
|
e572a3641d | ||
|
|
2b467832fb | ||
|
|
77557c80b1 | ||
|
|
9088369f89 | ||
|
|
36ef967f0e | ||
|
|
dd190ee056 | ||
|
|
4c32d3ce7a | ||
|
|
4608c00140 | ||
|
|
708317f314 | ||
|
|
636c1993d5 | ||
|
|
895875c849 | ||
|
|
1aea710c53 | ||
|
|
5085eb2f25 | ||
|
|
ad5b1c9917 | ||
|
|
34cab33b76 | ||
|
|
c836f1147f | ||
|
|
f43921f344 | ||
|
|
811e70ae3a | ||
|
|
5fd50e6181 | ||
|
|
3767341605 | ||
|
|
9f83eec36b | ||
|
|
126159878c | ||
|
|
78141b2528 | ||
|
|
56db8adb5a | ||
|
|
90b4baba12 | ||
|
|
54c56a4cc8 | ||
|
|
b123282778 | ||
|
|
f4562c7106 | ||
|
|
6211e7e651 | ||
|
|
3e4a01a673 | ||
|
|
a42353b41a | ||
|
|
d2ce18e33e | ||
|
|
7b81dc44e5 | ||
|
|
5e81719cea | ||
|
|
2f3788fc63 | ||
|
|
a98780cef2 | ||
|
|
ff0e30c885 | ||
|
|
4aacc58382 | ||
|
|
dec22b8633 | ||
|
|
37d8ea92c6 | ||
|
|
7eb46dd218 | ||
|
|
623bdd7344 | ||
|
|
c3ae1b5b92 | ||
|
|
19d3ba0505 | ||
|
|
9493f2d59a | ||
|
|
68ecd652f7 | ||
|
|
e67800e4e2 | ||
|
|
7f90f26830 | ||
|
|
6477c1899d | ||
|
|
03514f9f6a | ||
|
|
d11ac09bda | ||
|
|
667f83fd2f | ||
|
|
15ba59a9aa | ||
|
|
a46d6dc146 | ||
|
|
cf523bc811 | ||
|
|
9bd8095e0b | ||
|
|
6cfa9a0dfe | ||
|
|
7daa39a0b5 | ||
|
|
5fc7bc29ee | ||
|
|
83f3f8bedc | ||
|
|
12585a8969 |
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@@ -14,11 +14,11 @@ jobs:
|
||||
distribution: [ temurin ]
|
||||
experimental: [ false ]
|
||||
include:
|
||||
- os: macos-14
|
||||
- os: macos-15
|
||||
jdk: 17.0.13
|
||||
distribution: temurin
|
||||
experimental: false
|
||||
- os: windows-2022
|
||||
- os: windows-2025
|
||||
jdk: 17.0.13
|
||||
distribution: temurin
|
||||
experimental: false
|
||||
@@ -26,14 +26,16 @@ jobs:
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
allowed-endpoints: >
|
||||
api.adoptium.net:443
|
||||
github.com:443
|
||||
github-registry-files.githubusercontent.com:443
|
||||
jitpack.io:443
|
||||
maven.pkg.github.com:443
|
||||
objects.githubusercontent.com:443
|
||||
repo.maven.apache.org:443
|
||||
# We run the build twice for each supported JDK: once against the
|
||||
@@ -42,7 +44,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@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
uses: s4u/setup-maven-action@4f7fb9d9675e899ca81c6161dadbba0189a4ebb1 # v1.18.0
|
||||
with:
|
||||
java-version: ${{ matrix.jdk }}
|
||||
java-distribution: ${{ matrix.distribution }}
|
||||
@@ -53,6 +55,8 @@ jobs:
|
||||
run: mvn -T1C install javadoc:jar
|
||||
- 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
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Remove installed project artifacts
|
||||
run: mvn dependency:purge-local-repository -DmanualInclude='${project.groupId}' -DresolutionFuzziness=groupId
|
||||
|
||||
|
||||
8
.github/workflows/codeql.yml
vendored
8
.github/workflows/codeql.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -34,19 +34,19 @@ 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@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
uses: s4u/setup-maven-action@4f7fb9d9675e899ca81c6161dadbba0189a4ebb1 # v1.18.0
|
||||
with:
|
||||
java-version: 17.0.13
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.9
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
||||
uses: github/codeql-action/init@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Perform minimal build
|
||||
if: matrix.language == 'java'
|
||||
run: mvn -T1C clean package -DskipTests -Dverification.skip
|
||||
- name: Perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
||||
uses: github/codeql-action/analyze@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
|
||||
with:
|
||||
category: /language:${{ matrix.language }}
|
||||
|
||||
7
.github/workflows/deploy-website.yml
vendored
7
.github/workflows/deploy-website.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -21,6 +21,7 @@ jobs:
|
||||
api.github.com:443
|
||||
bestpractices.coreinfrastructure.org:443
|
||||
blog.picnic.nl:443
|
||||
docs.github.com:443
|
||||
errorprone.info:443
|
||||
github.com:443
|
||||
img.shields.io:443
|
||||
@@ -42,7 +43,7 @@ jobs:
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: ruby/setup-ruby@a2bbe5b1b236842c1cb7dd11e8e3b51e0a616acc # v1.202.0
|
||||
- uses: ruby/setup-ruby@1a615958ad9d422dd932dc1d5823942ee002799f # v1.227.0
|
||||
with:
|
||||
working-directory: ./website
|
||||
bundler-cache: true
|
||||
@@ -74,7 +75,7 @@ jobs:
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
6
.github/workflows/openssf-scorecard.yml
vendored
6
.github/workflows/openssf-scorecard.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -42,12 +42,12 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run OpenSSF Scorecard analysis
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: ${{ github.ref == 'refs/heads/master' }}
|
||||
- name: Update GitHub's code scanning dashboard
|
||||
uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
||||
uses: github/codeql-action/upload-sarif@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
6
.github/workflows/pitest-analyze-pr.yml
vendored
6
.github/workflows/pitest-analyze-pr.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.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@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
uses: s4u/setup-maven-action@4f7fb9d9675e899ca81c6161dadbba0189a4ebb1 # v1.18.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@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: pitest-reports
|
||||
path: ./target/pit-reports-ci
|
||||
|
||||
4
.github/workflows/pitest-update-pr.yml
vendored
4
.github/workflows/pitest-update-pr.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.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@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
uses: s4u/setup-maven-action@4f7fb9d9675e899ca81c6161dadbba0189a4ebb1 # v1.18.0
|
||||
with:
|
||||
java-version: 17.0.13
|
||||
java-distribution: temurin
|
||||
|
||||
12
.github/workflows/run-integration-tests.yml
vendored
12
.github/workflows/run-integration-tests.yml
vendored
@@ -22,14 +22,14 @@ jobs:
|
||||
integration-test: [ "checkstyle", "metrics", "prometheus-java-client" ]
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
# XXX: After updating the validation build flags in
|
||||
# `integration-tests/prometheus-java-client.sh`, review whether the
|
||||
# Docker domains specified here can be dropped.
|
||||
allowed-endpoints: >
|
||||
# XXX: After updating the validation build flags in
|
||||
# `integration-tests/prometheus-java-client.sh`, review whether the
|
||||
# Docker domains specified here can be dropped.
|
||||
api.adoptium.net:443
|
||||
auth.docker.io:443
|
||||
checkstyle.org:443
|
||||
@@ -43,7 +43,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@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
uses: s4u/setup-maven-action@4f7fb9d9675e899ca81c6161dadbba0189a4ebb1 # v1.18.0
|
||||
with:
|
||||
checkout-ref: "refs/pull/${{ github.event.issue.number }}/head"
|
||||
java-version: 17.0.13
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
run: xvfb-run "./integration-tests/${{ matrix.integration-test }}.sh" "${{ runner.temp }}/artifacts"
|
||||
- name: Upload artifacts on failure
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: "integration-test-${{ matrix.integration-test }}"
|
||||
path: "${{ runner.temp }}/artifacts"
|
||||
|
||||
4
.github/workflows/sonarcloud.yml
vendored
4
.github/workflows/sonarcloud.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.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@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
uses: s4u/setup-maven-action@4f7fb9d9675e899ca81c6161dadbba0189a4ebb1 # v1.18.0
|
||||
with:
|
||||
checkout-fetch-depth: 0
|
||||
java-version: 17.0.13
|
||||
|
||||
20
README.md
20
README.md
@@ -205,12 +205,13 @@ Relevant Maven build parameters:
|
||||
version of Error Prone. This is useful e.g. when testing a locally built
|
||||
Error Prone SNAPSHOT.
|
||||
- `-Perror-prone-fork` runs the build using Picnic's [Error Prone
|
||||
fork][error-prone-fork-repo], hosted on [Jitpack][error-prone-fork-jitpack].
|
||||
This fork generally contains a few changes on top of the latest Error Prone
|
||||
release.
|
||||
fork][error-prone-fork-repo], hosted using [GitHub
|
||||
Packages][error-prone-fork-packages]. This fork generally contains a few
|
||||
changes on top of the latest Error Prone release. Using this profile
|
||||
generally requires passing `-s settings.xml`, with [suitably
|
||||
configured][github-packages-auth] `GITHUB_ACTOR` and `GITHUB_TOKEN`
|
||||
environment variables.
|
||||
- `-Pself-check` runs the checks defined by this project against itself.
|
||||
Pending a release of [google/error-prone#3301][error-prone-pull-3301], this
|
||||
flag must currently be used in combination with `-Perror-prone-fork`.
|
||||
|
||||
Other highly relevant commands:
|
||||
|
||||
@@ -235,8 +236,9 @@ Other highly relevant commands:
|
||||
against _all_ code in the current working directory. For more information
|
||||
check the [PIT Maven plugin][pitest-maven].
|
||||
|
||||
When running the project's tests in IntelliJ IDEA, you might see the following
|
||||
error:
|
||||
Opening the project in IntelliJ IDEA may require running `mvn clean install`
|
||||
first. Additionally, when running the project's tests using the IDE, you might
|
||||
see the following error:
|
||||
|
||||
```
|
||||
java: exporting a package from system module jdk.compiler is not allowed with --release
|
||||
@@ -274,14 +276,14 @@ channel; please see our [security policy][security] for details.
|
||||
[contributing]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/CONTRIBUTING.md
|
||||
[contributing-pull-request]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/CONTRIBUTING.md#-opening-a-pull-request
|
||||
[error-prone-bugchecker]: https://github.com/google/error-prone/blob/master/check_api/src/main/java/com/google/errorprone/bugpatterns/BugChecker.java
|
||||
[error-prone-fork-jitpack]: https://jitpack.io/#PicnicSupermarket/error-prone
|
||||
[error-prone-fork-packages]: https://github.com/PicnicSupermarket/error-prone/packages
|
||||
[error-prone-fork-repo]: https://github.com/PicnicSupermarket/error-prone
|
||||
[error-prone-gradle-installation-guide]: https://github.com/tbroyer/gradle-errorprone-plugin
|
||||
[error-prone-installation-guide]: https://errorprone.info/docs/installation#maven
|
||||
[error-prone-orig-repo]: https://github.com/google/error-prone
|
||||
[error-prone-pull-3301]: https://github.com/google/error-prone/pull/3301
|
||||
[github-actions-build-badge]: https://github.com/PicnicSupermarket/error-prone-support/actions/workflows/build.yml/badge.svg
|
||||
[github-actions-build-master]: https://github.com/PicnicSupermarket/error-prone-support/actions/workflows/build.yml?query=branch:master&event=push
|
||||
[github-packages-auth]: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry#authenticating-to-github-packages
|
||||
[google-java-format]: https://github.com/google/google-java-format
|
||||
[idea-288052]: https://youtrack.jetbrains.com/issue/IDEA-288052
|
||||
[license-badge]: https://img.shields.io/github/license/PicnicSupermarket/error-prone-support
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.19.2-SNAPSHOT</version>
|
||||
<version>0.22.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>documentation-support</artifactId>
|
||||
@@ -15,24 +15,6 @@
|
||||
<url>https://error-prone.picnic.tech</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>error-prone-utils</artifactId>
|
||||
@@ -72,6 +54,24 @@
|
||||
<artifactId>auto-value-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
||||
@@ -2,6 +2,7 @@ package tech.picnic.errorprone.documentation;
|
||||
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.staticMethod;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
@@ -167,7 +168,10 @@ public final class BugPatternTestExtractor implements Extractor<BugPatternTestCa
|
||||
* is safe, because this code is guarded by an earlier call to `#getClassUnderTest(..)`,
|
||||
* which ensures that `tree` is part of a longer method invocation chain.
|
||||
*/
|
||||
MethodInvocationTree inputTree = (MethodInvocationTree) ASTHelpers.getReceiver(tree);
|
||||
MethodInvocationTree inputTree =
|
||||
(MethodInvocationTree)
|
||||
requireNonNull(
|
||||
ASTHelpers.getReceiver(tree), "Instance method invocation must have receiver");
|
||||
|
||||
String path = ASTHelpers.constValue(inputTree.getArguments().get(0), String.class);
|
||||
Optional<String> inputCode = getSourceCode(inputTree);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.19.2-SNAPSHOT</version>
|
||||
<version>0.22.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
@@ -15,31 +15,6 @@
|
||||
<url>https://error-prone.picnic.tech</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>documentation-support</artifactId>
|
||||
@@ -87,6 +62,41 @@
|
||||
<artifactId>auto-value-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- XXX: JSR-305 (meta-)annotation usage by some dependencies triggers
|
||||
NullAway to attempt to load said annotations. As such some modules
|
||||
require these annotations to be on the classpath. Periodically review
|
||||
whether we can drop this dependeny declaration. See
|
||||
https://github.com/uber/NullAway/issues/1171. -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
||||
@@ -11,6 +11,7 @@ import static com.google.errorprone.matchers.Matchers.not;
|
||||
import static com.google.errorprone.matchers.Matchers.returnStatement;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.toType;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
@@ -79,7 +80,10 @@ public final class DirectReturn extends BugChecker implements BlockTreeMatcher {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
Symbol variableSymbol = ASTHelpers.getSymbol(((ReturnTree) finalStatement).getExpression());
|
||||
Symbol variableSymbol =
|
||||
requireNonNull(
|
||||
ASTHelpers.getSymbol(((ReturnTree) finalStatement).getExpression()),
|
||||
"Missing symbol for returned variable");
|
||||
StatementTree precedingStatement = statements.get(statements.size() - 2);
|
||||
|
||||
return tryMatchAssignment(variableSymbol, precedingStatement)
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.PERFORMANCE;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static com.google.errorprone.matchers.method.MethodMatchers.instanceMethod;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Verify;
|
||||
import com.google.common.base.VerifyException;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.annotations.Var;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import java.util.Collections;
|
||||
import java.util.Formattable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags {@link String#format} and {@link String#formatted} invocations
|
||||
* that can be omitted by delegating to another format method.
|
||||
*/
|
||||
// XXX: The special-casing of Throwable applies only to SLF4J 1.6.0+; see
|
||||
// https://www.slf4j.org/faq.html#paramException. That should be documented.
|
||||
// XXX: Some of the `Matcher`s defined here are also declared by the `Slf4jLogStatement` and
|
||||
// `RedundantStringConversion` checks. Look into deduplicating them.
|
||||
// XXX: Should we also simplify e.g. `LOG.error(String.join("sep", arg1, arg2), throwable)`? Perhaps
|
||||
// that's too obscure.
|
||||
// XXX: This check currently only flags string format expressions that are a direct argument to
|
||||
// another format-capable method invocation. Indirect cases, such as where the result is assigned to
|
||||
// a variable, are currently not covered.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "String formatting can be deferred",
|
||||
link = BUG_PATTERNS_BASE_URL + "EagerStringFormatting",
|
||||
linkType = CUSTOM,
|
||||
severity = WARNING,
|
||||
tags = {PERFORMANCE, SIMPLIFICATION})
|
||||
public final class EagerStringFormatting extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> FORMATTABLE = isSubtypeOf(Formattable.class);
|
||||
private static final Matcher<ExpressionTree> LOCALE = isSubtypeOf(Locale.class);
|
||||
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> REQUIRE_NON_NULL_INVOCATION =
|
||||
staticMethod().onClass(Objects.class.getCanonicalName()).named("requireNonNull");
|
||||
private static final Matcher<ExpressionTree> GUAVA_GUARD_INVOCATION =
|
||||
anyOf(
|
||||
staticMethod()
|
||||
.onClass(Preconditions.class.getCanonicalName())
|
||||
.namedAnyOf("checkArgument", "checkNotNull", "checkState"),
|
||||
staticMethod()
|
||||
.onClass(Verify.class.getCanonicalName())
|
||||
.namedAnyOf("verify", "verifyNotNull"));
|
||||
private static final Matcher<ExpressionTree> SLF4J_LOGGER_INVOCATION =
|
||||
instanceMethod()
|
||||
.onDescendantOf("org.slf4j.Logger")
|
||||
.namedAnyOf("trace", "debug", "info", "warn", "error");
|
||||
private static final Matcher<ExpressionTree> STATIC_FORMAT_STRING =
|
||||
staticMethod().onClass(String.class.getCanonicalName()).named("format");
|
||||
private static final Matcher<ExpressionTree> INSTANCE_FORMAT_STRING =
|
||||
instanceMethod().onDescendantOf(String.class.getCanonicalName()).named("formatted");
|
||||
private static final String MESSAGE_NEVER_NULL_ARGUMENT =
|
||||
"String formatting never yields `null` expression";
|
||||
|
||||
/** Instantiates a new {@link EagerStringFormatting} instance. */
|
||||
public EagerStringFormatting() {}
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
Tree parent = state.getPath().getParentPath().getLeaf();
|
||||
if (!(parent instanceof MethodInvocationTree methodInvocation)) {
|
||||
/*
|
||||
* Fast path: this isn't a method invocation whose result is an argument to another method
|
||||
* invocation.
|
||||
*/
|
||||
// XXX: This logic assumes that the string format operation isn't redundantly wrapped in
|
||||
// parentheses. Similar assumptions likely exist throughout the code base. Investigate how to
|
||||
// structurally cover such cases.
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return StringFormatExpression.tryCreate(tree, state)
|
||||
.map(expr -> analyzeFormatStringContext(expr, methodInvocation, state))
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
|
||||
private Description analyzeFormatStringContext(
|
||||
StringFormatExpression stringFormat, MethodInvocationTree context, VisitorState state) {
|
||||
if (REQUIRE_NON_NULL_INVOCATION.matches(context, state)) {
|
||||
return analyzeRequireNonNullStringFormatContext(stringFormat, context);
|
||||
}
|
||||
|
||||
if (GUAVA_GUARD_INVOCATION.matches(context, state)) {
|
||||
return analyzeGuavaGuardStringFormatContext(stringFormat, context, state);
|
||||
}
|
||||
|
||||
if (SLF4J_LOGGER_INVOCATION.matches(context, state)) {
|
||||
return analyzeSlf4jLoggerStringFormatContext(stringFormat, context, state);
|
||||
}
|
||||
|
||||
/*
|
||||
* The string formatting operation does not appear to happen in a context that admits of
|
||||
* simplification or optimization.
|
||||
*/
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
private Description analyzeRequireNonNullStringFormatContext(
|
||||
StringFormatExpression stringFormat, MethodInvocationTree context) {
|
||||
List<? extends ExpressionTree> arguments = context.getArguments();
|
||||
if (arguments.size() != 2 || arguments.get(0).equals(stringFormat.expression())) {
|
||||
/* Vacuous validation that string formatting doesn't yield `null`. */
|
||||
return buildDescription(context).setMessage(MESSAGE_NEVER_NULL_ARGUMENT).build();
|
||||
}
|
||||
|
||||
if (stringFormat.arguments().stream()
|
||||
.anyMatch(EagerStringFormatting::isNonFinalLocalVariable)) {
|
||||
/*
|
||||
* The format operation depends on a variable that isn't final or effectively final; moving
|
||||
* it into a lambda expression would cause a compilation error.
|
||||
*/
|
||||
return buildDescription(context)
|
||||
.setMessage(message() + " (but this requires introducing an effectively final variable)")
|
||||
.build();
|
||||
}
|
||||
|
||||
/* Suggest that the string formatting is deferred. */
|
||||
return describeMatch(context, SuggestedFix.prefixWith(stringFormat.expression(), "() -> "));
|
||||
}
|
||||
|
||||
private Description analyzeGuavaGuardStringFormatContext(
|
||||
StringFormatExpression stringFormat, MethodInvocationTree context, VisitorState state) {
|
||||
List<? extends ExpressionTree> arguments = context.getArguments();
|
||||
if (arguments.get(0).equals(stringFormat.expression())) {
|
||||
/*
|
||||
* Vacuous `checkNotNull` or `verifyNotNull` validation that string formatting doesn't yield
|
||||
* `null`.
|
||||
*/
|
||||
return buildDescription(context).setMessage(MESSAGE_NEVER_NULL_ARGUMENT).build();
|
||||
}
|
||||
|
||||
if (stringFormat.simplifiableFormatString().isEmpty() || arguments.size() > 2) {
|
||||
/*
|
||||
* The format string cannot be simplified, or the format string produces a format string
|
||||
* itself, or its result is the input to another format operation. These are complex cases
|
||||
* that we'll only flag.
|
||||
*/
|
||||
return createSimplificationSuggestion(context, "Guava");
|
||||
}
|
||||
|
||||
return describeMatch(context, stringFormat.suggestFlattening("%s", state));
|
||||
}
|
||||
|
||||
private Description analyzeSlf4jLoggerStringFormatContext(
|
||||
StringFormatExpression stringFormat, MethodInvocationTree context, VisitorState state) {
|
||||
if (stringFormat.simplifiableFormatString().isEmpty()) {
|
||||
/* We can't simplify this case; only flag it. */
|
||||
return createSimplificationSuggestion(context, "SLF4J");
|
||||
}
|
||||
|
||||
List<? extends ExpressionTree> arguments = context.getArguments();
|
||||
int leftOffset = SLF4J_MARKER.matches(arguments.get(0), state) ? 1 : 0;
|
||||
int rightOffset = THROWABLE.matches(arguments.get(arguments.size() - 1), state) ? 1 : 0;
|
||||
if (arguments.size() != leftOffset + 1 + rightOffset) {
|
||||
/*
|
||||
* The format string produces a format string itself, or its result is the input to another
|
||||
* format operation. This is a complex case that we'll only flag.
|
||||
*/
|
||||
return createSimplificationSuggestion(context, "SLF4J");
|
||||
}
|
||||
|
||||
return describeMatch(context, stringFormat.suggestFlattening("{}", state));
|
||||
}
|
||||
|
||||
private static boolean isNonFinalLocalVariable(Tree tree) {
|
||||
Symbol symbol = ASTHelpers.getSymbol(tree);
|
||||
return symbol instanceof VarSymbol
|
||||
&& symbol.owner instanceof MethodSymbol
|
||||
&& !ASTHelpers.isConsideredFinal(symbol);
|
||||
}
|
||||
|
||||
private Description createSimplificationSuggestion(MethodInvocationTree context, String library) {
|
||||
return buildDescription(context)
|
||||
.setMessage(
|
||||
"%s (assuming that %s's simplified formatting support suffices)"
|
||||
.formatted(message(), library))
|
||||
.build();
|
||||
}
|
||||
|
||||
/** Description of a string format expression. */
|
||||
@AutoValue
|
||||
abstract static class StringFormatExpression {
|
||||
/** The full string format expression. */
|
||||
abstract MethodInvocationTree expression();
|
||||
|
||||
/** The format string expression. */
|
||||
abstract Tree formatString();
|
||||
|
||||
/** The string format arguments to be plugged into its format string. */
|
||||
abstract ImmutableList<ExpressionTree> arguments();
|
||||
|
||||
/**
|
||||
* The constant format string, if it contains only {@code %s} placeholders, and the number of
|
||||
* said placeholders matches the number of format arguments.
|
||||
*/
|
||||
abstract Optional<String> simplifiableFormatString();
|
||||
|
||||
private SuggestedFix suggestFlattening(String newPlaceholder, VisitorState state) {
|
||||
return SuggestedFix.replace(
|
||||
expression(),
|
||||
Stream.concat(
|
||||
Stream.of(deriveFormatStringExpression(newPlaceholder, state)),
|
||||
arguments().stream().map(arg -> SourceCode.treeToString(arg, state)))
|
||||
.collect(joining(", ")));
|
||||
}
|
||||
|
||||
private String deriveFormatStringExpression(String newPlaceholder, VisitorState state) {
|
||||
String formatString =
|
||||
String.format(
|
||||
simplifiableFormatString()
|
||||
.orElseThrow(() -> new VerifyException("Format string cannot be simplified")),
|
||||
Collections.nCopies(arguments().size(), newPlaceholder).toArray());
|
||||
|
||||
/*
|
||||
* If the suggested replacement format string is the same as the original, then use the
|
||||
* expression's existing source code representation. This way string constant references are
|
||||
* not unnecessarily replaced.
|
||||
*/
|
||||
return formatString.equals(ASTHelpers.constValue(formatString(), String.class))
|
||||
? SourceCode.treeToString(formatString(), state)
|
||||
: SourceCode.toStringConstantExpression(formatString, state);
|
||||
}
|
||||
|
||||
private static Optional<StringFormatExpression> tryCreate(
|
||||
MethodInvocationTree tree, VisitorState state) {
|
||||
if (INSTANCE_FORMAT_STRING.matches(tree, state)) {
|
||||
return Optional.of(
|
||||
create(
|
||||
tree,
|
||||
requireNonNull(ASTHelpers.getReceiver(tree), "Receiver unexpectedly absent"),
|
||||
ImmutableList.copyOf(tree.getArguments()),
|
||||
state));
|
||||
}
|
||||
|
||||
if (STATIC_FORMAT_STRING.matches(tree, state)) {
|
||||
List<? extends ExpressionTree> arguments = tree.getArguments();
|
||||
int argOffset = LOCALE.matches(arguments.get(0), state) ? 1 : 0;
|
||||
return Optional.of(
|
||||
create(
|
||||
tree,
|
||||
arguments.get(argOffset),
|
||||
ImmutableList.copyOf(arguments.subList(argOffset + 1, arguments.size())),
|
||||
state));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static StringFormatExpression create(
|
||||
MethodInvocationTree expression,
|
||||
Tree formatString,
|
||||
ImmutableList<ExpressionTree> arguments,
|
||||
VisitorState state) {
|
||||
return new AutoValue_EagerStringFormatting_StringFormatExpression(
|
||||
expression,
|
||||
formatString,
|
||||
arguments,
|
||||
Optional.ofNullable(ASTHelpers.constValue(formatString, String.class))
|
||||
.filter(template -> isSimplifiable(template, arguments, state)));
|
||||
}
|
||||
|
||||
private static boolean isSimplifiable(
|
||||
String formatString, ImmutableList<ExpressionTree> arguments, VisitorState state) {
|
||||
if (arguments.stream().anyMatch(arg -> FORMATTABLE.matches(arg, state))) {
|
||||
/* `Formattable` arguments can have arbitrary format semantics. */
|
||||
return false;
|
||||
}
|
||||
|
||||
@Var int placeholderCount = 0;
|
||||
for (int p = formatString.indexOf('%'); p != -1; p = formatString.indexOf('%', p + 2)) {
|
||||
if (p == formatString.length() - 1) {
|
||||
/* Malformed format string with trailing `%`. */
|
||||
return false;
|
||||
}
|
||||
|
||||
char modifier = formatString.charAt(p + 1);
|
||||
if (modifier == 's') {
|
||||
placeholderCount++;
|
||||
} else if (modifier != '%') {
|
||||
/* Only `%s` and `%%` (a literal `%`) are supported. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return placeholderCount == arguments.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
@@ -33,6 +34,8 @@ import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Types;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -113,7 +116,7 @@ public final class ExplicitArgumentEnumeration extends BugChecker
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "doesNotContainAnyElementsOf", "doesNotContain")
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "hasSameElementsAs", "containsOnly")
|
||||
.put(STEP_VERIFIER_STEP, "expectNextSequence", "expectNext")
|
||||
.build();
|
||||
.buildOrThrow();
|
||||
|
||||
/** Instantiates a new {@link ExplicitArgumentEnumeration} instance. */
|
||||
public ExplicitArgumentEnumeration() {}
|
||||
@@ -178,30 +181,45 @@ public final class ExplicitArgumentEnumeration extends BugChecker
|
||||
state.getTypes())
|
||||
.collect(toImmutableList());
|
||||
|
||||
/*
|
||||
* If all overloads have a single parameter, and at least one of them is a varargs method, then
|
||||
* we assume that unwrapping the iterable argument will cause a suitable overload to be invoked.
|
||||
* (Note that there may be multiple varargs overloads, either with different parameter types, or
|
||||
* due to method overriding; this check does not attempt to determine which exact method or
|
||||
* overload will be invoked as a result of the suggested simplification.)
|
||||
*
|
||||
* Note that this is a (highly!) imperfect heuristic, but it is sufficient to prevent e.g.
|
||||
* unwrapping of arguments to `org.jooq.impl.DSL#row`, which can cause the expression's return
|
||||
* type to change from `RowN` to (e.g.) `Row2`.
|
||||
*/
|
||||
// XXX: There are certainly cases where it _would_ be nice to unwrap the arguments to
|
||||
// `org.jooq.impl.DSL#row(Collection<?>)`. Look into this.
|
||||
// XXX: Ideally we do check that one of the overloads accepts the unwrapped arguments.
|
||||
// XXX: Ideally we validate that eligible overloads have compatible return types.
|
||||
boolean hasLikelySuitableVarargsOverload =
|
||||
overloads.stream().allMatch(m -> m.params().size() == 1)
|
||||
&& overloads.stream().anyMatch(MethodSymbol::isVarArgs);
|
||||
|
||||
return hasLikelySuitableVarargsOverload
|
||||
return hasLikelySuitableVarargsOverload(method, overloads, state)
|
||||
? Optional.of(SourceCode.unwrapMethodInvocation(argument, state))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether it is likely that, if the argument to the given method is unwrapped, a suitable
|
||||
* varargs overload will be invoked instead.
|
||||
*
|
||||
* <p>If all overloads have a single parameter, and at least one of them is a suitably-typed
|
||||
* varargs method, then we assume that unwrapping the iterable argument will cause a suitable
|
||||
* overload to be invoked. (Note that there may be multiple varargs overloads due to method
|
||||
* overriding; this check does not attempt to determine which exact method or overload will be
|
||||
* invoked as a result of the suggested simplification.)
|
||||
*
|
||||
* <p>Note that this is a (highly!) imperfect heuristic, but it is sufficient to prevent e.g.
|
||||
* unwrapping of arguments to `org.jooq.impl.DSL#row`, which can cause the expression's return
|
||||
* type to change from `RowN` to (e.g.) `Row2`.
|
||||
*/
|
||||
// XXX: There are certainly cases where it _would_ be nice to unwrap the arguments to
|
||||
// `org.jooq.impl.DSL#row(Collection<?>)`. Look into this.
|
||||
// XXX: Ideally we validate that eligible overloads have compatible return types.
|
||||
private static boolean hasLikelySuitableVarargsOverload(
|
||||
MethodSymbol method, ImmutableList<MethodSymbol> overloads, VisitorState state) {
|
||||
Types types = state.getTypes();
|
||||
// XXX: This logic is fragile, as it assumes that the method parameter's type is of the form
|
||||
// `X<T>`, where `T` is the type of the explicitly enumerated values passed to the expression to
|
||||
// be unwrapped. This should generally hold, given the types returned by the
|
||||
// `EXPLICIT_ITERABLE_CREATOR` expressions: `Iterable<T>`, `List<T>`, `Set<T>`, etc.
|
||||
Type parameterType =
|
||||
Iterables.getOnlyElement(
|
||||
Iterables.getOnlyElement(method.getParameters()).type.getTypeArguments());
|
||||
return overloads.stream().allMatch(m -> m.params().size() == 1)
|
||||
&& overloads.stream()
|
||||
.filter(MethodSymbol::isVarArgs)
|
||||
.map(m -> types.elemtype(Iterables.getOnlyElement(m.getParameters()).type))
|
||||
.anyMatch(varArgsType -> types.containsType(parameterType, varArgsType));
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix> trySuggestCallingCustomAlternative(
|
||||
MethodInvocationTree tree, MethodInvocationTree argument, VisitorState state) {
|
||||
return ALTERNATIVE_METHODS.rowMap().entrySet().stream()
|
||||
|
||||
@@ -17,6 +17,7 @@ import static com.google.errorprone.matchers.Matchers.isSameType;
|
||||
import static com.google.errorprone.matchers.Matchers.methodHasParameters;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.toType;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.function.Predicate.not;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
@@ -129,7 +130,10 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
Type parameterType = ASTHelpers.getType(Iterables.getOnlyElement(tree.getParameters()));
|
||||
Type parameterType =
|
||||
requireNonNull(
|
||||
ASTHelpers.getType(Iterables.getOnlyElement(tree.getParameters())),
|
||||
"Missing type for method parameter");
|
||||
|
||||
return findMethodSourceAnnotation(tree, state)
|
||||
.flatMap(
|
||||
@@ -173,7 +177,9 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
|
||||
|
||||
private static Optional<MethodTree> findMatchingSibling(
|
||||
MethodTree tree, Predicate<? super MethodTree> predicate, VisitorState state) {
|
||||
return state.findEnclosing(ClassTree.class).getMembers().stream()
|
||||
return requireNonNull(state.findEnclosing(ClassTree.class), "No class enclosing method")
|
||||
.getMembers()
|
||||
.stream()
|
||||
.filter(MethodTree.class::isInstance)
|
||||
.map(MethodTree.class::cast)
|
||||
.filter(not(tree::equals))
|
||||
|
||||
@@ -5,6 +5,7 @@ import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
@@ -86,7 +87,9 @@ public final class NonEmptyMono extends BugChecker implements MethodInvocationTr
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
|
||||
ExpressionTree receiver =
|
||||
requireNonNull(
|
||||
ASTHelpers.getReceiver(tree), "Instance method invocation must have receiver");
|
||||
if (!NON_EMPTY_MONO.matches(receiver, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.sun.source.tree.Tree;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import java.time.Clock;
|
||||
import java.time.InstantSource;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
@@ -69,6 +70,7 @@ public final class NonStaticImport extends BugChecker implements CompilationUnit
|
||||
ImmutableSet.of(
|
||||
ASTHelpers.class.getCanonicalName(),
|
||||
Clock.class.getCanonicalName(),
|
||||
InstantSource.class.getCanonicalName(),
|
||||
Strings.class.getCanonicalName(),
|
||||
VisitorState.class.getCanonicalName(),
|
||||
ZoneOffset.class.getCanonicalName(),
|
||||
@@ -129,6 +131,7 @@ public final class NonStaticImport extends BugChecker implements CompilationUnit
|
||||
"builder",
|
||||
"copyOf",
|
||||
"create",
|
||||
"EPOCH",
|
||||
"from",
|
||||
"getDefaultInstance",
|
||||
"INSTANCE",
|
||||
@@ -182,7 +185,7 @@ public final class NonStaticImport extends BugChecker implements CompilationUnit
|
||||
}
|
||||
}
|
||||
|
||||
return imports.build();
|
||||
return imports.buildOrThrow();
|
||||
}
|
||||
|
||||
private static boolean shouldNotBeStaticallyImported(String type, String member) {
|
||||
|
||||
@@ -28,8 +28,6 @@ import tech.picnic.errorprone.utils.SourceCode;
|
||||
/** A {@link BugChecker} that flags SLF4J usages that are likely to be in error. */
|
||||
// XXX: The special-casing of Throwable applies only to SLF4J 1.6.0+; see
|
||||
// https://www.slf4j.org/faq.html#paramException. That should be documented.
|
||||
// XXX: Also simplify `LOG.error(String.format("Something %s", arg), throwable)`.
|
||||
// XXX: Also simplify `LOG.error(String.join("sep", arg1, arg2), throwable)`? Perhaps too obscure.
|
||||
// XXX: Write a similar checker for Spring RestTemplates, String.format and friends, Guava
|
||||
// preconditions, ...
|
||||
@AutoService(BugChecker.class)
|
||||
|
||||
@@ -54,7 +54,7 @@ public final class SpringMvcAnnotation extends BugChecker implements AnnotationT
|
||||
.put("PATCH", "PatchMapping")
|
||||
.put("POST", "PostMapping")
|
||||
.put("PUT", "PutMapping")
|
||||
.build();
|
||||
.buildOrThrow();
|
||||
|
||||
/** Instantiates a new {@link SpringMvcAnnotation} instance. */
|
||||
public SpringMvcAnnotation() {}
|
||||
|
||||
@@ -16,10 +16,12 @@ 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.MemberReferenceTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MemberReferenceTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
@@ -41,7 +43,8 @@ import java.time.ZonedDateTime;
|
||||
linkType = CUSTOM,
|
||||
severity = WARNING,
|
||||
tags = FRAGILE_CODE)
|
||||
public final class TimeZoneUsage extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
public final class TimeZoneUsage extends BugChecker
|
||||
implements MethodInvocationTreeMatcher, MemberReferenceTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> BANNED_TIME_METHOD =
|
||||
anyOf(
|
||||
@@ -59,6 +62,10 @@ public final class TimeZoneUsage extends BugChecker implements MethodInvocationT
|
||||
"tickMillis",
|
||||
"tickMinutes",
|
||||
"tickSeconds"),
|
||||
staticMethod()
|
||||
.onClassAny(Instant.class.getCanonicalName())
|
||||
.named("now")
|
||||
.withNoParameters(),
|
||||
staticMethod()
|
||||
.onClassAny(
|
||||
LocalDate.class.getCanonicalName(),
|
||||
@@ -67,17 +74,22 @@ public final class TimeZoneUsage extends BugChecker implements MethodInvocationT
|
||||
OffsetDateTime.class.getCanonicalName(),
|
||||
OffsetTime.class.getCanonicalName(),
|
||||
ZonedDateTime.class.getCanonicalName())
|
||||
.named("now"),
|
||||
staticMethod()
|
||||
.onClassAny(Instant.class.getCanonicalName())
|
||||
.named("now")
|
||||
.withNoParameters());
|
||||
.named("now"));
|
||||
|
||||
/** Instantiates a new {@link TimeZoneUsage} instance. */
|
||||
public TimeZoneUsage() {}
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
return getDescription(tree, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description matchMemberReference(MemberReferenceTree tree, VisitorState state) {
|
||||
return getDescription(tree, state);
|
||||
}
|
||||
|
||||
private Description getDescription(ExpressionTree tree, VisitorState state) {
|
||||
return BANNED_TIME_METHOD.matches(tree, state)
|
||||
? buildDescription(tree).build()
|
||||
: Description.NO_MATCH;
|
||||
|
||||
@@ -18,6 +18,7 @@ final class AssertJCharSequenceRules {
|
||||
@BeforeTemplate
|
||||
void before(CharSequence charSequence) {
|
||||
Refaster.anyOf(
|
||||
assertThat(charSequence.isEmpty()).isTrue(),
|
||||
assertThat(charSequence.length()).isEqualTo(0L),
|
||||
assertThat(charSequence.length()).isNotPositive());
|
||||
}
|
||||
@@ -33,6 +34,7 @@ final class AssertJCharSequenceRules {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(CharSequence charSequence) {
|
||||
return Refaster.anyOf(
|
||||
assertThat(charSequence.isEmpty()).isFalse(),
|
||||
assertThat(charSequence.length()).isNotEqualTo(0),
|
||||
assertThat(charSequence.length()).isPositive());
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.util.Collection;
|
||||
import org.assertj.core.api.AbstractIntegerAssert;
|
||||
import org.assertj.core.api.AbstractIterableAssert;
|
||||
import org.assertj.core.api.AbstractIterableSizeAssert;
|
||||
import org.assertj.core.api.EnumerableAssert;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
@@ -21,6 +24,11 @@ final class AssertJEnumerableRules {
|
||||
enumAssert.hasSizeLessThan(1));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(AbstractIterableAssert<?, ?, E, ?> enumAssert) {
|
||||
enumAssert.size().isNotPositive();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(EnumerableAssert<?, E> enumAssert) {
|
||||
enumAssert.isEmpty();
|
||||
@@ -34,30 +42,175 @@ final class AssertJEnumerableRules {
|
||||
enumAssert.hasSizeGreaterThan(0), enumAssert.hasSizeGreaterThanOrEqualTo(1));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
AbstractIterableAssert<?, ?, E, ?> before(AbstractIterableAssert<?, ?, E, ?> enumAssert) {
|
||||
return Refaster.anyOf(
|
||||
enumAssert.size().isNotEqualTo(0).returnToIterable(),
|
||||
enumAssert.size().isPositive().returnToIterable());
|
||||
}
|
||||
|
||||
// XXX: If this template matches, then the expression's return type changes incompatibly.
|
||||
// Consider moving this template to a separate block (statement) rule.
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before2(AbstractIterableAssert<?, ?, E, ?> enumAssert) {
|
||||
return Refaster.anyOf(enumAssert.size().isNotEqualTo(0), enumAssert.size().isPositive());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, E> after(EnumerableAssert<?, E> enumAssert) {
|
||||
return enumAssert.isNotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static final class EnumerableAssertHasSameSizeAs<S, T> {
|
||||
static final class EnumerableAssertHasSize<E> {
|
||||
@BeforeTemplate
|
||||
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, Iterable<T> iterable) {
|
||||
AbstractIterableAssert<?, ?, E, ?> before(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isEqualTo(size).returnToIterable();
|
||||
}
|
||||
|
||||
// XXX: If this template matches, then the expression's return type changes incompatibly.
|
||||
// Consider moving this template to a separate block (statement) rule.
|
||||
@BeforeTemplate
|
||||
AbstractIterableSizeAssert<?, ?, E, ?> before2(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isEqualTo(size);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, E> after(EnumerableAssert<?, E> enumAssert, int size) {
|
||||
return enumAssert.hasSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
static final class EnumerableAssertHasSizeLessThan<E> {
|
||||
@BeforeTemplate
|
||||
AbstractIterableAssert<?, ?, E, ?> before(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isLessThan(size).returnToIterable();
|
||||
}
|
||||
|
||||
// XXX: If this template matches, then the expression's return type changes incompatibly.
|
||||
// Consider moving this template to a separate block (statement) rule.
|
||||
@BeforeTemplate
|
||||
AbstractIterableSizeAssert<?, ?, E, ?> before2(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isLessThan(size);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, E> after(EnumerableAssert<?, E> enumAssert, int size) {
|
||||
return enumAssert.hasSizeLessThan(size);
|
||||
}
|
||||
}
|
||||
|
||||
static final class EnumerableAssertHasSizeLessThanOrEqualTo<E> {
|
||||
@BeforeTemplate
|
||||
AbstractIterableAssert<?, ?, E, ?> before(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isLessThanOrEqualTo(size).returnToIterable();
|
||||
}
|
||||
|
||||
// XXX: If this template matches, then the expression's return type changes incompatibly.
|
||||
// Consider moving this template to a separate block (statement) rule.
|
||||
@BeforeTemplate
|
||||
AbstractIterableSizeAssert<?, ?, E, ?> before2(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isLessThanOrEqualTo(size);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, E> after(EnumerableAssert<?, E> enumAssert, int size) {
|
||||
return enumAssert.hasSizeLessThanOrEqualTo(size);
|
||||
}
|
||||
}
|
||||
|
||||
static final class EnumerableAssertHasSizeGreaterThan<E> {
|
||||
@BeforeTemplate
|
||||
AbstractIterableAssert<?, ?, E, ?> before(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isGreaterThan(size).returnToIterable();
|
||||
}
|
||||
|
||||
// XXX: If this template matches, then the expression's return type changes incompatibly.
|
||||
// Consider moving this template to a separate block (statement) rule.
|
||||
@BeforeTemplate
|
||||
AbstractIterableSizeAssert<?, ?, E, ?> before2(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isGreaterThan(size);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, E> after(EnumerableAssert<?, E> enumAssert, int size) {
|
||||
return enumAssert.hasSizeGreaterThan(size);
|
||||
}
|
||||
}
|
||||
|
||||
static final class EnumerableAssertHasSizeGreaterThanOrEqualTo<E> {
|
||||
@BeforeTemplate
|
||||
AbstractIterableAssert<?, ?, E, ?> before(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isGreaterThanOrEqualTo(size).returnToIterable();
|
||||
}
|
||||
|
||||
// XXX: If this template matches, then the expression's return type changes incompatibly.
|
||||
// Consider moving this template to a separate block (statement) rule.
|
||||
@BeforeTemplate
|
||||
AbstractIterableSizeAssert<?, ?, E, ?> before2(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int size) {
|
||||
return enumAssert.size().isGreaterThanOrEqualTo(size);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, E> after(EnumerableAssert<?, E> enumAssert, int size) {
|
||||
return enumAssert.hasSizeGreaterThanOrEqualTo(size);
|
||||
}
|
||||
}
|
||||
|
||||
static final class EnumerableAssertHasSizeBetween<E> {
|
||||
@BeforeTemplate
|
||||
AbstractIterableAssert<?, ?, E, ?> before(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int lower, int upper) {
|
||||
return enumAssert.size().isBetween(lower, upper).returnToIterable();
|
||||
}
|
||||
|
||||
// XXX: If this template matches, then the expression's return type changes incompatibly.
|
||||
// Consider moving this template to a separate block (statement) rule.
|
||||
@BeforeTemplate
|
||||
AbstractIterableSizeAssert<?, ?, E, ?> before2(
|
||||
AbstractIterableAssert<?, ?, E, ?> enumAssert, int lower, int upper) {
|
||||
return enumAssert.size().isBetween(lower, upper);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, E> after(EnumerableAssert<?, E> enumAssert, int lower, int upper) {
|
||||
return enumAssert.hasSizeBetween(lower, upper);
|
||||
}
|
||||
}
|
||||
|
||||
static final class EnumerableAssertHasSameSizeAs<S, E> {
|
||||
@BeforeTemplate
|
||||
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, Iterable<E> iterable) {
|
||||
return enumAssert.hasSize(Iterables.size(iterable));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, Collection<T> iterable) {
|
||||
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, Collection<E> iterable) {
|
||||
return enumAssert.hasSize(iterable.size());
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, T[] iterable) {
|
||||
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, E[] iterable) {
|
||||
return enumAssert.hasSize(iterable.length);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
EnumerableAssert<?, S> before(EnumerableAssert<?, S> enumAssert, CharSequence iterable) {
|
||||
return enumAssert.hasSize(iterable.length());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
EnumerableAssert<?, S> after(EnumerableAssert<?, S> enumAssert, Iterable<T> iterable) {
|
||||
EnumerableAssert<?, S> after(EnumerableAssert<?, S> enumAssert, Iterable<E> iterable) {
|
||||
return enumAssert.hasSameSizeAs(iterable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Collection;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractIntegerAssert;
|
||||
import org.assertj.core.api.IterableAssert;
|
||||
import org.assertj.core.api.ObjectAssert;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
@OnlineDocumentation
|
||||
final class AssertJIterableRules {
|
||||
private AssertJIterableRules() {}
|
||||
|
||||
static final class AssertThatIterableIsEmpty<E> {
|
||||
@BeforeTemplate
|
||||
void before(Iterable<E> iterable) {
|
||||
assertThat(iterable.iterator()).isExhausted();
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Collection<E> iterable) {
|
||||
assertThat(iterable.isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Collection<E> iterable) {
|
||||
assertThat(iterable).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIterableIsNotEmpty<E> {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(Iterable<E> iterable) {
|
||||
return assertThat(iterable.iterator()).hasNext();
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(Collection<E> iterable) {
|
||||
return assertThat(iterable.isEmpty()).isFalse();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<E> after(Iterable<E> iterable) {
|
||||
return assertThat(iterable).isNotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIterableSize<E> {
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before(Iterable<E> iterable) {
|
||||
return assertThat(Iterables.size(iterable));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before(Collection<E> iterable) {
|
||||
return assertThat(iterable.size());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractIntegerAssert<?> after(Iterable<E> iterable) {
|
||||
return assertThat(iterable).size();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: In practice this rule isn't very useful, as it only matches invocations of
|
||||
// `assertThat(E)`. In most cases a more specific overload of `assertThat` is invoked, in which
|
||||
// case this rule won't match. Look into a more robust approach.
|
||||
static final class AssertThatIterableHasOneElementEqualTo<S, E extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectAssert<S> before(Iterable<S> iterable, E element) {
|
||||
return assertThat(Iterables.getOnlyElement(iterable)).isEqualTo(element);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<S> after(Iterable<S> iterable, E element) {
|
||||
return assertThat(iterable).containsExactly(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Iterator;
|
||||
import org.assertj.core.api.AbstractBooleanAssert;
|
||||
import org.assertj.core.api.IteratorAssert;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
@OnlineDocumentation
|
||||
final class AssertJIteratorRules {
|
||||
private AssertJIteratorRules() {}
|
||||
|
||||
static final class AssertThatHasNext<T> {
|
||||
@BeforeTemplate
|
||||
AbstractBooleanAssert<?> before(Iterator<T> iterator) {
|
||||
return assertThat(iterator.hasNext()).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IteratorAssert<T> after(Iterator<T> iterator) {
|
||||
return assertThat(iterator).hasNext();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIsExhausted<T> {
|
||||
@BeforeTemplate
|
||||
AbstractBooleanAssert<?> before(Iterator<T> iterator) {
|
||||
return assertThat(iterator.hasNext()).isFalse();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IteratorAssert<T> after(Iterator<T> iterator) {
|
||||
return assertThat(iterator).isExhausted();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import com.google.errorprone.refaster.annotation.Matches;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractBooleanAssert;
|
||||
import org.assertj.core.api.AbstractCollectionAssert;
|
||||
@@ -182,13 +181,13 @@ final class AssertJMapRules {
|
||||
static final class AssertThatMapContainsOnlyKeys<K, V> {
|
||||
@BeforeTemplate
|
||||
AbstractCollectionAssert<?, Collection<? extends K>, K, ?> before(
|
||||
Map<K, V> map, Set<? extends K> keys) {
|
||||
Map<K, V> map, Iterable<? extends K> keys) {
|
||||
return assertThat(map.keySet()).hasSameElementsAs(keys);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
MapAssert<K, V> after(Map<K, V> map, Set<? extends K> keys) {
|
||||
MapAssert<K, V> after(Map<K, V> map, Iterable<? extends K> keys) {
|
||||
return assertThat(map).containsOnlyKeys(keys);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package tech.picnic.errorprone.refasterrules;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
@@ -12,7 +11,6 @@ import com.google.errorprone.refaster.annotation.Matches;
|
||||
import com.google.errorprone.refaster.annotation.NotMatches;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalDouble;
|
||||
@@ -22,9 +20,7 @@ import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Stream;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractCollectionAssert;
|
||||
import org.assertj.core.api.AbstractComparableAssert;
|
||||
import org.assertj.core.api.AbstractDoubleAssert;
|
||||
import org.assertj.core.api.AbstractIntegerAssert;
|
||||
import org.assertj.core.api.AbstractLongAssert;
|
||||
@@ -254,120 +250,19 @@ final class AssertJRules {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Iterable
|
||||
//
|
||||
|
||||
static final class AssertThatIterableIsEmpty<E> {
|
||||
@BeforeTemplate
|
||||
void before(Iterable<E> iterable) {
|
||||
Refaster.anyOf(
|
||||
assertThat(iterable).hasSize(0),
|
||||
assertThat(iterable.iterator().hasNext()).isFalse(),
|
||||
assertThat(Iterables.size(iterable)).isEqualTo(0L),
|
||||
assertThat(Iterables.size(iterable)).isNotPositive());
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Collection<E> iterable) {
|
||||
Refaster.anyOf(
|
||||
assertThat(iterable.isEmpty()).isTrue(),
|
||||
assertThat(iterable.size()).isEqualTo(0L),
|
||||
assertThat(iterable.size()).isNotPositive());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Collection<E> iterable) {
|
||||
assertThat(iterable).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIterableIsNotEmpty<E> {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(Iterable<E> iterable) {
|
||||
return Refaster.anyOf(
|
||||
assertThat(iterable.iterator().hasNext()).isTrue(),
|
||||
assertThat(Iterables.size(iterable)).isNotEqualTo(0),
|
||||
assertThat(Iterables.size(iterable)).isPositive());
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(Collection<E> iterable) {
|
||||
return Refaster.anyOf(
|
||||
assertThat(iterable.isEmpty()).isFalse(),
|
||||
assertThat(iterable.size()).isNotEqualTo(0),
|
||||
assertThat(iterable.size()).isPositive());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<E> after(Iterable<E> iterable) {
|
||||
return assertThat(iterable).isNotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIterableHasSize<E> {
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before(Iterable<E> iterable, int length) {
|
||||
return assertThat(Iterables.size(iterable)).isEqualTo(length);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
AbstractIntegerAssert<?> before(Collection<E> iterable, int length) {
|
||||
return assertThat(iterable.size()).isEqualTo(length);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<E> after(Iterable<E> iterable, int length) {
|
||||
return assertThat(iterable).hasSize(length);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIterableHasOneElementEqualTo<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectAssert<S> before(Iterable<S> iterable, T element) {
|
||||
return assertThat(Iterables.getOnlyElement(iterable)).isEqualTo(element);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<S> after(Iterable<S> iterable, T element) {
|
||||
return assertThat(iterable).containsExactly(element);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: This overload is here because `assertThat` has an overload for `Comparable` types.
|
||||
// Unfortunately this still doesn't convince Refaster to match this rule in the context of
|
||||
// Comparable types. Figure out why! Note that this also affects the `AssertThatOptional` rule.
|
||||
static final class AssertThatIterableHasOneComparableElementEqualTo<
|
||||
S extends Comparable<? super S>, T extends S> {
|
||||
@BeforeTemplate
|
||||
AbstractComparableAssert<?, S> before(Iterable<S> iterable, T element) {
|
||||
return assertThat(Iterables.getOnlyElement(iterable)).isEqualTo(element);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
IterableAssert<S> after(Iterable<S> iterable, T element) {
|
||||
return assertThat(iterable).containsExactly(element);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// List
|
||||
//
|
||||
|
||||
static final class AssertThatListsAreEqual<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ListAssert<S> before(List<S> list1, List<T> list2) {
|
||||
ListAssert<S> before(List<S> list1, Iterable<T> list2) {
|
||||
return assertThat(list1).isEqualTo(list2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ListAssert<S> after(List<S> list1, List<T> list2) {
|
||||
ListAssert<S> after(List<S> list1, Iterable<T> list2) {
|
||||
return assertThat(list1).containsExactlyElementsOf(list2);
|
||||
}
|
||||
}
|
||||
@@ -378,7 +273,7 @@ final class AssertJRules {
|
||||
|
||||
static final class AssertThatSetsAreEqual<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
AbstractCollectionAssert<?, ?, S, ?> before(Set<S> set1, Set<T> set2) {
|
||||
AbstractCollectionAssert<?, ?, S, ?> before(Set<S> set1, Iterable<T> set2) {
|
||||
return Refaster.anyOf(
|
||||
assertThat(set1).isEqualTo(set2),
|
||||
assertThat(set1).containsExactlyInAnyOrderElementsOf(set2));
|
||||
@@ -386,7 +281,7 @@ final class AssertJRules {
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractCollectionAssert<?, ?, S, ?> after(Set<S> set1, Set<T> set2) {
|
||||
AbstractCollectionAssert<?, ?, S, ?> after(Set<S> set1, Iterable<T> set2) {
|
||||
return assertThat(set1).hasSameElementsAs(set2);
|
||||
}
|
||||
}
|
||||
@@ -397,13 +292,13 @@ final class AssertJRules {
|
||||
|
||||
static final class AssertThatMultisetsAreEqual<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
AbstractCollectionAssert<?, ?, S, ?> before(Multiset<S> multiset1, Multiset<T> multiset2) {
|
||||
AbstractCollectionAssert<?, ?, S, ?> before(Multiset<S> multiset1, Iterable<T> multiset2) {
|
||||
return assertThat(multiset1).isEqualTo(multiset2);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractCollectionAssert<?, ?, S, ?> after(Multiset<S> multiset1, Multiset<T> multiset2) {
|
||||
AbstractCollectionAssert<?, ?, S, ?> after(Multiset<S> multiset1, Iterable<T> multiset2) {
|
||||
return assertThat(multiset1).containsExactlyInAnyOrderElementsOf(multiset2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractBooleanAssert;
|
||||
import org.assertj.core.api.AbstractStringAssert;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
@@ -31,19 +32,6 @@ final class AssertJStringRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatStringIsEmpty {
|
||||
@BeforeTemplate
|
||||
void before(String string) {
|
||||
assertThat(string.isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(String string) {
|
||||
assertThat(string).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
static final class AbstractStringAssertStringIsNotEmpty {
|
||||
@BeforeTemplate
|
||||
AbstractStringAssert<?> before(AbstractStringAssert<?> stringAssert) {
|
||||
@@ -56,16 +44,29 @@ final class AssertJStringRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatStringIsNotEmpty {
|
||||
static final class AssertThatStringContains {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(String string) {
|
||||
return assertThat(string.isEmpty()).isFalse();
|
||||
AbstractBooleanAssert<?> before(String string, CharSequence substring) {
|
||||
return assertThat(string.contains(substring)).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractAssert<?, ?> after(String string) {
|
||||
return assertThat(string).isNotEmpty();
|
||||
AbstractStringAssert<?> after(String string, CharSequence substring) {
|
||||
return assertThat(string).contains(substring);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatStringDoesNotContain {
|
||||
@BeforeTemplate
|
||||
AbstractBooleanAssert<?> before(String string, CharSequence substring) {
|
||||
return assertThat(string.contains(substring)).isFalse();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractStringAssert<?> after(String string, CharSequence substring) {
|
||||
return assertThat(string).doesNotContain(substring);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,18 +121,18 @@ final class AssortedRules {
|
||||
*/
|
||||
static final class DisjointSets<T> {
|
||||
@BeforeTemplate
|
||||
boolean before(Set<T> set1, Set<T> set2) {
|
||||
return Sets.intersection(set1, set2).isEmpty();
|
||||
boolean before(Set<T> collection1, Set<T> collection2) {
|
||||
return Sets.intersection(collection1, collection2).isEmpty();
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
boolean before2(Set<T> set1, Set<T> set2) {
|
||||
return set1.stream().noneMatch(set2::contains);
|
||||
boolean before2(Collection<T> collection1, Collection<T> collection2) {
|
||||
return collection1.stream().noneMatch(collection2::contains);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
boolean after(Set<T> set1, Set<T> set2) {
|
||||
return disjoint(set1, set2);
|
||||
boolean after(Collection<T> collection1, Collection<T> collection2) {
|
||||
return disjoint(collection1, collection2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.AlsoNegation;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/** Refaster rules related to expressions dealing with {@link CharSequence}s. */
|
||||
@OnlineDocumentation
|
||||
final class CharSequenceRules {
|
||||
private CharSequenceRules() {}
|
||||
|
||||
/**
|
||||
* Prefer {@link CharSequence#isEmpty()} over alternatives that consult the char sequence's
|
||||
* length.
|
||||
*/
|
||||
// XXX: Drop this rule once we (and OpenRewrite) no longer support projects targeting Java 14 or
|
||||
// below.
|
||||
static final class CharSequenceIsEmpty {
|
||||
@BeforeTemplate
|
||||
boolean before(CharSequence charSequence) {
|
||||
return Refaster.anyOf(
|
||||
charSequence.length() == 0, charSequence.length() <= 0, charSequence.length() < 1);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@AlsoNegation
|
||||
boolean after(CharSequence charSequence) {
|
||||
return charSequence.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,14 +158,14 @@ final class CollectionRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class SetRemoveAllCollection<T, S extends T> {
|
||||
static final class CollectionRemoveAllFromCollectionBlock<T, S extends T> {
|
||||
@BeforeTemplate
|
||||
void before(Set<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
void before(Collection<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
elementsToRemove.forEach(removeFrom::remove);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before2(Set<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
void before2(Collection<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
for (T element : elementsToRemove) {
|
||||
removeFrom.remove(element);
|
||||
}
|
||||
@@ -175,14 +175,14 @@ final class CollectionRules {
|
||||
// that this is supported out of the box. After doing so, also drop the `S extends T` type
|
||||
// constraint; ideally this check applies to any `S`.
|
||||
@BeforeTemplate
|
||||
void before3(Set<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
void before3(Collection<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
for (S element : elementsToRemove) {
|
||||
removeFrom.remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(Set<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
void after(Collection<T> removeFrom, Collection<S> elementsToRemove) {
|
||||
removeFrom.removeAll(elementsToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.AlsoNegation;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import java.io.File;
|
||||
@@ -11,6 +12,7 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
@@ -141,4 +143,35 @@ final class FileRules {
|
||||
return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke {@link File#mkdirs()} before {@link Files#exists(Path, LinkOption...)} to avoid
|
||||
* concurrency issues.
|
||||
*/
|
||||
static final class PathToFileMkDirsFilesExists {
|
||||
@BeforeTemplate
|
||||
boolean before(Path path) {
|
||||
return Files.exists(path) || path.toFile().mkdirs();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@AlsoNegation
|
||||
boolean after(Path path) {
|
||||
return path.toFile().mkdirs() || Files.exists(path);
|
||||
}
|
||||
}
|
||||
|
||||
/** Invoke {@link File#mkdirs()} before {@link File#exists()} to avoid concurrency issues. */
|
||||
static final class FileMkDirsFileExists {
|
||||
@BeforeTemplate
|
||||
boolean before(File file) {
|
||||
return file.exists() || file.mkdirs();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@AlsoNegation
|
||||
boolean after(File file) {
|
||||
return file.mkdirs() || file.exists();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ final class ImmutableListMultimapRules {
|
||||
* Prefer {@link ImmutableListMultimap#builder()} over the associated constructor on constructions
|
||||
* that produce a less-specific type.
|
||||
*/
|
||||
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
|
||||
// https://github.com/google/error-prone/pull/2706.
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableListMultimapBuilder<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableMultimap.Builder<K, V> before() {
|
||||
|
||||
@@ -28,8 +28,7 @@ final class ImmutableListRules {
|
||||
private ImmutableListRules() {}
|
||||
|
||||
/** Prefer {@link ImmutableList#builder()} over the associated constructor. */
|
||||
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
|
||||
// https://github.com/google/error-prone/pull/2706.
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableListBuilder<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableList.Builder<T> before() {
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Matches;
|
||||
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
@@ -31,8 +32,7 @@ final class ImmutableMapRules {
|
||||
private ImmutableMapRules() {}
|
||||
|
||||
/** Prefer {@link ImmutableMap#builder()} over the associated constructor. */
|
||||
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
|
||||
// https://github.com/google/error-prone/pull/2706.
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableMapBuilder<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableMap.Builder<K, V> before() {
|
||||
@@ -45,12 +45,28 @@ final class ImmutableMapRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableMap.Builder#buildOrThrow()} over the less explicit {@link
|
||||
* ImmutableMap.Builder#build()}.
|
||||
*/
|
||||
static final class ImmutableMapBuilderBuildOrThrow<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before(ImmutableMap.Builder<K, V> builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(ImmutableMap.Builder<K, V> builder) {
|
||||
return builder.buildOrThrow();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableMap#of(Object, Object)} over more contrived alternatives. */
|
||||
static final class EntryToImmutableMap<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before(Map.Entry<? extends K, ? extends V> entry) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.<K, V>builder().put(entry).build(),
|
||||
ImmutableMap.<K, V>builder().put(entry).buildOrThrow(),
|
||||
Stream.of(entry).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)));
|
||||
}
|
||||
|
||||
@@ -105,16 +121,17 @@ final class ImmutableMapRules {
|
||||
/** Prefer {@link ImmutableMap#copyOf(Iterable)} over more contrived alternatives. */
|
||||
static final class EntryIterableToImmutableMap<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before(Map<? extends K, ? extends V> iterable) {
|
||||
Map<K, V> before(Map<? extends K, ? extends V> iterable) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.copyOf(iterable.entrySet()),
|
||||
ImmutableMap.<K, V>builder().putAll(iterable).build());
|
||||
ImmutableMap.<K, V>builder().putAll(iterable).buildOrThrow(),
|
||||
Map.copyOf(iterable));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before(Iterable<? extends Map.Entry<? extends K, ? extends V>> iterable) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.<K, V>builder().putAll(iterable).build(),
|
||||
ImmutableMap.<K, V>builder().putAll(iterable).buildOrThrow(),
|
||||
Streams.stream(iterable).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)));
|
||||
}
|
||||
|
||||
@@ -140,8 +157,6 @@ final class ImmutableMapRules {
|
||||
@Placeholder(allowsIdentity = true)
|
||||
abstract V valueFunction(@MayOptionallyUse E element);
|
||||
|
||||
// XXX: We could add variants in which the entry is created some other way, but we have another
|
||||
// rule that covers canonicalization to `Map.entry`.
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before(Stream<E> stream) {
|
||||
return stream
|
||||
@@ -225,7 +240,11 @@ final class ImmutableMapRules {
|
||||
static final class ImmutableMapOf<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before() {
|
||||
return Refaster.anyOf(ImmutableMap.<K, V>builder().build(), emptyMap(), Map.of());
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.<K, V>builder().buildOrThrow(),
|
||||
ImmutableMap.ofEntries(),
|
||||
emptyMap(),
|
||||
Map.of());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -244,7 +263,10 @@ final class ImmutableMapRules {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.<K, V>builder().put(k1, v1).build(), singletonMap(k1, v1), Map.of(k1, v1));
|
||||
ImmutableMap.<K, V>builder().put(k1, v1).buildOrThrow(),
|
||||
ImmutableMap.ofEntries(Map.entry(k1, v1)),
|
||||
singletonMap(k1, v1),
|
||||
Map.of(k1, v1));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -262,7 +284,8 @@ final class ImmutableMapRules {
|
||||
static final class ImmutableMapOf2<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1, K k2, V v2) {
|
||||
return Map.of(k1, v1, k2, v2);
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.ofEntries(Map.entry(k1, v1), Map.entry(k2, v2)), Map.of(k1, v1, k2, v2));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -280,7 +303,9 @@ final class ImmutableMapRules {
|
||||
static final class ImmutableMapOf3<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1, K k2, V v2, K k3, V v3) {
|
||||
return Map.of(k1, v1, k2, v2, k3, v3);
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.ofEntries(Map.entry(k1, v1), Map.entry(k2, v2), Map.entry(k3, v3)),
|
||||
Map.of(k1, v1, k2, v2, k3, v3));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -300,7 +325,10 @@ final class ImmutableMapRules {
|
||||
static final class ImmutableMapOf4<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
|
||||
return Map.of(k1, v1, k2, v2, k3, v3, k4, v4);
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.ofEntries(
|
||||
Map.entry(k1, v1), Map.entry(k2, v2), Map.entry(k3, v3), Map.entry(k4, v4)),
|
||||
Map.of(k1, v1, k2, v2, k3, v3, k4, v4));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -320,7 +348,14 @@ final class ImmutableMapRules {
|
||||
static final class ImmutableMapOf5<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
|
||||
return Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.ofEntries(
|
||||
Map.entry(k1, v1),
|
||||
Map.entry(k2, v2),
|
||||
Map.entry(k3, v3),
|
||||
Map.entry(k4, v4),
|
||||
Map.entry(k5, v5)),
|
||||
Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -338,14 +373,14 @@ final class ImmutableMapRules {
|
||||
abstract boolean keyFilter(@MayOptionallyUse K key);
|
||||
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before(ImmutableMap<K, V> map) {
|
||||
ImmutableMap<K, V> before(Map<K, V> map) {
|
||||
return map.entrySet().stream()
|
||||
.filter(e -> keyFilter(e.getKey()))
|
||||
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(ImmutableMap<K, V> map) {
|
||||
ImmutableMap<K, V> after(Map<K, V> map) {
|
||||
return ImmutableMap.copyOf(Maps.filterKeys(map, k -> keyFilter(k)));
|
||||
}
|
||||
}
|
||||
@@ -359,18 +394,34 @@ final class ImmutableMapRules {
|
||||
abstract boolean valueFilter(@MayOptionallyUse V value);
|
||||
|
||||
@BeforeTemplate
|
||||
ImmutableMap<K, V> before(ImmutableMap<K, V> map) {
|
||||
ImmutableMap<K, V> before(Map<K, V> map) {
|
||||
return map.entrySet().stream()
|
||||
.filter(e -> valueFilter(e.getValue()))
|
||||
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(ImmutableMap<K, V> map) {
|
||||
ImmutableMap<K, V> after(Map<K, V> map) {
|
||||
return ImmutableMap.copyOf(Maps.filterValues(map, v -> valueFilter(v)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableMap#ofEntries(Map.Entry[])} over alternatives that don't communicate the
|
||||
* immutability of the resulting map at the type level.
|
||||
*/
|
||||
static final class ImmutableMapOfEntries<K, V> {
|
||||
@BeforeTemplate
|
||||
Map<K, V> before(@Repeated Map.Entry<? extends K, ? extends V> entries) {
|
||||
return Map.ofEntries(entries);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(@Repeated Map.Entry<? extends K, ? extends V> entries) {
|
||||
return ImmutableMap.ofEntries(entries);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add a rule for this:
|
||||
// Maps.transformValues(streamOfEntries.collect(groupBy(fun)), ImmutableMap::copyOf)
|
||||
// ->
|
||||
|
||||
@@ -21,8 +21,7 @@ final class ImmutableMultisetRules {
|
||||
private ImmutableMultisetRules() {}
|
||||
|
||||
/** Prefer {@link ImmutableMultiset#builder()} over the associated constructor. */
|
||||
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
|
||||
// https://github.com/google/error-prone/pull/2706.
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableMultisetBuilder<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableMultiset.Builder<T> before() {
|
||||
|
||||
@@ -29,8 +29,7 @@ final class ImmutableSetMultimapRules {
|
||||
private ImmutableSetMultimapRules() {}
|
||||
|
||||
/** Prefer {@link ImmutableSetMultimap#builder()} over the associated constructor. */
|
||||
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
|
||||
// https://github.com/google/error-prone/pull/2706.
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableSetMultimapBuilder<K, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableSetMultimap.Builder<K, V> before() {
|
||||
|
||||
@@ -29,8 +29,7 @@ final class ImmutableSetRules {
|
||||
private ImmutableSetRules() {}
|
||||
|
||||
/** Prefer {@link ImmutableSet#builder()} over the associated constructor. */
|
||||
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
|
||||
// https://github.com/google/error-prone/pull/2706.
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableSetBuilder<T> {
|
||||
@BeforeTemplate
|
||||
ImmutableSet.Builder<T> before() {
|
||||
|
||||
@@ -37,8 +37,7 @@ final class ImmutableSortedMapRules {
|
||||
* Prefer {@link ImmutableSortedMap#naturalOrder()} over the alternative that requires explicitly
|
||||
* providing the {@link Comparator}.
|
||||
*/
|
||||
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
|
||||
// https://github.com/google/error-prone/pull/2706.
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableSortedMapNaturalOrderBuilder<K extends Comparable<? super K>, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableSortedMap.Builder<K, V> before() {
|
||||
@@ -55,8 +54,7 @@ final class ImmutableSortedMapRules {
|
||||
* Prefer {@link ImmutableSortedMap#reverseOrder()} over the alternative that requires explicitly
|
||||
* providing the {@link Comparator}.
|
||||
*/
|
||||
// XXX: This drops generic type information, sometimes leading to non-compilable code. See
|
||||
// https://github.com/google/error-prone/pull/2706.
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableSortedMapReverseOrderBuilder<K extends Comparable<? super K>, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableSortedMap.Builder<K, V> before() {
|
||||
@@ -73,7 +71,7 @@ final class ImmutableSortedMapRules {
|
||||
static final class EmptyImmutableSortedMap<K extends Comparable<? super K>, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableSortedMap<K, V> before() {
|
||||
return ImmutableSortedMap.<K, V>naturalOrder().build();
|
||||
return ImmutableSortedMap.<K, V>naturalOrder().buildOrThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -91,7 +89,7 @@ final class ImmutableSortedMapRules {
|
||||
static final class PairToImmutableSortedMap<K extends Comparable<? super K>, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableSortedMap<K, V> before(K key, V value) {
|
||||
return ImmutableSortedMap.<K, V>naturalOrder().put(key, value).build();
|
||||
return ImmutableSortedMap.<K, V>naturalOrder().put(key, value).buildOrThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -107,7 +105,7 @@ final class ImmutableSortedMapRules {
|
||||
@BeforeTemplate
|
||||
ImmutableSortedMap<K, V> before(Map.Entry<? extends K, ? extends V> entry) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableSortedMap.<K, V>naturalOrder().put(entry).build(),
|
||||
ImmutableSortedMap.<K, V>naturalOrder().put(entry).buildOrThrow(),
|
||||
Stream.of(entry)
|
||||
.collect(
|
||||
toImmutableSortedMap(naturalOrder(), Map.Entry::getKey, Map.Entry::getValue)));
|
||||
@@ -128,7 +126,7 @@ final class ImmutableSortedMapRules {
|
||||
return Refaster.anyOf(
|
||||
ImmutableSortedMap.copyOf(iterable, naturalOrder()),
|
||||
ImmutableSortedMap.copyOf(iterable.entrySet()),
|
||||
ImmutableSortedMap.<K, V>naturalOrder().putAll(iterable).build());
|
||||
ImmutableSortedMap.<K, V>naturalOrder().putAll(iterable).buildOrThrow());
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
@@ -136,7 +134,7 @@ final class ImmutableSortedMapRules {
|
||||
Iterable<? extends Map.Entry<? extends K, ? extends V>> iterable) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableSortedMap.copyOf(iterable, naturalOrder()),
|
||||
ImmutableSortedMap.<K, V>naturalOrder().putAll(iterable).build(),
|
||||
ImmutableSortedMap.<K, V>naturalOrder().putAll(iterable).buildOrThrow(),
|
||||
Streams.stream(iterable)
|
||||
.collect(
|
||||
toImmutableSortedMap(
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static com.google.common.collect.ImmutableTable.toImmutableTable;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.Tables;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
|
||||
import com.google.errorprone.refaster.annotation.Placeholder;
|
||||
import com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/** Refaster rules related to expressions dealing with {@link ImmutableTable}s. */
|
||||
@OnlineDocumentation
|
||||
final class ImmutableTableRules {
|
||||
private ImmutableTableRules() {}
|
||||
|
||||
/** Prefer {@link ImmutableTable#builder()} over the associated constructor. */
|
||||
// XXX: This rule may drop generic type information, leading to non-compilable code.
|
||||
static final class ImmutableTableBuilder<R, C, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableTable.Builder<R, C, V> before() {
|
||||
return new ImmutableTable.Builder<>();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableTable.Builder<R, C, V> after() {
|
||||
return ImmutableTable.builder();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link ImmutableTable.Builder#buildOrThrow()} over the less explicit {@link
|
||||
* ImmutableTable.Builder#build()}.
|
||||
*/
|
||||
static final class ImmutableTableBuilderBuildOrThrow<R, C, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableTable<R, C, V> before(ImmutableTable.Builder<R, C, V> builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableTable<R, C, V> after(ImmutableTable.Builder<R, C, V> builder) {
|
||||
return builder.buildOrThrow();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableTable#of(Object, Object, Object)} over more contrived alternatives. */
|
||||
static final class CellToImmutableTable<R, C, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableTable<R, C, V> before(Table.Cell<? extends R, ? extends C, ? extends V> cell) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableTable.<R, C, V>builder().put(cell).buildOrThrow(),
|
||||
Stream.of(cell)
|
||||
.collect(
|
||||
toImmutableTable(
|
||||
Table.Cell::getRowKey, Table.Cell::getColumnKey, Table.Cell::getValue)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableTable<R, C, V> after(Table.Cell<? extends R, ? extends C, ? extends V> cell) {
|
||||
return ImmutableTable.of(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't map a stream's elements to table cells, only to subsequently collect them into an {@link
|
||||
* ImmutableTable}. The collection can be performed directly.
|
||||
*/
|
||||
abstract static class StreamOfCellsToImmutableTable<E, R, C, V> {
|
||||
@Placeholder(allowsIdentity = true)
|
||||
abstract R rowFunction(@MayOptionallyUse E element);
|
||||
|
||||
@Placeholder(allowsIdentity = true)
|
||||
abstract C columnFunction(@MayOptionallyUse E element);
|
||||
|
||||
@Placeholder(allowsIdentity = true)
|
||||
abstract V valueFunction(@MayOptionallyUse E element);
|
||||
|
||||
@BeforeTemplate
|
||||
ImmutableTable<R, C, V> before(Stream<E> stream) {
|
||||
return stream
|
||||
.map(e -> Tables.immutableCell(rowFunction(e), columnFunction(e), valueFunction(e)))
|
||||
.collect(
|
||||
toImmutableTable(
|
||||
Table.Cell::getRowKey, Table.Cell::getColumnKey, Table.Cell::getValue));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
ImmutableTable<R, C, V> after(Stream<E> stream) {
|
||||
return stream.collect(
|
||||
toImmutableTable(e -> rowFunction(e), e -> columnFunction(e), e -> valueFunction(e)));
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link ImmutableTable#of()} over more contrived alternatives . */
|
||||
static final class ImmutableTableOf<R, C, V> {
|
||||
@BeforeTemplate
|
||||
ImmutableTable<R, C, V> before() {
|
||||
return ImmutableTable.<R, C, V>builder().buildOrThrow();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableTable<R, C, V> after() {
|
||||
return ImmutableTable.of();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.assertj.core.api.Assertions.offset;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
@@ -34,7 +36,8 @@ import tech.picnic.errorprone.refaster.annotation.TypeMigration;
|
||||
* <p>Note that, while both libraries throw an {@link AssertionError} in case of an assertion
|
||||
* failure, the exact subtype used generally differs.
|
||||
*/
|
||||
// XXX: Not all JUnit `Assertions` methods have an associated Refaster rule yet; expand this class.
|
||||
// XXX: The `AssertThat*Array*ContainsExactly*` rules assume that `expected` and `actual` are not
|
||||
// both `null`.
|
||||
// XXX: Introduce a `@Matcher` on `Executable` and `ThrowingSupplier` expressions, such that they
|
||||
// are only matched if they are also compatible with the `ThrowingCallable` functional interface.
|
||||
// When implementing such a matcher, note that expressions with a non-void return type such as
|
||||
@@ -50,39 +53,6 @@ import tech.picnic.errorprone.refaster.annotation.TypeMigration;
|
||||
"assertAll(String, Collection<Executable>)",
|
||||
"assertAll(String, Executable[])",
|
||||
"assertAll(String, Stream<Executable>)",
|
||||
"assertArrayEquals(boolean[], boolean[])",
|
||||
"assertArrayEquals(boolean[], boolean[], String)",
|
||||
"assertArrayEquals(boolean[], boolean[], Supplier<String>)",
|
||||
"assertArrayEquals(byte[], byte[])",
|
||||
"assertArrayEquals(byte[], byte[], String)",
|
||||
"assertArrayEquals(byte[], byte[], Supplier<String>)",
|
||||
"assertArrayEquals(char[], char[])",
|
||||
"assertArrayEquals(char[], char[], String)",
|
||||
"assertArrayEquals(char[], char[], Supplier<String>)",
|
||||
"assertArrayEquals(double[], double[])",
|
||||
"assertArrayEquals(double[], double[], double)",
|
||||
"assertArrayEquals(double[], double[], double, String)",
|
||||
"assertArrayEquals(double[], double[], double, Supplier<String>)",
|
||||
"assertArrayEquals(double[], double[], String)",
|
||||
"assertArrayEquals(double[], double[], Supplier<String>)",
|
||||
"assertArrayEquals(float[], float[])",
|
||||
"assertArrayEquals(float[], float[], float)",
|
||||
"assertArrayEquals(float[], float[], float, String)",
|
||||
"assertArrayEquals(float[], float[], float, Supplier<String>)",
|
||||
"assertArrayEquals(float[], float[], String)",
|
||||
"assertArrayEquals(float[], float[], Supplier<String>)",
|
||||
"assertArrayEquals(int[], int[])",
|
||||
"assertArrayEquals(int[], int[], String)",
|
||||
"assertArrayEquals(int[], int[], Supplier<String>)",
|
||||
"assertArrayEquals(long[], long[])",
|
||||
"assertArrayEquals(long[], long[], String)",
|
||||
"assertArrayEquals(long[], long[], Supplier<String>)",
|
||||
"assertArrayEquals(Object[], Object[])",
|
||||
"assertArrayEquals(Object[], Object[], String)",
|
||||
"assertArrayEquals(Object[], Object[], Supplier<String>)",
|
||||
"assertArrayEquals(short[], short[])",
|
||||
"assertArrayEquals(short[], short[], String)",
|
||||
"assertArrayEquals(short[], short[], Supplier<String>)",
|
||||
"assertEquals(Byte, Byte)",
|
||||
"assertEquals(Byte, byte)",
|
||||
"assertEquals(byte, Byte)",
|
||||
@@ -302,6 +272,436 @@ import tech.picnic.errorprone.refaster.annotation.TypeMigration;
|
||||
final class JUnitToAssertJRules {
|
||||
private JUnitToAssertJRules() {}
|
||||
|
||||
static final class AssertThatBooleanArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(boolean[] actual, boolean[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean[] actual, boolean[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatBooleanArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(boolean[] actual, String message, boolean[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean[] actual, String message, boolean[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatBooleanArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(boolean[] actual, Supplier<String> message, boolean[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(boolean[] actual, Supplier<String> message, boolean[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatByteArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(byte[] actual, byte[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(byte[] actual, byte[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatByteArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(byte[] actual, String message, byte[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(byte[] actual, String message, byte[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatByteArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(byte[] actual, Supplier<String> message, byte[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(byte[] actual, Supplier<String> message, byte[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatCharArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(char[] actual, char[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(char[] actual, char[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatCharArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(char[] actual, String message, char[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(char[] actual, String message, char[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatCharArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(char[] actual, Supplier<String> message, char[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(char[] actual, Supplier<String> message, char[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatShortArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(short[] actual, short[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(short[] actual, short[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatShortArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(short[] actual, String message, short[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(short[] actual, String message, short[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatShortArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(short[] actual, Supplier<String> message, short[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(short[] actual, Supplier<String> message, short[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIntArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(int[] actual, int[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(int[] actual, int[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIntArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(int[] actual, String message, int[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(int[] actual, String message, int[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatIntArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(int[] actual, Supplier<String> message, int[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(int[] actual, Supplier<String> message, int[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatLongArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(long[] actual, long[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(long[] actual, long[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatLongArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(long[] actual, String message, long[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(long[] actual, String message, long[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatLongArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(long[] actual, Supplier<String> message, long[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(long[] actual, Supplier<String> message, long[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatFloatArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(float[] actual, float[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float[] actual, float[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatFloatArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(float[] actual, String message, float[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float[] actual, String message, float[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatFloatArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(float[] actual, Supplier<String> message, float[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float[] actual, Supplier<String> message, float[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatFloatArrayContainsExactlyWithOffset {
|
||||
@BeforeTemplate
|
||||
void before(float[] actual, float[] expected, float delta) {
|
||||
assertArrayEquals(expected, actual, delta);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float[] actual, float[] expected, float delta) {
|
||||
assertThat(actual).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatFloatArrayWithFailMessageContainsExactlyWithOffset {
|
||||
@BeforeTemplate
|
||||
void before(float[] actual, String message, float[] expected, float delta) {
|
||||
assertArrayEquals(expected, actual, delta, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float[] actual, String message, float[] expected, float delta) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatFloatArrayWithFailMessageSupplierContainsExactlyWithOffset {
|
||||
@BeforeTemplate
|
||||
void before(float[] actual, Supplier<String> message, float[] expected, float delta) {
|
||||
assertArrayEquals(expected, actual, delta, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float[] actual, Supplier<String> message, float[] expected, float delta) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatDoubleArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(double[] actual, double[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double[] actual, double[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatDoubleArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(double[] actual, String message, double[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double[] actual, String message, double[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatDoubleArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(double[] actual, Supplier<String> message, double[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double[] actual, Supplier<String> message, double[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatDoubleArrayContainsExactlyWithOffset {
|
||||
@BeforeTemplate
|
||||
void before(double[] actual, double[] expected, double delta) {
|
||||
assertArrayEquals(expected, actual, delta);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double[] actual, double[] expected, double delta) {
|
||||
assertThat(actual).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatDoubleArrayWithFailMessageContainsExactlyWithOffset {
|
||||
@BeforeTemplate
|
||||
void before(double[] actual, String message, double[] expected, double delta) {
|
||||
assertArrayEquals(expected, actual, delta, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double[] actual, String message, double[] expected, double delta) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatDoubleArrayWithFailMessageSupplierContainsExactlyWithOffset {
|
||||
@BeforeTemplate
|
||||
void before(
|
||||
double[] actual, Supplier<String> messageSupplier, double[] expected, double delta) {
|
||||
assertArrayEquals(expected, actual, delta, messageSupplier);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double[] actual, Supplier<String> messageSupplier, double[] expected, double delta) {
|
||||
assertThat(actual).withFailMessage(messageSupplier).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatObjectArrayContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(Object[] actual, Object[] expected) {
|
||||
assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object[] actual, Object[] expected) {
|
||||
assertThat(actual).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatObjectArrayWithFailMessageContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(Object[] actual, String message, Object[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object[] actual, String message, Object[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatObjectArrayWithFailMessageSupplierContainsExactly {
|
||||
@BeforeTemplate
|
||||
void before(Object[] actual, Supplier<String> message, Object[] expected) {
|
||||
assertArrayEquals(expected, actual, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(Object[] actual, Supplier<String> message, Object[] expected) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected);
|
||||
}
|
||||
}
|
||||
|
||||
static final class Fail<T> {
|
||||
@BeforeTemplate
|
||||
T before() {
|
||||
|
||||
@@ -3,6 +3,7 @@ package tech.picnic.errorprone.refasterrules;
|
||||
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
import static java.util.Objects.requireNonNullElseGet;
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
@@ -94,11 +95,14 @@ final class NullRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Objects#isNull(Object)} over the equivalent lambda function. */
|
||||
/**
|
||||
* Prefer {@link Objects#isNull(Object)} over the equivalent lambda function or more contrived
|
||||
* alternatives.
|
||||
*/
|
||||
static final class IsNullFunction<T> {
|
||||
@BeforeTemplate
|
||||
Predicate<T> before() {
|
||||
return o -> o == null;
|
||||
return Refaster.anyOf(o -> o == null, not(Objects::nonNull));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -107,11 +111,14 @@ final class NullRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Objects#nonNull(Object)} over the equivalent lambda function. */
|
||||
/**
|
||||
* Prefer {@link Objects#nonNull(Object)} over the equivalent lambda function or more contrived
|
||||
* alternatives.
|
||||
*/
|
||||
static final class NonNullFunction<T> {
|
||||
@BeforeTemplate
|
||||
Predicate<T> before() {
|
||||
return o -> o != null;
|
||||
return Refaster.anyOf(o -> o != null, not(Objects::isNull));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
|
||||
@@ -282,6 +282,8 @@ final class OptionalRules {
|
||||
// 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.)
|
||||
// XXX: Perhaps `stream.mapMulti(Optional::ifPresent)` is what we should use. See
|
||||
// https://github.com/palantir/gradle-baseline/pull/2996.
|
||||
static final class StreamFlatMapOptional<T> {
|
||||
@BeforeTemplate
|
||||
Stream<T> before(Stream<Optional<T>> stream) {
|
||||
|
||||
@@ -8,12 +8,15 @@ import com.google.common.primitives.Floats;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.google.common.primitives.Shorts;
|
||||
import com.google.common.primitives.UnsignedBytes;
|
||||
import com.google.common.primitives.UnsignedInts;
|
||||
import com.google.common.primitives.UnsignedLongs;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.AlsoNegation;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/** Refaster rules related to expressions dealing with primitives. */
|
||||
@@ -525,10 +528,7 @@ final class PrimitiveRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer JDK's {@link Integer#toUnsignedString(int,int)} over third-party or more verbose
|
||||
* alternatives.
|
||||
*/
|
||||
/** Prefer JDK's {@link Integer#toUnsignedString(int,int)} over third-party alternatives. */
|
||||
static final class IntegerToUnsignedStringWithRadix {
|
||||
@BeforeTemplate
|
||||
String before(int i, int radix) {
|
||||
@@ -541,10 +541,7 @@ final class PrimitiveRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer JDK's {@link Long#toUnsignedString(long,int)} over third-party or more verbose
|
||||
* alternatives.
|
||||
*/
|
||||
/** Prefer JDK's {@link Long#toUnsignedString(long,int)} over third-party alternatives. */
|
||||
static final class LongToUnsignedStringWithRadix {
|
||||
@BeforeTemplate
|
||||
String before(long i, int radix) {
|
||||
@@ -556,4 +553,49 @@ final class PrimitiveRules {
|
||||
return Long.toUnsignedString(i, radix);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer JDK's {@link Arrays#compareUnsigned(byte[], byte[])} over third-party alternatives. */
|
||||
// XXX: This rule will yield non-compilable code if the result of the replaced expression is
|
||||
// dereferenced. Investigate how to make this safe.
|
||||
static final class ArraysCompareUnsignedBytes {
|
||||
@BeforeTemplate
|
||||
Comparator<byte[]> before() {
|
||||
return UnsignedBytes.lexicographicalComparator();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Comparator<byte[]> after() {
|
||||
return Arrays::compareUnsigned;
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer JDK's {@link Arrays#compareUnsigned(int[], int[])} over third-party alternatives. */
|
||||
// XXX: This rule will yield non-compilable code if the result of the replaced expression is
|
||||
// dereferenced. Investigate how to make this safe.
|
||||
static final class ArraysCompareUnsignedInts {
|
||||
@BeforeTemplate
|
||||
Comparator<int[]> before() {
|
||||
return UnsignedInts.lexicographicalComparator();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Comparator<int[]> after() {
|
||||
return Arrays::compareUnsigned;
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer JDK's {@link Arrays#compareUnsigned(long[], long[])} over third-party alternatives. */
|
||||
// XXX: This rule will yield non-compilable code if the result of the replaced expression is
|
||||
// dereferenced. Investigate how to make this safe.
|
||||
static final class ArraysCompareUnsignedLongs {
|
||||
@BeforeTemplate
|
||||
Comparator<long[]> before() {
|
||||
return UnsignedLongs.lexicographicalComparator();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Comparator<long[]> after() {
|
||||
return Arrays::compareUnsigned;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,9 +489,16 @@ final class ReactorRules {
|
||||
return Flux.range(value, 1);
|
||||
}
|
||||
|
||||
// XXX: Consider generalizing part of this template using an Error Prone check that covers any
|
||||
// sequence of explicitly enumerated values passed to an iteration order-preserving collection
|
||||
// factory method.
|
||||
@BeforeTemplate
|
||||
Flux<T> before(T value) {
|
||||
return Mono.just(value).repeat().take(1);
|
||||
return Refaster.anyOf(
|
||||
Mono.just(value).flux(),
|
||||
Mono.just(value).repeat().take(1),
|
||||
Flux.fromIterable(ImmutableList.of(value)),
|
||||
Flux.fromIterable(ImmutableSet.of(value)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -508,8 +515,14 @@ final class ReactorRules {
|
||||
mono.switchIfEmpty(Mono.empty()), mono.flux().next(), mono.flux().singleOrEmpty());
|
||||
}
|
||||
|
||||
// XXX: Consider filing a SonarCloud issue for the S2637 false positive.
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before2(Mono<@Nullable Void> mono) {
|
||||
@SuppressWarnings({
|
||||
"java:S2637" /* False positive: result is never `null`. */,
|
||||
"java:S4968" /* Result may be `Mono<Void>`. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
Mono<? extends @Nullable Void> before2(Mono<@Nullable Void> mono) {
|
||||
return Refaster.anyOf(mono.ignoreElement(), mono.then());
|
||||
}
|
||||
|
||||
@@ -889,6 +902,38 @@ final class ReactorRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer immediately unwrapping {@link Optional} transformation results inside {@link
|
||||
* Flux#mapNotNull(Function)} over more contrived alternatives.
|
||||
*/
|
||||
abstract static class FluxMapNotNullTransformationOrElse<T, S> {
|
||||
@Placeholder(allowsIdentity = true)
|
||||
abstract Optional<S> transformation(@MayOptionallyUse T value);
|
||||
|
||||
@BeforeTemplate
|
||||
Flux<S> before(Flux<T> flux) {
|
||||
return flux.map(v -> transformation(v)).mapNotNull(o -> o.orElse(null));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<S> after(Flux<T> flux) {
|
||||
return flux.mapNotNull(x -> transformation(x).orElse(null));
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Flux#mapNotNull(Function)} over more contrived alternatives. */
|
||||
static final class FluxMapNotNullOrElse<T> {
|
||||
@BeforeTemplate
|
||||
Flux<T> before(Flux<Optional<T>> flux) {
|
||||
return flux.filter(Optional::isPresent).map(Optional::orElseThrow);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Flux<T> after(Flux<Optional<T>> flux) {
|
||||
return flux.mapNotNull(x -> x.orElse(null));
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Mono#flux()}} over more contrived alternatives. */
|
||||
static final class MonoFlux<T> {
|
||||
@BeforeTemplate
|
||||
@@ -906,12 +951,18 @@ final class ReactorRules {
|
||||
/** Prefer direct invocation of {@link Mono#then()}} over more contrived alternatives. */
|
||||
static final class MonoThen<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Mono<T> mono) {
|
||||
return Refaster.anyOf(mono.ignoreElement().then(), mono.flux().then());
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Mono<T> mono) {
|
||||
return Refaster.anyOf(
|
||||
mono.ignoreElement().then(),
|
||||
mono.flux().then(),
|
||||
Mono.when(mono),
|
||||
Mono.whenDelayError(mono));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Mono<T> mono) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Mono<T> mono) {
|
||||
return mono.then();
|
||||
}
|
||||
}
|
||||
@@ -919,17 +970,25 @@ final class ReactorRules {
|
||||
/** Avoid vacuous invocations of {@link Flux#ignoreElements()}. */
|
||||
static final class FluxThen<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Flux<T> flux) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Flux<T> flux) {
|
||||
return flux.ignoreElements().then();
|
||||
}
|
||||
|
||||
// XXX: Consider filing a SonarCloud issue for the S2637 false positive.
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before2(Flux<@Nullable Void> flux) {
|
||||
@SuppressWarnings({
|
||||
"java:S2637" /* False positive: result is never `null`. */,
|
||||
"java:S4968" /* Result may be `Mono<Void>`. */,
|
||||
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
|
||||
})
|
||||
Mono<? extends @Nullable Void> before2(Flux<@Nullable Void> flux) {
|
||||
return flux.ignoreElements();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Flux<T> flux) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Flux<T> flux) {
|
||||
return flux.then();
|
||||
}
|
||||
}
|
||||
@@ -937,12 +996,14 @@ final class ReactorRules {
|
||||
/** Avoid vacuous invocations of {@link Mono#ignoreElement()}. */
|
||||
static final class MonoThenEmpty<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Mono<T> mono, Publisher<@Nullable Void> publisher) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Mono<T> mono, Publisher<@Nullable Void> publisher) {
|
||||
return mono.ignoreElement().thenEmpty(publisher);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Mono<T> mono, Publisher<@Nullable Void> publisher) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Mono<T> mono, Publisher<@Nullable Void> publisher) {
|
||||
return mono.thenEmpty(publisher);
|
||||
}
|
||||
}
|
||||
@@ -950,12 +1011,14 @@ final class ReactorRules {
|
||||
/** Avoid vacuous invocations of {@link Flux#ignoreElements()}. */
|
||||
static final class FluxThenEmpty<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Flux<T> flux, Publisher<@Nullable Void> publisher) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Flux<T> flux, Publisher<@Nullable Void> publisher) {
|
||||
return flux.ignoreElements().thenEmpty(publisher);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Flux<T> flux, Publisher<@Nullable Void> publisher) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Flux<T> flux, Publisher<@Nullable Void> publisher) {
|
||||
return flux.thenEmpty(publisher);
|
||||
}
|
||||
}
|
||||
@@ -1011,7 +1074,8 @@ final class ReactorRules {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before2(Mono<T> mono1, Mono<@Nullable Void> mono2) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before2(Mono<T> mono1, Mono<@Nullable Void> mono2) {
|
||||
return mono1.thenEmpty(mono2);
|
||||
}
|
||||
|
||||
@@ -1029,7 +1093,8 @@ final class ReactorRules {
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before2(Flux<T> flux, Mono<@Nullable Void> mono) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before2(Flux<T> flux, Mono<@Nullable Void> mono) {
|
||||
return flux.thenEmpty(mono);
|
||||
}
|
||||
|
||||
@@ -1046,10 +1111,12 @@ final class ReactorRules {
|
||||
// rule. Consider introducing an Error Prone check for this.
|
||||
static final class MonoSingleOptional<T> {
|
||||
@BeforeTemplate
|
||||
Mono<Optional<T>> before(Mono<T> mono) {
|
||||
Mono<Optional<T>> before(Mono<T> mono, Optional<T> optional, Mono<Optional<T>> alternate) {
|
||||
return Refaster.anyOf(
|
||||
mono.flux().collect(toOptional()),
|
||||
mono.map(Optional::of).defaultIfEmpty(Optional.empty()),
|
||||
mono.map(Optional::of),
|
||||
mono.singleOptional().defaultIfEmpty(optional),
|
||||
mono.singleOptional().switchIfEmpty(alternate),
|
||||
mono.transform(Mono::singleOptional));
|
||||
}
|
||||
|
||||
@@ -2142,6 +2209,22 @@ final class ReactorRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't propagate {@link Mono} cancellations to upstream cache value computations, as completion
|
||||
* of such computations may benefit concurrent or subsequent cache usages.
|
||||
*/
|
||||
static final class MonoFromFutureAsyncLoadingCacheGetAll<K1, K2 extends K1, V> {
|
||||
@BeforeTemplate
|
||||
Mono<Map<K1, V>> before(AsyncLoadingCache<K1, V> cache, Iterable<K2> keys) {
|
||||
return Mono.fromFuture(() -> cache.getAll(keys));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<Map<K1, V>> after(AsyncLoadingCache<K1, V> cache, Iterable<K2> keys) {
|
||||
return Mono.fromFuture(() -> cache.getAll(keys), /* suppressCancel= */ true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link Flux#fromStream(Supplier)} over {@link Flux#fromStream(Stream)}, as the former
|
||||
* yields a {@link Flux} that is more likely to behave as expected when subscribed to more than
|
||||
|
||||
@@ -23,14 +23,16 @@ final class RxJava2AdapterRules {
|
||||
/** Use the fluent API style when using {@link RxJava2Adapter#completableToMono}. */
|
||||
static final class CompletableToMono {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Completable completable) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> before(Completable completable) {
|
||||
return Refaster.anyOf(
|
||||
RxJava2Adapter.completableToMono(completable),
|
||||
completable.to(RxJava2Adapter::completableToMono));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Mono<@Nullable Void> after(Completable completable) {
|
||||
@SuppressWarnings("java:S4968" /* Result may be `Mono<Void>`. */)
|
||||
Mono<? extends @Nullable Void> after(Completable completable) {
|
||||
return completable.as(RxJava2Adapter::completableToMono);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,11 +29,14 @@ final class StringRules {
|
||||
private StringRules() {}
|
||||
|
||||
/** Prefer {@link String#isEmpty()} over alternatives that consult the string's length. */
|
||||
// XXX: Now that we build with JDK 15+, this rule can be generalized to cover all `CharSequence`
|
||||
// subtypes. This does require a mechanism (perhaps an annotation, or a separate Maven module) to
|
||||
// make sure that non-String expressions are rewritten only if client code also targets JDK 15+.
|
||||
// XXX: Drop this rule once we (and OpenRewrite) no longer support projects targeting Java 14 or
|
||||
// below. The `CharSequenceIsEmpty` rule then suffices. (This rule exists so that e.g. projects
|
||||
// that target JDK 11 can disable `CharSequenceIsEmpty` without losing a valuable rule.)
|
||||
// XXX: Look into a more general approach to supporting different Java language levels, such as
|
||||
// rule selection based on some annotation, or a separate Maven module.
|
||||
static final class StringIsEmpty {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("CharSequenceIsEmpty" /* This is a more specific template. */)
|
||||
boolean before(String str) {
|
||||
return Refaster.anyOf(str.length() == 0, str.length() <= 0, str.length() < 1);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -65,16 +66,18 @@ final class SuggestedFixRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link SuggestedFix#swap(Tree, Tree)} over more contrived alternatives. */
|
||||
/**
|
||||
* Prefer {@link SuggestedFix#swap(Tree, Tree, VisitorState)} over more contrived alternatives.
|
||||
*/
|
||||
static final class SuggestedFixSwap {
|
||||
@BeforeTemplate
|
||||
SuggestedFix before(Tree tree1, Tree tree2) {
|
||||
return SuggestedFix.builder().swap(tree1, tree2).build();
|
||||
SuggestedFix before(Tree tree1, Tree tree2, VisitorState state) {
|
||||
return SuggestedFix.builder().swap(tree1, tree2, state).build();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
SuggestedFix after(Tree tree1, Tree tree2) {
|
||||
return SuggestedFix.swap(tree1, tree2);
|
||||
SuggestedFix after(Tree tree1, Tree tree2, VisitorState state) {
|
||||
return SuggestedFix.swap(tree1, tree2, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,71 +53,20 @@ import tech.picnic.errorprone.refaster.annotation.TypeMigration;
|
||||
// XXX: As-is these rules do not result in a complete migration:
|
||||
// - Expressions containing comments are skipped due to a limitation of Refaster.
|
||||
// - Assertions inside lambda expressions are also skipped. Unclear why.
|
||||
// XXX: The `assertEquals` tests for this class generally use the same expression for `expected` and
|
||||
// XXX: Many of the test expressions for these rules use the same expression for `expected` and
|
||||
// `actual`, which makes the validation weaker than necessary; fix this. (And investigate whether we
|
||||
// can introduce validation for this.)
|
||||
@OnlineDocumentation
|
||||
@TypeMigration(
|
||||
of = Assert.class,
|
||||
unmigratedMethods = {
|
||||
// XXX: Add migrations for the methods below.
|
||||
"assertEquals(Boolean, Boolean)",
|
||||
"assertEquals(Boolean, boolean)",
|
||||
"assertEquals(boolean, Boolean)",
|
||||
"assertEquals(Boolean, Boolean, String)",
|
||||
"assertEquals(Boolean, boolean, String)",
|
||||
"assertEquals(boolean, Boolean, String)",
|
||||
"assertEquals(Byte, Byte)",
|
||||
"assertEquals(Byte, byte)",
|
||||
"assertEquals(byte, Byte)",
|
||||
"assertEquals(Byte, Byte, String)",
|
||||
"assertEquals(Byte, byte, String)",
|
||||
"assertEquals(byte, Byte, String)",
|
||||
"assertEquals(char, Character)",
|
||||
"assertEquals(char, Character, String)",
|
||||
"assertEquals(Character, char)",
|
||||
"assertEquals(Character, char, String)",
|
||||
"assertEquals(Character, Character)",
|
||||
"assertEquals(Character, Character, String)",
|
||||
"assertEquals(Double, Double)",
|
||||
"assertEquals(Double, double)",
|
||||
"assertEquals(double, Double)",
|
||||
"assertEquals(Double, Double, String)",
|
||||
"assertEquals(Double, double, String)",
|
||||
"assertEquals(double, Double, String)",
|
||||
"assertEquals(double[], double[], double)",
|
||||
"assertEquals(double[], double[], double, String)",
|
||||
"assertEquals(Float, Float)",
|
||||
"assertEquals(Float, float)",
|
||||
"assertEquals(float, Float)",
|
||||
"assertEquals(Float, Float, String)",
|
||||
"assertEquals(Float, float, String)",
|
||||
"assertEquals(float, Float, String)",
|
||||
"assertEquals(float[], float[], float)",
|
||||
"assertEquals(float[], float[], float, String)",
|
||||
"assertEquals(int, Integer)",
|
||||
"assertEquals(int, Integer, String)",
|
||||
"assertEquals(Integer, int)",
|
||||
"assertEquals(Integer, int, String)",
|
||||
"assertEquals(Integer, Integer)",
|
||||
"assertEquals(Integer, Integer, String)",
|
||||
"assertEquals(Long, Long)",
|
||||
"assertEquals(Long, long)",
|
||||
"assertEquals(long, Long)",
|
||||
"assertEquals(Long, Long, String)",
|
||||
"assertEquals(Long, long, String)",
|
||||
"assertEquals(Short, Short)",
|
||||
"assertEquals(Short, short)",
|
||||
"assertEquals(short, Short)",
|
||||
"assertEquals(Short, Short, String)",
|
||||
"assertEquals(Short, short, String)",
|
||||
"assertEquals(short, Short, String)",
|
||||
/*
|
||||
* These `assertEqualsDeep` methods cannot (easily) be expressed using AssertJ because they
|
||||
* mix regular equality and array equality:
|
||||
*/
|
||||
"assertEqualsDeep(Map<?, ?>, Map<?, ?>)",
|
||||
"assertEqualsDeep(Map<?, ?>, Map<?, ?>, String)",
|
||||
"assertEqualsDeep(Set<?>, Set<?>)",
|
||||
"assertEqualsDeep(Set<?>, Set<?>, String)",
|
||||
// XXX: Add migrations for the methods below.
|
||||
"assertEqualsNoOrder(Collection<?>, Collection<?>)",
|
||||
@@ -351,47 +300,168 @@ final class TestNGToAssertJRules {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S1448" /* Each variant requires a separate `@BeforeTemplate` method. */)
|
||||
static final class AssertEqual {
|
||||
@BeforeTemplate
|
||||
void before(boolean actual, boolean expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(boolean actual, Boolean expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Boolean actual, boolean expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Boolean actual, Boolean expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(byte actual, byte expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(byte actual, Byte expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Byte actual, byte expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Byte actual, Byte expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(char actual, char expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(char actual, Character expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Character actual, char expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Character actual, Character expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(short actual, short expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(short actual, Short expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Short actual, short expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Short actual, Short expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(int actual, int expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(int actual, Integer expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Integer actual, int expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Integer actual, Integer expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(long actual, long expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(long actual, Long expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Long actual, long expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Long actual, Long expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(float actual, float expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(float actual, Float expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Float actual, float expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Float actual, Float expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(double actual, double expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(double actual, Double expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Double actual, double expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Double actual, Double expected) {
|
||||
assertEquals(actual, expected);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Object actual, Object expected) {
|
||||
assertEquals(actual, expected);
|
||||
@@ -414,47 +484,168 @@ final class TestNGToAssertJRules {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S1448" /* Each variant requires a separate `@BeforeTemplate` method. */)
|
||||
static final class AssertEqualWithMessage {
|
||||
@BeforeTemplate
|
||||
void before(boolean actual, String message, boolean expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(boolean actual, String message, Boolean expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Boolean actual, String message, boolean expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Boolean actual, String message, Boolean expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(byte actual, String message, byte expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(byte actual, String message, Byte expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Byte actual, String message, byte expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Byte actual, String message, Byte expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(char actual, String message, char expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(char actual, String message, Character expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Character actual, String message, char expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Character actual, String message, Character expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(short actual, String message, short expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(short actual, String message, Short expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Short actual, String message, short expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Short actual, String message, Short expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(int actual, String message, int expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(int actual, String message, Integer expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Integer actual, String message, int expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Integer actual, String message, Integer expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(long actual, String message, long expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(long actual, String message, Long expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Long actual, String message, long expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Long actual, String message, Long expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(float actual, String message, float expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(float actual, String message, Float expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Float actual, String message, float expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Float actual, String message, Float expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(double actual, String message, double expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(double actual, String message, Double expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Double actual, String message, double expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Double actual, String message, Double expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
void before(Object actual, String message, Object expected) {
|
||||
assertEquals(actual, expected, message);
|
||||
@@ -485,7 +676,7 @@ final class TestNGToAssertJRules {
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float actual, float expected, float delta) {
|
||||
void after(Float actual, float expected, float delta) {
|
||||
assertThat(actual).isCloseTo(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
@@ -635,6 +826,58 @@ final class TestNGToAssertJRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertEqualFloatArraysWithDelta {
|
||||
@BeforeTemplate
|
||||
void before(float[] actual, float[] expected, float delta) {
|
||||
assertEquals(actual, expected, delta);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float[] actual, float[] expected, float delta) {
|
||||
assertThat(actual).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertEqualFloatArraysWithDeltaWithMessage {
|
||||
@BeforeTemplate
|
||||
void before(float[] actual, String message, float[] expected, float delta) {
|
||||
assertEquals(actual, expected, delta, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(float[] actual, String message, float[] expected, float delta) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertEqualDoubleArraysWithDelta {
|
||||
@BeforeTemplate
|
||||
void before(double[] actual, double[] expected, double delta) {
|
||||
assertEquals(actual, expected, delta);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double[] actual, double[] expected, double delta) {
|
||||
assertThat(actual).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertEqualDoubleArraysWithDeltaWithMessage {
|
||||
@BeforeTemplate
|
||||
void before(double[] actual, String message, double[] expected, double delta) {
|
||||
assertEquals(actual, expected, delta, message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(double[] actual, String message, double[] expected, double delta) {
|
||||
assertThat(actual).withFailMessage(message).containsExactly(expected, offset(delta));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertEqualArraysIrrespectiveOfOrder {
|
||||
@BeforeTemplate
|
||||
void before(Object[] actual, Object[] expected) {
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
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 EagerStringFormattingTest {
|
||||
@Test
|
||||
void identification() {
|
||||
CompilationTestHelper.newInstance(EagerStringFormatting.class, getClass())
|
||||
.expectErrorMessage("DEFER", m -> m.contains("String formatting can be deferred\n"))
|
||||
.expectErrorMessage(
|
||||
"DEFER_EXTRA_VARIABLE",
|
||||
m ->
|
||||
m.contains(
|
||||
"String formatting can be deferred (but this requires introducing an effectively final variable)"))
|
||||
.expectErrorMessage(
|
||||
"DEFER_SIMPLIFIED_GUAVA",
|
||||
m ->
|
||||
m.contains(
|
||||
"String formatting can be deferred (assuming that Guava's simplified formatting support suffices)"))
|
||||
.expectErrorMessage(
|
||||
"DEFER_SIMPLIFIED_SLF4J",
|
||||
m ->
|
||||
m.contains(
|
||||
"String formatting can be deferred (assuming that SLF4J's simplified formatting support suffices)"))
|
||||
.expectErrorMessage(
|
||||
"VACUOUS", m -> m.contains("String formatting never yields `null` expression"))
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
"import static com.google.common.base.Preconditions.checkNotNull;",
|
||||
"import static com.google.common.base.Preconditions.checkState;",
|
||||
"import static com.google.common.base.Verify.verify;",
|
||||
"import static com.google.common.base.Verify.verifyNotNull;",
|
||||
"import static java.util.Objects.requireNonNull;",
|
||||
"",
|
||||
"import java.util.Formattable;",
|
||||
"import java.util.Locale;",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
"",
|
||||
" private int nonFinalField = 0;",
|
||||
"",
|
||||
" void m() {",
|
||||
" Formattable formattable = (formatter, flags, width, precision) -> {};",
|
||||
" int effectivelyFinalLocal = 0;",
|
||||
" /* A local variable that is also not effectively final. */",
|
||||
" int nonFinalLocal = 0;",
|
||||
" nonFinalLocal = 1;",
|
||||
"",
|
||||
" String.format(\"%s\", \"foo\");",
|
||||
" String.format(Locale.US, \"%s\", \"foo\");",
|
||||
" \"%s\".formatted(\"foo\");",
|
||||
" String.format(\"%s\", \"foo\", \"bar\");",
|
||||
" String.format(\"%s %s\", \"foo\", \"bar\");",
|
||||
" String.format(\"%s %s %%\", \"foo\", \"bar\");",
|
||||
"",
|
||||
" System.out.println(String.format(\"%s\", nonFinalLocal));",
|
||||
"",
|
||||
" requireNonNull(\"never-null\");",
|
||||
" requireNonNull(\"never-null\", () -> String.format(\"Format string: %s\", nonFinalField));",
|
||||
" // BUG: Diagnostic matches: VACUOUS",
|
||||
" requireNonNull(String.format(\"Never-null format string: %s\", nonFinalField));",
|
||||
" // BUG: Diagnostic matches: VACUOUS",
|
||||
" requireNonNull(\"Never-null format string: %s\".formatted(nonFinalField), \"message\");",
|
||||
" // BUG: Diagnostic matches: VACUOUS",
|
||||
" requireNonNull(",
|
||||
" String.format(\"Never-null format string\"), String.format(\"Malformed format string: %\"));",
|
||||
" // BUG: Diagnostic matches: DEFER_EXTRA_VARIABLE",
|
||||
" requireNonNull(\"never-null\", String.format(\"Format string: %s\", nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" requireNonNull(\"never-null\", String.format(\"Format string: %s\", effectivelyFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" requireNonNull(",
|
||||
" \"never-null\",",
|
||||
" String.format(",
|
||||
" \"Custom format string: %s, %d, %s\", getClass(), nonFinalField, \"string-constant\"));",
|
||||
"",
|
||||
" checkArgument(true);",
|
||||
" checkNotNull(\"never-null\");",
|
||||
" checkState(false);",
|
||||
" verify(true);",
|
||||
" verifyNotNull(\"never-null\");",
|
||||
" checkArgument(false, \"Without format string\");",
|
||||
" checkNotNull(\"never-null\", \"Without format string\");",
|
||||
" checkState(true, \"Without format string\");",
|
||||
" verify(false, \"Without format string\");",
|
||||
" verifyNotNull(\"never-null\", \"Without format string\");",
|
||||
" checkArgument(true, \"With format string: %s\", nonFinalLocal);",
|
||||
" checkNotNull(\"never-null\", \"With format string: %s\", nonFinalLocal);",
|
||||
" checkState(false, \"With format string: %s\", nonFinalLocal);",
|
||||
" verify(true, \"With format string: %s\", nonFinalLocal);",
|
||||
" verifyNotNull(\"never-null\", \"With format string: %s\", nonFinalLocal);",
|
||||
" // BUG: Diagnostic matches: VACUOUS",
|
||||
" checkNotNull(String.format(\"Never-null format string: %s\", nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: VACUOUS",
|
||||
" verifyNotNull(\"Never-null format string: %s\".formatted(nonFinalLocal), \"message\");",
|
||||
" // BUG: Diagnostic matches: VACUOUS",
|
||||
" checkNotNull(",
|
||||
" String.format(\"Never-null format string\"), String.format(\"Malformed format string: %\"));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" checkArgument(true, String.format(toString()));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" checkNotNull(\"never-null\", toString().formatted());",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" checkState(true, String.format(\"Custom format string: %d\", nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" verify(true, \"Mismatched format string:\".formatted(nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" verifyNotNull(\"never-null\", \"Mismatched format string: %d\".formatted());",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" checkArgument(true, String.format(\"Malformed format string: %\"));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" checkNotNull(\"never-null\", \"Format string with `Formattable`: %s\".formatted(formattable));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" checkState(true, String.format(\"Generated format string: %%s\"), nonFinalLocal);",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_GUAVA",
|
||||
" verify(",
|
||||
" true,",
|
||||
" \"Format string with format string argument: %s\",",
|
||||
" String.format(\"Format string argument: %s\", nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" verifyNotNull(",
|
||||
" \"never-null\", String.format(\"Format string: %s, %s\", nonFinalLocal, nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" checkArgument(true, \"Format string: %s%%\".formatted(nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" checkNotNull(",
|
||||
" \"never-null\", String.format(Locale.US, \"Format string with locale: %s\", nonFinalLocal));",
|
||||
"",
|
||||
" LOG.trace(\"Without format string\");",
|
||||
" LOG.debug(\"With format string: {}\", nonFinalLocal);",
|
||||
" LOG.info((Marker) null, \"With marker\");",
|
||||
" LOG.warn((Marker) null, \"With marker and format string: {}\", nonFinalLocal);",
|
||||
" LOG.error(\"With throwable\", new RuntimeException());",
|
||||
" LOG.trace(\"With throwable and format string: {}\", nonFinalLocal, new RuntimeException());",
|
||||
" LOG.debug((Marker) null, \"With marker and throwable\", new RuntimeException());",
|
||||
" LOG.info(",
|
||||
" (Marker) null,",
|
||||
" \"With marker, throwable and format string: {}\",",
|
||||
" nonFinalLocal,",
|
||||
" new RuntimeException());",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.warn(String.format(toString()));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.error(toString().formatted());",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.trace(String.format(\"Custom format string: %d\", nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.debug(\"Mismatched format string:\".formatted(nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.info(\"Mismatched format string %d:\".formatted());",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.warn(String.format(\"Malformed format string: %\"));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.error(\"Format string with `Formattable`: %s\".formatted(formattable));",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.trace(String.format(\"Generated format string: {}\"), nonFinalLocal);",
|
||||
" // BUG: Diagnostic matches: DEFER_SIMPLIFIED_SLF4J",
|
||||
" LOG.debug(",
|
||||
" \"Format string with format string argument: {}\",",
|
||||
" String.format(\"Format string argument: %s\", nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" LOG.info(String.format(\"Vacuous format string %%\"));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" LOG.warn(String.format(\"With format string: %s, %s\", nonFinalLocal, nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" LOG.error(String.format(Locale.ROOT, \"With vacuous localized format string %%\"));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" LOG.trace((Marker) null, String.format(\"With marker and format string: %s\", nonFinalLocal));",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" LOG.debug(",
|
||||
" String.format(\"With throwable and format string: %s\", nonFinalLocal),",
|
||||
" new RuntimeException());",
|
||||
" // BUG: Diagnostic matches: DEFER",
|
||||
" LOG.info(",
|
||||
" (Marker) null,",
|
||||
" String.format(\"With marker, throwable and format string: %s\", nonFinalLocal),",
|
||||
" new RuntimeException());",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(EagerStringFormatting.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
"import static com.google.common.base.Preconditions.checkNotNull;",
|
||||
"import static com.google.common.base.Preconditions.checkState;",
|
||||
"import static com.google.common.base.Verify.verify;",
|
||||
"import static com.google.common.base.Verify.verifyNotNull;",
|
||||
"import static java.util.Objects.requireNonNull;",
|
||||
"",
|
||||
"import java.util.Locale;",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
" private static final String GUAVA_COMPATIBLE_PATTERN = \"with-only-%s-placeholder\";",
|
||||
" private static final String GUAVA_INCOMPATIBLE_PATTERN = \"with-%%-marker\";",
|
||||
"",
|
||||
" void m() {",
|
||||
" requireNonNull(\"never-null\", String.format(\"Format string: %s\", 0));",
|
||||
"",
|
||||
" checkArgument(true, String.format(\"Vacuous format string %%\"));",
|
||||
" checkNotNull(\"never-null\", \"Format string: %s %s%%\".formatted(1, 2));",
|
||||
" checkState(false, String.format(Locale.US, \"Format string with locale: %s\", 3));",
|
||||
" verify(true, GUAVA_COMPATIBLE_PATTERN.formatted(4));",
|
||||
" verifyNotNull(\"never-null\", String.format(Locale.ENGLISH, GUAVA_COMPATIBLE_PATTERN, 5));",
|
||||
" checkArgument(false, GUAVA_INCOMPATIBLE_PATTERN.formatted());",
|
||||
" checkNotNull(\"never-null\", String.format(GUAVA_INCOMPATIBLE_PATTERN));",
|
||||
"",
|
||||
" LOG.trace(\"Vacuous format string %%\".formatted());",
|
||||
" LOG.debug(String.format(\"With format string: %s, %s%%\", 6, 7));",
|
||||
" LOG.info(String.format(Locale.ROOT, \"With vacuous localized format string %%\"));",
|
||||
" LOG.warn((Marker) null, \"With marker and format string: %s\".formatted(8));",
|
||||
" LOG.error(",
|
||||
" String.format(Locale.US, \"With throwable and format string: %s, %s\", 9, 10),",
|
||||
" new RuntimeException());",
|
||||
" LOG.trace(",
|
||||
" (Marker) null,",
|
||||
" \"With marker, throwable and format string: %s\".formatted(11),",
|
||||
" new RuntimeException());",
|
||||
" LOG.debug(GUAVA_COMPATIBLE_PATTERN.formatted(12));",
|
||||
" LOG.info(String.format(Locale.ENGLISH, GUAVA_COMPATIBLE_PATTERN, 13));",
|
||||
" LOG.warn(GUAVA_INCOMPATIBLE_PATTERN.formatted());",
|
||||
" LOG.error(String.format(GUAVA_INCOMPATIBLE_PATTERN));",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static com.google.common.base.Preconditions.checkArgument;",
|
||||
"import static com.google.common.base.Preconditions.checkNotNull;",
|
||||
"import static com.google.common.base.Preconditions.checkState;",
|
||||
"import static com.google.common.base.Verify.verify;",
|
||||
"import static com.google.common.base.Verify.verifyNotNull;",
|
||||
"import static java.util.Objects.requireNonNull;",
|
||||
"",
|
||||
"import java.util.Locale;",
|
||||
"import org.slf4j.Logger;",
|
||||
"import org.slf4j.LoggerFactory;",
|
||||
"import org.slf4j.Marker;",
|
||||
"",
|
||||
"class A {",
|
||||
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
|
||||
" private static final String GUAVA_COMPATIBLE_PATTERN = \"with-only-%s-placeholder\";",
|
||||
" private static final String GUAVA_INCOMPATIBLE_PATTERN = \"with-%%-marker\";",
|
||||
"",
|
||||
" void m() {",
|
||||
" requireNonNull(\"never-null\", () -> String.format(\"Format string: %s\", 0));",
|
||||
"",
|
||||
" checkArgument(true, \"Vacuous format string %\");",
|
||||
" checkNotNull(\"never-null\", \"Format string: %s %s%\", 1, 2);",
|
||||
" checkState(false, \"Format string with locale: %s\", 3);",
|
||||
" verify(true, GUAVA_COMPATIBLE_PATTERN, 4);",
|
||||
" verifyNotNull(\"never-null\", GUAVA_COMPATIBLE_PATTERN, 5);",
|
||||
" checkArgument(false, \"with-%-marker\");",
|
||||
" checkNotNull(\"never-null\", \"with-%-marker\");",
|
||||
"",
|
||||
" LOG.trace(\"Vacuous format string %\");",
|
||||
" LOG.debug(\"With format string: {}, {}%\", 6, 7);",
|
||||
" LOG.info(\"With vacuous localized format string %\");",
|
||||
" LOG.warn((Marker) null, \"With marker and format string: {}\", 8);",
|
||||
" LOG.error(\"With throwable and format string: {}, {}\", 9, 10, new RuntimeException());",
|
||||
" LOG.trace(",
|
||||
" (Marker) null, \"With marker, throwable and format string: {}\", 11, new RuntimeException());",
|
||||
" LOG.debug(\"with-only-{}-placeholder\", 12);",
|
||||
" LOG.info(\"with-only-{}-placeholder\", 13);",
|
||||
" LOG.warn(\"with-%-marker\");",
|
||||
" LOG.error(\"with-%-marker\");",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@ final class ExplicitArgumentEnumerationTest {
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"import io.micrometer.core.instrument.Counter;",
|
||||
"import io.micrometer.core.instrument.Tag;",
|
||||
"import org.jooq.impl.DSL;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.test.StepVerifier;",
|
||||
@@ -32,6 +34,8 @@ final class ExplicitArgumentEnumerationTest {
|
||||
"",
|
||||
" DSL.row(ImmutableList.of(1, 2));",
|
||||
"",
|
||||
" Counter.builder(\"foo\").tags(ImmutableList.of(Tag.of(\"bar\", \"baz\")));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" unaryMethod(ImmutableList.of(1, 2));",
|
||||
" unaryMethodWithLessVisibleOverload(ImmutableList.of(1, 2));",
|
||||
|
||||
@@ -55,6 +55,10 @@ final class NonStaticImportTest {
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.time.Instant.MIN;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.time.InstantSource.system;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.time.LocalDate.EPOCH;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
"import static java.time.ZoneOffset.SHORT_IDS;",
|
||||
"import static java.time.ZoneOffset.UTC;",
|
||||
"// BUG: Diagnostic contains:",
|
||||
@@ -71,6 +75,7 @@ final class NonStaticImportTest {
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import java.time.Instant;",
|
||||
"import java.time.LocalDate;",
|
||||
"import java.time.ZoneOffset;",
|
||||
"import java.util.Locale;",
|
||||
"import java.util.Map;",
|
||||
@@ -82,8 +87,10 @@ final class NonStaticImportTest {
|
||||
" void m() {",
|
||||
" nullToEmpty(null);",
|
||||
" copyOf(ImmutableList.of());",
|
||||
" LocalDate epoch = EPOCH;",
|
||||
" int max = MAX_VALUE;",
|
||||
" int min = MIN_VALUE;",
|
||||
" system();",
|
||||
" systemUTC();",
|
||||
" Instant minInstant = MIN;",
|
||||
" Map<String, String> shortIds = SHORT_IDS;",
|
||||
|
||||
@@ -21,6 +21,7 @@ final class TimeZoneUsageTest {
|
||||
"import java.time.OffsetTime;",
|
||||
"import java.time.ZoneId;",
|
||||
"import java.time.ZonedDateTime;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
@@ -31,68 +32,122 @@ final class TimeZoneUsageTest {
|
||||
" Clock.tick(clock, Duration.ZERO);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.systemUTC();",
|
||||
" clock.getZone();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.systemDefaultZone();",
|
||||
" Mono.fromSupplier(clock::getZone);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" clock.withZone(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(clock::withZone);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.system(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(Clock::system);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.systemDefaultZone();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(Clock::systemDefaultZone);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.systemUTC();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(Clock::systemUTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.tickMillis(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(Clock::tickMillis);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.tickMinutes(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(Clock::tickMinutes);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Clock.tickSeconds(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" clock.getZone();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" clock.withZone(UTC);",
|
||||
" Mono.<ZoneId>empty().map(Clock::tickSeconds);",
|
||||
"",
|
||||
" Instant.now(clock);",
|
||||
" Mono.<Clock>empty().map(Instant::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Instant.now();",
|
||||
" // This is equivalent to `clock.instant()`, which is fine.",
|
||||
" Instant.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(Instant::now);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDate.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(LocalDate::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDate.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<Clock>empty().map(LocalDate::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDate.now(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(LocalDate::now);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDateTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(LocalDateTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDateTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<Clock>empty().map(LocalDateTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalDateTime.now(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(LocalDateTime::now);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(LocalTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<Clock>empty().map(LocalTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" LocalTime.now(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(LocalTime::now);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetDateTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(OffsetDateTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetDateTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<Clock>empty().map(OffsetDateTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetDateTime.now(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(OffsetDateTime::now);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(OffsetTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<Clock>empty().map(OffsetTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" OffsetTime.now(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(OffsetTime::now);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ZonedDateTime.now();",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.fromSupplier(ZonedDateTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ZonedDateTime.now(clock);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<Clock>empty().map(ZonedDateTime::now);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ZonedDateTime.now(UTC);",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Mono.<ZoneId>empty().map(ZonedDateTime::now);",
|
||||
" }",
|
||||
"",
|
||||
" abstract class ForwardingClock extends Clock {",
|
||||
|
||||
@@ -23,6 +23,8 @@ final class RefasterRulesTest {
|
||||
AssertJEnumerableRules.class,
|
||||
AssertJFloatRules.class,
|
||||
AssertJIntegerRules.class,
|
||||
AssertJIterableRules.class,
|
||||
AssertJIteratorRules.class,
|
||||
AssertJLongRules.class,
|
||||
AssertJMapRules.class,
|
||||
AssertJNumberRules.class,
|
||||
@@ -36,13 +38,13 @@ final class RefasterRulesTest {
|
||||
AssortedRules.class,
|
||||
BigDecimalRules.class,
|
||||
BugCheckerRules.class,
|
||||
CharSequenceRules.class,
|
||||
ClassRules.class,
|
||||
CollectionRules.class,
|
||||
ComparatorRules.class,
|
||||
DoubleStreamRules.class,
|
||||
EqualityRules.class,
|
||||
FileRules.class,
|
||||
InputStreamRules.class,
|
||||
ImmutableEnumSetRules.class,
|
||||
ImmutableListRules.class,
|
||||
ImmutableListMultimapRules.class,
|
||||
@@ -53,6 +55,8 @@ final class RefasterRulesTest {
|
||||
ImmutableSortedMapRules.class,
|
||||
ImmutableSortedMultisetRules.class,
|
||||
ImmutableSortedSetRules.class,
|
||||
ImmutableTableRules.class,
|
||||
InputStreamRules.class,
|
||||
IntStreamRules.class,
|
||||
JUnitRules.class,
|
||||
JUnitToAssertJRules.class,
|
||||
|
||||
@@ -8,13 +8,16 @@ import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class AssertJCharSequenceRulesTest implements RefasterRuleCollectionTestCase {
|
||||
void testAssertThatCharSequenceIsEmpty() {
|
||||
assertThat("foo".length()).isEqualTo(0L);
|
||||
assertThat("foo".length()).isNotPositive();
|
||||
assertThat("foo".isEmpty()).isTrue();
|
||||
assertThat("bar".length()).isEqualTo(0L);
|
||||
assertThat("baz".length()).isNotPositive();
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testAssertThatCharSequenceIsNotEmpty() {
|
||||
return ImmutableSet.of(
|
||||
assertThat("foo".length()).isNotEqualTo(0), assertThat("bar".length()).isPositive());
|
||||
assertThat("foo".isEmpty()).isFalse(),
|
||||
assertThat("bar".length()).isNotEqualTo(0),
|
||||
assertThat("baz".length()).isPositive());
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatCharSequenceHasSize() {
|
||||
|
||||
@@ -9,11 +9,15 @@ import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
final class AssertJCharSequenceRulesTest implements RefasterRuleCollectionTestCase {
|
||||
void testAssertThatCharSequenceIsEmpty() {
|
||||
assertThat("foo").isEmpty();
|
||||
assertThat("foo").isEmpty();
|
||||
assertThat("bar").isEmpty();
|
||||
assertThat("baz").isEmpty();
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testAssertThatCharSequenceIsNotEmpty() {
|
||||
return ImmutableSet.of(assertThat("foo").isNotEmpty(), assertThat("bar").isNotEmpty());
|
||||
return ImmutableSet.of(
|
||||
assertThat("foo").isNotEmpty(),
|
||||
assertThat("bar").isNotEmpty(),
|
||||
assertThat("baz").isNotEmpty());
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatCharSequenceHasSize() {
|
||||
|
||||
@@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.EnumerableAssert;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
@@ -14,20 +15,63 @@ final class AssertJEnumerableRulesTest implements RefasterRuleCollectionTestCase
|
||||
}
|
||||
|
||||
void testEnumerableAssertIsEmpty() {
|
||||
assertThat(ImmutableSet.of()).hasSize(0);
|
||||
assertThat(ImmutableSet.of()).hasSizeLessThanOrEqualTo(0);
|
||||
assertThat(ImmutableSet.of()).hasSizeLessThan(1);
|
||||
assertThat(ImmutableSet.of(1)).hasSize(0);
|
||||
assertThat(ImmutableSet.of(2)).hasSizeLessThanOrEqualTo(0);
|
||||
assertThat(ImmutableSet.of(3)).hasSizeLessThan(1);
|
||||
assertThat(ImmutableSet.of(4)).size().isNotPositive();
|
||||
}
|
||||
|
||||
ImmutableSet<EnumerableAssert<?, Character>> testEnumerableAssertIsNotEmpty() {
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertIsNotEmpty() {
|
||||
return ImmutableSet.of(
|
||||
assertThat("foo").hasSizeGreaterThan(0), assertThat("bar").hasSizeGreaterThanOrEqualTo(1));
|
||||
assertThat(ImmutableSet.of(1)).hasSizeGreaterThan(0),
|
||||
assertThat(ImmutableSet.of(2)).hasSizeGreaterThanOrEqualTo(1),
|
||||
assertThat(ImmutableSet.of(3)).size().isNotEqualTo(0).returnToIterable(),
|
||||
assertThat(ImmutableSet.of(4)).size().isPositive().returnToIterable(),
|
||||
assertThat(ImmutableSet.of(5)).size().isNotEqualTo(0),
|
||||
assertThat(ImmutableSet.of(6)).size().isPositive());
|
||||
}
|
||||
|
||||
ImmutableSet<EnumerableAssert<?, Integer>> testEnumerableAssertHasSameSizeAs() {
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSize() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSize(Iterables.size(ImmutableSet.of(2))),
|
||||
assertThat(ImmutableSet.of(3)).hasSize(ImmutableSet.of(4).size()),
|
||||
assertThat(ImmutableSet.of(5)).hasSize(new Integer[0].length));
|
||||
assertThat(ImmutableSet.of(1)).size().isEqualTo(2).returnToIterable(),
|
||||
assertThat(ImmutableSet.of(3)).size().isEqualTo(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeLessThan() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).size().isLessThan(2).returnToIterable(),
|
||||
assertThat(ImmutableSet.of(3)).size().isLessThan(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeLessThanOrEqualTo() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).size().isLessThanOrEqualTo(2).returnToIterable(),
|
||||
assertThat(ImmutableSet.of(3)).size().isLessThanOrEqualTo(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeGreaterThan() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).size().isGreaterThan(2).returnToIterable(),
|
||||
assertThat(ImmutableSet.of(3)).size().isGreaterThan(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeGreaterThanOrEqualTo() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).size().isGreaterThanOrEqualTo(2).returnToIterable(),
|
||||
assertThat(ImmutableSet.of(3)).size().isGreaterThanOrEqualTo(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeBetween() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).size().isBetween(2, 3).returnToIterable(),
|
||||
assertThat(ImmutableSet.of(4)).size().isBetween(5, 6));
|
||||
}
|
||||
|
||||
ImmutableSet<EnumerableAssert<?, Character>> testEnumerableAssertHasSameSizeAs() {
|
||||
return ImmutableSet.of(
|
||||
assertThat("foo").hasSize(Iterables.size(ImmutableSet.of(1))),
|
||||
assertThat("bar").hasSize(ImmutableSet.of(2).size()),
|
||||
assertThat("baz").hasSize(new Integer[0].length),
|
||||
assertThat("qux").hasSize("quux".length()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.EnumerableAssert;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
@@ -14,19 +15,62 @@ final class AssertJEnumerableRulesTest implements RefasterRuleCollectionTestCase
|
||||
}
|
||||
|
||||
void testEnumerableAssertIsEmpty() {
|
||||
assertThat(ImmutableSet.of()).isEmpty();
|
||||
assertThat(ImmutableSet.of()).isEmpty();
|
||||
assertThat(ImmutableSet.of()).isEmpty();
|
||||
assertThat(ImmutableSet.of(1)).isEmpty();
|
||||
assertThat(ImmutableSet.of(2)).isEmpty();
|
||||
assertThat(ImmutableSet.of(3)).isEmpty();
|
||||
assertThat(ImmutableSet.of(4)).isEmpty();
|
||||
}
|
||||
|
||||
ImmutableSet<EnumerableAssert<?, Character>> testEnumerableAssertIsNotEmpty() {
|
||||
return ImmutableSet.of(assertThat("foo").isNotEmpty(), assertThat("bar").isNotEmpty());
|
||||
}
|
||||
|
||||
ImmutableSet<EnumerableAssert<?, Integer>> testEnumerableAssertHasSameSizeAs() {
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertIsNotEmpty() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSameSizeAs(ImmutableSet.of(2)),
|
||||
assertThat(ImmutableSet.of(3)).hasSameSizeAs(ImmutableSet.of(4)),
|
||||
assertThat(ImmutableSet.of(5)).hasSameSizeAs(new Integer[0]));
|
||||
assertThat(ImmutableSet.of(1)).isNotEmpty(),
|
||||
assertThat(ImmutableSet.of(2)).isNotEmpty(),
|
||||
assertThat(ImmutableSet.of(3)).isNotEmpty(),
|
||||
assertThat(ImmutableSet.of(4)).isNotEmpty(),
|
||||
assertThat(ImmutableSet.of(5)).isNotEmpty(),
|
||||
assertThat(ImmutableSet.of(6)).isNotEmpty());
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSize() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSize(2), assertThat(ImmutableSet.of(3)).hasSize(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeLessThan() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSizeLessThan(2),
|
||||
assertThat(ImmutableSet.of(3)).hasSizeLessThan(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeLessThanOrEqualTo() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSizeLessThanOrEqualTo(2),
|
||||
assertThat(ImmutableSet.of(3)).hasSizeLessThanOrEqualTo(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeGreaterThan() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSizeGreaterThan(2),
|
||||
assertThat(ImmutableSet.of(3)).hasSizeGreaterThan(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeGreaterThanOrEqualTo() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSizeGreaterThanOrEqualTo(2),
|
||||
assertThat(ImmutableSet.of(3)).hasSizeGreaterThanOrEqualTo(4));
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testEnumerableAssertHasSizeBetween() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).hasSizeBetween(2, 3),
|
||||
assertThat(ImmutableSet.of(4)).hasSizeBetween(5, 6));
|
||||
}
|
||||
|
||||
ImmutableSet<EnumerableAssert<?, Character>> testEnumerableAssertHasSameSizeAs() {
|
||||
return ImmutableSet.of(
|
||||
assertThat("foo").hasSameSizeAs(ImmutableSet.of(1)),
|
||||
assertThat("bar").hasSameSizeAs(ImmutableSet.of(2)),
|
||||
assertThat("baz").hasSameSizeAs(new Integer[0]),
|
||||
assertThat("qux").hasSameSizeAs("quux"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractIntegerAssert;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class AssertJIterableRulesTest implements RefasterRuleCollectionTestCase {
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(Iterables.class);
|
||||
}
|
||||
|
||||
void testAssertThatIterableIsEmpty() {
|
||||
assertThat(ImmutableSet.of(1).iterator()).isExhausted();
|
||||
assertThat(ImmutableSet.of(2).isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testAssertThatIterableIsNotEmpty() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1).iterator()).hasNext(),
|
||||
assertThat(ImmutableSet.of(2).isEmpty()).isFalse());
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractIntegerAssert<?>> testAssertThatIterableSize() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(Iterables.size(ImmutableSet.of(1))), assertThat(ImmutableSet.of(2).size()));
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatIterableHasOneElementEqualTo() {
|
||||
return assertThat(Iterables.getOnlyElement(ImmutableSet.of(new Object()))).isEqualTo("foo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractIntegerAssert;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class AssertJIterableRulesTest implements RefasterRuleCollectionTestCase {
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(Iterables.class);
|
||||
}
|
||||
|
||||
void testAssertThatIterableIsEmpty() {
|
||||
assertThat(ImmutableSet.of(1)).isEmpty();
|
||||
assertThat(ImmutableSet.of(2)).isEmpty();
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractAssert<?, ?>> testAssertThatIterableIsNotEmpty() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).isNotEmpty(), assertThat(ImmutableSet.of(2)).isNotEmpty());
|
||||
}
|
||||
|
||||
ImmutableSet<AbstractIntegerAssert<?>> testAssertThatIterableSize() {
|
||||
return ImmutableSet.of(
|
||||
assertThat(ImmutableSet.of(1)).size(), assertThat(ImmutableSet.of(2)).size());
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatIterableHasOneElementEqualTo() {
|
||||
return assertThat(ImmutableSet.of(new Object())).containsExactly("foo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class AssertJIteratorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
AbstractAssert<?, ?> testAssertThatHasNext() {
|
||||
return assertThat(ImmutableSet.of().iterator().hasNext()).isTrue();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatIsExhausted() {
|
||||
return assertThat(ImmutableSet.of().iterator().hasNext()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class AssertJIteratorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
AbstractAssert<?, ?> testAssertThatHasNext() {
|
||||
return assertThat(ImmutableSet.of().iterator()).hasNext();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatIsExhausted() {
|
||||
return assertThat(ImmutableSet.of().iterator()).isExhausted();
|
||||
}
|
||||
}
|
||||
@@ -21,16 +21,16 @@ final class AssertJStringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
assertThat("foo").isEqualTo("");
|
||||
}
|
||||
|
||||
void testAssertThatStringIsEmpty() {
|
||||
assertThat("foo".isEmpty()).isTrue();
|
||||
}
|
||||
|
||||
AbstractStringAssert<?> testAbstractStringAssertStringIsNotEmpty() {
|
||||
return assertThat("foo").isNotEqualTo("");
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatStringIsNotEmpty() {
|
||||
return assertThat("foo".isEmpty()).isFalse();
|
||||
AbstractAssert<?, ?> testAssertThatStringContains() {
|
||||
return assertThat("foo".contains("bar")).isTrue();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatStringDoesNotContain() {
|
||||
return assertThat("foo".contains("bar")).isFalse();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatMatches() {
|
||||
|
||||
@@ -22,16 +22,16 @@ final class AssertJStringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
assertThat("foo").isEmpty();
|
||||
}
|
||||
|
||||
void testAssertThatStringIsEmpty() {
|
||||
assertThat("foo").isEmpty();
|
||||
}
|
||||
|
||||
AbstractStringAssert<?> testAbstractStringAssertStringIsNotEmpty() {
|
||||
return assertThat("foo").isNotEmpty();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatStringIsNotEmpty() {
|
||||
return assertThat("foo").isNotEmpty();
|
||||
AbstractAssert<?, ?> testAssertThatStringContains() {
|
||||
return assertThat("foo").contains("bar");
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatStringDoesNotContain() {
|
||||
return assertThat("foo").doesNotContain("bar");
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatMatches() {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class CharSequenceRulesTest implements RefasterRuleCollectionTestCase {
|
||||
ImmutableSet<Boolean> testCharSequenceIsEmpty() {
|
||||
return ImmutableSet.of(
|
||||
new StringBuilder("foo").length() == 0,
|
||||
new StringBuilder("bar").length() <= 0,
|
||||
new StringBuilder("baz").length() < 1,
|
||||
new StringBuilder("qux").length() != 0,
|
||||
new StringBuilder("quux").length() > 0,
|
||||
new StringBuilder("corge").length() >= 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class CharSequenceRulesTest implements RefasterRuleCollectionTestCase {
|
||||
ImmutableSet<Boolean> testCharSequenceIsEmpty() {
|
||||
return ImmutableSet.of(
|
||||
new StringBuilder("foo").isEmpty(),
|
||||
new StringBuilder("bar").isEmpty(),
|
||||
new StringBuilder("baz").isEmpty(),
|
||||
!new StringBuilder("qux").isEmpty(),
|
||||
!new StringBuilder("quux").isEmpty(),
|
||||
!new StringBuilder("corge").isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Iterables.removeAll(new ArrayList<>(), ImmutableSet.of("foo"));
|
||||
}
|
||||
|
||||
void testSetRemoveAllCollection() {
|
||||
void testCollectionRemoveAllFromCollectionBlock() {
|
||||
ImmutableSet.of("foo").forEach(new HashSet<>()::remove);
|
||||
for (Number element : ImmutableList.of(1)) {
|
||||
new HashSet<Number>().remove(element);
|
||||
|
||||
@@ -58,7 +58,7 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return new ArrayList<>().removeAll(ImmutableSet.of("foo"));
|
||||
}
|
||||
|
||||
void testSetRemoveAllCollection() {
|
||||
void testCollectionRemoveAllFromCollectionBlock() {
|
||||
new HashSet<>().removeAll(ImmutableSet.of("foo"));
|
||||
new HashSet<Number>().removeAll(ImmutableList.of(1));
|
||||
new HashSet<Number>().removeAll(ImmutableSet.of(2));
|
||||
|
||||
@@ -39,4 +39,16 @@ final class FileRulesTest implements RefasterRuleCollectionTestCase {
|
||||
File testFilesCreateTempFileInCustomDirectoryToFile() throws IOException {
|
||||
return File.createTempFile("foo", "bar", new File("baz"));
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testPathToFileMkDirsFilesExists() {
|
||||
return ImmutableSet.of(
|
||||
Files.exists(Path.of("foo")) || Path.of("foo").toFile().mkdirs(),
|
||||
!Files.exists(Path.of("bar")) && !Path.of("bar").toFile().mkdirs());
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testFileMkDirsFileExists() {
|
||||
return ImmutableSet.of(
|
||||
new File("foo").exists() || new File("foo").mkdirs(),
|
||||
!new File("bar").exists() && !new File("bar").mkdirs());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,16 @@ final class FileRulesTest implements RefasterRuleCollectionTestCase {
|
||||
File testFilesCreateTempFileInCustomDirectoryToFile() throws IOException {
|
||||
return Files.createTempFile(new File("baz").toPath(), "foo", "bar").toFile();
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testPathToFileMkDirsFilesExists() {
|
||||
return ImmutableSet.of(
|
||||
Path.of("foo").toFile().mkdirs() || Files.exists(Path.of("foo")),
|
||||
!Path.of("bar").toFile().mkdirs() && !Files.exists(Path.of("bar")));
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testFileMkDirsFileExists() {
|
||||
return ImmutableSet.of(
|
||||
new File("foo").mkdirs() || new File("foo").exists(),
|
||||
!new File("bar").mkdirs() && !new File("bar").exists());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,13 @@ final class ImmutableMapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return new ImmutableMap.Builder<>();
|
||||
}
|
||||
|
||||
ImmutableMap<Object, Object> testImmutableMapBuilderBuildOrThrow() {
|
||||
return ImmutableMap.builder().build();
|
||||
}
|
||||
|
||||
ImmutableSet<ImmutableMap<String, Integer>> testEntryToImmutableMap() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.<String, Integer>builder().put(Map.entry("foo", 1)).build(),
|
||||
ImmutableMap.<String, Integer>builder().put(Map.entry("foo", 1)).buildOrThrow(),
|
||||
Stream.of(Map.entry("foo", 1))
|
||||
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)));
|
||||
}
|
||||
@@ -51,13 +55,14 @@ final class ImmutableMapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
ImmutableMap.copyOf(Maps.asMap(ImmutableSet.of(10), Integer::valueOf)));
|
||||
}
|
||||
|
||||
ImmutableSet<ImmutableMap<String, Integer>> testEntryIterableToImmutableMap() {
|
||||
ImmutableSet<Map<String, Integer>> testEntryIterableToImmutableMap() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.copyOf(ImmutableMap.of("foo", 1).entrySet()),
|
||||
ImmutableMap.<String, Integer>builder().putAll(ImmutableMap.of("foo", 1)).build(),
|
||||
ImmutableMap.<String, Integer>builder().putAll(ImmutableMap.of("foo", 1)).buildOrThrow(),
|
||||
Map.copyOf(ImmutableMap.of("foo", 1)),
|
||||
ImmutableMap.<String, Integer>builder()
|
||||
.putAll(ImmutableMap.of("foo", 1).entrySet())
|
||||
.build(),
|
||||
.buildOrThrow(),
|
||||
ImmutableMap.of("foo", 1).entrySet().stream()
|
||||
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)),
|
||||
Streams.stream(Iterables.cycle(Map.entry("foo", 1)))
|
||||
@@ -100,32 +105,51 @@ final class ImmutableMapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.<String, String>builder().build(),
|
||||
ImmutableMap.<String, String>builder().buildOrThrow(),
|
||||
ImmutableMap.ofEntries(),
|
||||
Collections.<String, String>emptyMap(),
|
||||
Map.<String, String>of());
|
||||
}
|
||||
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf1() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.<String, String>builder().put("k1", "v1").build(),
|
||||
ImmutableMap.<String, String>builder().put("k1", "v1").buildOrThrow(),
|
||||
ImmutableMap.ofEntries(Map.entry("k1", "v1")),
|
||||
Collections.singletonMap("k1", "v1"),
|
||||
Map.of("k1", "v1"));
|
||||
}
|
||||
|
||||
Map<String, String> testImmutableMapOf2() {
|
||||
return Map.of("k1", "v1", "k2", "v2");
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf2() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.ofEntries(Map.entry("k1", "v1"), Map.entry("k2", "v2")),
|
||||
Map.of("k1", "v1", "k2", "v2"));
|
||||
}
|
||||
|
||||
Map<String, String> testImmutableMapOf3() {
|
||||
return Map.of("k1", "v1", "k2", "v2", "k3", "v3");
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf3() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.ofEntries(Map.entry("k1", "v1"), Map.entry("k2", "v2"), Map.entry("k3", "v3")),
|
||||
Map.of("k1", "v1", "k2", "v2", "k3", "v3"));
|
||||
}
|
||||
|
||||
Map<String, String> testImmutableMapOf4() {
|
||||
return Map.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4");
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf4() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.ofEntries(
|
||||
Map.entry("k1", "v1"),
|
||||
Map.entry("k2", "v2"),
|
||||
Map.entry("k3", "v3"),
|
||||
Map.entry("k4", "v4")),
|
||||
Map.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4"));
|
||||
}
|
||||
|
||||
Map<String, String> testImmutableMapOf5() {
|
||||
return Map.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4", "k5", "v5");
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf5() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.ofEntries(
|
||||
Map.entry("k1", "v1"),
|
||||
Map.entry("k2", "v2"),
|
||||
Map.entry("k3", "v3"),
|
||||
Map.entry("k4", "v4"),
|
||||
Map.entry("k5", "v5")),
|
||||
Map.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4", "k5", "v5"));
|
||||
}
|
||||
|
||||
ImmutableMap<String, Integer> testImmutableMapCopyOfMapsFilterKeys() {
|
||||
@@ -139,4 +163,11 @@ final class ImmutableMapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
.filter(entry -> entry.getValue() > 0)
|
||||
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||
}
|
||||
|
||||
ImmutableSet<Map<String, Integer>> testImmutableMapOfEntries() {
|
||||
return ImmutableSet.of(
|
||||
Map.ofEntries(),
|
||||
Map.ofEntries(Map.entry("foo", 1)),
|
||||
Map.ofEntries(Map.entry("bar", 2), Map.entry("baz", 3)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ final class ImmutableMapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableMap.builder();
|
||||
}
|
||||
|
||||
ImmutableMap<Object, Object> testImmutableMapBuilderBuildOrThrow() {
|
||||
return ImmutableMap.builder().buildOrThrow();
|
||||
}
|
||||
|
||||
ImmutableSet<ImmutableMap<String, Integer>> testEntryToImmutableMap() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of(Map.entry("foo", 1).getKey(), Map.entry("foo", 1).getValue()),
|
||||
@@ -46,8 +50,9 @@ final class ImmutableMapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Maps.toMap(ImmutableSet.of(10), Integer::valueOf));
|
||||
}
|
||||
|
||||
ImmutableSet<ImmutableMap<String, Integer>> testEntryIterableToImmutableMap() {
|
||||
ImmutableSet<Map<String, Integer>> testEntryIterableToImmutableMap() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.copyOf(ImmutableMap.of("foo", 1)),
|
||||
ImmutableMap.copyOf(ImmutableMap.of("foo", 1)),
|
||||
ImmutableMap.copyOf(ImmutableMap.of("foo", 1)),
|
||||
ImmutableMap.copyOf(ImmutableMap.of("foo", 1).entrySet()),
|
||||
@@ -83,28 +88,39 @@ final class ImmutableMapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf() {
|
||||
return ImmutableSet.of(ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of());
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of());
|
||||
}
|
||||
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf1() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of("k1", "v1"), ImmutableMap.of("k1", "v1"), ImmutableMap.of("k1", "v1"));
|
||||
ImmutableMap.of("k1", "v1"),
|
||||
ImmutableMap.of("k1", "v1"),
|
||||
ImmutableMap.of("k1", "v1"),
|
||||
ImmutableMap.of("k1", "v1"));
|
||||
}
|
||||
|
||||
Map<String, String> testImmutableMapOf2() {
|
||||
return ImmutableMap.of("k1", "v1", "k2", "v2");
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf2() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of("k1", "v1", "k2", "v2"), ImmutableMap.of("k1", "v1", "k2", "v2"));
|
||||
}
|
||||
|
||||
Map<String, String> testImmutableMapOf3() {
|
||||
return ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3");
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf3() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3"),
|
||||
ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3"));
|
||||
}
|
||||
|
||||
Map<String, String> testImmutableMapOf4() {
|
||||
return ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4");
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf4() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4"),
|
||||
ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4"));
|
||||
}
|
||||
|
||||
Map<String, String> testImmutableMapOf5() {
|
||||
return ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4", "k5", "v5");
|
||||
ImmutableSet<Map<String, String>> testImmutableMapOf5() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4", "k5", "v5"),
|
||||
ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3", "k4", "v4", "k5", "v5"));
|
||||
}
|
||||
|
||||
ImmutableMap<String, Integer> testImmutableMapCopyOfMapsFilterKeys() {
|
||||
@@ -114,4 +130,11 @@ final class ImmutableMapRulesTest implements RefasterRuleCollectionTestCase {
|
||||
ImmutableMap<String, Integer> testImmutableMapCopyOfMapsFilterValues() {
|
||||
return ImmutableMap.copyOf(Maps.filterValues(ImmutableMap.of("foo", 1), v -> v > 0));
|
||||
}
|
||||
|
||||
ImmutableSet<Map<String, Integer>> testImmutableMapOfEntries() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableMap.ofEntries(),
|
||||
ImmutableMap.ofEntries(Map.entry("foo", 1)),
|
||||
ImmutableMap.ofEntries(Map.entry("bar", 2), Map.entry("baz", 3)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,16 +32,16 @@ final class ImmutableSortedMapRulesTest implements RefasterRuleCollectionTestCas
|
||||
}
|
||||
|
||||
ImmutableSortedMap<String, Integer> testEmptyImmutableSortedMap() {
|
||||
return ImmutableSortedMap.<String, Integer>naturalOrder().build();
|
||||
return ImmutableSortedMap.<String, Integer>naturalOrder().buildOrThrow();
|
||||
}
|
||||
|
||||
ImmutableSortedMap<String, Integer> testPairToImmutableSortedMap() {
|
||||
return ImmutableSortedMap.<String, Integer>naturalOrder().put("foo", 1).build();
|
||||
return ImmutableSortedMap.<String, Integer>naturalOrder().put("foo", 1).buildOrThrow();
|
||||
}
|
||||
|
||||
ImmutableSet<ImmutableSortedMap<String, Integer>> testEntryToImmutableSortedMap() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableSortedMap.<String, Integer>naturalOrder().put(Map.entry("foo", 1)).build(),
|
||||
ImmutableSortedMap.<String, Integer>naturalOrder().put(Map.entry("foo", 1)).buildOrThrow(),
|
||||
Stream.of(Map.entry("foo", 1))
|
||||
.collect(toImmutableSortedMap(naturalOrder(), Map.Entry::getKey, Map.Entry::getValue)));
|
||||
}
|
||||
@@ -52,10 +52,10 @@ final class ImmutableSortedMapRulesTest implements RefasterRuleCollectionTestCas
|
||||
ImmutableSortedMap.copyOf(ImmutableSortedMap.of("foo", 1).entrySet()),
|
||||
ImmutableSortedMap.<String, Integer>naturalOrder()
|
||||
.putAll(ImmutableSortedMap.of("foo", 1))
|
||||
.build(),
|
||||
.buildOrThrow(),
|
||||
ImmutableSortedMap.<String, Integer>naturalOrder()
|
||||
.putAll(ImmutableSortedMap.of("foo", 1).entrySet())
|
||||
.build(),
|
||||
.buildOrThrow(),
|
||||
ImmutableSortedMap.of("foo", 1).entrySet().stream()
|
||||
.collect(toImmutableSortedMap(naturalOrder(), Map.Entry::getKey, Map.Entry::getValue)),
|
||||
Streams.stream(Iterables.cycle(Map.entry("foo", 1)))
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static com.google.common.collect.ImmutableTable.toImmutableTable;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.Tables;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class ImmutableTableRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(Table.class);
|
||||
}
|
||||
|
||||
ImmutableTable.Builder<String, Integer, String> testImmutableTableBuilder() {
|
||||
return new ImmutableTable.Builder<>();
|
||||
}
|
||||
|
||||
ImmutableTable<Object, Object, Object> testImmutableTableBuilderBuildOrThrow() {
|
||||
return ImmutableTable.builder().build();
|
||||
}
|
||||
|
||||
ImmutableSet<ImmutableTable<String, Integer, String>> testCellToImmutableTable() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableTable.<String, Integer, String>builder()
|
||||
.put(Tables.immutableCell("foo", 1, "bar"))
|
||||
.buildOrThrow(),
|
||||
Stream.of(Tables.immutableCell("baz", 2, "qux"))
|
||||
.collect(
|
||||
toImmutableTable(
|
||||
Table.Cell::getRowKey, Table.Cell::getColumnKey, Table.Cell::getValue)));
|
||||
}
|
||||
|
||||
ImmutableTable<Integer, String, Integer> testStreamOfCellsToImmutableTable() {
|
||||
return Stream.of(1, 2, 3)
|
||||
.map(n -> Tables.immutableCell(n, n.toString(), n * 2))
|
||||
.collect(
|
||||
toImmutableTable(
|
||||
Table.Cell::getRowKey, Table.Cell::getColumnKey, Table.Cell::getValue));
|
||||
}
|
||||
|
||||
ImmutableTable<String, String, String> testImmutableTableOf() {
|
||||
return ImmutableTable.<String, String, String>builder().buildOrThrow();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static com.google.common.collect.ImmutableTable.toImmutableTable;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.Tables;
|
||||
import java.util.stream.Stream;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class ImmutableTableRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(Table.class);
|
||||
}
|
||||
|
||||
ImmutableTable.Builder<String, Integer, String> testImmutableTableBuilder() {
|
||||
return ImmutableTable.builder();
|
||||
}
|
||||
|
||||
ImmutableTable<Object, Object, Object> testImmutableTableBuilderBuildOrThrow() {
|
||||
return ImmutableTable.builder().buildOrThrow();
|
||||
}
|
||||
|
||||
ImmutableSet<ImmutableTable<String, Integer, String>> testCellToImmutableTable() {
|
||||
return ImmutableSet.of(
|
||||
ImmutableTable.of(
|
||||
Tables.immutableCell("foo", 1, "bar").getRowKey(),
|
||||
Tables.immutableCell("foo", 1, "bar").getColumnKey(),
|
||||
Tables.immutableCell("foo", 1, "bar").getValue()),
|
||||
ImmutableTable.of(
|
||||
Tables.immutableCell("baz", 2, "qux").getRowKey(),
|
||||
Tables.immutableCell("baz", 2, "qux").getColumnKey(),
|
||||
Tables.immutableCell("baz", 2, "qux").getValue()));
|
||||
}
|
||||
|
||||
ImmutableTable<Integer, String, Integer> testStreamOfCellsToImmutableTable() {
|
||||
return Stream.of(1, 2, 3).collect(toImmutableTable(n -> n, n -> n.toString(), n -> n * 2));
|
||||
}
|
||||
|
||||
ImmutableTable<String, String, String> testImmutableTableOf() {
|
||||
return ImmutableTable.of();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static org.assertj.core.api.Assertions.offset;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
@@ -24,6 +26,8 @@ final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
assertInstanceOf(null, null),
|
||||
assertThrows(null, null),
|
||||
assertThrowsExactly(null, null),
|
||||
offset(0.0),
|
||||
(Runnable) () -> assertArrayEquals((int[]) null, null),
|
||||
(Runnable) () -> assertFalse(true),
|
||||
(Runnable) () -> assertNotNull(null),
|
||||
(Runnable) () -> assertNotSame(null, null),
|
||||
@@ -32,6 +36,138 @@ final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
(Runnable) () -> assertTrue(true));
|
||||
}
|
||||
|
||||
void testAssertThatBooleanArrayContainsExactly() {
|
||||
assertArrayEquals(new boolean[] {true}, new boolean[] {false});
|
||||
}
|
||||
|
||||
void testAssertThatBooleanArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new boolean[] {true}, new boolean[] {false}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatBooleanArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new boolean[] {true}, new boolean[] {false}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatByteArrayContainsExactly() {
|
||||
assertArrayEquals(new byte[] {1}, new byte[] {2});
|
||||
}
|
||||
|
||||
void testAssertThatByteArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new byte[] {1}, new byte[] {2}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatByteArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new byte[] {1}, new byte[] {2}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatCharArrayContainsExactly() {
|
||||
assertArrayEquals(new char[] {'a'}, new char[] {'b'});
|
||||
}
|
||||
|
||||
void testAssertThatCharArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new char[] {'a'}, new char[] {'b'}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatCharArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new char[] {'a'}, new char[] {'b'}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatShortArrayContainsExactly() {
|
||||
assertArrayEquals(new short[] {1}, new short[] {2});
|
||||
}
|
||||
|
||||
void testAssertThatShortArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new short[] {1}, new short[] {2}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatShortArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new short[] {1}, new short[] {2}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatIntArrayContainsExactly() {
|
||||
assertArrayEquals(new int[] {1}, new int[] {2});
|
||||
}
|
||||
|
||||
void testAssertThatIntArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new int[] {1}, new int[] {2}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatIntArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new int[] {1}, new int[] {2}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatLongArrayContainsExactly() {
|
||||
assertArrayEquals(new long[] {1L}, new long[] {2L});
|
||||
}
|
||||
|
||||
void testAssertThatLongArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new long[] {1L}, new long[] {2L}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatLongArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new long[] {1L}, new long[] {2L}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayContainsExactly() {
|
||||
assertArrayEquals(new float[] {1.0F}, new float[] {2.0F});
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new float[] {1.0F}, new float[] {2.0F}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new float[] {1.0F}, new float[] {2.0F}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayContainsExactlyWithOffset() {
|
||||
assertArrayEquals(new float[] {1.0F}, new float[] {2.0F}, 0.1f);
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayWithFailMessageContainsExactlyWithOffset() {
|
||||
assertArrayEquals(new float[] {1.0F}, new float[] {2.0F}, 0.1f, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayWithFailMessageSupplierContainsExactlyWithOffset() {
|
||||
assertArrayEquals(new float[] {1.0F}, new float[] {2.0F}, 0.1f, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayContainsExactly() {
|
||||
assertArrayEquals(new double[] {1.0}, new double[] {2.0});
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new double[] {1.0}, new double[] {2.0}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new double[] {1.0}, new double[] {2.0}, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayContainsExactlyWithOffset() {
|
||||
assertArrayEquals(new double[] {1.0}, new double[] {2.0}, 0.1);
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayWithFailMessageContainsExactlyWithOffset() {
|
||||
assertArrayEquals(new double[] {1.0}, new double[] {2.0}, 0.1, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayWithFailMessageSupplierContainsExactlyWithOffset() {
|
||||
assertArrayEquals(new double[] {1.0}, new double[] {2.0}, 0.1, () -> "foo");
|
||||
}
|
||||
|
||||
void testAssertThatObjectArrayContainsExactly() {
|
||||
assertArrayEquals(new Object[] {"foo"}, new Object[] {"bar"});
|
||||
}
|
||||
|
||||
void testAssertThatObjectArrayWithFailMessageContainsExactly() {
|
||||
assertArrayEquals(new Object[] {"foo"}, new Object[] {"bar"}, "foo");
|
||||
}
|
||||
|
||||
void testAssertThatObjectArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertArrayEquals(new Object[] {"foo"}, new Object[] {"bar"}, () -> "foo");
|
||||
}
|
||||
|
||||
Object testFail() {
|
||||
return Assertions.fail();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package tech.picnic.errorprone.refasterrules;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.offset;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
@@ -27,6 +29,8 @@ final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
assertInstanceOf(null, null),
|
||||
assertThrows(null, null),
|
||||
assertThrowsExactly(null, null),
|
||||
offset(0.0),
|
||||
(Runnable) () -> assertArrayEquals((int[]) null, null),
|
||||
(Runnable) () -> assertFalse(true),
|
||||
(Runnable) () -> assertNotNull(null),
|
||||
(Runnable) () -> assertNotSame(null, null),
|
||||
@@ -35,6 +39,150 @@ final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
(Runnable) () -> assertTrue(true));
|
||||
}
|
||||
|
||||
void testAssertThatBooleanArrayContainsExactly() {
|
||||
assertThat(new boolean[] {false}).containsExactly(new boolean[] {true});
|
||||
}
|
||||
|
||||
void testAssertThatBooleanArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new boolean[] {false}).withFailMessage("foo").containsExactly(new boolean[] {true});
|
||||
}
|
||||
|
||||
void testAssertThatBooleanArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new boolean[] {false})
|
||||
.withFailMessage(() -> "foo")
|
||||
.containsExactly(new boolean[] {true});
|
||||
}
|
||||
|
||||
void testAssertThatByteArrayContainsExactly() {
|
||||
assertThat(new byte[] {2}).containsExactly(new byte[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatByteArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new byte[] {2}).withFailMessage("foo").containsExactly(new byte[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatByteArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new byte[] {2}).withFailMessage(() -> "foo").containsExactly(new byte[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatCharArrayContainsExactly() {
|
||||
assertThat(new char[] {'b'}).containsExactly(new char[] {'a'});
|
||||
}
|
||||
|
||||
void testAssertThatCharArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new char[] {'b'}).withFailMessage("foo").containsExactly(new char[] {'a'});
|
||||
}
|
||||
|
||||
void testAssertThatCharArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new char[] {'b'}).withFailMessage(() -> "foo").containsExactly(new char[] {'a'});
|
||||
}
|
||||
|
||||
void testAssertThatShortArrayContainsExactly() {
|
||||
assertThat(new short[] {2}).containsExactly(new short[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatShortArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new short[] {2}).withFailMessage("foo").containsExactly(new short[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatShortArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new short[] {2}).withFailMessage(() -> "foo").containsExactly(new short[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatIntArrayContainsExactly() {
|
||||
assertThat(new int[] {2}).containsExactly(new int[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatIntArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new int[] {2}).withFailMessage("foo").containsExactly(new int[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatIntArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new int[] {2}).withFailMessage(() -> "foo").containsExactly(new int[] {1});
|
||||
}
|
||||
|
||||
void testAssertThatLongArrayContainsExactly() {
|
||||
assertThat(new long[] {2L}).containsExactly(new long[] {1L});
|
||||
}
|
||||
|
||||
void testAssertThatLongArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new long[] {2L}).withFailMessage("foo").containsExactly(new long[] {1L});
|
||||
}
|
||||
|
||||
void testAssertThatLongArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new long[] {2L}).withFailMessage(() -> "foo").containsExactly(new long[] {1L});
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayContainsExactly() {
|
||||
assertThat(new float[] {2.0F}).containsExactly(new float[] {1.0F});
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new float[] {2.0F}).withFailMessage("foo").containsExactly(new float[] {1.0F});
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new float[] {2.0F}).withFailMessage(() -> "foo").containsExactly(new float[] {1.0F});
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayContainsExactlyWithOffset() {
|
||||
assertThat(new float[] {2.0F}).containsExactly(new float[] {1.0F}, offset(0.1f));
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayWithFailMessageContainsExactlyWithOffset() {
|
||||
assertThat(new float[] {2.0F})
|
||||
.withFailMessage("foo")
|
||||
.containsExactly(new float[] {1.0F}, offset(0.1f));
|
||||
}
|
||||
|
||||
void testAssertThatFloatArrayWithFailMessageSupplierContainsExactlyWithOffset() {
|
||||
assertThat(new float[] {2.0F})
|
||||
.withFailMessage(() -> "foo")
|
||||
.containsExactly(new float[] {1.0F}, offset(0.1f));
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayContainsExactly() {
|
||||
assertThat(new double[] {2.0}).containsExactly(new double[] {1.0});
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new double[] {2.0}).withFailMessage("foo").containsExactly(new double[] {1.0});
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new double[] {2.0}).withFailMessage(() -> "foo").containsExactly(new double[] {1.0});
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayContainsExactlyWithOffset() {
|
||||
assertThat(new double[] {2.0}).containsExactly(new double[] {1.0}, offset(0.1));
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayWithFailMessageContainsExactlyWithOffset() {
|
||||
assertThat(new double[] {2.0})
|
||||
.withFailMessage("foo")
|
||||
.containsExactly(new double[] {1.0}, offset(0.1));
|
||||
}
|
||||
|
||||
void testAssertThatDoubleArrayWithFailMessageSupplierContainsExactlyWithOffset() {
|
||||
assertThat(new double[] {2.0})
|
||||
.withFailMessage(() -> "foo")
|
||||
.containsExactly(new double[] {1.0}, offset(0.1));
|
||||
}
|
||||
|
||||
void testAssertThatObjectArrayContainsExactly() {
|
||||
assertThat(new Object[] {"bar"}).containsExactly(new Object[] {"foo"});
|
||||
}
|
||||
|
||||
void testAssertThatObjectArrayWithFailMessageContainsExactly() {
|
||||
assertThat(new Object[] {"bar"}).withFailMessage("foo").containsExactly(new Object[] {"foo"});
|
||||
}
|
||||
|
||||
void testAssertThatObjectArrayWithFailMessageSupplierContainsExactly() {
|
||||
assertThat(new Object[] {"bar"})
|
||||
.withFailMessage(() -> "foo")
|
||||
.containsExactly(new Object[] {"foo"});
|
||||
}
|
||||
|
||||
Object testFail() {
|
||||
return org.assertj.core.api.Assertions.fail();
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.function.Predicate;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class NullRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(MoreObjects.class, Optional.class);
|
||||
return ImmutableSet.of(MoreObjects.class, Optional.class, not(null));
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testIsNull() {
|
||||
@@ -30,11 +32,11 @@ final class NullRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Optional.ofNullable("foo").orElseGet(() -> "bar");
|
||||
}
|
||||
|
||||
long testIsNullFunction() {
|
||||
return Stream.of("foo").filter(s -> s == null).count();
|
||||
ImmutableSet<Predicate<String>> testIsNullFunction() {
|
||||
return ImmutableSet.of(s -> s == null, not(Objects::nonNull));
|
||||
}
|
||||
|
||||
long testNonNullFunction() {
|
||||
return Stream.of("foo").filter(s -> s != null).count();
|
||||
ImmutableSet<Predicate<String>> testNonNullFunction() {
|
||||
return ImmutableSet.of(s -> s != null, not(Objects::isNull));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,19 @@ package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
import static java.util.Objects.requireNonNullElseGet;
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.function.Predicate;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class NullRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(MoreObjects.class, Optional.class);
|
||||
return ImmutableSet.of(MoreObjects.class, Optional.class, not(null));
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testIsNull() {
|
||||
@@ -32,11 +33,11 @@ final class NullRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return requireNonNullElseGet("foo", () -> "bar");
|
||||
}
|
||||
|
||||
long testIsNullFunction() {
|
||||
return Stream.of("foo").filter(Objects::isNull).count();
|
||||
ImmutableSet<Predicate<String>> testIsNullFunction() {
|
||||
return ImmutableSet.of(Objects::isNull, Objects::isNull);
|
||||
}
|
||||
|
||||
long testNonNullFunction() {
|
||||
return Stream.of("foo").filter(Objects::nonNull).count();
|
||||
ImmutableSet<Predicate<String>> testNonNullFunction() {
|
||||
return ImmutableSet.of(Objects::nonNull, Objects::nonNull);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import com.google.common.primitives.Floats;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.google.common.primitives.Shorts;
|
||||
import com.google.common.primitives.UnsignedBytes;
|
||||
import com.google.common.primitives.UnsignedInts;
|
||||
import com.google.common.primitives.UnsignedLongs;
|
||||
import java.util.Comparator;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@@ -25,6 +27,7 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Ints.class,
|
||||
Longs.class,
|
||||
Shorts.class,
|
||||
UnsignedBytes.class,
|
||||
UnsignedInts.class,
|
||||
UnsignedLongs.class);
|
||||
}
|
||||
@@ -222,4 +225,16 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
|
||||
String testLongToUnsignedStringWithRadix() {
|
||||
return UnsignedLongs.toString(1, 2);
|
||||
}
|
||||
|
||||
Comparator<byte[]> testArraysCompareUnsignedBytes() {
|
||||
return UnsignedBytes.lexicographicalComparator();
|
||||
}
|
||||
|
||||
Comparator<int[]> testArraysCompareUnsignedInts() {
|
||||
return UnsignedInts.lexicographicalComparator();
|
||||
}
|
||||
|
||||
Comparator<long[]> testArraysCompareUnsignedLongs() {
|
||||
return UnsignedLongs.lexicographicalComparator();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,11 @@ import com.google.common.primitives.Floats;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.common.primitives.Longs;
|
||||
import com.google.common.primitives.Shorts;
|
||||
import com.google.common.primitives.UnsignedBytes;
|
||||
import com.google.common.primitives.UnsignedInts;
|
||||
import com.google.common.primitives.UnsignedLongs;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
|
||||
final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@@ -25,6 +28,7 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Ints.class,
|
||||
Longs.class,
|
||||
Shorts.class,
|
||||
UnsignedBytes.class,
|
||||
UnsignedInts.class,
|
||||
UnsignedLongs.class);
|
||||
}
|
||||
@@ -222,4 +226,16 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
|
||||
String testLongToUnsignedStringWithRadix() {
|
||||
return Long.toUnsignedString(1, 2);
|
||||
}
|
||||
|
||||
Comparator<byte[]> testArraysCompareUnsignedBytes() {
|
||||
return Arrays::compareUnsigned;
|
||||
}
|
||||
|
||||
Comparator<int[]> testArraysCompareUnsignedInts() {
|
||||
return Arrays::compareUnsigned;
|
||||
}
|
||||
|
||||
Comparator<long[]> testArraysCompareUnsignedLongs() {
|
||||
return Arrays::compareUnsigned;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -187,7 +188,12 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Flux<Integer>> testFluxJust() {
|
||||
return ImmutableSet.of(Flux.range(0, 1), Mono.just(2).repeat().take(1));
|
||||
return ImmutableSet.of(
|
||||
Flux.range(0, 1),
|
||||
Mono.just(2).flux(),
|
||||
Mono.just(3).repeat().take(1),
|
||||
Flux.fromIterable(ImmutableList.of(4)),
|
||||
Flux.fromIterable(ImmutableSet.of(5)));
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<?>> testMonoIdentity() {
|
||||
@@ -325,6 +331,14 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Flux.just(1).switchMap(n -> Mono.fromSupplier(() -> n * 2)));
|
||||
}
|
||||
|
||||
Flux<String> testFluxMapNotNullTransformationOrElse() {
|
||||
return Flux.just(1).map(x -> Optional.of(x.toString())).mapNotNull(x -> x.orElse(null));
|
||||
}
|
||||
|
||||
Flux<Integer> testFluxMapNotNullOrElse() {
|
||||
return Flux.just(Optional.of(1)).filter(Optional::isPresent).map(Optional::orElseThrow);
|
||||
}
|
||||
|
||||
ImmutableSet<Flux<String>> testMonoFlux() {
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").flatMapMany(Mono::just),
|
||||
@@ -333,7 +347,11 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<Void>> testMonoThen() {
|
||||
return ImmutableSet.of(Mono.just("foo").ignoreElement().then(), Mono.just("bar").flux().then());
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").ignoreElement().then(),
|
||||
Mono.just("bar").flux().then(),
|
||||
Mono.when(Mono.just("baz")),
|
||||
Mono.whenDelayError(Mono.just("qux")));
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<Void>> testFluxThen() {
|
||||
@@ -379,8 +397,10 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
ImmutableSet<Mono<Optional<String>>> testMonoSingleOptional() {
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").flux().collect(toOptional()),
|
||||
Mono.just("bar").map(Optional::of).defaultIfEmpty(Optional.empty()),
|
||||
Mono.just("baz").transform(Mono::singleOptional));
|
||||
Mono.just("bar").map(Optional::of),
|
||||
Mono.just("baz").singleOptional().defaultIfEmpty(Optional.empty()),
|
||||
Mono.just("quux").singleOptional().switchIfEmpty(Mono.just(Optional.empty())),
|
||||
Mono.just("quuz").transform(Mono::singleOptional));
|
||||
}
|
||||
|
||||
Mono<Number> testMonoCast() {
|
||||
@@ -737,6 +757,11 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Mono.fromFuture(() -> ((AsyncLoadingCache<Integer, String>) null).get(0));
|
||||
}
|
||||
|
||||
Mono<Map<Integer, String>> testMonoFromFutureAsyncLoadingCacheGetAll() {
|
||||
return Mono.fromFuture(
|
||||
() -> ((AsyncLoadingCache<Integer, String>) null).getAll(ImmutableSet.of()));
|
||||
}
|
||||
|
||||
Flux<Integer> testFluxFromStreamSupplier() {
|
||||
return Flux.fromStream(Stream.of(1));
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -191,7 +192,7 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Flux<Integer>> testFluxJust() {
|
||||
return ImmutableSet.of(Flux.just(0), Flux.just(2));
|
||||
return ImmutableSet.of(Flux.just(0), Flux.just(2), Flux.just(3), Flux.just(4), Flux.just(5));
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<?>> testMonoIdentity() {
|
||||
@@ -325,13 +326,25 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Flux.just(1).mapNotNull(n -> n * 2));
|
||||
}
|
||||
|
||||
Flux<String> testFluxMapNotNullTransformationOrElse() {
|
||||
return Flux.just(1).mapNotNull(x -> Optional.of(x.toString()).orElse(null));
|
||||
}
|
||||
|
||||
Flux<Integer> testFluxMapNotNullOrElse() {
|
||||
return Flux.just(Optional.of(1)).mapNotNull(x -> x.orElse(null));
|
||||
}
|
||||
|
||||
ImmutableSet<Flux<String>> testMonoFlux() {
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").flux(), Mono.just("bar").flux(), Mono.just("baz").flux());
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<Void>> testMonoThen() {
|
||||
return ImmutableSet.of(Mono.just("foo").then(), Mono.just("bar").then());
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").then(),
|
||||
Mono.just("bar").then(),
|
||||
Mono.just("baz").then(),
|
||||
Mono.just("qux").then());
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<Void>> testFluxThen() {
|
||||
@@ -375,7 +388,9 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").singleOptional(),
|
||||
Mono.just("bar").singleOptional(),
|
||||
Mono.just("baz").singleOptional());
|
||||
Mono.just("baz").singleOptional(),
|
||||
Mono.just("quux").singleOptional(),
|
||||
Mono.just("quuz").singleOptional());
|
||||
}
|
||||
|
||||
Mono<Number> testMonoCast() {
|
||||
@@ -711,6 +726,11 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Mono.fromFuture(() -> ((AsyncLoadingCache<Integer, String>) null).get(0), true);
|
||||
}
|
||||
|
||||
Mono<Map<Integer, String>> testMonoFromFutureAsyncLoadingCacheGetAll() {
|
||||
return Mono.fromFuture(
|
||||
() -> ((AsyncLoadingCache<Integer, String>) null).getAll(ImmutableSet.of()), true);
|
||||
}
|
||||
|
||||
Flux<Integer> testFluxFromStreamSupplier() {
|
||||
return Flux.fromStream(() -> Stream.of(1));
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
"foo".length() == 0,
|
||||
"bar".length() <= 0,
|
||||
"baz".length() < 1,
|
||||
"foo".length() != 0,
|
||||
"bar".length() > 0,
|
||||
"baz".length() >= 1);
|
||||
"qux".length() != 0,
|
||||
"quux".length() > 0,
|
||||
"corge".length() >= 1);
|
||||
}
|
||||
|
||||
boolean testStringIsEmptyPredicate() {
|
||||
|
||||
@@ -31,9 +31,9 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
"foo".isEmpty(),
|
||||
"bar".isEmpty(),
|
||||
"baz".isEmpty(),
|
||||
!"foo".isEmpty(),
|
||||
!"bar".isEmpty(),
|
||||
!"baz".isEmpty());
|
||||
!"qux".isEmpty(),
|
||||
!"quux".isEmpty(),
|
||||
!"corge".isEmpty());
|
||||
}
|
||||
|
||||
boolean testStringIsEmptyPredicate() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
@@ -23,7 +24,9 @@ final class SuggestedFixRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
SuggestedFix testSuggestedFixSwap() {
|
||||
return SuggestedFix.builder().swap((Tree) null, (ExpressionTree) null).build();
|
||||
return SuggestedFix.builder()
|
||||
.swap((Tree) null, (ExpressionTree) null, (VisitorState) null)
|
||||
.build();
|
||||
}
|
||||
|
||||
SuggestedFix testSuggestedFixPrefixWith() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
@@ -23,7 +24,7 @@ final class SuggestedFixRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
SuggestedFix testSuggestedFixSwap() {
|
||||
return SuggestedFix.swap((Tree) null, (ExpressionTree) null);
|
||||
return SuggestedFix.swap((Tree) null, (ExpressionTree) null, (VisitorState) null);
|
||||
}
|
||||
|
||||
SuggestedFix testSuggestedFixPrefixWith() {
|
||||
|
||||
@@ -96,31 +96,79 @@ final class TestNGToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
void testAssertEqual() {
|
||||
assertEquals(true, true);
|
||||
assertEquals((byte) 0, (byte) 0);
|
||||
assertEquals((char) 0, (char) 0);
|
||||
assertEquals((short) 0, (short) 0);
|
||||
assertEquals(0, 0);
|
||||
assertEquals(0L, 0L);
|
||||
assertEquals(0.0F, 0.0F);
|
||||
assertEquals(0.0, 0.0);
|
||||
assertEquals(new Object(), new Object());
|
||||
assertEquals(true, false);
|
||||
assertEquals(true, Boolean.FALSE);
|
||||
assertEquals(Boolean.TRUE, false);
|
||||
assertEquals(Boolean.TRUE, Boolean.FALSE);
|
||||
assertEquals((byte) 0, (byte) 1);
|
||||
assertEquals((byte) 0, Byte.decode("1"));
|
||||
assertEquals(Byte.decode("0"), (byte) 1);
|
||||
assertEquals(Byte.decode("0"), Byte.decode("1"));
|
||||
assertEquals('a', 'b');
|
||||
assertEquals('a', Character.valueOf('b'));
|
||||
assertEquals(Character.valueOf('a'), 'b');
|
||||
assertEquals(Character.valueOf('a'), Character.valueOf('b'));
|
||||
assertEquals((short) 0, (short) 1);
|
||||
assertEquals((short) 0, Short.decode("1"));
|
||||
assertEquals(Short.decode("0"), (short) 1);
|
||||
assertEquals(Short.decode("0"), Short.decode("1"));
|
||||
assertEquals(0, 1);
|
||||
assertEquals(0, Integer.valueOf(1));
|
||||
assertEquals(Integer.valueOf(0), 1);
|
||||
assertEquals(Integer.valueOf(0), Integer.valueOf(1));
|
||||
assertEquals(0L, 1L);
|
||||
assertEquals(0L, Long.valueOf(1));
|
||||
assertEquals(Long.valueOf(0), 1L);
|
||||
assertEquals(Long.valueOf(0), Long.valueOf(1));
|
||||
assertEquals(0.0F, 1.0F);
|
||||
assertEquals(0.0F, Float.valueOf(1.0F));
|
||||
assertEquals(Float.valueOf(0.0F), 1.0F);
|
||||
assertEquals(Float.valueOf(0.0F), Float.valueOf(1.0F));
|
||||
assertEquals(0.0, 1.0);
|
||||
assertEquals(0.0, Double.valueOf(1.0));
|
||||
assertEquals(Double.valueOf(0.0), 1.0);
|
||||
assertEquals(Double.valueOf(0.0), Double.valueOf(1.0));
|
||||
assertEquals(new Object(), new StringBuilder());
|
||||
assertEquals("actual", "expected");
|
||||
assertEquals(ImmutableMap.of(), ImmutableMap.of());
|
||||
assertEquals(ImmutableMap.of(), ImmutableMap.of(1, 2));
|
||||
}
|
||||
|
||||
void testAssertEqualWithMessage() {
|
||||
assertEquals(true, true, "foo");
|
||||
assertEquals((byte) 0, (byte) 0, "bar");
|
||||
assertEquals((char) 0, (char) 0, "baz");
|
||||
assertEquals((short) 0, (short) 0, "qux");
|
||||
assertEquals(0, 0, "quux");
|
||||
assertEquals(0L, 0L, "quuz");
|
||||
assertEquals(0.0F, 0.0F, "corge");
|
||||
assertEquals(0.0, 0.0, "grault");
|
||||
assertEquals(new Object(), new Object(), "garply");
|
||||
assertEquals("actual", "expected", "waldo");
|
||||
assertEquals(ImmutableMap.of(), ImmutableMap.of(), "plugh");
|
||||
assertEquals(true, false, "foo");
|
||||
assertEquals(true, Boolean.FALSE, "bar");
|
||||
assertEquals(Boolean.TRUE, false, "baz");
|
||||
assertEquals(Boolean.TRUE, Boolean.FALSE, "qux");
|
||||
assertEquals((byte) 0, (byte) 1, "quux");
|
||||
assertEquals((byte) 0, Byte.decode("1"), "corge");
|
||||
assertEquals(Byte.decode("0"), (byte) 1, "grault");
|
||||
assertEquals(Byte.decode("0"), Byte.decode("1"), "garply");
|
||||
assertEquals('a', 'b', "waldo");
|
||||
assertEquals('a', Character.valueOf('b'), "fred");
|
||||
assertEquals(Character.valueOf('a'), 'b', "plugh");
|
||||
assertEquals(Character.valueOf('a'), Character.valueOf('b'), "xyzzy");
|
||||
assertEquals((short) 0, (short) 1, "thud");
|
||||
assertEquals((short) 0, Short.decode("1"), "foo");
|
||||
assertEquals(Short.decode("0"), (short) 1, "bar");
|
||||
assertEquals(Short.decode("0"), Short.decode("1"), "baz");
|
||||
assertEquals(0, 1, "qux");
|
||||
assertEquals(0, Integer.valueOf(1), "quux");
|
||||
assertEquals(Integer.valueOf(0), 1, "corge");
|
||||
assertEquals(Integer.valueOf(0), Integer.valueOf(1), "grault");
|
||||
assertEquals(0L, 1L, "garply");
|
||||
assertEquals(0L, Long.valueOf(1), "waldo");
|
||||
assertEquals(Long.valueOf(0), 1L, "fred");
|
||||
assertEquals(Long.valueOf(0), Long.valueOf(1), "plugh");
|
||||
assertEquals(0.0F, 1.0F, "xyzzy");
|
||||
assertEquals(0.0F, Float.valueOf(1.0F), "thud");
|
||||
assertEquals(Float.valueOf(0.0F), 1.0F, "foo");
|
||||
assertEquals(Float.valueOf(0.0F), Float.valueOf(1.0F), "bar");
|
||||
assertEquals(0.0, 1.0, "baz");
|
||||
assertEquals(0.0, Double.valueOf(1.0), "qux");
|
||||
assertEquals(Double.valueOf(0.0), 1.0, "quux");
|
||||
assertEquals(Double.valueOf(0.0), Double.valueOf(1.0), "corge");
|
||||
assertEquals(new Object(), new StringBuilder(), "grault");
|
||||
assertEquals("actual", "expected", "garply");
|
||||
assertEquals(ImmutableMap.of(), ImmutableMap.of(1, 2), "waldo");
|
||||
}
|
||||
|
||||
void testAssertEqualFloatsWithDelta() {
|
||||
@@ -163,6 +211,22 @@ final class TestNGToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
assertEquals(new Object[0], new Object[0], "garply");
|
||||
}
|
||||
|
||||
void testAssertEqualFloatArraysWithDelta() {
|
||||
assertEquals(new float[0], new float[0], 0.0F);
|
||||
}
|
||||
|
||||
void testAssertEqualFloatArraysWithDeltaWithMessage() {
|
||||
assertEquals(new float[0], new float[0], 0.0F, "foo");
|
||||
}
|
||||
|
||||
void testAssertEqualDoubleArraysWithDelta() {
|
||||
assertEquals(new double[0], new double[0], 0.0);
|
||||
}
|
||||
|
||||
void testAssertEqualDoubleArraysWithDeltaWithMessage() {
|
||||
assertEquals(new double[0], new double[0], 0.0, "foo");
|
||||
}
|
||||
|
||||
void testAssertEqualArraysIrrespectiveOfOrder() {
|
||||
assertEqualsNoOrder(new Object[0], new Object[0]);
|
||||
}
|
||||
|
||||
@@ -101,31 +101,79 @@ final class TestNGToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
void testAssertEqual() {
|
||||
assertThat(true).isEqualTo(true);
|
||||
assertThat((byte) 0).isEqualTo((byte) 0);
|
||||
assertThat((char) 0).isEqualTo((char) 0);
|
||||
assertThat((short) 0).isEqualTo((short) 0);
|
||||
assertThat(0).isEqualTo(0);
|
||||
assertThat(0L).isEqualTo(0L);
|
||||
assertThat(0.0F).isEqualTo(0.0F);
|
||||
assertThat(0.0).isEqualTo(0.0);
|
||||
assertThat(new Object()).isEqualTo(new Object());
|
||||
assertThat(true).isEqualTo(false);
|
||||
assertThat(true).isEqualTo(Boolean.FALSE);
|
||||
assertThat(Boolean.TRUE).isEqualTo(false);
|
||||
assertThat(Boolean.TRUE).isEqualTo(Boolean.FALSE);
|
||||
assertThat((byte) 0).isEqualTo((byte) 1);
|
||||
assertThat((byte) 0).isEqualTo(Byte.decode("1"));
|
||||
assertThat(Byte.decode("0")).isEqualTo((byte) 1);
|
||||
assertThat(Byte.decode("0")).isEqualTo(Byte.decode("1"));
|
||||
assertThat('a').isEqualTo('b');
|
||||
assertThat('a').isEqualTo(Character.valueOf('b'));
|
||||
assertThat(Character.valueOf('a')).isEqualTo('b');
|
||||
assertThat(Character.valueOf('a')).isEqualTo(Character.valueOf('b'));
|
||||
assertThat((short) 0).isEqualTo((short) 1);
|
||||
assertThat((short) 0).isEqualTo(Short.decode("1"));
|
||||
assertThat(Short.decode("0")).isEqualTo((short) 1);
|
||||
assertThat(Short.decode("0")).isEqualTo(Short.decode("1"));
|
||||
assertThat(0).isEqualTo(1);
|
||||
assertThat(0).isEqualTo(Integer.valueOf(1));
|
||||
assertThat(Integer.valueOf(0)).isEqualTo(1);
|
||||
assertThat(Integer.valueOf(0)).isEqualTo(Integer.valueOf(1));
|
||||
assertThat(0L).isEqualTo(1L);
|
||||
assertThat(0L).isEqualTo(Long.valueOf(1));
|
||||
assertThat(Long.valueOf(0)).isEqualTo(1L);
|
||||
assertThat(Long.valueOf(0)).isEqualTo(Long.valueOf(1));
|
||||
assertThat(0.0F).isEqualTo(1.0F);
|
||||
assertThat(0.0F).isEqualTo(Float.valueOf(1.0F));
|
||||
assertThat(Float.valueOf(0.0F)).isEqualTo(1.0F);
|
||||
assertThat(Float.valueOf(0.0F)).isEqualTo(Float.valueOf(1.0F));
|
||||
assertThat(0.0).isEqualTo(1.0);
|
||||
assertThat(0.0).isEqualTo(Double.valueOf(1.0));
|
||||
assertThat(Double.valueOf(0.0)).isEqualTo(1.0);
|
||||
assertThat(Double.valueOf(0.0)).isEqualTo(Double.valueOf(1.0));
|
||||
assertThat(new Object()).isEqualTo(new StringBuilder());
|
||||
assertThat("actual").isEqualTo("expected");
|
||||
assertThat(ImmutableMap.of()).isEqualTo(ImmutableMap.of());
|
||||
assertThat(ImmutableMap.of()).isEqualTo(ImmutableMap.of(1, 2));
|
||||
}
|
||||
|
||||
void testAssertEqualWithMessage() {
|
||||
assertThat(true).withFailMessage("foo").isEqualTo(true);
|
||||
assertThat((byte) 0).withFailMessage("bar").isEqualTo((byte) 0);
|
||||
assertThat((char) 0).withFailMessage("baz").isEqualTo((char) 0);
|
||||
assertThat((short) 0).withFailMessage("qux").isEqualTo((short) 0);
|
||||
assertThat(0).withFailMessage("quux").isEqualTo(0);
|
||||
assertThat(0L).withFailMessage("quuz").isEqualTo(0L);
|
||||
assertThat(0.0F).withFailMessage("corge").isEqualTo(0.0F);
|
||||
assertThat(0.0).withFailMessage("grault").isEqualTo(0.0);
|
||||
assertThat(new Object()).withFailMessage("garply").isEqualTo(new Object());
|
||||
assertThat("actual").withFailMessage("waldo").isEqualTo("expected");
|
||||
assertThat(ImmutableMap.of()).withFailMessage("plugh").isEqualTo(ImmutableMap.of());
|
||||
assertThat(true).withFailMessage("foo").isEqualTo(false);
|
||||
assertThat(true).withFailMessage("bar").isEqualTo(Boolean.FALSE);
|
||||
assertThat(Boolean.TRUE).withFailMessage("baz").isEqualTo(false);
|
||||
assertThat(Boolean.TRUE).withFailMessage("qux").isEqualTo(Boolean.FALSE);
|
||||
assertThat((byte) 0).withFailMessage("quux").isEqualTo((byte) 1);
|
||||
assertThat((byte) 0).withFailMessage("corge").isEqualTo(Byte.decode("1"));
|
||||
assertThat(Byte.decode("0")).withFailMessage("grault").isEqualTo((byte) 1);
|
||||
assertThat(Byte.decode("0")).withFailMessage("garply").isEqualTo(Byte.decode("1"));
|
||||
assertThat('a').withFailMessage("waldo").isEqualTo('b');
|
||||
assertThat('a').withFailMessage("fred").isEqualTo(Character.valueOf('b'));
|
||||
assertThat(Character.valueOf('a')).withFailMessage("plugh").isEqualTo('b');
|
||||
assertThat(Character.valueOf('a')).withFailMessage("xyzzy").isEqualTo(Character.valueOf('b'));
|
||||
assertThat((short) 0).withFailMessage("thud").isEqualTo((short) 1);
|
||||
assertThat((short) 0).withFailMessage("foo").isEqualTo(Short.decode("1"));
|
||||
assertThat(Short.decode("0")).withFailMessage("bar").isEqualTo((short) 1);
|
||||
assertThat(Short.decode("0")).withFailMessage("baz").isEqualTo(Short.decode("1"));
|
||||
assertThat(0).withFailMessage("qux").isEqualTo(1);
|
||||
assertThat(0).withFailMessage("quux").isEqualTo(Integer.valueOf(1));
|
||||
assertThat(Integer.valueOf(0)).withFailMessage("corge").isEqualTo(1);
|
||||
assertThat(Integer.valueOf(0)).withFailMessage("grault").isEqualTo(Integer.valueOf(1));
|
||||
assertThat(0L).withFailMessage("garply").isEqualTo(1L);
|
||||
assertThat(0L).withFailMessage("waldo").isEqualTo(Long.valueOf(1));
|
||||
assertThat(Long.valueOf(0)).withFailMessage("fred").isEqualTo(1L);
|
||||
assertThat(Long.valueOf(0)).withFailMessage("plugh").isEqualTo(Long.valueOf(1));
|
||||
assertThat(0.0F).withFailMessage("xyzzy").isEqualTo(1.0F);
|
||||
assertThat(0.0F).withFailMessage("thud").isEqualTo(Float.valueOf(1.0F));
|
||||
assertThat(Float.valueOf(0.0F)).withFailMessage("foo").isEqualTo(1.0F);
|
||||
assertThat(Float.valueOf(0.0F)).withFailMessage("bar").isEqualTo(Float.valueOf(1.0F));
|
||||
assertThat(0.0).withFailMessage("baz").isEqualTo(1.0);
|
||||
assertThat(0.0).withFailMessage("qux").isEqualTo(Double.valueOf(1.0));
|
||||
assertThat(Double.valueOf(0.0)).withFailMessage("quux").isEqualTo(1.0);
|
||||
assertThat(Double.valueOf(0.0)).withFailMessage("corge").isEqualTo(Double.valueOf(1.0));
|
||||
assertThat(new Object()).withFailMessage("grault").isEqualTo(new StringBuilder());
|
||||
assertThat("actual").withFailMessage("garply").isEqualTo("expected");
|
||||
assertThat(ImmutableMap.of()).withFailMessage("waldo").isEqualTo(ImmutableMap.of(1, 2));
|
||||
}
|
||||
|
||||
void testAssertEqualFloatsWithDelta() {
|
||||
@@ -168,6 +216,22 @@ final class TestNGToAssertJRulesTest implements RefasterRuleCollectionTestCase {
|
||||
assertThat(new Object[0]).withFailMessage("garply").containsExactly(new Object[0]);
|
||||
}
|
||||
|
||||
void testAssertEqualFloatArraysWithDelta() {
|
||||
assertThat(new float[0]).containsExactly(new float[0], offset(0.0F));
|
||||
}
|
||||
|
||||
void testAssertEqualFloatArraysWithDeltaWithMessage() {
|
||||
assertThat(new float[0]).withFailMessage("foo").containsExactly(new float[0], offset(0.0F));
|
||||
}
|
||||
|
||||
void testAssertEqualDoubleArraysWithDelta() {
|
||||
assertThat(new double[0]).containsExactly(new double[0], offset(0.0));
|
||||
}
|
||||
|
||||
void testAssertEqualDoubleArraysWithDeltaWithMessage() {
|
||||
assertThat(new double[0]).withFailMessage("foo").containsExactly(new double[0], offset(0.0));
|
||||
}
|
||||
|
||||
void testAssertEqualArraysIrrespectiveOfOrder() {
|
||||
assertThat(new Object[0]).containsExactlyInAnyOrder(new Object[0]);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.19.2-SNAPSHOT</version>
|
||||
<version>0.22.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-experimental</artifactId>
|
||||
@@ -15,26 +15,6 @@
|
||||
<url>https://error-prone.picnic.tech</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>error-prone-utils</artifactId>
|
||||
@@ -45,6 +25,26 @@
|
||||
<artifactId>auto-service-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.sun.source.tree.ReturnTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -126,7 +127,7 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Symbol sym = ASTHelpers.getSymbol(methodSelect);
|
||||
Symbol sym = ASTHelpers.getSymbol(subTree);
|
||||
return ASTHelpers.isStatic(sym)
|
||||
? constructFix(lambdaExpr, sym.owner, methodSelect)
|
||||
: constructFix(lambdaExpr, "this", methodSelect);
|
||||
@@ -200,7 +201,8 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
|
||||
Name sName = target.getSimpleName();
|
||||
Optional<SuggestedFix.Builder> fix = constructFix(lambdaExpr, sName, methodName);
|
||||
|
||||
if (!"java.lang".equals(ASTHelpers.enclosingPackage(target).toString())) {
|
||||
PackageSymbol pkg = ASTHelpers.enclosingPackage(target);
|
||||
if (pkg != null && !"java.lang".equals(pkg.toString())) {
|
||||
Name fqName = target.getQualifiedName();
|
||||
if (!sName.equals(fqName)) {
|
||||
return fix.map(b -> b.addImport(fqName.toString()));
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.19.2-SNAPSHOT</version>
|
||||
<version>0.22.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-guidelines</artifactId>
|
||||
@@ -15,31 +15,6 @@
|
||||
<url>https://error-prone.picnic.tech</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>documentation-support</artifactId>
|
||||
@@ -68,6 +43,31 @@
|
||||
<artifactId>auto-service-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.googlejavaformat</groupId>
|
||||
<artifactId>google-java-format</artifactId>
|
||||
|
||||
@@ -46,7 +46,6 @@ import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
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;
|
||||
|
||||
@@ -102,7 +101,8 @@ public final class ExhaustiveRefasterTypeMigration extends BugChecker implements
|
||||
AnnotationTree migrationAnnotation = migrationAnnotations.onlyMatchingNode();
|
||||
AnnotationMirror annotationMirror = ASTHelpers.getAnnotationMirror(migrationAnnotation);
|
||||
TypeSymbol migratedType = getMigratedType(annotationMirror);
|
||||
if (migratedType.asType().isPrimitive() || !(migratedType instanceof ClassSymbol)) {
|
||||
if (migratedType.asType().isPrimitive()
|
||||
|| !(migratedType instanceof ClassSymbol migratedClass)) {
|
||||
return buildDescription(migrationAnnotation)
|
||||
.setMessage(String.format("Migration of type '%s' is unsupported", migratedType))
|
||||
.build();
|
||||
@@ -111,7 +111,7 @@ public final class ExhaustiveRefasterTypeMigration extends BugChecker implements
|
||||
ImmutableList<String> methodsClaimedUnmigrated = getMethodsClaimedUnmigrated(annotationMirror);
|
||||
ImmutableList<String> unmigratedMethods =
|
||||
getMethodsDefinitelyUnmigrated(
|
||||
tree, (ClassSymbol) migratedType, signatureOrder(methodsClaimedUnmigrated), state);
|
||||
tree, migratedClass, signatureOrder(methodsClaimedUnmigrated), state);
|
||||
|
||||
if (unmigratedMethods.equals(methodsClaimedUnmigrated)) {
|
||||
return Description.NO_MATCH;
|
||||
@@ -160,17 +160,11 @@ public final class ExhaustiveRefasterTypeMigration extends BugChecker implements
|
||||
.getValue().stream().map(a -> a.getValue().toString()).collect(toImmutableList());
|
||||
}
|
||||
|
||||
// XXX: Once only JDK 14 and above are supported, change the
|
||||
// `m.getModifiers().contains(Modifier.PUBLIC)` check to just `m.isPublic()`.
|
||||
private static ImmutableList<String> getMethodsDefinitelyUnmigrated(
|
||||
ClassTree tree, ClassSymbol migratedType, Comparator<String> comparator, VisitorState state) {
|
||||
Set<MethodSymbol> publicMethods =
|
||||
Streams.stream(
|
||||
ASTHelpers.scope(migratedType.members())
|
||||
.getSymbols(
|
||||
m ->
|
||||
m.getModifiers().contains(Modifier.PUBLIC)
|
||||
&& m instanceof MethodSymbol))
|
||||
migratedType.members().getSymbols(m -> m.isPublic() && m instanceof MethodSymbol))
|
||||
.map(MethodSymbol.class::cast)
|
||||
.collect(toCollection(HashSet::new));
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.19.2-SNAPSHOT</version>
|
||||
<version>0.22.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-utils</artifactId>
|
||||
@@ -16,22 +16,22 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${groupId.error-prone}</groupId>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package tech.picnic.errorprone.utils;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -115,9 +117,15 @@ public final class AnnotationAttributeMatcher implements Serializable {
|
||||
}
|
||||
|
||||
private static String extractAttributeName(ExpressionTree expr) {
|
||||
return (expr instanceof AssignmentTree assignment)
|
||||
? ASTHelpers.getSymbol(assignment.getVariable()).getSimpleName().toString()
|
||||
: "value";
|
||||
if (!(expr instanceof AssignmentTree assignment)) {
|
||||
return "value";
|
||||
}
|
||||
|
||||
return requireNonNull(
|
||||
ASTHelpers.getSymbol(assignment.getVariable()),
|
||||
"Missing symbol for annotation attribute")
|
||||
.getSimpleName()
|
||||
.toString();
|
||||
}
|
||||
|
||||
// XXX: The caller of this method can be implemented more efficiently in case of a "wholeTypes"
|
||||
|
||||
@@ -63,9 +63,11 @@ public final class SourceCode {
|
||||
* 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
|
||||
* that it does not superfluously escape single quote characters (the latter only does the
|
||||
* "clean thing" starting from JDK 23). It is different from {@link
|
||||
* VisitorState#getConstantExpression(Object)} in that it is more performant and accepts any
|
||||
* {@link CharSequence} instance.
|
||||
* @see <a href="https://bugs.openjdk.org/browse/JDK-8325078">JDK-8325078</a>
|
||||
*/
|
||||
// XXX: Drop this method if https://github.com/google/error-prone/pull/4586 is merged and released
|
||||
// with the proposed `CharSequence` compatibility change.
|
||||
|
||||
@@ -303,14 +303,7 @@ final class SourceCodeTest {
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@@ -14875,7 +14875,7 @@
|
||||
final String defaultValue = getDefaultValue(propertyName, field, instance);
|
||||
--- a/src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java
|
||||
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/site/SiteUtil.java
|
||||
@@ -19,6 +19,14 @@
|
||||
@@ -19,6 +19,15 @@
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.site;
|
||||
|
||||
@@ -14886,11 +14886,12 @@
|
||||
+
|
||||
+import com.google.common.base.Strings;
|
||||
+import com.google.common.collect.ImmutableList;
|
||||
+import com.google.common.collect.ImmutableMap;
|
||||
+import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.puppycrawl.tools.checkstyle.Checker;
|
||||
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
|
||||
@@ -55,7 +63,6 @@ import java.net.URI;
|
||||
@@ -55,7 +64,6 @@ import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -14898,7 +14899,7 @@
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -72,7 +79,6 @@ import java.util.Optional;
|
||||
@@ -72,7 +80,6 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -14906,7 +14907,31 @@
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -156,7 +162,7 @@ public final class SiteUtil {
|
||||
@@ -131,12 +138,17 @@ public final class SiteUtil {
|
||||
|
||||
/** Class name and their corresponding parent module name. */
|
||||
private static final Map<Class<?>, String> CLASS_TO_PARENT_MODULE =
|
||||
- Map.ofEntries(
|
||||
- Map.entry(AbstractCheck.class, TreeWalker.class.getSimpleName()),
|
||||
- Map.entry(TreeWalkerFilter.class, TreeWalker.class.getSimpleName()),
|
||||
- Map.entry(AbstractFileSetCheck.class, Checker.class.getSimpleName()),
|
||||
- Map.entry(Filter.class, Checker.class.getSimpleName()),
|
||||
- Map.entry(BeforeExecutionFileFilter.class, Checker.class.getSimpleName()));
|
||||
+ ImmutableMap.of(
|
||||
+ AbstractCheck.class,
|
||||
+ TreeWalker.class.getSimpleName(),
|
||||
+ TreeWalkerFilter.class,
|
||||
+ TreeWalker.class.getSimpleName(),
|
||||
+ AbstractFileSetCheck.class,
|
||||
+ Checker.class.getSimpleName(),
|
||||
+ Filter.class,
|
||||
+ Checker.class.getSimpleName(),
|
||||
+ BeforeExecutionFileFilter.class,
|
||||
+ Checker.class.getSimpleName());
|
||||
|
||||
/** Set of properties that every check has. */
|
||||
private static final Set<String> CHECK_PROPERTIES = getProperties(AbstractCheck.class);
|
||||
@@ -156,7 +168,7 @@ public final class SiteUtil {
|
||||
|
||||
/** Set of properties that are undocumented. Those are internal properties. */
|
||||
private static final Set<String> UNDOCUMENTED_PROPERTIES =
|
||||
@@ -14915,7 +14940,7 @@
|
||||
"SuppressWithNearbyCommentFilter.fileContents", "SuppressionCommentFilter.fileContents");
|
||||
|
||||
/** Properties that can not be gathered from class instance. */
|
||||
@@ -294,27 +300,25 @@ public final class SiteUtil {
|
||||
@@ -294,27 +306,25 @@ public final class SiteUtil {
|
||||
|
||||
/** Path to main source code folder. */
|
||||
private static final String MAIN_FOLDER_PATH =
|
||||
@@ -14932,16 +14957,16 @@
|
||||
+ new File(Path.of(MAIN_FOLDER_PATH, CHECKS, NAMING, "AbstractNameCheck.java").toString()),
|
||||
new File(
|
||||
- Paths.get(MAIN_FOLDER_PATH, CHECKS, NAMING, "AbstractNameCheck.java").toString()),
|
||||
- new File(
|
||||
- Paths.get(MAIN_FOLDER_PATH, CHECKS, "javadoc", "AbstractJavadocCheck.java")
|
||||
- .toString()),
|
||||
- new File(Paths.get(MAIN_FOLDER_PATH, "api", "AbstractFileSetCheck.java").toString()),
|
||||
+ Path.of(MAIN_FOLDER_PATH, CHECKS, "javadoc", "AbstractJavadocCheck.java").toString()),
|
||||
+ new File(Path.of(MAIN_FOLDER_PATH, "api", "AbstractFileSetCheck.java").toString()),
|
||||
new File(
|
||||
- Paths.get(MAIN_FOLDER_PATH, CHECKS, "header", "AbstractHeaderCheck.java").toString()),
|
||||
- Paths.get(MAIN_FOLDER_PATH, CHECKS, "javadoc", "AbstractJavadocCheck.java")
|
||||
- .toString()),
|
||||
- new File(Paths.get(MAIN_FOLDER_PATH, "api", "AbstractFileSetCheck.java").toString()),
|
||||
+ Path.of(MAIN_FOLDER_PATH, CHECKS, "header", "AbstractHeaderCheck.java").toString()),
|
||||
new File(
|
||||
- Paths.get(MAIN_FOLDER_PATH, CHECKS, "header", "AbstractHeaderCheck.java").toString()),
|
||||
- new File(
|
||||
- Paths.get(MAIN_FOLDER_PATH, CHECKS, "metrics", "AbstractClassCouplingCheck.java")
|
||||
+ Path.of(MAIN_FOLDER_PATH, CHECKS, "metrics", "AbstractClassCouplingCheck.java")
|
||||
.toString()),
|
||||
@@ -14951,7 +14976,7 @@
|
||||
.toString()));
|
||||
|
||||
/** Private utility constructor. */
|
||||
@@ -475,7 +479,7 @@ public final class SiteUtil {
|
||||
@@ -475,7 +485,7 @@ public final class SiteUtil {
|
||||
* @throws MacroExecutionException if an I/O error occurs.
|
||||
*/
|
||||
public static Set<Path> getXdocsTemplatesFilePaths() throws MacroExecutionException {
|
||||
@@ -14960,7 +14985,7 @@
|
||||
try (Stream<Path> stream =
|
||||
Files.find(
|
||||
directory,
|
||||
@@ -483,7 +487,7 @@ public final class SiteUtil {
|
||||
@@ -483,7 +493,7 @@ public final class SiteUtil {
|
||||
(path, attr) -> {
|
||||
return attr.isRegularFile() && path.toString().endsWith(".xml.template");
|
||||
})) {
|
||||
@@ -14969,7 +14994,7 @@
|
||||
} catch (IOException ioException) {
|
||||
throw new MacroExecutionException("Failed to find xdocs templates", ioException);
|
||||
}
|
||||
@@ -510,7 +514,7 @@ public final class SiteUtil {
|
||||
@@ -510,7 +520,7 @@ public final class SiteUtil {
|
||||
}
|
||||
|
||||
// If parent class is not found, check interfaces
|
||||
@@ -14978,7 +15003,7 @@
|
||||
final Class<?>[] interfaces = moduleClass.getInterfaces();
|
||||
for (Class<?> interfaceClass : interfaces) {
|
||||
parentModuleName = CLASS_TO_PARENT_MODULE.get(interfaceClass);
|
||||
@@ -520,7 +524,7 @@ public final class SiteUtil {
|
||||
@@ -520,7 +530,7 @@ public final class SiteUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14987,7 +15012,7 @@
|
||||
final String message =
|
||||
String.format(
|
||||
Locale.ROOT, "Failed to find parent module for %s", moduleClass.getSimpleName());
|
||||
@@ -544,7 +548,7 @@ public final class SiteUtil {
|
||||
@@ -544,7 +554,7 @@ public final class SiteUtil {
|
||||
prop -> {
|
||||
return !isGlobalProperty(clss, prop) && !isUndocumentedProperty(clss, prop);
|
||||
})
|
||||
@@ -14996,7 +15021,7 @@
|
||||
properties.addAll(getNonExplicitProperties(instance, clss));
|
||||
return new TreeSet<>(properties);
|
||||
}
|
||||
@@ -663,7 +667,7 @@ public final class SiteUtil {
|
||||
@@ -663,7 +673,7 @@ public final class SiteUtil {
|
||||
treeWalkerConfig.addChild(scraperCheckConfig);
|
||||
try {
|
||||
checker.configure(defaultConfiguration);
|
||||
@@ -15005,7 +15030,7 @@
|
||||
checker.process(filesToProcess);
|
||||
checker.destroy();
|
||||
} catch (CheckstyleException checkstyleException) {
|
||||
@@ -986,9 +990,7 @@ public final class SiteUtil {
|
||||
@@ -986,9 +996,7 @@ public final class SiteUtil {
|
||||
if (value != null && Array.getLength(value) > 0) {
|
||||
result =
|
||||
removeSquareBrackets(
|
||||
@@ -15016,7 +15041,7 @@
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
@@ -1020,8 +1022,7 @@ public final class SiteUtil {
|
||||
@@ -1020,8 +1028,7 @@ public final class SiteUtil {
|
||||
result = "";
|
||||
} else {
|
||||
try (Stream<?> valuesStream = getValuesStream(value)) {
|
||||
@@ -15026,7 +15051,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1062,10 +1063,7 @@ public final class SiteUtil {
|
||||
@@ -1062,10 +1069,7 @@ public final class SiteUtil {
|
||||
private static String getIntArrayPropertyValue(Object value) {
|
||||
try (IntStream stream = getIntStream(value)) {
|
||||
String result =
|
||||
@@ -15038,7 +15063,7 @@
|
||||
if (result.isEmpty()) {
|
||||
result = CURLY_BRACKETS;
|
||||
}
|
||||
@@ -1170,11 +1168,11 @@ public final class SiteUtil {
|
||||
@@ -1170,11 +1174,11 @@ public final class SiteUtil {
|
||||
*/
|
||||
public static List<Integer> getDifference(int[] tokens, int... subtractions) {
|
||||
final Set<Integer> subtractionsSet =
|
||||
@@ -15052,7 +15077,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1221,7 +1219,7 @@ public final class SiteUtil {
|
||||
@@ -1221,7 +1225,7 @@ public final class SiteUtil {
|
||||
throw new MacroExecutionException("Failed to get parent path for " + templatePath);
|
||||
}
|
||||
return templatePathParent
|
||||
@@ -15377,7 +15402,7 @@
|
||||
- if (name == null) {
|
||||
- throw new IllegalArgumentException(String.format(Locale.ROOT, TOKEN_ID_EXCEPTION_FORMAT, id));
|
||||
- }
|
||||
+ checkArgument(name != null, String.format(Locale.ROOT, TOKEN_ID_EXCEPTION_FORMAT, id));
|
||||
+ checkArgument(name != null, TOKEN_ID_EXCEPTION_FORMAT, id);
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -15389,11 +15414,11 @@
|
||||
- throw new IllegalArgumentException(
|
||||
- String.format(Locale.ROOT, TOKEN_NAME_EXCEPTION_FORMAT, name));
|
||||
- }
|
||||
+ checkArgument(id != null, String.format(Locale.ROOT, TOKEN_NAME_EXCEPTION_FORMAT, name));
|
||||
+ checkArgument(id != null, TOKEN_NAME_EXCEPTION_FORMAT, name);
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -165,10 +163,9 @@ public final class TokenUtil {
|
||||
@@ -165,10 +163,7 @@ public final class TokenUtil {
|
||||
* @throws IllegalArgumentException when name is unknown
|
||||
*/
|
||||
public static String getShortDescription(String name) {
|
||||
@@ -15401,13 +15426,11 @@
|
||||
- throw new IllegalArgumentException(
|
||||
- String.format(Locale.ROOT, TOKEN_NAME_EXCEPTION_FORMAT, name));
|
||||
- }
|
||||
+ checkArgument(
|
||||
+ TOKEN_NAME_TO_VALUE.containsKey(name),
|
||||
+ String.format(Locale.ROOT, TOKEN_NAME_EXCEPTION_FORMAT, name));
|
||||
+ checkArgument(TOKEN_NAME_TO_VALUE.containsKey(name), TOKEN_NAME_EXCEPTION_FORMAT, name);
|
||||
|
||||
final String tokenTypes = "com.puppycrawl.tools.checkstyle.api.tokentypes";
|
||||
final ResourceBundle bundle = ResourceBundle.getBundle(tokenTypes, Locale.ROOT);
|
||||
@@ -344,7 +341,7 @@ public final class TokenUtil {
|
||||
@@ -344,7 +339,7 @@ public final class TokenUtil {
|
||||
public static BitSet asBitSet(String... tokens) {
|
||||
return Arrays.stream(tokens)
|
||||
.map(String::trim)
|
||||
@@ -15418,12 +15441,13 @@
|
||||
}
|
||||
--- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/UnmodifiableCollectionUtil.java
|
||||
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/UnmodifiableCollectionUtil.java
|
||||
@@ -19,13 +19,15 @@
|
||||
@@ -19,13 +19,16 @@
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.utils;
|
||||
|
||||
+import static java.util.stream.Collectors.toUnmodifiableList;
|
||||
+
|
||||
+import com.google.common.collect.ImmutableMap;
|
||||
+import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -15435,7 +15459,7 @@
|
||||
|
||||
/**
|
||||
* <div>Note: it simply wraps the existing JDK methods to provide a workaround for Pitest survival
|
||||
@@ -57,7 +59,7 @@ public final class UnmodifiableCollectionUtil {
|
||||
@@ -57,7 +60,7 @@ public final class UnmodifiableCollectionUtil {
|
||||
* @return An unmodifiable List containing elements of the specified type.
|
||||
*/
|
||||
public static <S, T> List<T> unmodifiableList(Collection<S> items, Class<T> elementType) {
|
||||
@@ -15444,7 +15468,16 @@
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,6 +94,6 @@ public final class UnmodifiableCollectionUtil {
|
||||
@@ -81,7 +84,7 @@ public final class UnmodifiableCollectionUtil {
|
||||
* @return an immutable copy of the input map
|
||||
*/
|
||||
public static <K, V> Map<K, V> copyOfMap(Map<? extends K, ? extends V> map) {
|
||||
- return Map.copyOf(map);
|
||||
+ return ImmutableMap.copyOf(map);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,6 +95,6 @@ public final class UnmodifiableCollectionUtil {
|
||||
* @return immutable set
|
||||
*/
|
||||
public static <T> Set<T> singleton(T obj) {
|
||||
@@ -56937,6 +56970,15 @@
|
||||
private static final Map<String, Class<?>> FULLY_QUALIFIED_CLASS_NAMES =
|
||||
ImmutableMap.<String, Class<?>>builder()
|
||||
.put("int", int.class)
|
||||
@@ -97,7 +96,7 @@ public class XdocsJavaDocsTest extends AbstractModuleTestSupport {
|
||||
.put("URI", URI.class)
|
||||
.put("WrapOption", WrapOption.class)
|
||||
.put("PARAM_LITERAL", int[].class)
|
||||
- .build();
|
||||
+ .buildOrThrow();
|
||||
|
||||
private static final List<List<Node>> CHECK_PROPERTIES = new ArrayList<>();
|
||||
private static final Map<String, String> CHECK_PROPERTY_DOC = new HashMap<>();
|
||||
@@ -115,14 +114,14 @@ public class XdocsJavaDocsTest extends AbstractModuleTestSupport {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
src/it/java/com/google/checkstyle/test/base/AbstractIndentationTestSupport.java:[100,21] [EagerStringFormatting] String formatting can be deferred (assuming that Guava's simplified formatting support suffices)
|
||||
src/it/java/com/google/checkstyle/test/base/AbstractIndentationTestSupport.java:[85,21] [EagerStringFormatting] String formatting can be deferred (assuming that Guava's simplified formatting support suffices)
|
||||
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:[116,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
@@ -105,6 +107,8 @@ src/test/java/com/puppycrawl/tools/checkstyle/checks/design/InterfaceIsTypeCheck
|
||||
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/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/indentation/IndentationCheckTest.java:[69,21] [EagerStringFormatting] String formatting can be deferred (assuming that Guava's simplified formatting support suffices)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java:[80,21] [EagerStringFormatting] String formatting can be deferred (assuming that Guava's simplified formatting support suffices)
|
||||
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)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocContentLocationCheckTest.java:[75,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `package` is not a valid identifier)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user