mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-21 00:01:20 +00:00
Compare commits
85 Commits
solutions-
...
sschroever
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51dc075f1c | ||
|
|
7daa39a0b5 | ||
|
|
5fc7bc29ee | ||
|
|
83f3f8bedc | ||
|
|
12585a8969 | ||
|
|
72b701cae3 | ||
|
|
24e3251eb0 | ||
|
|
f124749a4f | ||
|
|
2a3d9c8dd5 | ||
|
|
0fa59a5cec | ||
|
|
d316e8ac70 | ||
|
|
53fe15c356 | ||
|
|
acb8b651b7 | ||
|
|
ace6bc2813 | ||
|
|
f69fef2f52 | ||
|
|
d033b84b5b | ||
|
|
3e702733bc | ||
|
|
f212e9476d | ||
|
|
da00863e34 | ||
|
|
476916f381 | ||
|
|
67bf5b98a8 | ||
|
|
db7757c556 | ||
|
|
bfd309800b | ||
|
|
0121f7b33c | ||
|
|
8dbff50a8b | ||
|
|
aec56ce025 | ||
|
|
1b8ffd86b9 | ||
|
|
ee7be7e3b2 | ||
|
|
57825decf0 | ||
|
|
2b3e11bd24 | ||
|
|
23cb29b6fc | ||
|
|
ba1dd2cd08 | ||
|
|
75a9786f8f | ||
|
|
0b4fd8ddd1 | ||
|
|
2eda393c03 | ||
|
|
512a3bebad | ||
|
|
db18d6a1fc | ||
|
|
75ca3030f7 | ||
|
|
f484c3f10b | ||
|
|
0753de05d1 | ||
|
|
ab0847e49f | ||
|
|
f9383e4e94 | ||
|
|
50b6c31675 | ||
|
|
63e78933ac | ||
|
|
cd0e962ef7 | ||
|
|
107d135894 | ||
|
|
0bc43a32b9 | ||
|
|
1024f0e671 | ||
|
|
3eb7cf740f | ||
|
|
2713a7ed67 | ||
|
|
8ba75245b4 | ||
|
|
b3d391c80d | ||
|
|
43a1ea1d6c | ||
|
|
c4fd4871fc | ||
|
|
23bbb34fb7 | ||
|
|
56a82e56c0 | ||
|
|
8f0d870fff | ||
|
|
d531ceb9c6 | ||
|
|
dc87aeda6c | ||
|
|
1668546450 | ||
|
|
fc9c20062a | ||
|
|
27e9fe79a5 | ||
|
|
e37280b752 | ||
|
|
fff368c80a | ||
|
|
37cbee0f0a | ||
|
|
141822b614 | ||
|
|
b1bfc1fd36 | ||
|
|
13684ec59d | ||
|
|
a51ff4de4e | ||
|
|
da9b313ff7 | ||
|
|
6a50fe2d9c | ||
|
|
ed32cbae06 | ||
|
|
00549a3ba6 | ||
|
|
13f1fa3167 | ||
|
|
6396def588 | ||
|
|
7599b0f22f | ||
|
|
08eb7e7699 | ||
|
|
89f918c23e | ||
|
|
f08fc344f5 | ||
|
|
99aa656a1e | ||
|
|
86fbaf7403 | ||
|
|
563012549a | ||
|
|
4f46eb30d2 | ||
|
|
2f30082127 | ||
|
|
548506fbbb |
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
# additionally enabling all checks defined in this project and any Error
|
||||
# Prone checks available only from other artifact repositories.
|
||||
- name: Check out code and set up JDK and Maven
|
||||
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
|
||||
uses: s4u/setup-maven-action@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
with:
|
||||
java-version: ${{ matrix.jdk }}
|
||||
java-distribution: ${{ matrix.distribution }}
|
||||
@@ -54,6 +54,6 @@ jobs:
|
||||
- name: Build project with self-check against Error Prone fork
|
||||
run: mvn -T1C clean verify -Perror-prone-fork -Pnon-maven-central -Pself-check -s settings.xml
|
||||
- name: Remove installed project artifacts
|
||||
run: mvn build-helper:remove-project-artifact
|
||||
run: mvn dependency:purge-local-repository -DmanualInclude='${project.groupId}' -DresolutionFuzziness=groupId
|
||||
|
||||
# XXX: Enable Codecov once we "go public".
|
||||
|
||||
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@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
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@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
|
||||
uses: s4u/setup-maven-action@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
with:
|
||||
java-version: 17.0.13
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.9
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
||||
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@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
||||
with:
|
||||
category: /language:${{ matrix.language }}
|
||||
|
||||
8
.github/workflows/deploy-website.yml
vendored
8
.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@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -39,10 +39,10 @@ jobs:
|
||||
www.youtube.com:443
|
||||
youtrack.jetbrains.com:443
|
||||
- name: Check out code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: ruby/setup-ruby@7d3497fd78c07c0d84ebafa58d8dac60cd1f0763 # v1.199.0
|
||||
- uses: ruby/setup-ruby@a2bbe5b1b236842c1cb7dd11e8e3b51e0a616acc # v1.202.0
|
||||
with:
|
||||
working-directory: ./website
|
||||
bundler-cache: true
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
11
.github/workflows/openssf-scorecard.yml
vendored
11
.github/workflows/openssf-scorecard.yml
vendored
@@ -21,30 +21,33 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
allowed-endpoints: >
|
||||
api.deps.dev:443
|
||||
api.github.com:443
|
||||
api.osv.dev:443
|
||||
api.scorecard.dev:443
|
||||
api.securityscorecards.dev:443
|
||||
github.com:443
|
||||
index.docker.io:443
|
||||
oss-fuzz-build-logs.storage.googleapis.com:443
|
||||
repo.maven.apache.org:443
|
||||
*.sigstore.dev:443
|
||||
www.bestpractices.dev:443
|
||||
- name: Check out code
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run OpenSSF Scorecard analysis
|
||||
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: ${{ github.ref == 'refs/heads/master' }}
|
||||
- name: Update GitHub's code scanning dashboard
|
||||
uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
|
||||
uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
|
||||
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@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
objects.githubusercontent.com:443
|
||||
repo.maven.apache.org:443
|
||||
- name: Check out code and set up JDK and Maven
|
||||
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
|
||||
uses: s4u/setup-maven-action@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
with:
|
||||
checkout-fetch-depth: 2
|
||||
java-version: 17.0.13
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
- name: Aggregate Pitest reports
|
||||
run: mvn pitest-git:aggregate -DkilledEmoji=":tada:" -DmutantEmoji=":zombie:" -DtrailingText="Mutation testing report by [Pitest](https://pitest.org/). Review any surviving mutants by inspecting the line comments under [_Files changed_](${{ github.event.number }}/files)."
|
||||
- name: Upload Pitest reports as artifact
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
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@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
objects.githubusercontent.com:443
|
||||
repo.maven.apache.org:443
|
||||
- name: Check out code and set up JDK and Maven
|
||||
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
|
||||
uses: s4u/setup-maven-action@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
with:
|
||||
java-version: 17.0.13
|
||||
java-distribution: temurin
|
||||
|
||||
30
.github/workflows/run-integration-tests.yml
vendored
30
.github/workflows/run-integration-tests.yml
vendored
@@ -1,9 +1,9 @@
|
||||
# If requested by means of a pull request comment, runs integration tests
|
||||
# against the project, using the code found on the pull request branch.
|
||||
# XXX: Generalize this to a matrix build of multiple integration tests,
|
||||
# possibly using multiple JDK or OS versions.
|
||||
# XXX: Investigate whether the comment can specify which integration tests run
|
||||
# run. See this example of a dynamic build matrix:
|
||||
# XXX: Review whether then build matrix should also vary JDK or OS versions.
|
||||
# XXX: Support `/integration-test [name...]` comment syntax to specify the
|
||||
# subset of integration tests to run.
|
||||
# See this example of a dynamic build matrix:
|
||||
# https://docs.github.com/en/actions/learn-github-actions/expressions#example-returning-a-json-object
|
||||
name: "Integration tests"
|
||||
on:
|
||||
@@ -17,23 +17,33 @@ jobs:
|
||||
if: |
|
||||
github.event.issue.pull_request && contains(github.event.comment.body, '/integration-test')
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
integration-test: [ "checkstyle", "metrics", "prometheus-java-client" ]
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
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
|
||||
example.com:80
|
||||
github.com:443
|
||||
objects.githubusercontent.com:443
|
||||
oss.sonatype.org:443
|
||||
production.cloudflare.docker.com:443
|
||||
raw.githubusercontent.com:443
|
||||
registry-1.docker.io:443
|
||||
repo.maven.apache.org:443
|
||||
repository.sonatype.org:443
|
||||
- name: Check out code and set up JDK and Maven
|
||||
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
|
||||
uses: s4u/setup-maven-action@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
with:
|
||||
checkout-ref: "refs/pull/${{ github.event.issue.number }}/head"
|
||||
java-version: 17.0.13
|
||||
@@ -42,12 +52,12 @@ jobs:
|
||||
- name: Install project to local Maven repository
|
||||
run: mvn -T1C install -DskipTests -Dverification.skip
|
||||
- name: Run integration test
|
||||
run: xvfb-run ./integration-tests/checkstyle.sh "${{ runner.temp }}/artifacts"
|
||||
run: xvfb-run "./integration-tests/${{ matrix.integration-test }}.sh" "${{ runner.temp }}/artifacts"
|
||||
- name: Upload artifacts on failure
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: integration-test-checkstyle
|
||||
name: "integration-test-${{ matrix.integration-test }}"
|
||||
path: "${{ runner.temp }}/artifacts"
|
||||
- name: Remove installed project artifacts
|
||||
run: mvn build-helper:remove-project-artifact
|
||||
run: mvn dependency:purge-local-repository -DmanualInclude='${project.groupId}' -DresolutionFuzziness=groupId
|
||||
|
||||
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@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
|
||||
uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
*.sonarcloud.io:443
|
||||
sonarcloud.io:443
|
||||
- name: Check out code and set up JDK and Maven
|
||||
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
|
||||
uses: s4u/setup-maven-action@9a27433d289dd99d73851f653607c39d3444e8ba # v1.17.0
|
||||
with:
|
||||
checkout-fetch-depth: 0
|
||||
java-version: 17.0.13
|
||||
|
||||
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Binary file not shown.
18
.mvn/wrapper/maven-wrapper.properties
vendored
18
.mvn/wrapper/maven-wrapper.properties
vendored
@@ -1,18 +0,0 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
|
||||
@@ -3,11 +3,24 @@
|
||||
"extends": [
|
||||
"helpers:pinGitHubActionDigests"
|
||||
],
|
||||
"customManagers": [
|
||||
{
|
||||
"customType": "regex",
|
||||
"fileMatch": [
|
||||
"^integration-tests/.*(-init\\.patch|\\.sh)$"
|
||||
],
|
||||
"matchStrings": [
|
||||
"\\b(?<packageName>[a-z0-9_.-]+?:[a-z0-9_.-]+?):(?<currentValue>[^:]+?):[a-zA-Z0-9_-]+\\b",
|
||||
"<version>(?<currentValue>.*?)<!-- Renovate: (?<packageName>.*?) --></version>"
|
||||
],
|
||||
"datasourceTemplate": "maven"
|
||||
}
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchPackagePatterns": [
|
||||
"^org\\.springframework:spring-framework-bom$",
|
||||
"^org\\.springframework\\.boot:spring-boot[a-z-]*$"
|
||||
"matchPackageNames": [
|
||||
"/^org\\.springframework:spring-framework-bom$/",
|
||||
"/^org\\.springframework\\.boot:spring-boot[a-z-]*$/"
|
||||
],
|
||||
"separateMinorPatch": true
|
||||
},
|
||||
|
||||
@@ -217,7 +217,7 @@ Other highly relevant commands:
|
||||
- `mvn fmt:format` formats the code using
|
||||
[`google-java-format`][google-java-format].
|
||||
- [`./run-full-build.sh`][script-run-full-build] builds the project twice,
|
||||
where the second pass validates compatbility with Picnic's [Error Prone
|
||||
where the second pass validates compatibility with Picnic's [Error Prone
|
||||
fork][error-prone-fork-repo] and compliance of the code with any rules
|
||||
defined within this project. (Consider running this before [opening a pull
|
||||
request][contributing-pull-request], as the PR checks also perform this
|
||||
|
||||
@@ -167,6 +167,11 @@
|
||||
<artifactId>value-annotations</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
@@ -298,6 +303,9 @@
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs combine.children="append">
|
||||
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<!-- The Refaster input/output test classes used by
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.sun.source.tree.LambdaExpressionTree;
|
||||
import com.sun.source.tree.TypeCastTree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/**
|
||||
@@ -48,11 +49,14 @@ public final class ClassCastLambdaUsage extends BugChecker implements LambdaExpr
|
||||
}
|
||||
|
||||
Type type = ASTHelpers.getType(typeCast);
|
||||
if (type == null || type.isParameterized() || type.isPrimitive()) {
|
||||
if (type == null
|
||||
|| type.isParameterized()
|
||||
|| type.isPrimitive()
|
||||
|| type.getKind() == TypeKind.TYPEVAR) {
|
||||
/*
|
||||
* The method reference syntax does not support casting to parameterized types. Additionally,
|
||||
* `Class#cast` does not support the same range of type conversions between (boxed) primitive
|
||||
* types as the cast operator.
|
||||
* The method reference syntax does not support casting to parameterized types, and type
|
||||
* variables aren't supported either. Additionally, `Class#cast` does not support the same
|
||||
* range of type conversions between (boxed) primitive types as the cast operator.
|
||||
*/
|
||||
// XXX: Depending on the declared type of the value being cast, in some cases we _can_ rewrite
|
||||
// primitive casts. Add support for this.
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.PERFORMANCE;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.symbolMatcher;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.google.errorprone.util.Visibility;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.element.Element;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags single-argument method invocations with an iterable of explicitly
|
||||
* enumerated values, for which a semantically equivalent varargs variant (appears to) exists as
|
||||
* well.
|
||||
*
|
||||
* <p>This check drops selected {@link ImmutableSet#of} and {@link Set#of} invocations, with the
|
||||
* assumption that these operations do not deduplicate the collection of explicitly enumerated
|
||||
* values. It also drops {@link ImmutableMultiset#of} and {@link Set#of} invocations, with the
|
||||
* assumption that these do not materially impact iteration order.
|
||||
*
|
||||
* <p>This checker attempts to identify {@link Iterable}-accepting methods for which a varargs
|
||||
* overload exists, and suggests calling the varargs overload instead. This is an imperfect
|
||||
* heuristic, but it e.g. allows invocations of <a
|
||||
* href="https://immutables.github.io/immutable.html#copy-methods">Immutables-generated {@code
|
||||
* with*}</a> methods to be simplified.
|
||||
*/
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Iterable creation can be avoided by using a varargs alternative method",
|
||||
link = BUG_PATTERNS_BASE_URL + "ExplicitArgumentEnumeration",
|
||||
linkType = CUSTOM,
|
||||
severity = SUGGESTION,
|
||||
tags = {PERFORMANCE, SIMPLIFICATION})
|
||||
public final class ExplicitArgumentEnumeration extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> EXPLICIT_ITERABLE_CREATOR =
|
||||
anyOf(
|
||||
staticMethod()
|
||||
.onClassAny(
|
||||
ImmutableList.class.getCanonicalName(),
|
||||
ImmutableMultiset.class.getCanonicalName(),
|
||||
ImmutableSet.class.getCanonicalName(),
|
||||
List.class.getCanonicalName(),
|
||||
Set.class.getCanonicalName())
|
||||
.named("of"),
|
||||
allOf(
|
||||
staticMethod()
|
||||
.onClassAny(
|
||||
ImmutableList.class.getCanonicalName(),
|
||||
ImmutableMultiset.class.getCanonicalName(),
|
||||
ImmutableSet.class.getCanonicalName())
|
||||
.named("copyOf"),
|
||||
symbolMatcher(
|
||||
(symbol, state) ->
|
||||
state
|
||||
.getSymtab()
|
||||
.arrayClass
|
||||
.equals(((MethodSymbol) symbol).params().get(0).type.tsym))),
|
||||
staticMethod().onClass(Arrays.class.getCanonicalName()).named("asList"));
|
||||
private static final Matcher<ExpressionTree> IMMUTABLE_COLLECTION_BUILDER =
|
||||
instanceMethod().onDescendantOf(ImmutableCollection.Builder.class.getCanonicalName());
|
||||
private static final Matcher<ExpressionTree> OBJECT_ENUMERABLE_ASSERT =
|
||||
instanceMethod().onDescendantOf("org.assertj.core.api.ObjectEnumerableAssert");
|
||||
private static final Matcher<ExpressionTree> STEP_VERIFIER_STEP =
|
||||
instanceMethod().onDescendantOf("reactor.test.StepVerifier.Step");
|
||||
private static final ImmutableTable<Matcher<ExpressionTree>, String, String> ALTERNATIVE_METHODS =
|
||||
ImmutableTable.<Matcher<ExpressionTree>, String, String>builder()
|
||||
.put(IMMUTABLE_COLLECTION_BUILDER, "addAll", "add")
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "containsAnyElementsOf", "containsAnyOf")
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "containsAll", "contains")
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "containsExactlyElementsOf", "containsExactly")
|
||||
.put(
|
||||
OBJECT_ENUMERABLE_ASSERT,
|
||||
"containsExactlyInAnyOrderElementsOf",
|
||||
"containsExactlyInAnyOrder")
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "containsOnlyElementsOf", "containsOnly")
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "containsOnlyOnceElementsOf", "containsOnlyOnce")
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "doesNotContainAnyElementsOf", "doesNotContain")
|
||||
.put(OBJECT_ENUMERABLE_ASSERT, "hasSameElementsAs", "containsOnly")
|
||||
.put(STEP_VERIFIER_STEP, "expectNextSequence", "expectNext")
|
||||
.build();
|
||||
|
||||
/** Instantiates a new {@link ExplicitArgumentEnumeration} instance. */
|
||||
public ExplicitArgumentEnumeration() {}
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
if (tree.getArguments().size() != 1) {
|
||||
/* Performance optimization: non-unary method invocations cannot be simplified. */
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
MethodSymbol method = ASTHelpers.getSymbol(tree);
|
||||
if (!isUnaryIterableAcceptingMethod(method, state) || isLocalOverload(method, state)) {
|
||||
/*
|
||||
* This isn't a method invocation we can simplify, or it's an invocation of a local overload.
|
||||
* The latter type of invocation we do not suggest replacing, as this is fairly likely to
|
||||
* introduce an unbounded recursive call chain.
|
||||
*/
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
ExpressionTree argument = tree.getArguments().get(0);
|
||||
if (!EXPLICIT_ITERABLE_CREATOR.matches(argument, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return trySuggestCallingVarargsOverload(method, (MethodInvocationTree) argument, state)
|
||||
.or(() -> trySuggestCallingCustomAlternative(tree, (MethodInvocationTree) argument, state))
|
||||
.map(fix -> describeMatch(tree, fix))
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
|
||||
private static boolean isUnaryIterableAcceptingMethod(MethodSymbol method, VisitorState state) {
|
||||
List<VarSymbol> params = method.params();
|
||||
return !method.isVarArgs()
|
||||
&& params.size() == 1
|
||||
&& ASTHelpers.isSubtype(params.get(0).type, state.getSymtab().iterableType, state);
|
||||
}
|
||||
|
||||
private static boolean isLocalOverload(MethodSymbol calledMethod, VisitorState state) {
|
||||
MethodTree enclosingMethod = state.findEnclosing(MethodTree.class);
|
||||
if (enclosingMethod == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MethodSymbol callingMethod = ASTHelpers.getSymbol(enclosingMethod);
|
||||
return Objects.equals(callingMethod.getEnclosingElement(), calledMethod.getEnclosingElement())
|
||||
&& callingMethod.getSimpleName().equals(calledMethod.getSimpleName());
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix> trySuggestCallingVarargsOverload(
|
||||
MethodSymbol method, MethodInvocationTree argument, VisitorState state) {
|
||||
/*
|
||||
* Collect all overloads of the given method that we are sure to be able to call. Note that the
|
||||
* `isAtLeastAsVisible` check is conservative heuristic.
|
||||
*/
|
||||
ImmutableList<MethodSymbol> overloads =
|
||||
ASTHelpers.matchingMethods(
|
||||
method.getSimpleName(),
|
||||
m -> isAtLeastAsVisible(m, method),
|
||||
method.enclClass().type,
|
||||
state.getTypes())
|
||||
.collect(toImmutableList());
|
||||
|
||||
/*
|
||||
* If all overloads have a single parameter, and at least one of them is a varargs method, then
|
||||
* we assume that unwrapping the iterable argument will cause a suitable overload to be invoked.
|
||||
* (Note that there may be multiple varargs overloads, either with different parameter types, or
|
||||
* due to method overriding; this check does not attempt to determine which exact method or
|
||||
* overload will be invoked as a result of the suggested simplification.)
|
||||
*
|
||||
* Note that this is a (highly!) imperfect heuristic, but it is sufficient to prevent e.g.
|
||||
* unwrapping of arguments to `org.jooq.impl.DSL#row`, which can cause the expression's return
|
||||
* type to change from `RowN` to (e.g.) `Row2`.
|
||||
*/
|
||||
// XXX: There are certainly cases where it _would_ be nice to unwrap the arguments to
|
||||
// `org.jooq.impl.DSL#row(Collection<?>)`. Look into this.
|
||||
// XXX: Ideally we do check that one of the overloads accepts the unwrapped arguments.
|
||||
// XXX: Ideally we validate that eligible overloads have compatible return types.
|
||||
boolean hasLikelySuitableVarargsOverload =
|
||||
overloads.stream().allMatch(m -> m.params().size() == 1)
|
||||
&& overloads.stream().anyMatch(MethodSymbol::isVarArgs);
|
||||
|
||||
return hasLikelySuitableVarargsOverload
|
||||
? Optional.of(SourceCode.unwrapMethodInvocation(argument, state))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix> trySuggestCallingCustomAlternative(
|
||||
MethodInvocationTree tree, MethodInvocationTree argument, VisitorState state) {
|
||||
return ALTERNATIVE_METHODS.rowMap().entrySet().stream()
|
||||
.filter(e -> e.getKey().matches(tree, state))
|
||||
.findFirst()
|
||||
.flatMap(e -> trySuggestCallingCustomAlternative(tree, argument, state, e.getValue()));
|
||||
}
|
||||
|
||||
private static Optional<SuggestedFix> trySuggestCallingCustomAlternative(
|
||||
MethodInvocationTree tree,
|
||||
MethodInvocationTree argument,
|
||||
VisitorState state,
|
||||
Map<String, String> alternatives) {
|
||||
return Optional.ofNullable(
|
||||
alternatives.get(ASTHelpers.getSymbol(tree).getSimpleName().toString()))
|
||||
.map(
|
||||
replacement ->
|
||||
SuggestedFix.builder()
|
||||
.merge(SuggestedFixes.renameMethodInvocation(tree, replacement, state))
|
||||
.merge(SourceCode.unwrapMethodInvocation(argument, state))
|
||||
.build());
|
||||
}
|
||||
|
||||
private static boolean isAtLeastAsVisible(Element symbol, Element reference) {
|
||||
return Visibility.fromModifiers(symbol.getModifiers())
|
||||
.compareTo(Visibility.fromModifiers(reference.getModifiers()))
|
||||
>= 0;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Types;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
@@ -84,6 +85,7 @@ public final class IdentityConversion extends BugChecker implements MethodInvoca
|
||||
ImmutableSetMultimap.class.getCanonicalName(),
|
||||
ImmutableTable.class.getCanonicalName())
|
||||
.named("copyOf"),
|
||||
staticMethod().onClass(Instant.class.getCanonicalName()).namedAnyOf("from"),
|
||||
staticMethod().onClass(Matchers.class.getCanonicalName()).namedAnyOf("allOf", "anyOf"),
|
||||
staticMethod().onClass("reactor.adapter.rxjava.RxJava2Adapter"),
|
||||
staticMethod()
|
||||
|
||||
@@ -101,6 +101,8 @@ public final class JUnitMethodDeclaration extends BugChecker implements MethodTr
|
||||
.build());
|
||||
}
|
||||
|
||||
// XXX: Consider dropping leading underscores that otherwise result when canonicalizing
|
||||
// `test_some_method_name`.
|
||||
private static Optional<String> tryCanonicalizeMethodName(MethodSymbol symbol) {
|
||||
return Optional.of(symbol.getQualifiedName().toString())
|
||||
.filter(name -> name.startsWith(TEST_PREFIX))
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.LiteralTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.LiteralTree;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} that flags string constants with extraneous escaping. */
|
||||
// XXX: Also cover `\"` sequences inside text blocks. Note that this requires a more subtle
|
||||
// approach, as double-quote characters will need to remain escaped if removing the backslash would
|
||||
// create a new sequence of three or more double-quotes. (TBD whether we'd like to enforce a
|
||||
// "preferred" approach to escaping, e.g. by always escaping the last of a triplet, such that the
|
||||
// over-all number of escaped characters is minimized.)
|
||||
// XXX: Also flag `'\"'` char literals.
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Inside string expressions single quotes do not need to be escaped",
|
||||
link = BUG_PATTERNS_BASE_URL + "RedundantStringEscape",
|
||||
linkType = CUSTOM,
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class RedundantStringEscape extends BugChecker implements LiteralTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Instantiates a new {@link RedundantStringEscape} instance. */
|
||||
public RedundantStringEscape() {}
|
||||
|
||||
@Override
|
||||
public Description matchLiteral(LiteralTree tree, VisitorState state) {
|
||||
String constant = ASTHelpers.constValue(tree, String.class);
|
||||
if (constant == null || constant.indexOf('\'') < 0) {
|
||||
/* Fast path: this isn't a string constant with a single quote. */
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
String source = SourceCode.treeToString(tree, state);
|
||||
if (!containsBannedEscapeSequence(source)) {
|
||||
/* Semi-fast path: this expression doesn't contain an escaped single quote. */
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
/* Slow path: suggest dropping the escape characters. */
|
||||
return describeMatch(tree, SuggestedFix.replace(tree, dropRedundantEscapeSequences(source)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the given string constant source expression contains an escaped single quote.
|
||||
*
|
||||
* @implNote As the input is a literal Java string expression, it will start and end with a double
|
||||
* quote; as such any found backslash will not be the string's final character.
|
||||
*/
|
||||
private static boolean containsBannedEscapeSequence(String source) {
|
||||
for (int p = source.indexOf('\\'); p != -1; p = source.indexOf('\\', p + 2)) {
|
||||
if (source.charAt(p + 1) == '\'') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplifies the given string constant source expression by dropping the backslash preceding an
|
||||
* escaped single quote.
|
||||
*
|
||||
* @implNote Note that this method does not delegate to {@link
|
||||
* SourceCode#toStringConstantExpression}, as that operation may replace other Unicode
|
||||
* characters with their associated escape sequence.
|
||||
* @implNote As the input is a literal Java string expression, it will start and end with a double
|
||||
* quote; as such any found backslash will not be the string's final character.
|
||||
*/
|
||||
private static String dropRedundantEscapeSequences(String source) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int p = 0; p < source.length(); p++) {
|
||||
char c = source.charAt(p);
|
||||
if (c != '\\' || source.charAt(p + 1) != '\'') {
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ import tech.picnic.errorprone.utils.SourceCode;
|
||||
tags = LIKELY_ERROR)
|
||||
public final class Slf4jLogStatement extends BugChecker implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> MARKER = isSubtypeOf("org.slf4j.Marker");
|
||||
private static final Matcher<ExpressionTree> SLF4J_MARKER = isSubtypeOf("org.slf4j.Marker");
|
||||
private static final Matcher<ExpressionTree> THROWABLE = isSubtypeOf(Throwable.class);
|
||||
private static final Matcher<ExpressionTree> SLF4J_LOGGER_INVOCATION =
|
||||
instanceMethod()
|
||||
@@ -71,7 +71,7 @@ public final class Slf4jLogStatement extends BugChecker implements MethodInvocat
|
||||
* SLF4J log statements may accept a "marker" as a first argument, before the format string.
|
||||
* We ignore such markers.
|
||||
*/
|
||||
int lTrim = MARKER.matches(args.get(0), state) ? 1 : 0;
|
||||
int lTrim = SLF4J_MARKER.matches(args.get(0), state) ? 1 : 0;
|
||||
/*
|
||||
* SLF4J treats the final argument to a log statement specially if it is a `Throwabe`: it
|
||||
* will always choose to render the associated stacktrace, even if the argument has a
|
||||
|
||||
@@ -53,7 +53,7 @@ public final class Slf4jLoggerDeclaration extends BugChecker implements Variable
|
||||
private static final Matcher<ExpressionTree> IS_GET_LOGGER =
|
||||
staticMethod().onDescendantOf("org.slf4j.LoggerFactory").named("getLogger");
|
||||
private static final String CANONICAL_STATIC_LOGGER_NAME_FLAG =
|
||||
"Slf4jLogDeclaration:CanonicalStaticLoggerName";
|
||||
"Slf4jLoggerDeclaration:CanonicalStaticLoggerName";
|
||||
private static final String DEFAULT_CANONICAL_LOGGER_NAME = "LOG";
|
||||
private static final Matcher<ExpressionTree> IS_STATIC_ENCLOSING_CLASS_REFERENCE =
|
||||
classLiteral(Slf4jLoggerDeclaration::isEnclosingClassReference);
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.util.Constants;
|
||||
import java.util.Formattable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -37,7 +36,9 @@ import tech.picnic.errorprone.utils.SourceCode;
|
||||
*/
|
||||
// XXX: What about `v1 + "sep" + v2` and similar expressions? Do we want to rewrite those to
|
||||
// `String.join`, or should some `String.join` invocations be rewritten to use the `+` operator?
|
||||
// (The latter suggestion would conflict with the `FormatStringConcatenation` check.)
|
||||
// (The latter suggestion would conflict with the `FormatStringConcatenation` check, but does make
|
||||
// more sense when `"sep"` is a long string. Similarly for `String.format("%s some long text %s",
|
||||
// arg1, arg2)`.)
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Prefer `String#join` over `String#format`",
|
||||
@@ -150,7 +151,7 @@ public final class StringJoin extends BugChecker implements MethodInvocationTree
|
||||
SuggestedFix.Builder fix =
|
||||
SuggestedFix.builder()
|
||||
.replace(tree.getMethodSelect(), "String.join")
|
||||
.replace(arguments.next(), Constants.format(separator));
|
||||
.replace(arguments.next(), SourceCode.toStringConstantExpression(separator, state));
|
||||
|
||||
while (arguments.hasNext()) {
|
||||
ExpressionTree argument = arguments.next();
|
||||
|
||||
@@ -3,9 +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.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
@@ -15,7 +12,6 @@ import com.google.errorprone.refaster.annotation.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.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -204,32 +200,8 @@ final class AssertJRules {
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T element) {
|
||||
return Refaster.anyOf(
|
||||
iterAssert.containsAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element))),
|
||||
iterAssert.containsAnyOf(element),
|
||||
iterAssert.containsAll(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element))),
|
||||
iterAssert.containsSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element))),
|
||||
iterAssert.containsSequence(element),
|
||||
iterAssert.containsSubsequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element))),
|
||||
iterAssert.containsSubsequence(element));
|
||||
}
|
||||
|
||||
@@ -244,20 +216,7 @@ final class AssertJRules {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T element) {
|
||||
return Refaster.anyOf(
|
||||
iterAssert.doesNotContainAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element))),
|
||||
iterAssert.doesNotContainSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element))),
|
||||
iterAssert.doesNotContainSequence(element));
|
||||
return iterAssert.doesNotContainSequence(element);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -270,25 +229,7 @@ final class AssertJRules {
|
||||
static final class ObjectEnumerableContainsExactlyOneElement<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T element) {
|
||||
return Refaster.anyOf(
|
||||
iterAssert.containsExactlyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element))),
|
||||
iterAssert.containsExactlyInAnyOrderElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element))));
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> before2(
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, @NotMatches(IsArray.class) T element) {
|
||||
return iterAssert.containsExactlyInAnyOrder(element);
|
||||
}
|
||||
@@ -313,42 +254,6 @@ final class AssertJRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsOneDistinctElement<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T element) {
|
||||
return iterAssert.hasSameElementsAs(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T element) {
|
||||
return iterAssert.containsOnly(element);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableIsSubsetOfOneElement<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T element) {
|
||||
return iterAssert.isSubsetOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(element),
|
||||
Arrays.asList(element),
|
||||
ImmutableSet.of(element),
|
||||
ImmutableMultiset.of(element)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T element) {
|
||||
return iterAssert.isSubsetOf(element);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Iterable
|
||||
//
|
||||
@@ -359,6 +264,7 @@ final class AssertJRules {
|
||||
Refaster.anyOf(
|
||||
assertThat(iterable).hasSize(0),
|
||||
assertThat(iterable.iterator().hasNext()).isFalse(),
|
||||
assertThat(iterable.iterator()).isExhausted(),
|
||||
assertThat(Iterables.size(iterable)).isEqualTo(0L),
|
||||
assertThat(Iterables.size(iterable)).isNotPositive());
|
||||
}
|
||||
@@ -1155,824 +1061,6 @@ final class AssertJRules {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// BELOW: Generated code.
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: containsAnyOf
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableContainsAnyOfTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsAnyOf(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsAnyOfThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsAnyOf(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsAnyOfFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsAnyOf(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableContainsAnyOfFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsAnyOf(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: contains
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableContainsTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsAll(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.contains(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsAll(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.contains(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsAll(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.contains(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableContainsFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsAll(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.contains(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: containsExactly
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableContainsExactlyTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsExactlyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsExactly(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsExactlyThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsExactlyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsExactly(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsExactlyFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsExactlyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsExactly(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableContainsExactlyFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsExactlyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsExactly(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: containsExactlyInAnyOrder
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableContainsExactlyInAnyOrderTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsExactlyInAnyOrderElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsExactlyInAnyOrder(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsExactlyInAnyOrderThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsExactlyInAnyOrderElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsExactlyInAnyOrder(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsExactlyInAnyOrderFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsExactlyInAnyOrderElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsExactlyInAnyOrder(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableContainsExactlyInAnyOrderFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsExactlyInAnyOrderElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsExactlyInAnyOrder(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: containsSequence
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableContainsSequenceTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsSequence(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsSequenceThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsSequence(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsSequenceFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsSequence(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableContainsSequenceFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsSequence(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: containsSubsequence
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableContainsSubsequenceTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsSubsequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsSubsequence(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsSubsequenceThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsSubsequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsSubsequence(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsSubsequenceFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsSubsequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsSubsequence(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableContainsSubsequenceFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsSubsequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsSubsequence(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: doesNotContain
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableDoesNotContainTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.doesNotContainAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.doesNotContain(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableDoesNotContainThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.doesNotContainAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.doesNotContain(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableDoesNotContainFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.doesNotContainAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.doesNotContain(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableDoesNotContainFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.doesNotContainAnyElementsOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.doesNotContain(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: doesNotContainSequence
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableDoesNotContainSequenceTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.doesNotContainSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.doesNotContainSequence(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableDoesNotContainSequenceThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.doesNotContainSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.doesNotContainSequence(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableDoesNotContainSequenceFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.doesNotContainSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.doesNotContainSequence(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableDoesNotContainSequenceFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.doesNotContainSequence(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.doesNotContainSequence(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: containsOnly
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableContainsOnlyTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.hasSameElementsAs(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.containsOnly(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsOnlyThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.hasSameElementsAs(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.containsOnly(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableContainsOnlyFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.hasSameElementsAs(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.containsOnly(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableContainsOnlyFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.hasSameElementsAs(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.containsOnly(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ObjectEnumerableAssert: isSubsetOf
|
||||
//
|
||||
|
||||
static final class ObjectEnumerableIsSubsetOfTwoElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.isSubsetOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2),
|
||||
Arrays.asList(e1, e2),
|
||||
ImmutableSet.of(e1, e2),
|
||||
ImmutableMultiset.of(e1, e2)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2) {
|
||||
return iterAssert.isSubsetOf(e1, e2);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableIsSubsetOfThreeElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.isSubsetOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3),
|
||||
Arrays.asList(e1, e2, e3),
|
||||
ImmutableSet.of(e1, e2, e3),
|
||||
ImmutableMultiset.of(e1, e2, e3)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3) {
|
||||
return iterAssert.isSubsetOf(e1, e2, e3);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ObjectEnumerableIsSubsetOfFourElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.isSubsetOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4),
|
||||
Arrays.asList(e1, e2, e3, e4),
|
||||
ImmutableSet.of(e1, e2, e3, e4),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4) {
|
||||
return iterAssert.isSubsetOf(e1, e2, e3, e4);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Add variants for 6+ elements?
|
||||
static final class ObjectEnumerableIsSubsetOfFiveElements<S, T extends S> {
|
||||
@BeforeTemplate
|
||||
ObjectEnumerableAssert<?, S> before(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.isSubsetOf(
|
||||
Refaster.anyOf(
|
||||
ImmutableList.of(e1, e2, e3, e4, e5),
|
||||
Arrays.asList(e1, e2, e3, e4, e5),
|
||||
ImmutableSet.of(e1, e2, e3, e4, e5),
|
||||
ImmutableMultiset.of(e1, e2, e3, e4, e5)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@SuppressWarnings("unchecked")
|
||||
ObjectEnumerableAssert<?, S> after(
|
||||
ObjectEnumerableAssert<?, S> iterAssert, T e1, T e2, T e3, T e4, T e5) {
|
||||
return iterAssert.isSubsetOf(e1, e2, e3, e4, e5);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Above: Generated code.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Organize the code below.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -69,6 +70,32 @@ final class AssertJStringRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatStringContains {
|
||||
@BeforeTemplate
|
||||
AbstractBooleanAssert<?> before(String string, String substring) {
|
||||
return assertThat(string.contains(substring)).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractStringAssert<?> after(String string, String substring) {
|
||||
return assertThat(string).contains(substring);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatStringDoesNotContain {
|
||||
@BeforeTemplate
|
||||
AbstractBooleanAssert<?> before(String string, String substring) {
|
||||
return assertThat(string.contains(substring)).isFalse();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractStringAssert<?> after(String string, String substring) {
|
||||
return assertThat(string).doesNotContain(substring);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatMatches {
|
||||
@BeforeTemplate
|
||||
AbstractAssert<?, ?> before(String string, String regex) {
|
||||
|
||||
@@ -7,7 +7,10 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.InstanceOfAssertFactories.throwable;
|
||||
import static org.assertj.core.api.InstanceOfAssertFactories.type;
|
||||
|
||||
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.Repeated;
|
||||
@@ -16,6 +19,7 @@ import java.io.IOException;
|
||||
import org.assertj.core.api.AbstractObjectAssert;
|
||||
import org.assertj.core.api.AbstractThrowableAssert;
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.assertj.core.api.ThrowableAssertAlternative;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
|
||||
/**
|
||||
@@ -31,6 +35,21 @@ import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
final class AssertJThrowingCallableRules {
|
||||
private AssertJThrowingCallableRules() {}
|
||||
|
||||
static final class AssertThatThrownByIsInstanceOf<T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
void before(ThrowingCallable throwingCallable, Class<T> exceptionType) {
|
||||
Refaster.anyOf(
|
||||
assertThatThrownBy(throwingCallable).asInstanceOf(throwable(exceptionType)),
|
||||
assertThatThrownBy(throwingCallable).asInstanceOf(type(exceptionType)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
void after(ThrowingCallable throwingCallable, Class<T> exceptionType) {
|
||||
assertThatThrownBy(throwingCallable).isInstanceOf(exceptionType);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentException {
|
||||
@BeforeTemplate
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable) {
|
||||
@@ -61,6 +80,27 @@ final class AssertJThrowingCallableRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentExceptionRootCauseHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalArgumentException" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalArgumentException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.havingRootCause()
|
||||
.withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.rootCause()
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalArgumentExceptionHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
@@ -171,6 +211,27 @@ final class AssertJThrowingCallableRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalStateExceptionRootCauseHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByIllegalStateException" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIllegalStateException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.havingRootCause()
|
||||
.withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.rootCause()
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIllegalStateExceptionHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
@@ -279,6 +340,27 @@ final class AssertJThrowingCallableRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByNullPointerExceptionRootCauseHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByNullPointerException" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatNullPointerException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.havingRootCause()
|
||||
.withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
.rootCause()
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByNullPointerExceptionHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
@@ -386,6 +468,26 @@ final class AssertJThrowingCallableRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIOExceptionRootCauseHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatThrownByIOException" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatIOException()
|
||||
.isThrownBy(throwingCallable)
|
||||
.havingRootCause()
|
||||
.withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(ThrowingCallable throwingCallable, String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(IOException.class)
|
||||
.rootCause()
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByIOExceptionHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatThrownByIOException" /* This is a more specific template. */)
|
||||
@@ -452,24 +554,24 @@ final class AssertJThrowingCallableRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownBy {
|
||||
static final class AssertThatThrownByAsInstanceOfThrowable<T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable, Class<? extends Throwable> exceptionType) {
|
||||
ThrowableAssertAlternative<T> before(
|
||||
ThrowingCallable throwingCallable, Class<T> exceptionType) {
|
||||
return assertThatExceptionOfType(exceptionType).isThrownBy(throwingCallable);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
ThrowingCallable throwingCallable, Class<? extends Throwable> exceptionType) {
|
||||
return assertThatThrownBy(throwingCallable).isInstanceOf(exceptionType);
|
||||
AbstractThrowableAssert<?, T> after(ThrowingCallable throwingCallable, Class<T> exceptionType) {
|
||||
return assertThatThrownBy(throwingCallable).asInstanceOf(throwable(exceptionType));
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatThrownBy" /* This is a more specific template. */)
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByAsInstanceOfThrowable" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable,
|
||||
Class<? extends Throwable> exceptionType,
|
||||
@@ -489,9 +591,37 @@ final class AssertJThrowingCallableRules {
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByRootCauseHasMessage {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByAsInstanceOfThrowable" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable,
|
||||
Class<? extends Throwable> exceptionType,
|
||||
String message) {
|
||||
return assertThatExceptionOfType(exceptionType)
|
||||
.isThrownBy(throwingCallable)
|
||||
.havingRootCause()
|
||||
.withMessage(message);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
AbstractObjectAssert<?, ?> after(
|
||||
ThrowingCallable throwingCallable,
|
||||
Class<? extends Throwable> exceptionType,
|
||||
String message) {
|
||||
return assertThatThrownBy(throwingCallable)
|
||||
.isInstanceOf(exceptionType)
|
||||
.rootCause()
|
||||
.hasMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static final class AssertThatThrownByHasMessageParameters {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatThrownBy" /* This is a more specific template. */)
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByAsInstanceOfThrowable" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable,
|
||||
Class<? extends Throwable> exceptionType,
|
||||
@@ -517,7 +647,8 @@ final class AssertJThrowingCallableRules {
|
||||
|
||||
static final class AssertThatThrownByHasMessageStartingWith {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatThrownBy" /* This is a more specific template. */)
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByAsInstanceOfThrowable" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable,
|
||||
Class<? extends Throwable> exceptionType,
|
||||
@@ -541,7 +672,8 @@ final class AssertJThrowingCallableRules {
|
||||
|
||||
static final class AssertThatThrownByHasMessageContaining {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatThrownBy" /* This is a more specific template. */)
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByAsInstanceOfThrowable" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable,
|
||||
Class<? extends Throwable> exceptionType,
|
||||
@@ -565,7 +697,8 @@ final class AssertJThrowingCallableRules {
|
||||
|
||||
static final class AssertThatThrownByHasMessageNotContaining {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("AssertThatThrownBy" /* This is a more specific template. */)
|
||||
@SuppressWarnings(
|
||||
"AssertThatThrownByAsInstanceOfThrowable" /* This is a more specific template. */)
|
||||
AbstractObjectAssert<?, ?> before(
|
||||
ThrowingCallable throwingCallable,
|
||||
Class<? extends Throwable> exceptionType,
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.sun.tools.javac.util.Constants;
|
||||
import com.sun.tools.javac.util.Convert;
|
||||
import javax.lang.model.element.Name;
|
||||
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/** Refaster rules related to {@link com.google.errorprone.bugpatterns.BugChecker} classes. */
|
||||
@OnlineDocumentation
|
||||
@@ -56,16 +57,26 @@ final class BugCheckerRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer using the {@link Constants} API over more verbose alternatives. */
|
||||
/**
|
||||
* Prefer {@link SourceCode#toStringConstantExpression(Object,
|
||||
* com.google.errorprone.VisitorState)} over alternatives that unnecessarily escape single quote
|
||||
* characters.
|
||||
*/
|
||||
static final class ConstantsFormat {
|
||||
@BeforeTemplate
|
||||
String before(CharSequence value) {
|
||||
return Constants.format(value);
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
String before(String value) {
|
||||
return String.format("\"%s\"", Convert.quote(value));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
String after(String value) {
|
||||
return Constants.format(value);
|
||||
String after(CharSequence value) {
|
||||
return SourceCode.toStringConstantExpression(
|
||||
value, Refaster.emitCommentBefore("REPLACEME", null));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,12 @@ final class FileRules {
|
||||
/**
|
||||
* Prefer {@link Files#createTempFile(String, String, FileAttribute[])} over alternatives that
|
||||
* create files with more liberal permissions.
|
||||
*
|
||||
* <p>Note that {@link File#createTempFile} treats the given prefix as a path, and ignores all but
|
||||
* its file name. That is, the actual prefix used is derived from all characters following the
|
||||
* final file separator (if any). This is not the case with {@link Files#createTempFile}, which
|
||||
* will instead throw an {@link IllegalArgumentException} if the prefix contains any file
|
||||
* separators.
|
||||
*/
|
||||
static final class FilesCreateTempFileToFile {
|
||||
@BeforeTemplate
|
||||
@@ -117,6 +123,12 @@ final class FileRules {
|
||||
/**
|
||||
* Prefer {@link Files#createTempFile(Path, String, String, FileAttribute[])} over alternatives
|
||||
* that create files with more liberal permissions.
|
||||
*
|
||||
* <p>Note that {@link File#createTempFile} treats the given prefix as a path, and ignores all but
|
||||
* its file name. That is, the actual prefix used is derived from all characters following the
|
||||
* final file separator (if any). This is not the case with {@link Files#createTempFile}, which
|
||||
* will instead throw an {@link IllegalArgumentException} if the prefix contains any file
|
||||
* separators.
|
||||
*/
|
||||
static final class FilesCreateTempFileInCustomDirectoryToFile {
|
||||
@BeforeTemplate
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -31,8 +31,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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -279,6 +279,9 @@ final class OptionalRules {
|
||||
*/
|
||||
// XXX: Do we need the `.filter(Optional::isPresent)`? If it's absent the caller probably assumed
|
||||
// that the values are present. (If we drop it, we should rewrite vacuous filter steps.)
|
||||
// XXX: The rewritten `filter`/`map` expression may be more performant than its replacement. See
|
||||
// https://github.com/palantir/gradle-baseline/pull/2946. (There are plans to pair Refaster rules
|
||||
// with JMH benchmarks; this would be a great use case.)
|
||||
static final class StreamFlatMapOptional<T> {
|
||||
@BeforeTemplate
|
||||
Stream<T> before(Stream<Optional<T>> stream) {
|
||||
@@ -395,10 +398,7 @@ final class OptionalRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid unnecessary operations on an {@link Optional} that ultimately result in that very same
|
||||
* {@link Optional}.
|
||||
*/
|
||||
/** Don't unnecessarily transform an {@link Optional} to an equivalent instance. */
|
||||
static final class OptionalIdentity<T> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("NestedOptionals")
|
||||
|
||||
@@ -1742,6 +1742,91 @@ final class ReactorRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link PublisherProbe#assertWasSubscribed()} over more verbose alternatives. */
|
||||
static final class PublisherProbeAssertWasSubscribed<T> {
|
||||
@BeforeTemplate
|
||||
void before(PublisherProbe<T> probe) {
|
||||
Refaster.anyOf(
|
||||
assertThat(probe.wasSubscribed()).isTrue(),
|
||||
assertThat(probe.subscribeCount()).isNotNegative(),
|
||||
assertThat(probe.subscribeCount()).isNotEqualTo(0),
|
||||
assertThat(probe.subscribeCount()).isPositive());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(PublisherProbe<T> probe) {
|
||||
probe.assertWasSubscribed();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link PublisherProbe#assertWasNotSubscribed()} over more verbose alternatives. */
|
||||
static final class PublisherProbeAssertWasNotSubscribed<T> {
|
||||
@BeforeTemplate
|
||||
void before(PublisherProbe<T> probe) {
|
||||
Refaster.anyOf(
|
||||
assertThat(probe.wasSubscribed()).isFalse(),
|
||||
assertThat(probe.subscribeCount()).isEqualTo(0),
|
||||
assertThat(probe.subscribeCount()).isNotPositive());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(PublisherProbe<T> probe) {
|
||||
probe.assertWasNotSubscribed();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link PublisherProbe#assertWasCancelled()} over more verbose alternatives. */
|
||||
static final class PublisherProbeAssertWasCancelled<T> {
|
||||
@BeforeTemplate
|
||||
void before(PublisherProbe<T> probe) {
|
||||
assertThat(probe.wasCancelled()).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(PublisherProbe<T> probe) {
|
||||
probe.assertWasCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link PublisherProbe#assertWasNotCancelled()} over more verbose alternatives. */
|
||||
static final class PublisherProbeAssertWasNotCancelled<T> {
|
||||
@BeforeTemplate
|
||||
void before(PublisherProbe<T> probe) {
|
||||
assertThat(probe.wasCancelled()).isFalse();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(PublisherProbe<T> probe) {
|
||||
probe.assertWasNotCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link PublisherProbe#assertWasRequested()} over more verbose alternatives. */
|
||||
static final class PublisherProbeAssertWasRequested<T> {
|
||||
@BeforeTemplate
|
||||
void before(PublisherProbe<T> probe) {
|
||||
assertThat(probe.wasRequested()).isTrue();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(PublisherProbe<T> probe) {
|
||||
probe.assertWasRequested();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link PublisherProbe#assertWasNotRequested()} over more verbose alternatives. */
|
||||
static final class PublisherProbeAssertWasNotRequested<T> {
|
||||
@BeforeTemplate
|
||||
void before(PublisherProbe<T> probe) {
|
||||
assertThat(probe.wasRequested()).isFalse();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
void after(PublisherProbe<T> probe) {
|
||||
probe.assertWasNotRequested();
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Mono#as(Function)} when creating a {@link StepVerifier}. */
|
||||
static final class StepVerifierFromMono<T> {
|
||||
@BeforeTemplate
|
||||
@@ -1768,6 +1853,60 @@ final class ReactorRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link StepVerifier#verify()} over a dangling {@link
|
||||
* StepVerifier#verifyThenAssertThat()}.
|
||||
*/
|
||||
// XXX: Application of this rule (and several others in this class) will cause invalid code if the
|
||||
// result of the rewritten expression is dereferenced. Consider introducing a bug checker that
|
||||
// identifies rules that change the return type of an expression and annotates them accordingly.
|
||||
// The associated annotation can then be used to instruct an annotation processor to generate
|
||||
// corresponding `void` rules that match only statements. This would allow the `Refaster` check to
|
||||
// conditionally skip "not fully safe" rules. This allows conditionally flagging more dubious
|
||||
// code, at the risk of compilation failures. With this rule, for example, we want to explicitly
|
||||
// nudge users towards `StepVerifier.Step#assertNext(Consumer)` or
|
||||
// `StepVerifier.Step#expectNext(Object)`, together with `Step#verifyComplete()`.
|
||||
static final class StepVerifierVerify {
|
||||
@BeforeTemplate
|
||||
StepVerifier.Assertions before(StepVerifier stepVerifier) {
|
||||
return stepVerifier.verifyThenAssertThat();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(StepVerifier stepVerifier) {
|
||||
return stepVerifier.verify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link StepVerifier#verify(Duration)} over a dangling {@link
|
||||
* StepVerifier#verifyThenAssertThat(Duration)}.
|
||||
*/
|
||||
static final class StepVerifierVerifyDuration {
|
||||
@BeforeTemplate
|
||||
StepVerifier.Assertions before(StepVerifier stepVerifier, Duration duration) {
|
||||
return stepVerifier.verifyThenAssertThat(duration);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(StepVerifier stepVerifier, Duration duration) {
|
||||
return stepVerifier.verify(duration);
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily invoke {@link StepVerifier#verifyLater()} multiple times. */
|
||||
static final class StepVerifierVerifyLater {
|
||||
@BeforeTemplate
|
||||
StepVerifier before(StepVerifier stepVerifier) {
|
||||
return stepVerifier.verifyLater().verifyLater();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
StepVerifier after(StepVerifier stepVerifier) {
|
||||
return stepVerifier.verifyLater();
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily have {@link StepVerifier.Step} expect no elements. */
|
||||
static final class StepVerifierStepIdentity<T> {
|
||||
@BeforeTemplate
|
||||
@@ -1868,6 +2007,12 @@ final class ReactorRules {
|
||||
return step.expectErrorMatches(predicate).verify();
|
||||
}
|
||||
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("StepVerifierVerify" /* This is a more specific template. */)
|
||||
StepVerifier.Assertions before2(StepVerifier.LastStep step, Predicate<Throwable> predicate) {
|
||||
return step.expectError().verifyThenAssertThat().hasOperatorErrorMatching(predicate);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Duration after(StepVerifier.LastStep step, Predicate<Throwable> predicate) {
|
||||
return step.verifyErrorMatches(predicate);
|
||||
@@ -1890,6 +2035,30 @@ final class ReactorRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link StepVerifier.LastStep#verifyErrorSatisfies(Consumer)} with AssertJ over more
|
||||
* contrived alternatives.
|
||||
*/
|
||||
static final class StepVerifierLastStepVerifyErrorSatisfiesAssertJ<T extends Throwable> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("StepVerifierVerify" /* This is a more specific template. */)
|
||||
StepVerifier.Assertions before(StepVerifier.LastStep step, Class<T> clazz, String message) {
|
||||
return Refaster.anyOf(
|
||||
step.expectError()
|
||||
.verifyThenAssertThat()
|
||||
.hasOperatorErrorOfType(clazz)
|
||||
.hasOperatorErrorWithMessage(message),
|
||||
step.expectError(clazz).verifyThenAssertThat().hasOperatorErrorWithMessage(message),
|
||||
step.expectErrorMessage(message).verifyThenAssertThat().hasOperatorErrorOfType(clazz));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
|
||||
Duration after(StepVerifier.LastStep step, Class<T> clazz, String message) {
|
||||
return step.verifyErrorSatisfies(t -> assertThat(t).isInstanceOf(clazz).hasMessage(message));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link StepVerifier.LastStep#verifyErrorMessage(String)} over more verbose alternatives.
|
||||
*/
|
||||
|
||||
@@ -297,6 +297,22 @@ final class StreamRules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer an unconditional {@link Map#get(Object)} call followed by a {@code null} check over a
|
||||
* call to {@link Map#containsKey(Object)}, as the former avoids a second lookup operation.
|
||||
*/
|
||||
static final class StreamMapFilter<T, K, V> {
|
||||
@BeforeTemplate
|
||||
Stream<V> before(Stream<T> stream, Map<K, V> map) {
|
||||
return stream.filter(map::containsKey).map(map::get);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Stream<V> after(Stream<T> stream, Map<K, V> map) {
|
||||
return stream.map(map::get).filter(Objects::nonNull);
|
||||
}
|
||||
}
|
||||
|
||||
static final class StreamMin<T> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("java:S4266" /* This violation will be rewritten. */)
|
||||
|
||||
@@ -9,10 +9,12 @@ import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Utf8;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.errorprone.annotations.FormatMethod;
|
||||
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 com.google.errorprone.refaster.annotation.UseImportPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -29,11 +31,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);
|
||||
}
|
||||
@@ -345,4 +350,23 @@ final class StringRules {
|
||||
return string.startsWith(prefix, fromIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link String#formatted(Object...)} over {@link String#format(String, Object...)}, as
|
||||
* the former works more nicely with text blocks, while the latter does not appear advantageous in
|
||||
* any circumstance (assuming one targets JDK 15+).
|
||||
*/
|
||||
static final class StringFormatted {
|
||||
@BeforeTemplate
|
||||
@FormatMethod
|
||||
String before(String format, @Repeated Object args) {
|
||||
return String.format(format, args);
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@FormatMethod
|
||||
String after(String format, @Repeated Object args) {
|
||||
return format.formatted(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +142,63 @@ final class TimeRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't unnecessarily transform an {@link Instant} to an equivalent instance. */
|
||||
static final class InstantIdentity {
|
||||
@BeforeTemplate
|
||||
Instant before(Instant instant, TemporalUnit temporalUnit) {
|
||||
return Refaster.anyOf(
|
||||
instant.plus(Duration.ZERO),
|
||||
instant.plus(0, temporalUnit),
|
||||
instant.plusNanos(0),
|
||||
instant.plusMillis(0),
|
||||
instant.plusSeconds(0),
|
||||
instant.minus(Duration.ZERO),
|
||||
instant.minus(0, temporalUnit),
|
||||
instant.minusNanos(0),
|
||||
instant.minusMillis(0),
|
||||
instant.minusSeconds(0),
|
||||
Instant.parse(instant.toString()),
|
||||
instant.truncatedTo(ChronoUnit.NANOS),
|
||||
Instant.ofEpochSecond(instant.getEpochSecond(), instant.getNano()));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Instant after(Instant instant) {
|
||||
return instant;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer {@link Instant#truncatedTo(TemporalUnit)} over less obvious alternatives.
|
||||
*
|
||||
* <p>Note that {@link Instant#toEpochMilli()} throws an {@link ArithmeticException} for dates
|
||||
* very far in the past or future, while the suggested alternative doesn't.
|
||||
*/
|
||||
static final class InstantTruncatedToMilliseconds {
|
||||
@BeforeTemplate
|
||||
Instant before(Instant instant) {
|
||||
return Instant.ofEpochMilli(instant.toEpochMilli());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Instant after(Instant instant) {
|
||||
return instant.truncatedTo(ChronoUnit.MILLIS);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Instant#truncatedTo(TemporalUnit)} over less obvious alternatives. */
|
||||
static final class InstantTruncatedToSeconds {
|
||||
@BeforeTemplate
|
||||
Instant before(Instant instant) {
|
||||
return Instant.ofEpochSecond(instant.getEpochSecond());
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
Instant after(Instant instant) {
|
||||
return instant.truncatedTo(ChronoUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link Instant#atOffset(ZoneOffset)} over more verbose alternatives. */
|
||||
static final class InstantAtOffset {
|
||||
@BeforeTemplate
|
||||
|
||||
@@ -16,7 +16,7 @@ final class ClassCastLambdaUsageTest {
|
||||
"import java.util.stream.Stream;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" <T> void m() {",
|
||||
" Number localVariable = 0;",
|
||||
"",
|
||||
" Stream.of(0).map(i -> i);",
|
||||
@@ -32,13 +32,14 @@ final class ClassCastLambdaUsageTest {
|
||||
" i -> {",
|
||||
" return (Integer) i;",
|
||||
" });",
|
||||
" Stream.<ImmutableSet>of(ImmutableSet.of(5)).map(s -> (ImmutableSet<Number>) s);",
|
||||
" Stream.of(ImmutableSet.of(6)).map(s -> (ImmutableSet<?>) s);",
|
||||
" Stream.of(7).reduce((a, b) -> (Integer) a);",
|
||||
" IntStream.of(8).mapToObj(i -> (char) i);",
|
||||
" Stream.<ImmutableSet>of(ImmutableSet.of(6)).map(s -> (ImmutableSet<Number>) s);",
|
||||
" Stream.of(ImmutableSet.of(7)).map(s -> (ImmutableSet<?>) s);",
|
||||
" Stream.of(8).reduce((a, b) -> (Integer) a);",
|
||||
" IntStream.of(9).mapToObj(i -> (char) i);",
|
||||
" Stream.of(10).map(i -> (T) i);",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Stream.of(8).map(i -> (Integer) i);",
|
||||
" Stream.of(11).map(i -> (Integer) i);",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class ExplicitArgumentEnumerationTest {
|
||||
@Test
|
||||
void identification() {
|
||||
CompilationTestHelper.newInstance(ExplicitArgumentEnumeration.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"import org.jooq.impl.DSL;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.test.StepVerifier;",
|
||||
"",
|
||||
"class A {",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" private final int value = unaryMethod(ImmutableList.of(1, 2));",
|
||||
"",
|
||||
" void m() {",
|
||||
" ImmutableList<String> list = ImmutableList.of();",
|
||||
" assertThat(ImmutableList.of()).containsAnyElementsOf(list);",
|
||||
"",
|
||||
" ImmutableList.<ImmutableList<String>>builder().add(ImmutableList.of());",
|
||||
"",
|
||||
" DSL.row(ImmutableList.of(1, 2));",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" unaryMethod(ImmutableList.of(1, 2));",
|
||||
" unaryMethodWithLessVisibleOverload(ImmutableList.of(1, 2));",
|
||||
" binaryMethod(ImmutableList.of(1, 2), 3);",
|
||||
"",
|
||||
" ImmutableList.builder()",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" .addAll(ImmutableList.of())",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" .addAll(ImmutableList.copyOf(new String[0]))",
|
||||
" .addAll(ImmutableList.copyOf(ImmutableList.of()))",
|
||||
" .build();",
|
||||
"",
|
||||
" assertThat(ImmutableList.of(1))",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" .containsAnyElementsOf(ImmutableList.of(1))",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" .isSubsetOf(ImmutableList.of(1));",
|
||||
"",
|
||||
" Flux.just(1, 2)",
|
||||
" .as(StepVerifier::create)",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" .expectNextSequence(ImmutableList.of(1, 2))",
|
||||
" .verifyComplete();",
|
||||
"",
|
||||
" CompilationTestHelper.newInstance(BugChecker.class, getClass())",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" .setArgs(ImmutableList.of(\"foo\"))",
|
||||
" .withClasspath();",
|
||||
" }",
|
||||
"",
|
||||
" private int unaryMethod(ImmutableList<Integer> args) {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" private int unaryMethod(Integer... args) {",
|
||||
" return unaryMethod(ImmutableList.copyOf(args));",
|
||||
" }",
|
||||
"",
|
||||
" void unaryMethodWithLessVisibleOverload(ImmutableList<Integer> args) {}",
|
||||
"",
|
||||
" private void unaryMethodWithLessVisibleOverload(Integer... args) {",
|
||||
" unaryMethodWithLessVisibleOverload(ImmutableList.copyOf(args));",
|
||||
" }",
|
||||
"",
|
||||
" private void binaryMethod(ImmutableList<Integer> args, int extraArg) {}",
|
||||
"",
|
||||
" private void binaryMethod(Integer... args) {",
|
||||
" binaryMethod(ImmutableList.copyOf(args), 0);",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(ExplicitArgumentEnumeration.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableMultiset;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"import java.util.Arrays;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Set;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.test.StepVerifier;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" ImmutableList.builder().addAll(ImmutableList.of()).build();",
|
||||
"",
|
||||
" assertThat(ImmutableList.of()).containsAnyElementsOf(ImmutableMultiset.of());",
|
||||
" assertThat(ImmutableList.of()).containsAll(ImmutableSet.of());",
|
||||
" assertThat(ImmutableList.of()).containsExactlyElementsOf(List.of());",
|
||||
" assertThat(ImmutableList.of()).containsExactlyInAnyOrderElementsOf(Set.of());",
|
||||
" assertThat(ImmutableList.of()).containsSequence(Arrays.asList());",
|
||||
" assertThat(ImmutableList.of()).containsSubsequence(ImmutableList.of(1));",
|
||||
" assertThat(ImmutableList.of()).doesNotContainAnyElementsOf(ImmutableMultiset.of(2));",
|
||||
" assertThat(ImmutableList.of()).doesNotContainSequence(ImmutableSet.of(3));",
|
||||
" assertThat(ImmutableList.of()).doesNotContainSubsequence(List.of(4));",
|
||||
" assertThat(ImmutableList.of()).hasSameElementsAs(Set.of(5));",
|
||||
" assertThat(ImmutableList.of()).isSubsetOf(Arrays.asList(6));",
|
||||
"",
|
||||
" Flux.empty()",
|
||||
" .as(StepVerifier::create)",
|
||||
" .expectNextSequence(ImmutableList.of(1, 2))",
|
||||
" .verifyComplete();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(BugChecker.class, getClass())",
|
||||
" .setArgs(ImmutableList.of(\"foo\", \"bar\"));",
|
||||
" CompilationTestHelper.newInstance(BugChecker.class, getClass())",
|
||||
" .setArgs(ImmutableList.of(\"foo\", \"bar\"));",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||
"",
|
||||
"import com.google.common.collect.ImmutableList;",
|
||||
"import com.google.common.collect.ImmutableMultiset;",
|
||||
"import com.google.common.collect.ImmutableSet;",
|
||||
"import com.google.errorprone.BugCheckerRefactoringTestHelper;",
|
||||
"import com.google.errorprone.CompilationTestHelper;",
|
||||
"import com.google.errorprone.bugpatterns.BugChecker;",
|
||||
"import java.util.Arrays;",
|
||||
"import java.util.List;",
|
||||
"import java.util.Set;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.test.StepVerifier;",
|
||||
"",
|
||||
"class A {",
|
||||
" void m() {",
|
||||
" ImmutableList.builder().add().build();",
|
||||
"",
|
||||
" assertThat(ImmutableList.of()).containsAnyOf();",
|
||||
" assertThat(ImmutableList.of()).contains();",
|
||||
" assertThat(ImmutableList.of()).containsExactly();",
|
||||
" assertThat(ImmutableList.of()).containsExactlyInAnyOrder();",
|
||||
" assertThat(ImmutableList.of()).containsSequence();",
|
||||
" assertThat(ImmutableList.of()).containsSubsequence(1);",
|
||||
" assertThat(ImmutableList.of()).doesNotContain(2);",
|
||||
" assertThat(ImmutableList.of()).doesNotContainSequence(3);",
|
||||
" assertThat(ImmutableList.of()).doesNotContainSubsequence(4);",
|
||||
" assertThat(ImmutableList.of()).containsOnly(5);",
|
||||
" assertThat(ImmutableList.of()).isSubsetOf(6);",
|
||||
"",
|
||||
" Flux.empty().as(StepVerifier::create).expectNext(1, 2).verifyComplete();",
|
||||
"",
|
||||
" BugCheckerRefactoringTestHelper.newInstance(BugChecker.class, getClass()).setArgs(\"foo\", \"bar\");",
|
||||
" CompilationTestHelper.newInstance(BugChecker.class, getClass()).setArgs(\"foo\", \"bar\");",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,8 @@ final class IdentityConversionTest {
|
||||
"import com.google.common.collect.ImmutableTable;",
|
||||
"import com.google.errorprone.matchers.Matcher;",
|
||||
"import com.google.errorprone.matchers.Matchers;",
|
||||
"import java.time.Instant;",
|
||||
"import java.time.ZonedDateTime;",
|
||||
"import reactor.adapter.rxjava.RxJava2Adapter;",
|
||||
"import reactor.core.publisher.Flux;",
|
||||
"import reactor.core.publisher.Mono;",
|
||||
@@ -149,6 +151,10 @@ final class IdentityConversionTest {
|
||||
" // BUG: Diagnostic contains:",
|
||||
" ImmutableTable<Object, Object, Object> o11 = ImmutableTable.copyOf(ImmutableTable.of());",
|
||||
"",
|
||||
" Instant instant1 = Instant.from(ZonedDateTime.now());",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Instant instant2 = Instant.from(Instant.now());",
|
||||
"",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" Matcher allOf1 = Matchers.allOf(instanceMethod());",
|
||||
" Matcher allOf2 = Matchers.allOf(instanceMethod(), staticMethod());",
|
||||
|
||||
@@ -11,7 +11,7 @@ final class JUnitMethodDeclarationTest {
|
||||
CompilationTestHelper.newInstance(JUnitMethodDeclaration.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.arguments;",
|
||||
"import static org.junit.jupiter.params.provider.Arguments.*;",
|
||||
"",
|
||||
"import org.junit.jupiter.api.AfterAll;",
|
||||
"import org.junit.jupiter.api.AfterEach;",
|
||||
@@ -154,8 +154,10 @@ final class JUnitMethodDeclarationTest {
|
||||
" void overload() {}",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: (but note that `arguments` is already statically imported)",
|
||||
" void testArguments() {}",
|
||||
" // BUG: Diagnostic contains: (but note that another method named `arguments` is in scope)",
|
||||
" void testArguments() {",
|
||||
" arguments();",
|
||||
" }",
|
||||
"",
|
||||
" @Test",
|
||||
" // BUG: Diagnostic contains: (but note that `public` is not a valid identifier)",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
@@ -294,9 +293,8 @@ final class LexicographicalAnnotationAttributeListingTest {
|
||||
/* Some violations are not flagged because they are not in- or excluded. */
|
||||
CompilationTestHelper.newInstance(LexicographicalAnnotationAttributeListing.class, getClass())
|
||||
.setArgs(
|
||||
ImmutableList.of(
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Includes=pkg.A.Foo,pkg.A.Bar",
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value"))
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Includes=pkg.A.Foo,pkg.A.Bar",
|
||||
"-XepOpt:LexicographicalAnnotationAttributeListing:Excludes=pkg.A.Bar#value")
|
||||
.addSourceLines(
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
@@ -408,8 +407,7 @@ final class RedundantStringConversionTest {
|
||||
void identificationOfCustomConversionMethod() {
|
||||
CompilationTestHelper.newInstance(RedundantStringConversion.class, getClass())
|
||||
.setArgs(
|
||||
ImmutableList.of(
|
||||
"-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)"))
|
||||
"-XepOpt:RedundantStringConversion:ExtraConversionMethods=java.lang.Enum#name(),A#name(),A.B#toString(int)")
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.math.RoundingMode;",
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
final class RedundantStringEscapeTest {
|
||||
@Test
|
||||
void identification() {
|
||||
CompilationTestHelper.newInstance(RedundantStringEscape.class, getClass())
|
||||
.addSourceLines(
|
||||
"A.java",
|
||||
"import java.util.Arrays;",
|
||||
"import java.util.List;",
|
||||
"",
|
||||
"class A {",
|
||||
" List<String> m() {",
|
||||
" return Arrays.asList(",
|
||||
" \"foo\",",
|
||||
" \"ß\",",
|
||||
" \"'\",",
|
||||
" \"\\\"\",",
|
||||
" \"\\\\\",",
|
||||
" \"\\\\'\",",
|
||||
" \"'\\\\\",",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" \"\\\\\\'\",",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" \"\\'\\\\\",",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" \"\\'\",",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" \"'\\'\",",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" \"\\''\",",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" \"\\'\\'\",",
|
||||
" (",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" /* Leading comment. */ \"\\'\" /* Trailing comment. */),",
|
||||
" // BUG: Diagnostic contains:",
|
||||
" \"\\'foo\\\"bar\\'baz\\\"qux\\'\");",
|
||||
" }",
|
||||
"}")
|
||||
.doTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacement() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(RedundantStringEscape.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import java.util.Arrays;",
|
||||
"import java.util.List;",
|
||||
"",
|
||||
"class A {",
|
||||
" List<String> m() {",
|
||||
" return Arrays.asList(",
|
||||
" \"\\'\",",
|
||||
" \"'\\'\",",
|
||||
" \"\\''\",",
|
||||
" \"\\'\\'\",",
|
||||
" \"\\'ß\\'\",",
|
||||
" (",
|
||||
" /* Leading comment. */ \"\\'\" /* Trailing comment. */),",
|
||||
" \"\\'foo\\\"bar\\'baz\\\"qux\\'\");",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"import java.util.Arrays;",
|
||||
"import java.util.List;",
|
||||
"",
|
||||
"class A {",
|
||||
" List<String> m() {",
|
||||
" return Arrays.asList(",
|
||||
" \"'\",",
|
||||
" \"''\",",
|
||||
" \"''\",",
|
||||
" \"''\",",
|
||||
" \"'ß'\",",
|
||||
" (",
|
||||
" /* Leading comment. */ \"'\" /* Trailing comment. */),",
|
||||
" \"'foo\\\"bar'baz\\\"qux'\");",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package tech.picnic.errorprone.bugpatterns;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.CompilationTestHelper;
|
||||
@@ -189,7 +188,7 @@ final class Slf4jLoggerDeclarationTest {
|
||||
@Test
|
||||
void replacementWithCustomLoggerName() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(Slf4jLoggerDeclaration.class, getClass())
|
||||
.setArgs(ImmutableList.of("-XepOpt:Slf4jLogDeclaration:CanonicalStaticLoggerName=FOO_BAR"))
|
||||
.setArgs("-XepOpt:Slf4jLoggerDeclaration:CanonicalStaticLoggerName=FOO_BAR")
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"import org.slf4j.Logger;",
|
||||
|
||||
@@ -36,6 +36,7 @@ final class RefasterRulesTest {
|
||||
AssortedRules.class,
|
||||
BigDecimalRules.class,
|
||||
BugCheckerRules.class,
|
||||
CharSequenceRules.class,
|
||||
ClassRules.class,
|
||||
CollectionRules.class,
|
||||
ComparatorRules.class,
|
||||
|
||||
@@ -33,6 +33,14 @@ final class AssertJStringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return assertThat("foo".isEmpty()).isFalse();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatStringContains() {
|
||||
return assertThat("foo".contains("bar")).isTrue();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatStringDoesNotContain() {
|
||||
return assertThat("foo".contains("bar")).isFalse();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatMatches() {
|
||||
return assertThat("foo".matches(".*")).isTrue();
|
||||
}
|
||||
|
||||
@@ -34,6 +34,14 @@ final class AssertJStringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return assertThat("foo").isNotEmpty();
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatStringContains() {
|
||||
return assertThat("foo").contains("bar");
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatStringDoesNotContain() {
|
||||
return assertThat("foo").doesNotContain("bar");
|
||||
}
|
||||
|
||||
AbstractAssert<?, ?> testAssertThatMatches() {
|
||||
return assertThat("foo").matches(".*");
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.InstanceOfAssertFactories.throwable;
|
||||
import static org.assertj.core.api.InstanceOfAssertFactories.type;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.assertj.core.api.AbstractObjectAssert;
|
||||
@@ -20,7 +22,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
assertThatIOException(),
|
||||
assertThatIllegalArgumentException(),
|
||||
assertThatIllegalStateException(),
|
||||
assertThatNullPointerException());
|
||||
assertThatNullPointerException(),
|
||||
type(Throwable.class));
|
||||
}
|
||||
|
||||
void testAssertThatThrownByIsInstanceOf() {
|
||||
assertThatThrownBy(() -> {}).asInstanceOf(throwable(IllegalArgumentException.class));
|
||||
assertThatThrownBy(() -> {}).asInstanceOf(type(IllegalArgumentException.class));
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalArgumentException() {
|
||||
@@ -31,6 +39,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
return assertThatIllegalArgumentException().isThrownBy(() -> {}).withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalArgumentExceptionRootCauseHasMessage() {
|
||||
return assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> {})
|
||||
.havingRootCause()
|
||||
.withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalArgumentExceptionHasMessageParameters() {
|
||||
return assertThatIllegalArgumentException().isThrownBy(() -> {}).withMessage("foo %s", "bar");
|
||||
}
|
||||
@@ -59,6 +74,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
return assertThatIllegalStateException().isThrownBy(() -> {}).withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalStateExceptionRootCauseHasMessage() {
|
||||
return assertThatIllegalStateException()
|
||||
.isThrownBy(() -> {})
|
||||
.havingRootCause()
|
||||
.withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalStateExceptionHasMessageParameters() {
|
||||
return assertThatIllegalStateException().isThrownBy(() -> {}).withMessage("foo %s", "bar");
|
||||
}
|
||||
@@ -83,6 +105,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
return assertThatNullPointerException().isThrownBy(() -> {}).withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByNullPointerExceptionRootCauseHasMessage() {
|
||||
return assertThatNullPointerException()
|
||||
.isThrownBy(() -> {})
|
||||
.havingRootCause()
|
||||
.withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByNullPointerExceptionHasMessageParameters() {
|
||||
return assertThatNullPointerException().isThrownBy(() -> {}).withMessage("foo %s", "bar");
|
||||
}
|
||||
@@ -107,6 +136,10 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
return assertThatIOException().isThrownBy(() -> {}).withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIOExceptionRootCauseHasMessage() {
|
||||
return assertThatIOException().isThrownBy(() -> {}).havingRootCause().withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIOExceptionHasMessageParameters() {
|
||||
return assertThatIOException().isThrownBy(() -> {}).withMessage("foo %s", "bar");
|
||||
}
|
||||
@@ -123,7 +156,7 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
return assertThatIOException().isThrownBy(() -> {}).withMessageNotContaining("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownBy() {
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByAsInstanceOfThrowable() {
|
||||
return assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> {});
|
||||
}
|
||||
|
||||
@@ -133,6 +166,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
.withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByRootCauseHasMessage() {
|
||||
return assertThatExceptionOfType(IllegalArgumentException.class)
|
||||
.isThrownBy(() -> {})
|
||||
.havingRootCause()
|
||||
.withMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByHasMessageParameters() {
|
||||
return assertThatExceptionOfType(IllegalArgumentException.class)
|
||||
.isThrownBy(() -> {})
|
||||
|
||||
@@ -6,6 +6,8 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.InstanceOfAssertFactories.throwable;
|
||||
import static org.assertj.core.api.InstanceOfAssertFactories.type;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.IOException;
|
||||
@@ -21,7 +23,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
assertThatIOException(),
|
||||
assertThatIllegalArgumentException(),
|
||||
assertThatIllegalStateException(),
|
||||
assertThatNullPointerException());
|
||||
assertThatNullPointerException(),
|
||||
type(Throwable.class));
|
||||
}
|
||||
|
||||
void testAssertThatThrownByIsInstanceOf() {
|
||||
assertThatThrownBy(() -> {}).isInstanceOf(IllegalArgumentException.class);
|
||||
assertThatThrownBy(() -> {}).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalArgumentException() {
|
||||
@@ -34,6 +42,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
.hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalArgumentExceptionRootCauseHasMessage() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.rootCause()
|
||||
.hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalArgumentExceptionHasMessageParameters() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
@@ -68,6 +83,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
return assertThatThrownBy(() -> {}).isInstanceOf(IllegalStateException.class).hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalStateExceptionRootCauseHasMessage() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.rootCause()
|
||||
.hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIllegalStateExceptionHasMessageParameters() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
@@ -100,6 +122,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
return assertThatThrownBy(() -> {}).isInstanceOf(NullPointerException.class).hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByNullPointerExceptionRootCauseHasMessage() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
.rootCause()
|
||||
.hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByNullPointerExceptionHasMessageParameters() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(NullPointerException.class)
|
||||
@@ -132,6 +161,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
return assertThatThrownBy(() -> {}).isInstanceOf(IOException.class).hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIOExceptionRootCauseHasMessage() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(IOException.class)
|
||||
.rootCause()
|
||||
.hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByIOExceptionHasMessageParameters() {
|
||||
return assertThatThrownBy(() -> {}).isInstanceOf(IOException.class).hasMessage("foo %s", "bar");
|
||||
}
|
||||
@@ -152,8 +188,8 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
.hasMessageNotContaining("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownBy() {
|
||||
return assertThatThrownBy(() -> {}).isInstanceOf(IllegalArgumentException.class);
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByAsInstanceOfThrowable() {
|
||||
return assertThatThrownBy(() -> {}).asInstanceOf(throwable(IllegalArgumentException.class));
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByHasMessage() {
|
||||
@@ -162,6 +198,13 @@ final class AssertJThrowingCallableRulesTest implements RefasterRuleCollectionTe
|
||||
.hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByRootCauseHasMessage() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.rootCause()
|
||||
.hasMessage("foo");
|
||||
}
|
||||
|
||||
AbstractObjectAssert<?, ?> testAssertThatThrownByHasMessageParameters() {
|
||||
return assertThatThrownBy(() -> {})
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.sun.tools.javac.util.Constants;
|
||||
import com.sun.tools.javac.util.Convert;
|
||||
import javax.lang.model.element.Name;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
@@ -11,7 +12,7 @@ import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(Convert.class, FixChoosers.class);
|
||||
return ImmutableSet.of(Constants.class, Convert.class, FixChoosers.class);
|
||||
}
|
||||
|
||||
ImmutableSet<BugCheckerRefactoringTestHelper> testBugCheckerRefactoringTestHelperIdentity() {
|
||||
@@ -29,8 +30,8 @@ final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
|
||||
.addOutputLines("A.java", "class A {}");
|
||||
}
|
||||
|
||||
String testConstantsFormat() {
|
||||
return String.format("\"%s\"", Convert.quote("foo"));
|
||||
ImmutableSet<String> testConstantsFormat() {
|
||||
return ImmutableSet.of(Constants.format("foo"), String.format("\"%s\"", Convert.quote("bar")));
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testNameContentEquals() {
|
||||
|
||||
@@ -8,11 +8,12 @@ import com.sun.tools.javac.util.Constants;
|
||||
import com.sun.tools.javac.util.Convert;
|
||||
import javax.lang.model.element.Name;
|
||||
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(Convert.class, FixChoosers.class);
|
||||
return ImmutableSet.of(Constants.class, Convert.class, FixChoosers.class);
|
||||
}
|
||||
|
||||
ImmutableSet<BugCheckerRefactoringTestHelper> testBugCheckerRefactoringTestHelperIdentity() {
|
||||
@@ -28,8 +29,10 @@ final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
|
||||
.expectUnchanged();
|
||||
}
|
||||
|
||||
String testConstantsFormat() {
|
||||
return Constants.format("foo");
|
||||
ImmutableSet<String> testConstantsFormat() {
|
||||
return ImmutableSet.of(
|
||||
SourceCode.toStringConstantExpression("foo", /* REPLACEME */ null),
|
||||
SourceCode.toStringConstantExpression("bar", /* REPLACEME */ null));
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testNameContentEquals() {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
List.class,
|
||||
ImmutableCollection.class,
|
||||
ImmutableMap.class,
|
||||
assertThat(false),
|
||||
assertThat(0),
|
||||
maxBy(null),
|
||||
minBy(null),
|
||||
@@ -589,6 +590,35 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableSet.of(PublisherProbe.of(Mono.empty()), PublisherProbe.of(Flux.empty()));
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasSubscribed() {
|
||||
assertThat(PublisherProbe.of(Mono.just(1)).wasSubscribed()).isTrue();
|
||||
assertThat(PublisherProbe.of(Mono.just(2)).subscribeCount()).isNotNegative();
|
||||
assertThat(PublisherProbe.of(Mono.just(3)).subscribeCount()).isNotEqualTo(0);
|
||||
assertThat(PublisherProbe.of(Mono.just(4)).subscribeCount()).isPositive();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasNotSubscribed() {
|
||||
assertThat(PublisherProbe.of(Mono.just(1)).wasSubscribed()).isFalse();
|
||||
assertThat(PublisherProbe.of(Mono.just(2)).subscribeCount()).isEqualTo(0);
|
||||
assertThat(PublisherProbe.of(Mono.just(3)).subscribeCount()).isNotPositive();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasCancelled() {
|
||||
assertThat(PublisherProbe.empty().wasCancelled()).isTrue();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasNotCancelled() {
|
||||
assertThat(PublisherProbe.empty().wasCancelled()).isFalse();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasRequested() {
|
||||
assertThat(PublisherProbe.empty().wasRequested()).isTrue();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasNotRequested() {
|
||||
assertThat(PublisherProbe.empty().wasRequested()).isFalse();
|
||||
}
|
||||
|
||||
ImmutableSet<StepVerifier.FirstStep<Integer>> testStepVerifierFromMono() {
|
||||
return ImmutableSet.of(
|
||||
StepVerifier.create(Mono.just(1)), Mono.just(2).flux().as(StepVerifier::create));
|
||||
@@ -598,6 +628,18 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return StepVerifier.create(Flux.just(1));
|
||||
}
|
||||
|
||||
Object testStepVerifierVerify() {
|
||||
return Mono.empty().as(StepVerifier::create).expectError().verifyThenAssertThat();
|
||||
}
|
||||
|
||||
Object testStepVerifierVerifyDuration() {
|
||||
return Mono.empty().as(StepVerifier::create).expectError().verifyThenAssertThat(Duration.ZERO);
|
||||
}
|
||||
|
||||
StepVerifier testStepVerifierVerifyLater() {
|
||||
return Mono.empty().as(StepVerifier::create).expectError().verifyLater().verifyLater();
|
||||
}
|
||||
|
||||
ImmutableSet<StepVerifier.Step<Integer>> testStepVerifierStepIdentity() {
|
||||
return ImmutableSet.of(
|
||||
Mono.just(1).as(StepVerifier::create).expectNext(),
|
||||
@@ -638,17 +680,43 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
.verifyErrorSatisfies(t -> assertThat(t).isInstanceOf(AssertionError.class)));
|
||||
}
|
||||
|
||||
Duration testStepVerifierLastStepVerifyErrorMatches() {
|
||||
return Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.expectErrorMatches(IllegalArgumentException.class::equals)
|
||||
.verify();
|
||||
ImmutableSet<?> testStepVerifierLastStepVerifyErrorMatches() {
|
||||
return ImmutableSet.of(
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.expectErrorMatches(IllegalArgumentException.class::equals)
|
||||
.verify(),
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.expectError()
|
||||
.verifyThenAssertThat()
|
||||
.hasOperatorErrorMatching(IllegalStateException.class::equals));
|
||||
}
|
||||
|
||||
Duration testStepVerifierLastStepVerifyErrorSatisfies() {
|
||||
return Mono.empty().as(StepVerifier::create).expectErrorSatisfies(t -> {}).verify();
|
||||
}
|
||||
|
||||
ImmutableSet<?> testStepVerifierLastStepVerifyErrorSatisfiesAssertJ() {
|
||||
return ImmutableSet.of(
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.expectError()
|
||||
.verifyThenAssertThat()
|
||||
.hasOperatorErrorOfType(IllegalArgumentException.class)
|
||||
.hasOperatorErrorWithMessage("foo"),
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.expectError(IllegalStateException.class)
|
||||
.verifyThenAssertThat()
|
||||
.hasOperatorErrorWithMessage("bar"),
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.expectErrorMessage("baz")
|
||||
.verifyThenAssertThat()
|
||||
.hasOperatorErrorOfType(AssertionError.class));
|
||||
}
|
||||
|
||||
Duration testStepVerifierLastStepVerifyErrorMessage() {
|
||||
return Mono.empty().as(StepVerifier::create).expectErrorMessage("foo").verify();
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
List.class,
|
||||
ImmutableCollection.class,
|
||||
ImmutableMap.class,
|
||||
assertThat(false),
|
||||
assertThat(0),
|
||||
maxBy(null),
|
||||
minBy(null),
|
||||
@@ -577,6 +578,35 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableSet.of(PublisherProbe.empty(), PublisherProbe.empty());
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasSubscribed() {
|
||||
PublisherProbe.of(Mono.just(1)).assertWasSubscribed();
|
||||
PublisherProbe.of(Mono.just(2)).assertWasSubscribed();
|
||||
PublisherProbe.of(Mono.just(3)).assertWasSubscribed();
|
||||
PublisherProbe.of(Mono.just(4)).assertWasSubscribed();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasNotSubscribed() {
|
||||
PublisherProbe.of(Mono.just(1)).assertWasNotSubscribed();
|
||||
PublisherProbe.of(Mono.just(2)).assertWasNotSubscribed();
|
||||
PublisherProbe.of(Mono.just(3)).assertWasNotSubscribed();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasCancelled() {
|
||||
PublisherProbe.empty().assertWasCancelled();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasNotCancelled() {
|
||||
PublisherProbe.empty().assertWasNotCancelled();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasRequested() {
|
||||
PublisherProbe.empty().assertWasRequested();
|
||||
}
|
||||
|
||||
void testPublisherProbeAssertWasNotRequested() {
|
||||
PublisherProbe.empty().assertWasNotRequested();
|
||||
}
|
||||
|
||||
ImmutableSet<StepVerifier.FirstStep<Integer>> testStepVerifierFromMono() {
|
||||
return ImmutableSet.of(
|
||||
Mono.just(1).as(StepVerifier::create), Mono.just(2).as(StepVerifier::create));
|
||||
@@ -586,6 +616,18 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Flux.just(1).as(StepVerifier::create);
|
||||
}
|
||||
|
||||
Object testStepVerifierVerify() {
|
||||
return Mono.empty().as(StepVerifier::create).expectError().verify();
|
||||
}
|
||||
|
||||
Object testStepVerifierVerifyDuration() {
|
||||
return Mono.empty().as(StepVerifier::create).expectError().verify(Duration.ZERO);
|
||||
}
|
||||
|
||||
StepVerifier testStepVerifierVerifyLater() {
|
||||
return Mono.empty().as(StepVerifier::create).expectError().verifyLater();
|
||||
}
|
||||
|
||||
ImmutableSet<StepVerifier.Step<Integer>> testStepVerifierStepIdentity() {
|
||||
return ImmutableSet.of(
|
||||
Mono.just(1).as(StepVerifier::create),
|
||||
@@ -619,16 +661,36 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Mono.empty().as(StepVerifier::create).verifyError(AssertionError.class));
|
||||
}
|
||||
|
||||
Duration testStepVerifierLastStepVerifyErrorMatches() {
|
||||
return Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.verifyErrorMatches(IllegalArgumentException.class::equals);
|
||||
ImmutableSet<?> testStepVerifierLastStepVerifyErrorMatches() {
|
||||
return ImmutableSet.of(
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.verifyErrorMatches(IllegalArgumentException.class::equals),
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.verifyErrorMatches(IllegalStateException.class::equals));
|
||||
}
|
||||
|
||||
Duration testStepVerifierLastStepVerifyErrorSatisfies() {
|
||||
return Mono.empty().as(StepVerifier::create).verifyErrorSatisfies(t -> {});
|
||||
}
|
||||
|
||||
ImmutableSet<?> testStepVerifierLastStepVerifyErrorSatisfiesAssertJ() {
|
||||
return ImmutableSet.of(
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.verifyErrorSatisfies(
|
||||
t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("foo")),
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.verifyErrorSatisfies(
|
||||
t -> assertThat(t).isInstanceOf(IllegalStateException.class).hasMessage("bar")),
|
||||
Mono.empty()
|
||||
.as(StepVerifier::create)
|
||||
.verifyErrorSatisfies(
|
||||
t -> assertThat(t).isInstanceOf(AssertionError.class).hasMessage("baz")));
|
||||
}
|
||||
|
||||
Duration testStepVerifierLastStepVerifyErrorMessage() {
|
||||
return Mono.empty().as(StepVerifier::create).verifyErrorMessage("foo");
|
||||
}
|
||||
|
||||
@@ -141,6 +141,12 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Stream.of(1).findFirst().isPresent();
|
||||
}
|
||||
|
||||
Stream<Integer> testStreamMapFilter() {
|
||||
return Stream.of("foo")
|
||||
.filter(ImmutableMap.of(1, 2)::containsKey)
|
||||
.map(ImmutableMap.of(1, 2)::get);
|
||||
}
|
||||
|
||||
ImmutableSet<Optional<String>> testStreamMin() {
|
||||
return ImmutableSet.of(
|
||||
Stream.of("foo").max(comparingInt(String::length).reversed()),
|
||||
|
||||
@@ -141,6 +141,10 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Stream.of(1).findAny().isPresent();
|
||||
}
|
||||
|
||||
Stream<Integer> testStreamMapFilter() {
|
||||
return Stream.of("foo").map(ImmutableMap.of(1, 2)::get).filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
ImmutableSet<Optional<String>> testStreamMin() {
|
||||
return ImmutableSet.of(
|
||||
Stream.of("foo").min(comparingInt(String::length)),
|
||||
|
||||
@@ -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() {
|
||||
@@ -124,4 +124,8 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
boolean testStringStartsWith() {
|
||||
return "foo".substring(1).startsWith("bar");
|
||||
}
|
||||
|
||||
String testStringFormatted() {
|
||||
return String.format("%s%s", "foo", "bar");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
@@ -124,4 +124,8 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
|
||||
boolean testStringStartsWith() {
|
||||
return "foo".startsWith("bar", 1);
|
||||
}
|
||||
|
||||
String testStringFormatted() {
|
||||
return "%s%s".formatted("foo", "bar");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,32 @@ final class TimeRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return Instant.EPOCH.atZone(ZoneOffset.UTC).toOffsetDateTime();
|
||||
}
|
||||
|
||||
ImmutableSet<Instant> testInstantIdentity() {
|
||||
return ImmutableSet.of(
|
||||
Instant.EPOCH.plusMillis(1).plus(Duration.ZERO),
|
||||
Instant.EPOCH.plusMillis(2).plus(0, ChronoUnit.MILLIS),
|
||||
Instant.EPOCH.plusMillis(3).plusNanos(0L),
|
||||
Instant.EPOCH.plusMillis(4).plusMillis(0),
|
||||
Instant.EPOCH.plusMillis(5).plusSeconds(0L),
|
||||
Instant.EPOCH.plusMillis(6).minus(Duration.ZERO),
|
||||
Instant.EPOCH.plusMillis(7).minus(0, ChronoUnit.SECONDS),
|
||||
Instant.EPOCH.plusMillis(8).minusNanos(0L),
|
||||
Instant.EPOCH.plusMillis(9).minusMillis(0),
|
||||
Instant.EPOCH.plusMillis(10).minusSeconds(0L),
|
||||
Instant.parse(Instant.EPOCH.plusMillis(11).toString()),
|
||||
Instant.EPOCH.plusMillis(12).truncatedTo(ChronoUnit.NANOS),
|
||||
Instant.ofEpochSecond(
|
||||
Instant.EPOCH.plusMillis(13).getEpochSecond(), Instant.EPOCH.plusMillis(13).getNano()));
|
||||
}
|
||||
|
||||
Instant testInstantTruncatedToMilliseconds() {
|
||||
return Instant.ofEpochMilli(Instant.EPOCH.toEpochMilli());
|
||||
}
|
||||
|
||||
Instant testInstantTruncatedToSeconds() {
|
||||
return Instant.ofEpochSecond(Instant.EPOCH.getEpochSecond());
|
||||
}
|
||||
|
||||
OffsetDateTime testInstantAtOffset() {
|
||||
return OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,31 @@ final class TimeRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return OffsetDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
ImmutableSet<Instant> testInstantIdentity() {
|
||||
return ImmutableSet.of(
|
||||
Instant.EPOCH.plusMillis(1),
|
||||
Instant.EPOCH.plusMillis(2),
|
||||
Instant.EPOCH.plusMillis(3),
|
||||
Instant.EPOCH.plusMillis(4),
|
||||
Instant.EPOCH.plusMillis(5),
|
||||
Instant.EPOCH.plusMillis(6),
|
||||
Instant.EPOCH.plusMillis(7),
|
||||
Instant.EPOCH.plusMillis(8),
|
||||
Instant.EPOCH.plusMillis(9),
|
||||
Instant.EPOCH.plusMillis(10),
|
||||
Instant.EPOCH.plusMillis(11),
|
||||
Instant.EPOCH.plusMillis(12),
|
||||
Instant.EPOCH.plusMillis(13));
|
||||
}
|
||||
|
||||
Instant testInstantTruncatedToMilliseconds() {
|
||||
return Instant.EPOCH.truncatedTo(ChronoUnit.MILLIS);
|
||||
}
|
||||
|
||||
Instant testInstantTruncatedToSeconds() {
|
||||
return Instant.EPOCH.truncatedTo(ChronoUnit.SECONDS);
|
||||
}
|
||||
|
||||
OffsetDateTime testInstantAtOffset() {
|
||||
return Instant.EPOCH.atOffset(ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
@@ -118,6 +118,9 @@
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs combine.children="append">
|
||||
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@@ -30,8 +30,8 @@ import com.sun.source.tree.BinaryTree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.Tree.Kind;
|
||||
import com.sun.tools.javac.util.Constants;
|
||||
import javax.lang.model.element.Name;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags {@link BugChecker} declarations inside {@code
|
||||
@@ -126,7 +126,9 @@ public final class BugPatternLink extends BugChecker implements ClassTreeMatcher
|
||||
state,
|
||||
"link",
|
||||
ImmutableList.of(
|
||||
linkPrefix + " + " + Constants.format(tree.getSimpleName().toString()))));
|
||||
linkPrefix
|
||||
+ " + "
|
||||
+ SourceCode.toStringConstantExpression(tree.getSimpleName(), state))));
|
||||
|
||||
String linkType =
|
||||
SuggestedFixes.qualifyStaticImport(
|
||||
|
||||
@@ -26,8 +26,8 @@ import com.sun.source.tree.LiteralTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.util.Constants;
|
||||
import java.util.regex.Pattern;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
import tech.picnic.errorprone.utils.ThirdPartyLibrary;
|
||||
|
||||
/**
|
||||
@@ -123,7 +123,8 @@ public final class ErrorProneRuntimeClasspath extends BugChecker
|
||||
.setMessage("This type may not be on the runtime classpath; use a string literal instead")
|
||||
.addFix(
|
||||
SuggestedFix.replace(
|
||||
tree, Constants.format(receiver.owner.getQualifiedName().toString())))
|
||||
tree,
|
||||
SourceCode.toStringConstantExpression(receiver.owner.getQualifiedName(), state)))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -150,7 +151,9 @@ public final class ErrorProneRuntimeClasspath extends BugChecker
|
||||
original,
|
||||
identifier
|
||||
+ ".class.getCanonicalName()"
|
||||
+ (suffix.isEmpty() ? "" : (" + " + Constants.format(suffix))))
|
||||
+ (suffix.isEmpty()
|
||||
? ""
|
||||
: (" + " + SourceCode.toStringConstantExpression(suffix, state))))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ import com.sun.tools.javac.code.Attribute;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.TypeSymbol;
|
||||
import com.sun.tools.javac.util.Constants;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -49,6 +48,7 @@ import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that validates the claim made by {@link
|
||||
@@ -129,7 +129,9 @@ public final class ExhaustiveRefasterTypeMigration extends BugChecker implements
|
||||
migrationAnnotation,
|
||||
state,
|
||||
TYPE_MIGRATION_UNMIGRATED_METHODS_ELEMENT,
|
||||
unmigratedMethods.stream().map(Constants::format).collect(toImmutableList()))
|
||||
unmigratedMethods.stream()
|
||||
.map(m -> SourceCode.toStringConstantExpression(m, state))
|
||||
.collect(toImmutableList()))
|
||||
.build());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package tech.picnic.errorprone.utils;
|
||||
|
||||
import static tech.picnic.errorprone.utils.JavaKeywords.isValidIdentifier;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.ImportTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.IdentifierTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import java.util.Optional;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/** A set of helper methods for detecting conflicts that would be caused when applying fixes. */
|
||||
public final class ConflictDetection {
|
||||
@@ -24,9 +27,10 @@ public final class ConflictDetection {
|
||||
* <ul>
|
||||
* <li>Whether the rename would merely introduce a method overload, rather than clashing with an
|
||||
* existing method declaration in its class or a supertype.
|
||||
* <li>Whether the rename would in fact clash with a static import. (It could be that a static
|
||||
* import of the same name is only referenced from lexical scopes in which the method under
|
||||
* consideration cannot be referenced directly.)
|
||||
* <li>Whether the rename would in fact change the target of an existing method invocation in
|
||||
* the scope of its containing class. (It could e.g. be that said invocation targets an
|
||||
* identically-named method with different parameter types in some non-static nested type
|
||||
* declaration.)
|
||||
* </ul>
|
||||
*
|
||||
* @param method The method considered for renaming.
|
||||
@@ -43,11 +47,11 @@ public final class ConflictDetection {
|
||||
"a method named `%s` is already defined in this class or a supertype", newName));
|
||||
}
|
||||
|
||||
if (isSimpleNameStaticallyImported(newName, state)) {
|
||||
return Optional.of(String.format("`%s` is already statically imported", newName));
|
||||
if (isLocalMethodInvocation(newName, state)) {
|
||||
return Optional.of(String.format("another method named `%s` is in scope", newName));
|
||||
}
|
||||
|
||||
if (!isValidIdentifier(newName)) {
|
||||
if (!SourceCode.isValidIdentifier(newName)) {
|
||||
return Optional.of(String.format("`%s` is not a valid identifier", newName));
|
||||
}
|
||||
|
||||
@@ -60,16 +64,35 @@ public final class ConflictDetection {
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
private static boolean isSimpleNameStaticallyImported(String simpleName, VisitorState state) {
|
||||
return state.getPath().getCompilationUnit().getImports().stream()
|
||||
.filter(ImportTree::isStatic)
|
||||
.map(ImportTree::getQualifiedIdentifier)
|
||||
.map(tree -> getStaticImportSimpleName(tree, state))
|
||||
.anyMatch(simpleName::contentEquals);
|
||||
}
|
||||
private static boolean isLocalMethodInvocation(String name, VisitorState state) {
|
||||
return Boolean.TRUE.equals(
|
||||
new TreeScanner<Boolean, @Nullable Void>() {
|
||||
@Override
|
||||
public Boolean visitClass(ClassTree tree, @Nullable Void unused) {
|
||||
if (ASTHelpers.getSymbol(tree).isStatic()) {
|
||||
/*
|
||||
* Don't descend into static type definitions: in those context, any unqualified
|
||||
* method invocation cannot refer to a method in the outer scope.
|
||||
*/
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
private static CharSequence getStaticImportSimpleName(Tree tree, VisitorState state) {
|
||||
String source = SourceCode.treeToString(tree, state);
|
||||
return source.subSequence(source.lastIndexOf('.') + 1, source.length());
|
||||
return super.visitClass(tree, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitMethodInvocation(MethodInvocationTree tree, @Nullable Void unused) {
|
||||
return (tree.getMethodSelect() instanceof IdentifierTree identifier
|
||||
&& name.contentEquals(identifier.getName()))
|
||||
|| super.visitMethodInvocation(tree, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean reduce(Boolean r1, Boolean r2) {
|
||||
return Boolean.TRUE.equals(r1) || Boolean.TRUE.equals(r2);
|
||||
}
|
||||
}.scan(
|
||||
requireNonNull(state.findEnclosing(ClassTree.class), "No enclosing class").getMembers(),
|
||||
null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
package tech.picnic.errorprone.utils;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/** Utility class that can be used to identify reserved keywords of the Java language. */
|
||||
// XXX: This class is no longer only about keywords. Consider changing its name and class-level
|
||||
// documentation.
|
||||
public final class JavaKeywords {
|
||||
/**
|
||||
* Enumeration of boolean and null literals.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.10.3">JDK 17
|
||||
* JLS section 3.10.3: Boolean Literals</a>
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.10.8">JDK 17
|
||||
* JLS section 3.10.8: The Null Literal</a>
|
||||
*/
|
||||
private static final ImmutableSet<String> BOOLEAN_AND_NULL_LITERALS =
|
||||
ImmutableSet.of("true", "false", "null");
|
||||
|
||||
/**
|
||||
* List of all reserved keywords in the Java language.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.9">JDK 17 JLS
|
||||
* section 3.9: Keywords</a>
|
||||
*/
|
||||
private static final ImmutableSet<String> RESERVED_KEYWORDS =
|
||||
ImmutableSet.of(
|
||||
"_",
|
||||
"abstract",
|
||||
"assert",
|
||||
"boolean",
|
||||
"break",
|
||||
"byte",
|
||||
"case",
|
||||
"catch",
|
||||
"char",
|
||||
"class",
|
||||
"const",
|
||||
"continue",
|
||||
"default",
|
||||
"do",
|
||||
"double",
|
||||
"else",
|
||||
"enum",
|
||||
"extends",
|
||||
"final",
|
||||
"finally",
|
||||
"float",
|
||||
"for",
|
||||
"goto",
|
||||
"if",
|
||||
"implements",
|
||||
"import",
|
||||
"instanceof",
|
||||
"int",
|
||||
"interface",
|
||||
"long",
|
||||
"native",
|
||||
"new",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"return",
|
||||
"short",
|
||||
"static",
|
||||
"strictfp",
|
||||
"super",
|
||||
"switch",
|
||||
"synchronized",
|
||||
"this",
|
||||
"throw",
|
||||
"throws",
|
||||
"transient",
|
||||
"try",
|
||||
"void",
|
||||
"volatile",
|
||||
"while");
|
||||
|
||||
/**
|
||||
* List of all contextual keywords in the Java language.
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.9">JDK 17 JLS
|
||||
* section 3.9: Keywords</a>
|
||||
*/
|
||||
private static final ImmutableSet<String> CONTEXTUAL_KEYWORDS =
|
||||
ImmutableSet.of(
|
||||
"exports",
|
||||
"module",
|
||||
"non-sealed",
|
||||
"open",
|
||||
"opens",
|
||||
"permits",
|
||||
"provides",
|
||||
"record",
|
||||
"requires",
|
||||
"sealed",
|
||||
"to",
|
||||
"transitive",
|
||||
"uses",
|
||||
"var",
|
||||
"with",
|
||||
"yield");
|
||||
|
||||
/** List of all keywords in the Java language. */
|
||||
private static final ImmutableSet<String> ALL_KEYWORDS =
|
||||
Sets.union(RESERVED_KEYWORDS, CONTEXTUAL_KEYWORDS).immutableCopy();
|
||||
|
||||
private JavaKeywords() {}
|
||||
|
||||
/**
|
||||
* Tells whether the given string is a valid identifier in the Java language.
|
||||
*
|
||||
* @param str The string of interest.
|
||||
* @return {@code true} if the given string is a valid identifier in the Java language.
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.8">JDK 17 JLS
|
||||
* section 3.8: Identifiers</a>
|
||||
*/
|
||||
@SuppressWarnings("java:S1067" /* Chaining conjunctions like this does not impact readability. */)
|
||||
public static boolean isValidIdentifier(String str) {
|
||||
return !str.isEmpty()
|
||||
&& !isReservedKeyword(str)
|
||||
&& !BOOLEAN_AND_NULL_LITERALS.contains(str)
|
||||
&& Character.isJavaIdentifierStart(str.codePointAt(0))
|
||||
&& str.codePoints().skip(1).allMatch(Character::isUnicodeIdentifierPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the given string is a reserved keyword in the Java language.
|
||||
*
|
||||
* @param str The string of interest.
|
||||
* @return {@code true} if the given string is a reserved keyword in the Java language.
|
||||
*/
|
||||
public static boolean isReservedKeyword(String str) {
|
||||
return RESERVED_KEYWORDS.contains(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the given string is a contextual keyword in the Java language.
|
||||
*
|
||||
* @param str The string of interest.
|
||||
* @return {@code true} if the given string is a contextual keyword in the Java language.
|
||||
*/
|
||||
public static boolean isContextualKeyword(String str) {
|
||||
return CONTEXTUAL_KEYWORDS.contains(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the given string is a reserved or contextual keyword in the Java language.
|
||||
*
|
||||
* @param str The string of interest.
|
||||
* @return {@code true} if the given string is a reserved or contextual keyword in the Java
|
||||
* language.
|
||||
*/
|
||||
public static boolean isKeyword(String str) {
|
||||
return ALL_KEYWORDS.contains(str);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import com.sun.source.tree.Tree;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.Position;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.SourceVersion;
|
||||
|
||||
/**
|
||||
* A collection of Error Prone utility methods for dealing with the source code representation of
|
||||
@@ -28,6 +29,18 @@ public final class SourceCode {
|
||||
|
||||
private SourceCode() {}
|
||||
|
||||
/**
|
||||
* Tells whether the given string is a valid identifier in the Java language.
|
||||
*
|
||||
* @param str The string of interest.
|
||||
* @return {@code true} if the given string is a valid identifier in the Java language.
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.8">JDK 17 JLS
|
||||
* section 3.8: Identifiers</a>
|
||||
*/
|
||||
public static boolean isValidIdentifier(String str) {
|
||||
return str.indexOf('.') < 0 && SourceVersion.isName(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the given {@link Tree}, preferring the original source code
|
||||
* (if available) over its prettified representation.
|
||||
@@ -42,6 +55,24 @@ public final class SourceCode {
|
||||
return src != null ? src : tree.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Java string constant expression (i.e., a quoted string) representing the given input.
|
||||
*
|
||||
* @param value The value of interest.
|
||||
* @param state A {@link VisitorState} describing the context in which the given {@link Tree} is
|
||||
* found.
|
||||
* @return A non-{@code null} string.
|
||||
* @apiNote This method differs from {@link com.sun.tools.javac.util.Constants#format(Object)} in
|
||||
* that it does not superfluously escape single quote characters. It is different from {@link
|
||||
* VisitorState#getConstantExpression(Object)} in that it is more performant and accepts any
|
||||
* {@link CharSequence} instance.
|
||||
*/
|
||||
// XXX: Drop this method if https://github.com/google/error-prone/pull/4586 is merged and released
|
||||
// with the proposed `CharSequence` compatibility change.
|
||||
public static String toStringConstantExpression(Object value, VisitorState state) {
|
||||
return state.getConstantExpression(value instanceof CharSequence ? value.toString() : value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SuggestedFix} for the deletion of the given {@link Tree}, including any
|
||||
* whitespace that follows it.
|
||||
|
||||
@@ -21,13 +21,13 @@ final class ConflictDetectionTest {
|
||||
"pkg/A.java",
|
||||
"package pkg;",
|
||||
"",
|
||||
"import static pkg.A.B.method3t;",
|
||||
"import static pkg.A.StaticType.method3t;",
|
||||
"import static pkg.A.StaticType.method4t;",
|
||||
"",
|
||||
"import pkg.A.method4t;",
|
||||
"",
|
||||
"class A {",
|
||||
" void method1() {",
|
||||
" method3t();",
|
||||
" method4(method4t.class);",
|
||||
" }",
|
||||
"",
|
||||
@@ -37,7 +37,7 @@ final class ConflictDetectionTest {
|
||||
"",
|
||||
" void method2t() {}",
|
||||
"",
|
||||
" // BUG: Diagnostic contains: `method3t` is already statically imported",
|
||||
" // BUG: Diagnostic contains: another method named `method3t` is in scope",
|
||||
" void method3() {}",
|
||||
"",
|
||||
" void method4(Object o) {}",
|
||||
@@ -45,8 +45,34 @@ final class ConflictDetectionTest {
|
||||
" // BUG: Diagnostic contains: `int` is not a valid identifier",
|
||||
" void in() {}",
|
||||
"",
|
||||
" static class B {",
|
||||
" static void method3t() {}",
|
||||
" class InstanceType {",
|
||||
" void m() {",
|
||||
" System.out.println(method3t());",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" static class StaticType {",
|
||||
" static int method3t() {",
|
||||
" return 0;",
|
||||
" }",
|
||||
"",
|
||||
" static void method4t() {",
|
||||
" method4t();",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" record RecordType() {",
|
||||
" void m() {",
|
||||
" method4t();",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" enum EnumType {",
|
||||
" ELEM;",
|
||||
"",
|
||||
" void m() {",
|
||||
" method4t();",
|
||||
" }",
|
||||
" }",
|
||||
"",
|
||||
" class method4t {}",
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package tech.picnic.errorprone.utils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
final class JavaKeywordsTest {
|
||||
private static Stream<Arguments> isValidIdentifierTestCases() {
|
||||
/* { string, expected } */
|
||||
return Stream.of(
|
||||
arguments("", false),
|
||||
arguments("public", false),
|
||||
arguments("true", false),
|
||||
arguments("false", false),
|
||||
arguments("null", false),
|
||||
arguments("0", false),
|
||||
arguments("\0", false),
|
||||
arguments("a%\0", false),
|
||||
arguments("a", true),
|
||||
arguments("a0", true),
|
||||
arguments("_a0", true),
|
||||
arguments("test", true));
|
||||
}
|
||||
|
||||
@MethodSource("isValidIdentifierTestCases")
|
||||
@ParameterizedTest
|
||||
void isValidIdentifier(String string, boolean expected) {
|
||||
assertThat(JavaKeywords.isValidIdentifier(string)).isEqualTo(expected);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package tech.picnic.errorprone.utils;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
@@ -8,18 +10,80 @@ import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.AnnotationTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.LiteralTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.LiteralTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import javax.lang.model.element.Name;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
final class SourceCodeTest {
|
||||
private static Stream<Arguments> isValidIdentifierTestCases() {
|
||||
/* { string, expected } */
|
||||
return Stream.of(
|
||||
arguments("", false),
|
||||
arguments(".", false),
|
||||
arguments("a.", false),
|
||||
arguments(".a", false),
|
||||
arguments("a.b", false),
|
||||
arguments("public", false),
|
||||
arguments("true", false),
|
||||
arguments("false", false),
|
||||
arguments("null", false),
|
||||
arguments("0", false),
|
||||
arguments("\0", false),
|
||||
arguments("a%\0", false),
|
||||
arguments("a", true),
|
||||
arguments("a0", true),
|
||||
arguments("_a0", true),
|
||||
arguments("test", true));
|
||||
}
|
||||
|
||||
@MethodSource("isValidIdentifierTestCases")
|
||||
@ParameterizedTest
|
||||
void isValidIdentifier(String string, boolean expected) {
|
||||
assertThat(SourceCode.isValidIdentifier(string)).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toStringConstantExpression() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
ToStringConstantExpressionTestChecker.class, getClass())
|
||||
.addInputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" String m() {",
|
||||
" char a = 'c';",
|
||||
" char b = '\\'';",
|
||||
" return \"foo\\\"bar\\'baz\\bqux\";",
|
||||
" }",
|
||||
"}")
|
||||
.addOutputLines(
|
||||
"A.java",
|
||||
"class A {",
|
||||
" String m() {",
|
||||
" char a = 'c' /* 'c' */; /* \"a\" */",
|
||||
" char b = '\\'' /* '\\'' */; /* \"b\" */",
|
||||
" return \"foo\\\"bar\\'baz\\bqux\" /* \"foo\\\"bar'baz\\bqux\" */;",
|
||||
" }",
|
||||
"}")
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteWithTrailingWhitespaceAnnotations() {
|
||||
BugCheckerRefactoringTestHelper.newInstance(
|
||||
@@ -228,6 +292,41 @@ final class SourceCodeTest {
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that applies {@link SourceCode#toStringConstantExpression(Object,
|
||||
* VisitorState)} to string literals.
|
||||
*/
|
||||
@BugPattern(severity = ERROR, summary = "Interacts with `SourceCode` for testing purposes")
|
||||
public static final class ToStringConstantExpressionTestChecker extends BugChecker
|
||||
implements LiteralTreeMatcher, VariableTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Description matchLiteral(LiteralTree tree, VisitorState state) {
|
||||
// XXX: The character conversion is a workaround for the fact that `ASTHelpers#constValue`
|
||||
// returns an `Integer` value for `char` constants.
|
||||
return Optional.ofNullable(ASTHelpers.constValue(tree))
|
||||
.map(
|
||||
constant ->
|
||||
ASTHelpers.isSubtype(ASTHelpers.getType(tree), state.getSymtab().charType, state)
|
||||
? (char) (int) constant
|
||||
: constant)
|
||||
.map(constant -> describeMatch(tree, addComment(tree, constant, state)))
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description matchVariable(VariableTree tree, VisitorState state) {
|
||||
return describeMatch(
|
||||
tree, addComment(tree, ASTHelpers.getSymbol(tree).getSimpleName(), state));
|
||||
}
|
||||
|
||||
private static SuggestedFix addComment(Tree tree, Object value, VisitorState state) {
|
||||
return SuggestedFix.postfixWith(
|
||||
tree, "/* %s */".formatted(SourceCode.toStringConstantExpression(value, state)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that uses {@link SourceCode#deleteWithTrailingWhitespace(Tree,
|
||||
* VisitorState)} to suggest the deletion of annotations and methods with a name containing
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,34 +1,66 @@
|
||||
src/it/java/com/google/checkstyle/test/chapter7javadoc/rule711generalform/InvalidJavadocPositionTest.java:[35,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/com/google/checkstyle/test/chapter7javadoc/rule734nonrequiredjavadoc/InvalidJavadocPositionTest.java:[35,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/com/google/checkstyle/test/chapter7javadoc/rule734nonrequiredjavadoc/NonRequiredJavadocTest.java:[33,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/com/sun/checkstyle/test/chapter5comments/rule52documentationcomments/InvalidJavadocPositionTest.java:[35,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[117,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[169,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[116,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[166,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAbbreviationAsWordInNameTest.java:[91,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[104,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[101,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[71,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnnotationLocationTest.java:[69,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAnonInnerLengthTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAvoidEscapedUnicodeCharactersTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionAvoidNoArgumentSuperConstructorCallTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionCatchParameterNameTest.java:[166,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionCatchParameterNameTest.java:[193,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionCatchParameterNameTest.java:[161,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionCatchParameterNameTest.java:[187,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionClassMemberImpliedModifierTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionClassMemberImpliedModifierTest.java:[71,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionClassTypeParameterNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionClassTypeParameterNameTest.java:[69,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionConstructorsDeclarationGroupingTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionConstructorsDeclarationGroupingTest.java:[70,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `enum` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionDeclarationOrderTest.java:[64,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `static` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionEqualsAvoidNullTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `equals` is already defined in this class or a supertype)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionFinalClassTest.java:[38,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalImportTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalImportTest.java:[53,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `static` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalInstantiationTest.java:[91,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionLambdaBodyLengthTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalTokenTest.java:[56,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `native` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIllegalTokenTextTest.java:[91,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionIndentationTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionLambdaParameterNameTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMemberNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[109,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `protected` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[134,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `public` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[61,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `private` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodCountTest.java:[85,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `package` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMethodNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMissingJavadocTypeTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMissingOverrideTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMissingOverrideTest.java:[67,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMissingOverrideTest.java:[66,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMultipleStringLiteralsTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionMutableExceptionTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionNeedBracesTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `do` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionNoLineWrapTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionOuterTypeNumberTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionOverloadMethodsDeclarationOrderTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionParameterNumberTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionRecordComponentNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionRecordComponentNumberTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionReturnCountTest.java:[38,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `void` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionSeparatorWrapTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `class` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionSeparatorWrapTest.java:[60,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionSimplifyBooleanExpressionTest.java:[90,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `interface` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionSuperFinalizeTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionThrowsCountTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionTypeNameTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionUncommentedMainTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionUnnecessarySemicolonAfterTypeMemberDeclarationTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionUnnecessarySemicolonInTryWithResourcesTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/it/java/org/checkstyle/suppressionxpathfilter/XpathRegressionUnusedImportsTest.java:[57,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `static` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/DetailAstImplTest.java:[595,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/PackageNamesLoaderTest.java:[58,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/api/FilterSetTest.java:[49,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/api/FullIdentTest.java:[41,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/api/FullIdentTest.java:[42,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/AvoidEscapedUnicodeCharactersCheckTest.java:[77,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/DescendantTokenCheckTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/OrderedPropertiesCheckTest.java:[49,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
@@ -46,6 +78,7 @@ src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/ArrayTrailingCommaCh
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/AvoidDoubleBraceInitializationCheckTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/AvoidInlineConditionalsCheckTest.java:[36,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/AvoidNoArgumentSuperConstructorCallCheckTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/ConstructorsDeclarationGroupingCheckTest.java:[35,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/CovariantEqualsCheckTest.java:[36,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/DeclarationOrderCheckTest.java:[44,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/DefaultComesLastCheckTest.java:[55,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
@@ -70,8 +103,7 @@ src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessarySemicolon
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/UnnecessarySemicolonInTryWithResourcesCheckTest.java:[38,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/design/InterfaceIsTypeCheckTest.java:[37,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/design/MutableExceptionCheckTest.java:[54,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/design/ThrowsCountCheckTest.java:[39,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheckTest.java:[99,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `null` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportControlCheckTest.java:[100,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `null` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheckTest.java:[81,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/InvalidJavadocPositionCheckTest.java:[59,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocContentLocationCheckTest.java:[57,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
@@ -81,8 +113,8 @@ src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocNodeImplTest
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTagInfoTest.java:[230,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `throws` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTagInfoTest.java:[294,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `return` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTagTest.java:[58,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTypeCheckTest.java:[83,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `protected` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTypeCheckTest.java:[89,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `public` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTypeCheckTest.java:[84,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `protected` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTypeCheckTest.java:[90,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `public` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocVariableCheckTest.java:[60,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/MissingJavadocTypeCheckTest.java:[118,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `protected` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/MissingJavadocTypeCheckTest.java:[126,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `public` is not a valid identifier)
|
||||
@@ -133,7 +165,7 @@ src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithNearbyCommentF
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilterTest.java:[151,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/filters/SuppressionSingleFilterTest.java:[42,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `default` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/grammar/antlr4/Antlr4AstRegressionTest.java:[34,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `package` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/grammar/comments/CommentsTest.java:[53,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/grammar/comments/CommentsTest.java:[69,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/grammar/java8/DefaultMethodsTest.java:[40,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that `switch` is not a valid identifier)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/gui/BaseCellEditorTest.java:[31,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
src/test/java/com/puppycrawl/tools/checkstyle/utils/CheckUtilTest.java:[71,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `equals` is already defined in this class or a supertype)
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
--- a/pom.xml
|
||||
+++ b/pom.xml
|
||||
@@ -366,6 +366,12 @@
|
||||
<version>1.4.1</version>
|
||||
@@ -368,6 +368,12 @@
|
||||
<version>1.4.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
+ <dependency>
|
||||
+ <groupId>org.assertj</groupId>
|
||||
+ <artifactId>assertj-core</artifactId>
|
||||
+ <version>${assertj.version}</version>
|
||||
+ <version>3.27.0<!-- Renovate: org.assertj:assertj-bom --></version>
|
||||
+ <scope>test</scope>
|
||||
+ </dependency>
|
||||
<dependency>
|
||||
<groupId>nl.jqno.equalsverifier</groupId>
|
||||
<artifactId>equalsverifier</artifactId>
|
||||
@@ -2422,6 +2428,8 @@
|
||||
@@ -2421,9 +2427,13 @@
|
||||
<compilerArgs>
|
||||
<arg>-Xpkginfo:always</arg>
|
||||
<arg>-XDcompilePolicy=simple</arg>
|
||||
+ <!-- XXX: Drop this flag once the project uses Error Prone 2.36.0+ by default. -->
|
||||
+ <arg>--should-stop=ifError=FLOW</arg>
|
||||
<arg>
|
||||
-Xplugin:ErrorProne ${error-prone.configuration-args}
|
||||
</arg>
|
||||
@@ -22,7 +27,7 @@
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
@@ -2434,6 +2442,11 @@
|
||||
@@ -2436,6 +2446,11 @@
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
<version>${error-prone-support.version}</version>
|
||||
</path>
|
||||
@@ -34,8 +39,12 @@
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
@@ -2476,9 +2489,10 @@
|
||||
@@ -2476,11 +2491,14 @@
|
||||
<compilerArgs>
|
||||
<arg>-Xpkginfo:always</arg>
|
||||
<arg>-XDcompilePolicy=simple</arg>
|
||||
+ <!-- XXX: Drop this flag once the project uses Error Prone 2.36.0+ by default. -->
|
||||
+ <arg>--should-stop=ifError=FLOW</arg>
|
||||
<arg>
|
||||
-Xplugin:ErrorProne \
|
||||
- -XepExcludedPaths:.*[\\/]resources[\\/].* \
|
||||
@@ -46,7 +55,7 @@
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
@@ -2491,6 +2505,11 @@
|
||||
@@ -2493,6 +2511,11 @@
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
<version>${error-prone-support.version}</version>
|
||||
</path>
|
||||
@@ -58,6 +67,39 @@
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</execution>
|
||||
--- a/src/it/java/com/google/checkstyle/test/chapter2filebasic/rule21filename/FileNameTest.java
|
||||
+++ b/src/it/java/com/google/checkstyle/test/chapter2filebasic/rule21filename/FileNameTest.java
|
||||
@@ -23,6 +23,8 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.google.checkstyle.test.base.AbstractGoogleModuleTestSupport;
|
||||
|
||||
+// This class is referenced from another package.
|
||||
+@SuppressWarnings("JUnitClassModifiers")
|
||||
public class FileNameTest extends AbstractGoogleModuleTestSupport {
|
||||
|
||||
@Override
|
||||
--- a/src/it/java/com/google/checkstyle/test/chapter3filestructure/rule3sourcefile/SourceFileStructureTest.java
|
||||
+++ b/src/it/java/com/google/checkstyle/test/chapter3filestructure/rule3sourcefile/SourceFileStructureTest.java
|
||||
@@ -23,6 +23,8 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.google.checkstyle.test.base.AbstractGoogleModuleTestSupport;
|
||||
|
||||
+// This class is referenced from another package.
|
||||
+@SuppressWarnings("JUnitClassModifiers")
|
||||
public class SourceFileStructureTest extends AbstractGoogleModuleTestSupport {
|
||||
|
||||
@Override
|
||||
--- a/src/it/java/com/google/checkstyle/test/chapter3filestructure/toolongpackagetotestcoveragegooglesjavastylerule/PackageStatementTest.java
|
||||
+++ b/src/it/java/com/google/checkstyle/test/chapter3filestructure/toolongpackagetotestcoveragegooglesjavastylerule/PackageStatementTest.java
|
||||
@@ -23,6 +23,8 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.google.checkstyle.test.base.AbstractGoogleModuleTestSupport;
|
||||
|
||||
+// This class is referenced from another package.
|
||||
+@SuppressWarnings("JUnitClassModifiers")
|
||||
public class PackageStatementTest extends AbstractGoogleModuleTestSupport {
|
||||
|
||||
@Override
|
||||
--- a/src/main/java/com/puppycrawl/tools/checkstyle/DetailNodeTreeStringPrinter.java
|
||||
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/DetailNodeTreeStringPrinter.java
|
||||
@@ -63,6 +63,8 @@ public final class DetailNodeTreeStringPrinter {
|
||||
@@ -71,7 +113,7 @@
|
||||
final ParseStatus status = parser.parseJavadocAsDetailNode(blockComment);
|
||||
--- a/src/main/java/com/puppycrawl/tools/checkstyle/SarifLogger.java
|
||||
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/SarifLogger.java
|
||||
@@ -139,6 +139,9 @@ public class SarifLogger extends AbstractAutomaticBean implements AuditListener
|
||||
@@ -157,6 +157,9 @@ public class SarifLogger extends AbstractAutomaticBean implements AuditListener
|
||||
@Override
|
||||
public void auditFinished(AuditEvent event) {
|
||||
final String version = SarifLogger.class.getPackage().getImplementationVersion();
|
||||
@@ -83,7 +125,7 @@
|
||||
.replace(RESULTS_PLACEHOLDER, String.join(",\n", results));
|
||||
--- a/src/test/java/com/puppycrawl/tools/checkstyle/CheckerTest.java
|
||||
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/CheckerTest.java
|
||||
@@ -93,6 +93,8 @@ import de.thetaphi.forbiddenapis.SuppressForbidden;
|
||||
@@ -97,6 +97,8 @@ import de.thetaphi.forbiddenapis.SuppressForbidden;
|
||||
* @noinspectionreason ClassWithTooManyDependencies - complex tests require a large number
|
||||
* of imports
|
||||
*/
|
||||
@@ -125,7 +167,7 @@
|
||||
assertWithMessage("Exception is expected but got " + test).fail();
|
||||
--- a/src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java
|
||||
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java
|
||||
@@ -80,6 +80,8 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
|
||||
@@ -84,6 +84,8 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
|
||||
* @noinspectionreason ClassWithTooManyDependencies - complex tests require a
|
||||
* large number of imports
|
||||
*/
|
||||
|
||||
@@ -5,12 +5,12 @@ set -e -u -o pipefail
|
||||
test_name="$(basename "${0}" .sh)"
|
||||
project='checkstyle'
|
||||
repository='https://github.com/checkstyle/checkstyle.git'
|
||||
revision='checkstyle-10.14.0'
|
||||
# XXX: Configure Renovate to manage the AssertJ version declared here.
|
||||
additional_build_flags='-Dassertj.version=3.24.2'
|
||||
revision='checkstyle-10.21.0'
|
||||
additional_build_flags='-Perror-prone-compile,error-prone-test-compile -Dmaven.compiler.failOnError=true'
|
||||
additional_source_directories='${project.basedir}${file.separator}src${file.separator}it${file.separator}java,${project.basedir}${file.separator}src${file.separator}xdocs-examples${file.separator}java'
|
||||
patch_error_prone_flags='-XepOpt:Refaster:NamePattern=.*Workshop.*"'
|
||||
validation_error_prone_flags='-XepOpt:Refaster:NamePattern=.*Workshop.*"'
|
||||
shared_error_prone_flags='-XepExcludedPaths:(\Q${project.basedir}${file.separator}src${file.separator}\E(it|test|xdocs-examples)\Q${file.separator}resources\E|\Q${project.build.directory}${file.separator}\E).*'
|
||||
patch_error_prone_flags=''
|
||||
validation_error_prone_flags=''
|
||||
# Validation skips some tests:
|
||||
# - The `metadataFilesGenerationAllFiles` test is skipped because it makes line
|
||||
# number assertions that will fail when the code is formatted or patched.
|
||||
@@ -30,6 +30,7 @@ fi
|
||||
"${revision}" \
|
||||
"${additional_build_flags}" \
|
||||
"${additional_source_directories}" \
|
||||
"${shared_error_prone_flags}" \
|
||||
"${patch_error_prone_flags}" \
|
||||
"${validation_error_prone_flags}" \
|
||||
"${validation_build_flags}" \
|
||||
|
||||
11164
integration-tests/metrics-expected-changes.patch
Normal file
11164
integration-tests/metrics-expected-changes.patch
Normal file
File diff suppressed because it is too large
Load Diff
48
integration-tests/metrics-expected-warnings.txt
Normal file
48
integration-tests/metrics-expected-warnings.txt
Normal file
@@ -0,0 +1,48 @@
|
||||
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/CollectdReporter.java:[306,57] [rawtypes] found raw type: Gauge
|
||||
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[164,12] [cast] redundant cast to ByteBuffer
|
||||
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[169,11] [cast] redundant cast to ByteBuffer
|
||||
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[175,17] [cast] redundant cast to ByteBuffer
|
||||
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[200,8] [cast] redundant cast to ByteBuffer
|
||||
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[203,21] [cast] redundant cast to ByteBuffer
|
||||
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[206,11] [cast] redundant cast to ByteBuffer
|
||||
metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java:[250,36] [cast] redundant cast to ByteBuffer
|
||||
metrics-core/src/main/java/io/dropwizard/metrics5/CsvReporter.java:[390,35] [FormatStringConcatenation] Defer string concatenation to the invoked method
|
||||
metrics-core/src/main/java/io/dropwizard/metrics5/InstrumentedExecutorService.java:[244,25] [try] auto-closeable resource durationContext is never referenced in body of corresponding try statement
|
||||
metrics-core/src/main/java/io/dropwizard/metrics5/InstrumentedExecutorService.java:[266,25] [try] auto-closeable resource context is never referenced in body of corresponding try statement
|
||||
metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[431,14] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
|
||||
metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[436,16] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
|
||||
metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[449,17] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
|
||||
metrics-healthchecks/src/test/java/io/dropwizard/metrics5/health/HealthCheckTest.java:[189,46] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone
|
||||
metrics-healthchecks/src/test/java/io/dropwizard/metrics5/health/HealthCheckTest.java:[203,46] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone
|
||||
metrics-httpclient/src/test/java/io/dropwizard/metrics5/httpclient/HttpClientMetricNameStrategiesTest.java:[124,22] [deprecation] rewriteURI(URI,HttpHost,boolean) in URIUtils has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedAsyncClientConnectionManager.java:[29,62] [deprecation] getDefault() in DefaultClientTlsStrategy has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[116,50] [deprecation] ConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[160,12] [deprecation] DefaultHttpClientConnectionOperator(Lookup<ConnectionSocketFactory>,SchemePortResolver,DnsResolver) in DefaultHttpClientConnectionOperator has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[30,28] [deprecation] ConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[31,28] [deprecation] ConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[32,37] [deprecation] PlainConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[33,38] [deprecation] SSLConnectionSocketFactory in org.apache.hc.client5.http.ssl has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientConnectionManager.java:[96,21] [deprecation] ConnectionSocketFactory in org.apache.hc.client5.http.socket has been deprecated
|
||||
metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpRequestExecutor.java:[49,4] [deprecation] HttpRequestExecutor(Timeout,ConnectionReuseStrategy,Http1StreamListener) in HttpRequestExecutor has been deprecated
|
||||
metrics-httpclient5/src/test/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientsTest.java:[46,10] [deprecation] execute(ClassicHttpRequest) in HttpClient has been deprecated
|
||||
metrics-httpclient5/src/test/java/io/dropwizard/metrics5/httpclient5/InstrumentedHttpClientsTest.java:[68,12] [deprecation] execute(ClassicHttpRequest) in HttpClient has been deprecated
|
||||
metrics-influxdb/src/main/java/io/dropwizard/metrics5/influxdb/InfluxDbReporter.java:[282,14] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
|
||||
metrics-influxdb/src/main/java/io/dropwizard/metrics5/influxdb/InfluxDbReporter.java:[287,16] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
|
||||
metrics-jakarta-servlets/src/test/java/io/dropwizard/metrics5/servlets/HealthCheckServletTest.java:[31,67] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone
|
||||
metrics-jdbi3/src/test/java/io/dropwizard/metrics5/jdbi3/strategies/SmartNameStrategyTest.java:[18,10] [deprecation] InstrumentedTimingCollector in io.dropwizard.metrics5.jdbi3 has been deprecated
|
||||
metrics-jdbi3/src/test/java/io/dropwizard/metrics5/jdbi3/strategies/SmartNameStrategyTest.java:[24,20] [deprecation] InstrumentedTimingCollector in io.dropwizard.metrics5.jdbi3 has been deprecated
|
||||
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[101,74] [unchecked] unchecked cast
|
||||
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[56,74] [unchecked] unchecked cast
|
||||
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[65,74] [unchecked] unchecked cast
|
||||
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[74,74] [unchecked] unchecked cast
|
||||
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[83,74] [unchecked] unchecked cast
|
||||
metrics-jvm/src/test/java/io/dropwizard/metrics5/jvm/BufferPoolMetricSetTest.java:[92,74] [unchecked] unchecked cast
|
||||
metrics-legacy-adapter/src/main/java/com/codahale/metrics/MetricRegistry.java:[108,27] [rawtypes] found raw type: Gauge
|
||||
metrics-legacy-adapter/src/main/java/com/codahale/metrics/MetricRegistry.java:[112,27] [rawtypes] found raw type: Gauge
|
||||
metrics-legacy-adapter/src/main/java/com/codahale/metrics/MetricRegistry.java:[51,49] [rawtypes] found raw type: Gauge
|
||||
metrics-legacy-adapter/src/main/java/com/codahale/metrics/MetricRegistry.java:[51,9] [rawtypes] found raw type: Gauge
|
||||
metrics-legacy-adapter/src/test/java/com/codahale/metrics/MetricRegistryTest.java:[367,22] [rawtypes] found raw type: Gauge
|
||||
metrics-legacy-adapter/src/test/java/com/codahale/metrics/MetricRegistryTest.java:[50,4] [rawtypes] found raw type: Gauge
|
||||
metrics-log4j2/src/main/java/io/dropwizard/metrics5/log4j2/InstrumentedAppender.java:[85,4] [deprecation] AbstractAppender(String,Filter,Layout<? extends Serializable>,boolean) in AbstractAppender has been deprecated
|
||||
metrics-log4j2/src/main/java/io/dropwizard/metrics5/log4j2/InstrumentedAppender.java:[96,4] [deprecation] AbstractAppender(String,Filter,Layout<? extends Serializable>,boolean) in AbstractAppender has been deprecated
|
||||
metrics-servlets/src/test/java/io/dropwizard/metrics5/servlets/HealthCheckServletTest.java:[31,67] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone
|
||||
100
integration-tests/metrics-init.patch
Normal file
100
integration-tests/metrics-init.patch
Normal file
@@ -0,0 +1,100 @@
|
||||
--- a/metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics5/servlets/MetricsServlet.java
|
||||
+++ b/metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics5/servlets/MetricsServlet.java
|
||||
@@ -188,6 +188,9 @@ public class MetricsServlet extends HttpServlet {
|
||||
return mapper.writer();
|
||||
}
|
||||
|
||||
+ // Here `value` may be `null`, while `TimeUnit#valueOf` requires a non-`null` argument.
|
||||
+ // XXX: Investigate better nullness handling by `IdentityConversion`.
|
||||
+ @SuppressWarnings("IdentityConversion")
|
||||
protected TimeUnit parseTimeUnit(String value, TimeUnit defaultValue) {
|
||||
try {
|
||||
return TimeUnit.valueOf(String.valueOf(value).toUpperCase(Locale.US));
|
||||
--- a/metrics-servlets/src/main/java/io/dropwizard/metrics5/servlets/MetricsServlet.java
|
||||
+++ b/metrics-servlets/src/main/java/io/dropwizard/metrics5/servlets/MetricsServlet.java
|
||||
@@ -188,6 +188,9 @@ public class MetricsServlet extends HttpServlet {
|
||||
return mapper.writer();
|
||||
}
|
||||
|
||||
+ // Here `value` may be `null`, while `TimeUnit#valueOf` requires a non-`null` argument.
|
||||
+ // XXX: Investigate better nullness handling by `IdentityConversion`.
|
||||
+ @SuppressWarnings("IdentityConversion")
|
||||
protected TimeUnit parseTimeUnit(String value, TimeUnit defaultValue) {
|
||||
try {
|
||||
return TimeUnit.valueOf(String.valueOf(value).toUpperCase(Locale.US));
|
||||
--- a/pom.xml
|
||||
+++ b/pom.xml
|
||||
@@ -136,6 +136,27 @@
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
+ <dependencyManagement>
|
||||
+ <dependencies>
|
||||
+ <dependency>
|
||||
+ <groupId>com.google.errorprone</groupId>
|
||||
+ <artifactId>error_prone_annotations</artifactId>
|
||||
+ <version>${error-prone.version}</version>
|
||||
+ </dependency>
|
||||
+ <dependency>
|
||||
+ <groupId>com.google.guava</groupId>
|
||||
+ <artifactId>guava</artifactId>
|
||||
+ <version>33.4.0-jre<!-- Renovate: com.google.guava:guava-bom --></version>
|
||||
+ </dependency>
|
||||
+ </dependencies>
|
||||
+ </dependencyManagement>
|
||||
+ <dependencies>
|
||||
+ <dependency>
|
||||
+ <groupId>com.google.guava</groupId>
|
||||
+ <artifactId>guava</artifactId>
|
||||
+ </dependency>
|
||||
+ </dependencies>
|
||||
+
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jdk8</id>
|
||||
@@ -218,7 +239,9 @@
|
||||
<compilerArgs>
|
||||
<arg>-Xlint:all</arg>
|
||||
<arg>-XDcompilePolicy=simple</arg>
|
||||
- <arg>-Xplugin:ErrorProne -XepExcludedPaths:.*/target/generated-sources/.*</arg>
|
||||
+ <!-- XXX: Drop this flag once the project uses Error Prone 2.36.0+ by default. -->
|
||||
+ <arg>--should-stop=ifError=FLOW</arg>
|
||||
+ <arg>-Xplugin:ErrorProne ${error-prone.configuration-args}</arg>
|
||||
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
|
||||
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
|
||||
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
|
||||
@@ -229,12 +252,24 @@
|
||||
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
|
||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
|
||||
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
|
||||
+ <arg>-Xmaxwarns</arg>
|
||||
+ <arg>1000000</arg>
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
- <version>${errorprone.version}</version>
|
||||
+ <version>${error-prone.version}</version>
|
||||
+ </path>
|
||||
+ <path>
|
||||
+ <groupId>tech.picnic.error-prone-support</groupId>
|
||||
+ <artifactId>error-prone-contrib</artifactId>
|
||||
+ <version>${error-prone-support.version}</version>
|
||||
+ </path>
|
||||
+ <path>
|
||||
+ <groupId>tech.picnic.error-prone-support</groupId>
|
||||
+ <artifactId>refaster-runner</artifactId>
|
||||
+ <version>${error-prone-support.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
@@ -364,7 +399,7 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
- <release>8</release>
|
||||
+ <release>11</release>
|
||||
<fork>true</fork>
|
||||
<parameters>true</parameters>
|
||||
<showWarnings>true</showWarnings>
|
||||
36
integration-tests/metrics.sh
Executable file
36
integration-tests/metrics.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e -u -o pipefail
|
||||
|
||||
test_name="$(basename "${0}" .sh)"
|
||||
project='metrics'
|
||||
repository='https://github.com/dropwizard/metrics.git'
|
||||
revision='v5.0.0-rc22'
|
||||
additional_build_flags=''
|
||||
additional_source_directories=''
|
||||
# XXX: Minimize the diff by including
|
||||
# `-XepOpt:Slf4jLoggerDeclaration:CanonicalStaticLoggerName=LOGGER` once such
|
||||
# flags are supported in patch mode. See
|
||||
# https://github.com/google/error-prone/pull/4699.
|
||||
shared_error_prone_flags='-XepExcludedPaths:.*/target/generated-sources/.*'
|
||||
patch_error_prone_flags=''
|
||||
validation_error_prone_flags=''
|
||||
validation_build_flags=''
|
||||
|
||||
if [ "${#}" -gt 2 ] || ([ "${#}" = 2 ] && [ "${1:---sync}" != '--sync' ]); then
|
||||
>&2 echo "Usage: ${0} [--sync] [<report_directory>]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$(dirname "${0}")/run-integration-test.sh" \
|
||||
"${test_name}" \
|
||||
"${project}" \
|
||||
"${repository}" \
|
||||
"${revision}" \
|
||||
"${additional_build_flags}" \
|
||||
"${additional_source_directories}" \
|
||||
"${shared_error_prone_flags}" \
|
||||
"${patch_error_prone_flags}" \
|
||||
"${validation_error_prone_flags}" \
|
||||
"${validation_build_flags}" \
|
||||
$@
|
||||
10363
integration-tests/prometheus-java-client-expected-changes.patch
Normal file
10363
integration-tests/prometheus-java-client-expected-changes.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
integration-tests/it-exporter/it-exporter-httpserver-sample/src/main/java/io/prometheus/metrics/it/exporter/httpserver/HTTPServerSample.java:[15,5] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'SUCCESS', though note that this is not a private constant
|
||||
integration-tests/it-exporter/it-exporter-httpserver-sample/src/main/java/io/prometheus/metrics/it/exporter/httpserver/HTTPServerSample.java:[16,5] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'ERROR', though note that this is not a private constant
|
||||
integration-tests/it-exporter/it-exporter-no-protobuf/src/main/java/io/prometheus/metrics/it/exporter/httpserver/HTTPServerSample.java:[15,5] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'SUCCESS', though note that this is not a private constant
|
||||
integration-tests/it-exporter/it-exporter-no-protobuf/src/main/java/io/prometheus/metrics/it/exporter/httpserver/HTTPServerSample.java:[16,5] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'ERROR', though note that this is not a private constant
|
||||
integration-tests/it-exporter/it-exporter-servlet-jetty-sample/src/main/java/io/prometheus/metrics/it/exporter/servlet/jetty/ExporterServletJettySample.java:[18,5] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'SUCCESS', though note that this is not a private constant
|
||||
integration-tests/it-exporter/it-exporter-servlet-jetty-sample/src/main/java/io/prometheus/metrics/it/exporter/servlet/jetty/ExporterServletJettySample.java:[19,5] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'ERROR', though note that this is not a private constant
|
||||
integration-tests/it-exporter/it-exporter-servlet-tomcat-sample/src/main/java/io/prometheus/metrics/it/exporter/servlet/tomcat/ExporterServletTomcatSample.java:[21,5] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'SUCCESS', though note that this is not a private constant
|
||||
integration-tests/it-exporter/it-exporter-servlet-tomcat-sample/src/main/java/io/prometheus/metrics/it/exporter/servlet/tomcat/ExporterServletTomcatSample.java:[22,5] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'ERROR', though note that this is not a private constant
|
||||
prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/CounterTest.java:[180,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `incWithExemplar` is already defined in this class or a supertype)
|
||||
prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java:[96,30] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'IS_ENABLED', though note that this is not a private constant
|
||||
prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/NativeImageChecker.java:[11,24] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'IS_GRAAL_VM_NATIVE_IMAGE', though note that this is not a private constant
|
||||
prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java:[16,42] [ConstantNaming] Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention; consider renaming to 'DEFAULT_REGISTRY', though note that this is not a private constant
|
||||
prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/LabelTest.java:[19,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `toString` is already defined in this class or a supertype)
|
||||
prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/LabelTest.java:[24,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `equals` is already defined in this class or a supertype)
|
||||
prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/LabelTest.java:[29,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that a method named `hashCode` is already defined in this class or a supertype)
|
||||
prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/PrometheusNamingTest.java:[12,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that another method named `sanitizeMetricName` is in scope)
|
||||
prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/PrometheusNamingTest.java:[44,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that another method named `sanitizeLabelName` is in scope)
|
||||
prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/PrometheusNamingTest.java:[55,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that another method named `validateUnitName` is in scope)
|
||||
prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/PrometheusNamingTest.java:[67,8] [JUnitMethodDeclaration] This method's name should not redundantly start with `test` (but note that another method named `sanitizeUnitName` is in scope)
|
||||
36
integration-tests/prometheus-java-client-init.patch
Normal file
36
integration-tests/prometheus-java-client-init.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
--- a/pom.xml
|
||||
+++ b/pom.xml
|
||||
@@ -128,7 +128,6 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
- <scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
@@ -370,13 +369,24 @@
|
||||
-Xep:LongDoubleConversion:OFF
|
||||
-Xep:StringSplitter:OFF
|
||||
-XepExcludedPaths:.*/generated/.*
|
||||
+ ${error-prone.configuration-args}
|
||||
</arg>
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
- <version>2.36.0</version>
|
||||
+ <version>${error-prone.version}</version>
|
||||
+ </path>
|
||||
+ <path>
|
||||
+ <groupId>tech.picnic.error-prone-support</groupId>
|
||||
+ <artifactId>error-prone-contrib</artifactId>
|
||||
+ <version>${error-prone-support.version}</version>
|
||||
+ </path>
|
||||
+ <path>
|
||||
+ <groupId>tech.picnic.error-prone-support</groupId>
|
||||
+ <artifactId>refaster-runner</artifactId>
|
||||
+ <version>${error-prone-support.version}</version>
|
||||
</path>
|
||||
<!-- Other annotation processors go here.
|
||||
|
||||
40
integration-tests/prometheus-java-client.sh
Executable file
40
integration-tests/prometheus-java-client.sh
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e -u -o pipefail
|
||||
|
||||
test_name="$(basename "${0}" .sh)"
|
||||
project='prometheus-java-client'
|
||||
repository='https://github.com/prometheus/client_java.git'
|
||||
revision='v1.3.5'
|
||||
additional_build_flags='-Djava.version=11 -Dwarnings='
|
||||
additional_source_directories=''
|
||||
shared_error_prone_flags=''
|
||||
patch_error_prone_flags=''
|
||||
validation_error_prone_flags=''
|
||||
# Validation skips some tests:
|
||||
# - Starting from a clean repository, the `PushGatewayIT` tests reference a JAR
|
||||
# file that is created only after test completion, causing the tests to fail.
|
||||
# - The `SlidingWindowTest#rotate` test is flaky.
|
||||
# XXX: Drop the `SlidingWindowTest` exclusion once prometheus/client_java#1242
|
||||
# is resolved. For unclear reasons, it appears that without this exclusion the
|
||||
# integration tests are no longer executed, meaning that perhaps all flags
|
||||
# specified here can then be dropped.
|
||||
validation_build_flags='-Dtest=!PushGatewayIT,!SlidingWindowTest#rotate -Dsurefire.failIfNoSpecifiedTests=false'
|
||||
|
||||
if [ "${#}" -gt 2 ] || ([ "${#}" = 2 ] && [ "${1:---sync}" != '--sync' ]); then
|
||||
>&2 echo "Usage: ${0} [--sync] [<report_directory>]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$(dirname "${0}")/run-integration-test.sh" \
|
||||
"${test_name}" \
|
||||
"${project}" \
|
||||
"${repository}" \
|
||||
"${revision}" \
|
||||
"${additional_build_flags}" \
|
||||
"${additional_source_directories}" \
|
||||
"${shared_error_prone_flags}" \
|
||||
"${patch_error_prone_flags}" \
|
||||
"${validation_error_prone_flags}" \
|
||||
"${validation_build_flags}" \
|
||||
$@
|
||||
@@ -12,8 +12,8 @@ integration_test_root="$(cd "$(dirname -- "${0}")" && pwd)"
|
||||
error_prone_support_root="${integration_test_root}/.."
|
||||
repos_root="${integration_test_root}/.repos"
|
||||
|
||||
if [ "${#}" -lt 9 ] || [ "${#}" -gt 11 ] || ([ "${#}" = 11 ] && [ "${10:---sync}" != '--sync' ]); then
|
||||
>&2 echo "Usage: $(basename "${0}") <test_name> <project> <repository> <revision> <additional_build_flags> <additional_source_directories> <patch_error_prone_flags> <validation_error_prone_flags> <validation_build_flags> [--sync] [<report_directory>]"
|
||||
if [ "${#}" -lt 10 ] || [ "${#}" -gt 12 ] || ([ "${#}" = 12 ] && [ "${11:---sync}" != '--sync' ]); then
|
||||
>&2 echo "Usage: $(basename "${0}") <test_name> <project> <repository> <revision> <additional_build_flags> <additional_source_directories> <shared_error_prone_flags> <patch_error_prone_flags> <validation_error_prone_flags> <validation_build_flags> [--sync] [<report_directory>]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -23,11 +23,12 @@ repository="${3}"
|
||||
revision="${4}"
|
||||
additional_build_flags="${5}"
|
||||
additional_source_directories="${6}"
|
||||
patch_error_prone_flags="${7}"
|
||||
validation_error_prone_flags="${8}"
|
||||
validation_build_flags="${9}"
|
||||
do_sync="$([ "${#}" = 9 ] || [ "${10:-}" != '--sync' ] || echo 1)"
|
||||
report_directory="$([ "${#}" = 9 ] || ([ -z "${do_sync}" ] && echo "${10}") || ([ "${#}" = 10 ] || echo "${11}"))"
|
||||
shared_error_prone_flags="${7}"
|
||||
patch_error_prone_flags="${8}"
|
||||
validation_error_prone_flags="${9}"
|
||||
validation_build_flags="${10}"
|
||||
do_sync="$([ "${#}" = 10 ] || [ "${11:-}" != '--sync' ] || echo 1)"
|
||||
report_directory="$([ "${#}" = 10 ] || ([ -z "${do_sync}" ] && echo "${11}") || ([ "${#}" = 11 ] || echo "${12}"))"
|
||||
|
||||
if [ -n "${report_directory}" ]; then
|
||||
mkdir -p "${report_directory}"
|
||||
@@ -52,7 +53,6 @@ case "$(uname -s)" in
|
||||
esac
|
||||
|
||||
shared_build_flags="
|
||||
-Perror-prone-compile,error-prone-test-compile
|
||||
-Derror-prone.version=$(
|
||||
mvn -f "${error_prone_support_root}" help:evaluate -Dexpression=version.error-prone -q -DforceStdout
|
||||
)
|
||||
@@ -63,15 +63,9 @@ shared_build_flags="
|
||||
${additional_build_flags}
|
||||
"
|
||||
|
||||
# XXX: Configure Renovate to manage the fmt-maven-plugin version declared here.
|
||||
# XXX: Once GitHub actions uses Maven 3.9.2+, we can inline this variable with
|
||||
# version reference `${fmt.version}`, and `-Dfmt.version=2.21.1` added to
|
||||
# `shared_build_flags`.
|
||||
format_goal='com.spotify.fmt:fmt-maven-plugin:2.21.1:format'
|
||||
format_goal='com.spotify.fmt:fmt-maven-plugin:2.25:format'
|
||||
|
||||
error_prone_shared_flags='-XepExcludedPaths:(\Q${project.basedir}${file.separator}src${file.separator}\E(it|test|xdocs-examples)\Q${file.separator}resources\E|\Q${project.build.directory}${file.separator}\E).*'
|
||||
|
||||
error_prone_patch_flags="${error_prone_shared_flags} -XepPatchLocation:IN_PLACE -XepPatchChecks:$(
|
||||
error_prone_patch_flags="${shared_error_prone_flags} -XepPatchLocation:IN_PLACE -XepPatchChecks:$(
|
||||
find "${error_prone_support_root}" \
|
||||
-path "*/META-INF/services/com.google.errorprone.bugpatterns.BugChecker" \
|
||||
-not -path "*/error-prone-experimental/*" \
|
||||
@@ -81,7 +75,7 @@ error_prone_patch_flags="${error_prone_shared_flags} -XepPatchLocation:IN_PLACE
|
||||
| paste -s -d ',' -
|
||||
) ${patch_error_prone_flags}"
|
||||
|
||||
error_prone_validation_flags="${error_prone_shared_flags} -XepDisableAllChecks $(
|
||||
error_prone_validation_flags="${shared_error_prone_flags} -XepDisableAllChecks $(
|
||||
find "${error_prone_support_root}" \
|
||||
-path "*/META-INF/services/com.google.errorprone.bugpatterns.BugChecker" \
|
||||
-not -path "*/error-prone-experimental/*" \
|
||||
@@ -125,14 +119,22 @@ pushd "${project_root}"
|
||||
git config user.email || git config user.email 'integration-test@example.com'
|
||||
git config user.name || git config user.name 'Integration Test'
|
||||
|
||||
# Prepare the code for analysis by (a) applying the minimal set of changes
|
||||
# required to run Error Prone with Error Prone Support and (b) formatting the
|
||||
# code using the same method by which it will be formatted after each
|
||||
# compilation round. The initial formatting operation ensures that subsequent
|
||||
# modifications can be rendered in a clean manner.
|
||||
# Prepare the code for analysis by applying the minimal set of changes required
|
||||
# to run Error Prone with Error Prone Support.
|
||||
initial_patch="${integration_test_root}/${test_name}-init.patch"
|
||||
git clean -fdx
|
||||
git apply < "${integration_test_root}/${test_name}-init.patch"
|
||||
git apply < "${initial_patch}"
|
||||
git commit -m 'dependency: Introduce Error Prone Support' .
|
||||
if [ -n "${do_sync}" ]; then
|
||||
# The initial patch applied successfully, but if it was created against a
|
||||
# different version, then offsets may have changed. Here we update the patch
|
||||
# to exactly match the new state.
|
||||
git diff HEAD~1 | "${grep_command}" -vP '^(diff|index)' > "${initial_patch}"
|
||||
fi
|
||||
|
||||
# Format the patched code using the same method by which it will be formatted
|
||||
# after each compilation round. This initial formatting operation ensures that
|
||||
# subsequent modifications can be rendered in a clean manner.
|
||||
mvn ${shared_build_flags} "${format_goal}"
|
||||
git commit -m 'minor: Reformat using Google Java Format' .
|
||||
diff_base="$(git rev-parse HEAD)"
|
||||
@@ -141,10 +143,13 @@ diff_base="$(git rev-parse HEAD)"
|
||||
function apply_patch() {
|
||||
local extra_build_args="${1}"
|
||||
|
||||
mvn ${shared_build_flags} ${extra_build_args} \
|
||||
package "${format_goal}" \
|
||||
-Derror-prone.configuration-args="${error_prone_patch_flags}" \
|
||||
-DskipTests
|
||||
(
|
||||
set -x \
|
||||
&& mvn ${shared_build_flags} ${extra_build_args} \
|
||||
package "${format_goal}" \
|
||||
-Derror-prone.configuration-args="${error_prone_patch_flags}" \
|
||||
-DskipTests
|
||||
)
|
||||
|
||||
if ! git diff --exit-code; then
|
||||
git commit -m 'minor: Apply patches' .
|
||||
@@ -168,12 +173,13 @@ apply_patch ''
|
||||
# By also running the tests, we validate that the (majority of) applied changes
|
||||
# are behavior preserving.
|
||||
validation_build_log="${report_directory}/${test_name}-validation-build-log.txt"
|
||||
mvn ${shared_build_flags} \
|
||||
clean package \
|
||||
-Derror-prone.configuration-args="${error_prone_validation_flags}" \
|
||||
${validation_build_flags} \
|
||||
| tee "${validation_build_log}" \
|
||||
|| failure=1
|
||||
(
|
||||
set -x \
|
||||
&& mvn ${shared_build_flags} \
|
||||
clean package \
|
||||
-Derror-prone.configuration-args="${error_prone_validation_flags}" \
|
||||
${validation_build_flags}
|
||||
) | tee "${validation_build_log}" || failure=1
|
||||
|
||||
# Collect the applied changes.
|
||||
expected_changes="${integration_test_root}/${test_name}-expected-changes.patch"
|
||||
|
||||
308
mvnw
vendored
308
mvnw
vendored
@@ -1,308 +0,0 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Apache Maven Wrapper startup batch script, version 3.2.0
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||
. /usr/local/etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "$(uname)" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
|
||||
else
|
||||
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=$(java-config --jre-home)
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="$(which javac)"
|
||||
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=$(which readlink)
|
||||
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="$(dirname "\"$javaExecutable\"")"
|
||||
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
|
||||
else
|
||||
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
|
||||
fi
|
||||
javaHome="$(dirname "\"$javaExecutable\"")"
|
||||
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=$(cd "$wdir/.." || exit 1; pwd)
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
# Remove \r in case we run on Windows within Git Bash
|
||||
# and check out the repository with auto CRLF management
|
||||
# enabled. Otherwise, we may read lines that are delimited with
|
||||
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
|
||||
# splitting rules.
|
||||
tr -s '\r\n' ' ' < "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
log() {
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
printf '%s\n' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
|
||||
log "$MAVEN_PROJECTBASEDIR"
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if [ -r "$wrapperJarPath" ]; then
|
||||
log "Found $wrapperJarPath"
|
||||
else
|
||||
log "Couldn't find $wrapperJarPath, downloading it ..."
|
||||
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
else
|
||||
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
fi
|
||||
while IFS="=" read -r key value; do
|
||||
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
|
||||
safeValue=$(echo "$value" | tr -d '\r')
|
||||
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
|
||||
esac
|
||||
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
log "Downloading from: $wrapperUrl"
|
||||
|
||||
if $cygwin; then
|
||||
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
log "Found wget ... using wget"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
log "Found curl ... using curl"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
else
|
||||
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
else
|
||||
log "Falling back to using Java to download"
|
||||
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaSource=$(cygpath --path --windows "$javaSource")
|
||||
javaClass=$(cygpath --path --windows "$javaClass")
|
||||
fi
|
||||
if [ -e "$javaSource" ]; then
|
||||
if [ ! -e "$javaClass" ]; then
|
||||
log " - Compiling MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/javac" "$javaSource")
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
log " - Running MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
wrapperSha256Sum=""
|
||||
while IFS="=" read -r key value; do
|
||||
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
|
||||
esac
|
||||
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ -n "$wrapperSha256Sum" ]; then
|
||||
wrapperSha256Result=false
|
||||
if command -v sha256sum > /dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
elif command -v shasum > /dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
else
|
||||
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
|
||||
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
|
||||
exit 1
|
||||
fi
|
||||
if [ $wrapperSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
|
||||
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
# shellcheck disable=SC2086 # safe args
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
205
mvnw.cmd
vendored
205
mvnw.cmd
vendored
@@ -1,205 +0,0 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Apache Maven Wrapper startup batch script, version 3.2.0
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %WRAPPER_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
SET WRAPPER_SHA_256_SUM=""
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
|
||||
)
|
||||
IF NOT %WRAPPER_SHA_256_SUM%=="" (
|
||||
powershell -Command "&{"^
|
||||
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
|
||||
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
|
||||
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
|
||||
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
|
||||
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
|
||||
" exit 1;"^
|
||||
"}"^
|
||||
"}"
|
||||
if ERRORLEVEL 1 goto error
|
||||
)
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% ^
|
||||
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||
%MAVEN_OPTS% ^
|
||||
%MAVEN_DEBUG_OPTS% ^
|
||||
-classpath %WRAPPER_JAR% ^
|
||||
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||
|
||||
cmd /C exit /B %ERROR_CODE%
|
||||
184
pom.xml
184
pom.xml
@@ -48,7 +48,6 @@
|
||||
<module>refaster-runner</module>
|
||||
<module>refaster-support</module>
|
||||
<module>refaster-test-support</module>
|
||||
<module>workshop</module>
|
||||
</modules>
|
||||
|
||||
<scm child.scm.developerConnection.inherit.append.path="false" child.scm.url.inherit.append.path="false">
|
||||
@@ -212,16 +211,16 @@
|
||||
<version.auto-value>1.11.0</version.auto-value>
|
||||
<version.error-prone>${version.error-prone-orig}</version.error-prone>
|
||||
<version.error-prone-fork>v${version.error-prone-orig}-picnic-1</version.error-prone-fork>
|
||||
<version.error-prone-orig>2.35.1</version.error-prone-orig>
|
||||
<version.error-prone-orig>2.36.0</version.error-prone-orig>
|
||||
<version.error-prone-slf4j>0.1.28</version.error-prone-slf4j>
|
||||
<version.guava-beta-checker>1.0</version.guava-beta-checker>
|
||||
<version.jdk>17</version.jdk>
|
||||
<version.maven>3.9.9</version.maven>
|
||||
<version.mockito>5.14.2</version.mockito>
|
||||
<version.nopen-checker>1.0.1</version.nopen-checker>
|
||||
<version.nullaway>0.12.1</version.nullaway>
|
||||
<version.nullaway>0.12.2</version.nullaway>
|
||||
<version.pitest-git>1.1.4</version.pitest-git>
|
||||
<version.rewrite-templating>1.16.3</version.rewrite-templating>
|
||||
<version.rewrite-templating>1.20.2</version.rewrite-templating>
|
||||
<version.surefire>3.2.3</version.surefire>
|
||||
</properties>
|
||||
|
||||
@@ -300,7 +299,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson</groupId>
|
||||
<artifactId>jackson-bom</artifactId>
|
||||
<version>2.18.1</version>
|
||||
<version>2.18.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -337,7 +336,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.googlejavaformat</groupId>
|
||||
<artifactId>google-java-format</artifactId>
|
||||
<version>1.24.0</version>
|
||||
<version>1.25.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
@@ -347,7 +346,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava-bom</artifactId>
|
||||
<version>33.3.1-jre</version>
|
||||
<version>33.4.0-jre</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -368,13 +367,15 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-core</artifactId>
|
||||
<version>1.13.6</version>
|
||||
<artifactId>micrometer-bom</artifactId>
|
||||
<version>1.14.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-bom</artifactId>
|
||||
<version>2023.0.11</version>
|
||||
<version>2024.0.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -391,7 +392,7 @@
|
||||
<dependency>
|
||||
<groupId>io.swagger.core.v3</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>2.2.25</version>
|
||||
<version>2.2.27</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
@@ -426,7 +427,15 @@
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.15.10</version>
|
||||
<version>1.15.11</version>
|
||||
</dependency>
|
||||
<!-- Specified so that Renovate will file Maven upgrade PRs, which
|
||||
subsequently will cause `maven-enforcer-plugin` to require that
|
||||
developers build the project using the latest Maven release. -->
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-plugin-api</artifactId>
|
||||
<version>${version.maven}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
@@ -436,14 +445,14 @@
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-bom</artifactId>
|
||||
<version>3.26.3</version>
|
||||
<version>3.27.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.48.2</version>
|
||||
<version>3.48.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
@@ -455,6 +464,11 @@
|
||||
<artifactId>value-annotations</artifactId>
|
||||
<version>2.10.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
<version>3.19.16</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
@@ -463,7 +477,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.11.3</version>
|
||||
<version>5.11.4</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -477,14 +491,7 @@
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-core</artifactId>
|
||||
<version>5.2.0</version>
|
||||
</dependency>
|
||||
<!-- XXX: Drop this `rewrite-java-17` version declaration once
|
||||
`rewrite-recipe-bom` pulls in version 8.39.1 or greater. -->
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
<artifactId>rewrite-java-17</artifactId>
|
||||
<version>8.38.1</version>
|
||||
<version>5.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
@@ -494,7 +501,7 @@
|
||||
<dependency>
|
||||
<groupId>org.openrewrite.recipe</groupId>
|
||||
<artifactId>rewrite-recipe-bom</artifactId>
|
||||
<version>2.21.1</version>
|
||||
<version>2.23.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -508,19 +515,19 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>6.1.14</version>
|
||||
<version>6.2.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test</artifactId>
|
||||
<version>3.3.5</version>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-bom</artifactId>
|
||||
<version>6.3.4</version>
|
||||
<version>6.4.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -921,7 +928,7 @@
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>10.20.0</version>
|
||||
<version>10.21.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.spring.nohttp</groupId>
|
||||
@@ -1114,6 +1121,9 @@
|
||||
<requireMatchingCoordinates>
|
||||
<moduleNameMustMatchArtifactId>true</moduleNameMustMatchArtifactId>
|
||||
</requireMatchingCoordinates>
|
||||
<requireMavenVersion>
|
||||
<version>${version.maven}</version>
|
||||
</requireMavenVersion>
|
||||
<requireNoRepositories />
|
||||
<requirePluginVersions />
|
||||
<requireUpperBoundDeps />
|
||||
@@ -1217,7 +1227,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<version>3.11.2</version>
|
||||
<configuration>
|
||||
<additionalJOptions>
|
||||
<additionalJOption>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</additionalJOption>
|
||||
@@ -1300,15 +1310,10 @@
|
||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<version>2.4.0</version>
|
||||
<version>2.5.0</version>
|
||||
<configuration>
|
||||
<includedLicenses>
|
||||
<!-- The SPDX IDs of licenses of third-party
|
||||
@@ -1363,6 +1368,8 @@
|
||||
| BSD licence
|
||||
| BSD License 3
|
||||
| Eclipse Distribution License (New BSD License)
|
||||
| Eclipse Distribution License - v 1.0
|
||||
| EDL 1.0
|
||||
| New BSD License
|
||||
</licenseMerge>
|
||||
<licenseMerge>
|
||||
@@ -1447,11 +1454,42 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>versions-maven-plugin</artifactId>
|
||||
<version>2.17.1</version>
|
||||
<version>2.18.0</version>
|
||||
<configuration>
|
||||
<updateBuildOutputTimestampPolicy>never</updateBuildOutputTimestampPolicy>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.gaul</groupId>
|
||||
<artifactId>modernizer-maven-plugin</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<configuration>
|
||||
<exclusionPatterns>
|
||||
<!-- The plugin suggests replacing usages of
|
||||
Guava's `Iterables` class with
|
||||
`java.util.stream.Stream` equivalents, but the
|
||||
alternative is often more verbose, requiring
|
||||
unnecessary conversions to and from streams. -->
|
||||
<exclusionPattern>com/google/common/collect/Iterables\..*</exclusionPattern>
|
||||
</exclusionPatterns>
|
||||
<failOnViolations>false</failOnViolations>
|
||||
<ignorePackages>
|
||||
<!-- Some Refaster rules purposefully use outdated
|
||||
patterns in their `@BeforeTemplate` methods. -->
|
||||
<ignorePackage>tech.picnic.errorprone.refasterrules</ignorePackage>
|
||||
</ignorePackages>
|
||||
<javaVersion>${version.jdk}</javaVersion>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-modernizer</id>
|
||||
<goals>
|
||||
<goal>modernizer</goal>
|
||||
</goals>
|
||||
<phase>process-test-classes</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
@@ -1464,10 +1502,28 @@
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.kordamp.maven</groupId>
|
||||
<artifactId>pomchecker-maven-plugin</artifactId>
|
||||
<version>1.14.0</version>
|
||||
<configuration>
|
||||
<failOnError>false</failOnError>
|
||||
<release>false</release>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>check-maven-central-compliance</id>
|
||||
<goals>
|
||||
<goal>check-maven-central</goal>
|
||||
</goals>
|
||||
<phase>verify</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.pitest</groupId>
|
||||
<artifactId>pitest-maven</artifactId>
|
||||
<version>1.17.0</version>
|
||||
<version>1.17.3</version>
|
||||
<configuration>
|
||||
<excludedClasses>
|
||||
<!-- AutoValue generated classes. -->
|
||||
@@ -1521,7 +1577,7 @@
|
||||
<plugin>
|
||||
<groupId>org.sonarsource.scanner.maven</groupId>
|
||||
<artifactId>sonar-maven-plugin</artifactId>
|
||||
<version>4.0.0.4121</version>
|
||||
<version>5.0.0.4389</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
@@ -1818,6 +1874,14 @@
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>tidy-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.gaul</groupId>
|
||||
<artifactId>modernizer-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.kordamp.maven</groupId>
|
||||
<artifactId>pomchecker-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
@@ -1905,12 +1969,6 @@
|
||||
<!-- XXX: Enable this once we open-source
|
||||
this library. -->
|
||||
-Xep:BetaApi:OFF
|
||||
<!-- This check flags bad member names, but
|
||||
also type names that we may want to accept.
|
||||
Consider contributing a flag to toggle this
|
||||
behavior. See
|
||||
https://github.com/google/error-prone/issues/4616 -->
|
||||
-Xep:IdentifierName:OFF
|
||||
<!-- We don't target JDK 7. -->
|
||||
-Xep:Java7ApiChecker:OFF
|
||||
<!-- We don't target JDK 8. -->
|
||||
@@ -1926,6 +1984,9 @@
|
||||
<!-- XXX: Enable once there are fewer
|
||||
false-positives.
|
||||
-XepOpt:CheckReturnValue:CheckAllMethods=true -->
|
||||
<!-- XXX: Consider renaming flagged types
|
||||
instead. -->
|
||||
-XepOpt:IdentifierName:AllowInitialismsInTypeName=true
|
||||
-XepOpt:InlineMe:SkipInliningsWithComments=false
|
||||
-XepOpt:NullAway:AnnotatedPackages=tech.picnic
|
||||
-XepOpt:NullAway:AssertsEnabled=true
|
||||
@@ -1940,11 +2001,18 @@
|
||||
</arg>
|
||||
<!-- The Error Prone plugin makes certain
|
||||
assumptions about the state of the AST at the
|
||||
moment it is invoked. Those assumptions are met
|
||||
when using the `simple` compile policy. This
|
||||
flag may be dropped after resolution of
|
||||
moment it is invoked. Those assumptions require
|
||||
the `simple` compile policy. This flag may be
|
||||
dropped after resolution of
|
||||
https://bugs.openjdk.java.net/browse/JDK-8155674. -->
|
||||
<arg>-XDcompilePolicy=simple</arg>
|
||||
<!-- Similarly, Error Prone requires that flow
|
||||
analysis has been performed, e.g. to determine
|
||||
whether variables are effectively final. This
|
||||
flag may be dropped if it ever becomes the
|
||||
default. See
|
||||
https://bugs.openjdk.org/browse/JDK-8134117. -->
|
||||
<arg>--should-stop=ifError=FLOW</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@@ -2044,6 +2112,21 @@
|
||||
<failOnMissing>true</failOnMissing>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.gaul</groupId>
|
||||
<artifactId>modernizer-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<failOnViolations>true</failOnViolations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.kordamp.maven</groupId>
|
||||
<artifactId>pomchecker-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<failOnError>true</failOnError>
|
||||
<failOnWarning>true</failOnWarning>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
@@ -2115,6 +2198,13 @@
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
</plugin>
|
||||
<?SORTPOM RESUME?>
|
||||
<plugin>
|
||||
<groupId>org.kordamp.maven</groupId>
|
||||
<artifactId>pomchecker-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<release>true</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
@@ -1,8 +1,32 @@
|
||||
# An overview of Error Prone Support releases, along with compatible Error
|
||||
# Prone releases. This data was generated by `generate-version-compatibility-overview.sh`.
|
||||
releases:
|
||||
- version: 0.19.1
|
||||
compatible:
|
||||
- "2.36.0"
|
||||
- "2.35.1"
|
||||
- "2.35.0"
|
||||
- "2.34.0"
|
||||
- "2.33.0"
|
||||
- "2.32.0"
|
||||
- "2.31.0"
|
||||
- "2.30.0"
|
||||
- version: 0.19.0
|
||||
compatible:
|
||||
- "2.36.0"
|
||||
- "2.35.1"
|
||||
- "2.35.0"
|
||||
- "2.34.0"
|
||||
- "2.33.0"
|
||||
- "2.32.0"
|
||||
- "2.31.0"
|
||||
- "2.30.0"
|
||||
- version: 0.18.0
|
||||
compatible:
|
||||
- "2.36.0"
|
||||
- "2.35.1"
|
||||
- "2.35.0"
|
||||
- "2.34.0"
|
||||
- "2.33.0"
|
||||
- "2.32.0"
|
||||
- "2.31.0"
|
||||
|
||||
@@ -45,6 +45,13 @@ for eps_version in ${eps_versions}; do
|
||||
(set +u && echo n | sdk install maven "${mvn_version}")
|
||||
sdk use maven "${mvn_version}"
|
||||
|
||||
# As of version 2.36.0, Error Prone requires that the
|
||||
# `--should-stop=ifError=FLOW` flag is provided. Make sure that this flag is
|
||||
# always specified. (The `-XDcompilePolicy=simple` flag has been specified
|
||||
# since the first Error Prone Support release. It's okay if the added flag is
|
||||
# present more than once; the last variant listed wins.)
|
||||
sed -i 's,<arg>-XDcompilePolicy=simple</arg>,<arg>-XDcompilePolicy=simple</arg><arg>--should-stop=ifError=FLOW</arg>,' pom.xml
|
||||
|
||||
# Collect the list of checks supported by this version of Error Prone
|
||||
# Support.
|
||||
# XXX: Conditionally omit the `MethodReferenceUsage` exclusion once that
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
# Error Prone Workshop
|
||||
|
||||
Download the slides [here][eps-workshop-slides].
|
||||
|
||||
## Initial setup of the workshop
|
||||
|
||||
1. Start by cloning this repository locally from GitHub.
|
||||
2. Checkout the `workshop` branch.
|
||||
3. Make sure to run `mvn clean install` in the root of this repository.
|
||||
4. Open your code editor and familiarize yourself with the project structure.
|
||||
|
||||
In IntelliJ IDEA (or your preferred editor), try to run the
|
||||
`WorkshopRefasterRulesTest` test. You might see the following error:
|
||||
|
||||
```
|
||||
java: exporting a package from system module jdk.compiler is not allowed with --release
|
||||
```
|
||||
|
||||
If this happens, go to _File -> Settings... -> Build, Execution, Deployment ->
|
||||
Compiler -> Java Compiler_ and deselect the option _Use '--release' option for
|
||||
cross-compilation (Java 9 and later)_.
|
||||
|
||||
If you encounter any other bugs when running `mvn clean install`, make sure you
|
||||
are using a recent release of JDK 17.
|
||||
|
||||
Now the project is ready for the workshop.
|
||||
|
||||
## Part 1: Writing Refaster rules
|
||||
|
||||
During this part of the workshop we will implement multiple Refaster rules.
|
||||
|
||||
Go to the `workshop` module and navigate to the
|
||||
`tech.picnic.errorprone.workshop.refasterrules` package. There you can find one
|
||||
example and five different exercises to do. Make sure to open the
|
||||
`WorkshopRefasterRulesTest` class where you can enable tests. Per assignment
|
||||
there is a test in this class that you can enable (by dropping the `@Disabled`
|
||||
annotation) to validate your changes. The goal is to implement or improve the
|
||||
Refaster rules such that the enabled tests pass.
|
||||
|
||||
Tips:
|
||||
|
||||
* Go through the exercises in the proposed order.
|
||||
* The `XXX:` comments explain what needs to happen.
|
||||
* Find the test case for each Refaster rule by looking for the name of the
|
||||
Refaster rule, prefixed with `test`. For example, the
|
||||
`WorkshopAssignment0Rules.java` rule collection has a Refaster rule named
|
||||
`ExampleStringIsEmpty`. In the `WorkshopAssignment0RulesTestInput.java` and
|
||||
`WorkshopAssignment0RulesTestOutput.java` files there is a
|
||||
`testExampleStringIsEmpty` method that shows the input and output to test the
|
||||
Refaster rule.
|
||||
|
||||
## Part 2: Writing Error Prone checks
|
||||
|
||||
During this part of the workshop we will implement parts of multiple Error
|
||||
Prone `BugChecker`s. Each of these classes contain `XXX` comments explaining
|
||||
what needs to be implemented. However, before diving in, make sure to first
|
||||
navigate to a check's associated test class to drop the class-level `@Disabled`
|
||||
annotation. Upon initial execution the tests will fail; the goal is to get then
|
||||
to pass.
|
||||
|
||||
Some utility classes that you can use:
|
||||
|
||||
* `com.google.errorprone.util.ASTHelpers`: contains many common operations on
|
||||
the Abstract Syntax Tree.
|
||||
* `com.google.errorprone.fixes.SuggestedFixes`: contains helper methods for
|
||||
creating `Fix`es.
|
||||
|
||||
### Tips and tricks
|
||||
|
||||
If you are working from the command line, it is suggested to run commands in
|
||||
the `workshop` directory. To do this, navigate to the root of the repository
|
||||
and run:
|
||||
|
||||
```bash
|
||||
cd workshop
|
||||
```
|
||||
|
||||
In case you want to do a fast build to just compile the project, run:
|
||||
|
||||
```bash
|
||||
mvn clean install -DskipTests -Dverification.skip
|
||||
```
|
||||
|
||||
In case you want to run one test from the command line, run the following
|
||||
commands:
|
||||
|
||||
```bash
|
||||
mvn clean install -Dtest=WorkshopRefasterRulesTest -Dverification.skip
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
Make sure to use the latest version of JDK 21 or 17.
|
||||
|
||||
In some specific cases the `-Dverification.skip` is not correctly processed. In
|
||||
that case, use `-D"verification.skip"`.
|
||||
|
||||
In case there is an error mentioning the `BetaApi` check, please rebuild or try
|
||||
to `Reload All Maven projects`.
|
||||
|
||||
|
||||
[eps-github]: https://github.com/PicnicSupermarket/error-prone-support
|
||||
|
||||
[eps-workshop-slides]: https://docs.google.com/presentation/d/1XQJohAUGSmDyOywJCZWZBjmsRRt1FQ5ykE0F-NaY6Lo/edit?usp=sharing
|
||||
160
workshop/pom.xml
160
workshop/pom.xml
@@ -1,160 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.19.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>workshop</artifactId>
|
||||
|
||||
<name>Picnic :: Error Prone Support :: Workshop</name>
|
||||
<description>Project for the Error Prone Workshop.</description>
|
||||
<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>error-prone-utils</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-compiler</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-support</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
<artifactId>rewrite-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
<artifactId>rewrite-java</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
<artifactId>rewrite-java-11</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
<artifactId>rewrite-templating</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths combine.children="append">
|
||||
<path>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-compiler</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-support</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs combine.children="append">
|
||||
<arg>-Xplugin:RefasterRuleCompiler</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,38 +0,0 @@
|
||||
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
|
||||
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.MethodTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
|
||||
/** A {@link BugChecker} that flags empty methods that seemingly can simply be deleted. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "Empty method can likely be deleted",
|
||||
severity = WARNING,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class Assignment0DeleteEmptyMethod extends BugChecker implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Instantiates a new {@link Assignment0DeleteEmptyMethod} instance. */
|
||||
public Assignment0DeleteEmptyMethod() {}
|
||||
|
||||
@Override
|
||||
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||
if (tree.getBody() == null
|
||||
|| !tree.getBody().getStatements().isEmpty()
|
||||
|| ASTHelpers.hasAnnotation(tree, Override.class.getName(), state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return describeMatch(tree, SuggestedFix.delete(tree));
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||
import static com.google.errorprone.matchers.Matchers.argument;
|
||||
import static com.google.errorprone.matchers.Matchers.argumentCount;
|
||||
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||
import static com.google.errorprone.matchers.Matchers.nullLiteral;
|
||||
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags AssertJ {@code isEqualTo(null)} checks for simplification.
|
||||
*
|
||||
* <p>This bug checker cannot be replaced with a simple Refaster rule, as the Refaster approach
|
||||
* would require that all overloads of {@link org.assertj.core.api.Assert#isEqualTo(Object)} (such
|
||||
* as {@link org.assertj.core.api.AbstractStringAssert#isEqualTo(String)}) are explicitly
|
||||
* enumerated. This bug checker generically matches all such current and future overloads.
|
||||
*/
|
||||
@BugPattern(
|
||||
summary = "Prefer `.isNull()` over `.isEqualTo(null)`",
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class Assignment1AssertJIsNullMethod extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<MethodInvocationTree> ASSERT_IS_EQUAL_TO_NULL =
|
||||
allOf(
|
||||
instanceMethod().onDescendantOf("org.assertj.core.api.Assert").named("isEqualTo"),
|
||||
argumentCount(1),
|
||||
argument(0, nullLiteral()));
|
||||
|
||||
/** Instantiates a new {@link Assignment1AssertJIsNullMethod} instance. */
|
||||
public Assignment1AssertJIsNullMethod() {}
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
// This statement filters out `MethodInvocation`s that are *not* `assertThat().isEqualTo(null)`
|
||||
// statements.
|
||||
if (!ASSERT_IS_EQUAL_TO_NULL.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
SuggestedFix.Builder fix =
|
||||
SuggestedFix.builder().merge(SuggestedFixes.renameMethodInvocation(tree, "isNull", state));
|
||||
tree.getArguments().forEach(arg -> fix.merge(SuggestedFix.delete(arg)));
|
||||
|
||||
return describeMatch(tree, fix.build());
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.Matcher;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import java.util.List;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/**
|
||||
* A {@link BugChecker} that flags method invocations for which all arguments are wrapped using
|
||||
* {@link org.mockito.Mockito#eq}; this is redundant.
|
||||
*/
|
||||
@BugPattern(
|
||||
summary = "Don't unnecessarily use Mockito's `eq(...)`",
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class Assignment2DropMockitoEq extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> MOCKITO_EQ_METHOD =
|
||||
staticMethod().onClass("org.mockito.ArgumentMatchers").named("eq");
|
||||
|
||||
/** Instantiates a new {@link Assignment2DropMockitoEq} instance. */
|
||||
public Assignment2DropMockitoEq() {}
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
// XXX: Make sure to return `Description.NO_MATCH` if the `tree` doesn't have arguments, or if
|
||||
// the `isEqInvocation` method below returns `false` for at least one of the arguments.
|
||||
List<? extends ExpressionTree> arguments = tree.getArguments();
|
||||
if (arguments.isEmpty() || !arguments.stream().allMatch(arg -> isEqInvocation(arg, state))) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
SuggestedFix.Builder suggestedFix = SuggestedFix.builder();
|
||||
for (ExpressionTree arg : arguments) {
|
||||
suggestedFix.replace(
|
||||
arg,
|
||||
SourceCode.treeToString(
|
||||
Iterables.getOnlyElement(((MethodInvocationTree) arg).getArguments()), state));
|
||||
}
|
||||
|
||||
return describeMatch(tree, suggestedFix.build());
|
||||
}
|
||||
|
||||
private static boolean isEqInvocation(ExpressionTree tree, VisitorState state) {
|
||||
return tree instanceof MethodInvocationTree && MOCKITO_EQ_METHOD.matches(tree, state);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.MultiMatcher;
|
||||
import com.google.errorprone.matchers.MultiMatcher.MultiMatchResult;
|
||||
import com.google.errorprone.util.ASTHelpers;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import java.util.List;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} that flags redundant {@code @Autowired} constructor annotations. */
|
||||
@BugPattern(
|
||||
summary = "Omit `@Autowired` on a class' sole constructor, as it is redundant",
|
||||
severity = SUGGESTION,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class Assignment3DropAutowiredConstructorAnnotation extends BugChecker
|
||||
implements ClassTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final MultiMatcher<Tree, AnnotationTree> AUTOWIRED_ANNOTATION =
|
||||
annotations(AT_LEAST_ONE, isType("org.springframework.beans.factory.annotation.Autowired"));
|
||||
|
||||
/** Instantiates a new {@link Assignment3DropAutowiredConstructorAnnotation} instance. */
|
||||
public Assignment3DropAutowiredConstructorAnnotation() {}
|
||||
|
||||
@Override
|
||||
public Description matchClass(ClassTree tree, VisitorState state) {
|
||||
// XXX: Using the `ASTHelpers#getConstructors` method, return `Description.NO_MATCH` if we do
|
||||
// not have exactly 1 constructor (start by dropping `new ArrayList<>()` on the next line).
|
||||
List<MethodTree> constructors = ASTHelpers.getConstructors(tree);
|
||||
if (constructors.size() != 1) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
MultiMatchResult<AnnotationTree> hasAutowiredAnnotation =
|
||||
AUTOWIRED_ANNOTATION.multiMatchResult(Iterables.getOnlyElement(constructors), state);
|
||||
if (!hasAutowiredAnnotation.matches()) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
AnnotationTree annotation = hasAutowiredAnnotation.onlyMatchingNode();
|
||||
return describeMatch(annotation, SourceCode.deleteWithTrailingWhitespace(annotation, state));
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||
import static com.google.errorprone.matchers.Matchers.isType;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.fixes.SuggestedFixes;
|
||||
import com.google.errorprone.matchers.Description;
|
||||
import com.google.errorprone.matchers.MultiMatcher;
|
||||
import com.sun.source.tree.AnnotationTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import javax.lang.model.element.Modifier;
|
||||
|
||||
/** A {@link BugChecker} that flags non-canonical JUnit method declarations. */
|
||||
@AutoService(BugChecker.class)
|
||||
@BugPattern(
|
||||
summary = "JUnit method declaration can likely be improved",
|
||||
severity = WARNING,
|
||||
tags = SIMPLIFICATION)
|
||||
@SuppressWarnings({
|
||||
"UnusedMethod",
|
||||
"UnusedVariable"
|
||||
} /* This check is yet to be implemented as part of the demo. */)
|
||||
public final class Assignment4JUnitTestMethodDeclaration extends BugChecker
|
||||
implements MethodTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final ImmutableSet<Modifier> ILLEGAL_MODIFIERS =
|
||||
Sets.immutableEnumSet(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC);
|
||||
private static final MultiMatcher<MethodTree, AnnotationTree> TEST_METHOD =
|
||||
annotations(AT_LEAST_ONE, anyOf(isType("org.junit.jupiter.api.Test")));
|
||||
|
||||
/** Instantiates a new {@link Assignment4JUnitTestMethodDeclaration} instance. */
|
||||
public Assignment4JUnitTestMethodDeclaration() {}
|
||||
|
||||
@Override
|
||||
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||
if (!TEST_METHOD.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
|
||||
|
||||
// XXX: Part 2: Make sure that JUnit test methods don't use any of the modifiers from the
|
||||
// `ILLEGAL_MODIFIERS` field, by using `SuggestedFixes#removeModifiers` and
|
||||
// `SuggestedFix.Builder#merge`.
|
||||
SuggestedFixes.removeModifiers(tree.getModifiers(), state, ILLEGAL_MODIFIERS)
|
||||
.ifPresent(fixBuilder::merge);
|
||||
|
||||
if (fixBuilder.isEmpty()) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return describeMatch(tree, fixBuilder.build());
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
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.staticMethod;
|
||||
import static com.google.errorprone.suppliers.Suppliers.OBJECT_TYPE;
|
||||
|
||||
import com.google.common.primitives.Primitives;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.bugpatterns.BugChecker;
|
||||
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||
import com.google.errorprone.bugpatterns.TypesWithUndefinedEquality;
|
||||
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.google.errorprone.util.ASTHelpers.TargetType;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.MethodInvocationTree;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Types;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
/** A {@link BugChecker} that flags redundant identity conversions. */
|
||||
@BugPattern(
|
||||
summary = "Avoid or clarify identity conversions",
|
||||
severity = WARNING,
|
||||
tags = SIMPLIFICATION)
|
||||
public final class Assignment5DeleteIdentityConversion extends BugChecker
|
||||
implements MethodInvocationTreeMatcher {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Matcher<ExpressionTree> IS_CONVERSION_METHOD =
|
||||
anyOf(
|
||||
staticMethod()
|
||||
.onClassAny(
|
||||
Primitives.allWrapperTypes().stream()
|
||||
.map(Class::getName)
|
||||
.collect(toImmutableSet()))
|
||||
.named("valueOf"),
|
||||
staticMethod().onClass(String.class.getName()).named("valueOf"),
|
||||
staticMethod()
|
||||
.onClassAny(
|
||||
"com.google.common.collect.ImmutableBiMap",
|
||||
"com.google.common.collect.ImmutableList",
|
||||
"com.google.common.collect.ImmutableListMultimap",
|
||||
"com.google.common.collect.ImmutableMap",
|
||||
"com.google.common.collect.ImmutableMultimap",
|
||||
"com.google.common.collect.ImmutableMultiset",
|
||||
"com.google.common.collect.ImmutableRangeMap",
|
||||
"com.google.common.collect.ImmutableRangeSet",
|
||||
"com.google.common.collect.ImmutableSet",
|
||||
"com.google.common.collect.ImmutableSetMultimap",
|
||||
"com.google.common.collect.ImmutableTable")
|
||||
.named("copyOf"),
|
||||
staticMethod()
|
||||
.onClass("com.google.errorprone.matchers.Matchers")
|
||||
.namedAnyOf("allOf", "anyOf"));
|
||||
|
||||
/** Instantiates a new {@link Assignment5DeleteIdentityConversion} instance. */
|
||||
public Assignment5DeleteIdentityConversion() {}
|
||||
|
||||
@Override
|
||||
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||
List<? extends ExpressionTree> arguments = tree.getArguments();
|
||||
if (arguments.size() != 1 || !IS_CONVERSION_METHOD.matches(tree, state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
ExpressionTree sourceTree = arguments.get(0);
|
||||
Type sourceType = ASTHelpers.getType(sourceTree);
|
||||
Type resultType = ASTHelpers.getType(tree);
|
||||
TargetType targetType = ASTHelpers.targetType(state);
|
||||
if (sourceType == null || resultType == null || targetType == null) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
if (!state.getTypes().isSameType(sourceType, resultType)
|
||||
&& !isConvertibleWithWellDefinedEquality(sourceType, targetType.type(), state)) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
if (sourceType.isPrimitive()
|
||||
&& state.getPath().getParentPath().getLeaf() instanceof MemberSelectTree) {
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
|
||||
return buildDescription(tree)
|
||||
.addFix(SuggestedFix.replace(tree, SourceCode.treeToString(sourceTree, state)))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static boolean isConvertibleWithWellDefinedEquality(
|
||||
Type sourceType, Type targetType, VisitorState state) {
|
||||
Types types = state.getTypes();
|
||||
return !types.isSameType(targetType, OBJECT_TYPE.get(state))
|
||||
&& types.isConvertible(sourceType, targetType)
|
||||
&& Arrays.stream(TypesWithUndefinedEquality.values())
|
||||
.noneMatch(b -> b.matchesType(sourceType, state) || b.matchesType(targetType, state));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user