mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 08:11:25 +00:00
Compare commits
135 Commits
jbroudy/in
...
sschroever
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
044a30121e | ||
|
|
1cffbd0763 | ||
|
|
f0ad9d21e6 | ||
|
|
7138aa2100 | ||
|
|
de4667628f | ||
|
|
5e958fe20b | ||
|
|
baa921caac | ||
|
|
ba040bd191 | ||
|
|
a3a20b52e5 | ||
|
|
afcb9abb32 | ||
|
|
5a4c4feab2 | ||
|
|
168d19c046 | ||
|
|
e2569c48ae | ||
|
|
c59cb4a947 | ||
|
|
899fe6fc42 | ||
|
|
5d8d27176b | ||
|
|
d878a57a8e | ||
|
|
eaec12f460 | ||
|
|
da7dafb6e7 | ||
|
|
5a7aaf12d6 | ||
|
|
92e4d74e4b | ||
|
|
4a0bc0c210 | ||
|
|
53152499d6 | ||
|
|
61d92fb33f | ||
|
|
8690f49c35 | ||
|
|
d808f664ec | ||
|
|
7f5f4820e9 | ||
|
|
f7a4427852 | ||
|
|
0e956bcd44 | ||
|
|
5395fc60e1 | ||
|
|
d8cae04a98 | ||
|
|
7b14711ecf | ||
|
|
c3351b9ee1 | ||
|
|
40b3c87b72 | ||
|
|
726db5ce5b | ||
|
|
99d359c548 | ||
|
|
4744113411 | ||
|
|
ae8f940f55 | ||
|
|
8d7633df2d | ||
|
|
4a351cfbe3 | ||
|
|
bb01447760 | ||
|
|
f12ed17b96 | ||
|
|
854e05f044 | ||
|
|
82c22682c0 | ||
|
|
25b3817876 | ||
|
|
e2a2b086ad | ||
|
|
5f9a0c5e17 | ||
|
|
2a0ae0af13 | ||
|
|
7a051146b6 | ||
|
|
d9398001cb | ||
|
|
0be99cb12a | ||
|
|
70e2d3d43f | ||
|
|
441258f9f2 | ||
|
|
b96efb533c | ||
|
|
5af067cc23 | ||
|
|
0c84665e38 | ||
|
|
9316d81fe3 | ||
|
|
ec96c044d5 | ||
|
|
ae4ed9273f | ||
|
|
0ec882e62e | ||
|
|
fef9ba23f4 | ||
|
|
3bd415b910 | ||
|
|
2128624261 | ||
|
|
c53fcace76 | ||
|
|
ff3759984c | ||
|
|
6358d1e2e1 | ||
|
|
db53631e76 | ||
|
|
86b2d929ab | ||
|
|
0db4462a64 | ||
|
|
f8667fc655 | ||
|
|
d91f94e879 | ||
|
|
ad6c8593f2 | ||
|
|
873ee47e8d | ||
|
|
fed281dc2b | ||
|
|
277d30467d | ||
|
|
9673572114 | ||
|
|
6833ac582c | ||
|
|
8d99611af7 | ||
|
|
424b520b05 | ||
|
|
2687322720 | ||
|
|
77bc1079d6 | ||
|
|
72f888125a | ||
|
|
0157692fbe | ||
|
|
5ba70753f6 | ||
|
|
d59b62612e | ||
|
|
c34fa4decd | ||
|
|
2cb4bd0e57 | ||
|
|
0cf891c87b | ||
|
|
63ad14e76e | ||
|
|
457a8e229e | ||
|
|
ab037393f1 | ||
|
|
afdcf5222c | ||
|
|
7889148cae | ||
|
|
2003bd201b | ||
|
|
a27d635467 | ||
|
|
9151287560 | ||
|
|
c3a5106343 | ||
|
|
2c137c0024 | ||
|
|
1c5077f65d | ||
|
|
2a93011046 | ||
|
|
39dc9aa4c8 | ||
|
|
72ff8aed75 | ||
|
|
6739cb4a95 | ||
|
|
344f4e4058 | ||
|
|
ee74279ef9 | ||
|
|
1624ebf4c6 | ||
|
|
04847628f5 | ||
|
|
d21ac59cb5 | ||
|
|
32300ff2e5 | ||
|
|
302e20b212 | ||
|
|
8bd88bbe01 | ||
|
|
b2ef63107b | ||
|
|
e6caceba60 | ||
|
|
594f51c9d0 | ||
|
|
7e49b08a7e | ||
|
|
50443d179f | ||
|
|
ad1c98d3eb | ||
|
|
20d194b4d4 | ||
|
|
d899a8a10c | ||
|
|
c4b6a5fbe4 | ||
|
|
74d6c9a46b | ||
|
|
12d09ad496 | ||
|
|
34826413da | ||
|
|
01b7e5b78d | ||
|
|
d26bc18b0c | ||
|
|
cf772c47cd | ||
|
|
abb6cea861 | ||
|
|
db8cf3c860 | ||
|
|
458fb99d4e | ||
|
|
914d30a7ed | ||
|
|
0e46f9cf5f | ||
|
|
0f44844c51 | ||
|
|
827880bc45 | ||
|
|
84061fcd06 | ||
|
|
69386f0b3d |
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@@ -40,13 +40,13 @@ jobs:
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.9
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5
|
||||
uses: github/codeql-action/init@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Perform minimal build
|
||||
if: matrix.language == 'java'
|
||||
run: mvn -T1C clean package -DskipTests -Dverification.skip
|
||||
- name: Perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5
|
||||
uses: github/codeql-action/analyze@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
|
||||
with:
|
||||
category: /language:${{ matrix.language }}
|
||||
|
||||
2
.github/workflows/deploy-website.yml
vendored
2
.github/workflows/deploy-website.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: ruby/setup-ruby@28c4deda893d5a96a6b2d958c5b47fc18d65c9d3 # v1.213.0
|
||||
- uses: ruby/setup-ruby@1a615958ad9d422dd932dc1d5823942ee002799f # v1.227.0
|
||||
with:
|
||||
working-directory: ./website
|
||||
bundler-cache: true
|
||||
|
||||
4
.github/workflows/openssf-scorecard.yml
vendored
4
.github/workflows/openssf-scorecard.yml
vendored
@@ -42,12 +42,12 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run OpenSSF Scorecard analysis
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: ${{ github.ref == 'refs/heads/master' }}
|
||||
- name: Update GitHub's code scanning dashboard
|
||||
uses: github/codeql-action/upload-sarif@f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4 # v3.28.5
|
||||
uses: github/codeql-action/upload-sarif@5f8171a638ada777af81d42b55959a643bb29017 # v3.28.12
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
2
.github/workflows/pitest-analyze-pr.yml
vendored
2
.github/workflows/pitest-analyze-pr.yml
vendored
@@ -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@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: pitest-reports
|
||||
path: ./target/pit-reports-ci
|
||||
|
||||
17
.github/workflows/run-integration-tests.yml
vendored
17
.github/workflows/run-integration-tests.yml
vendored
@@ -7,19 +7,21 @@
|
||||
# https://docs.github.com/en/actions/learn-github-actions/expressions#example-returning-a-json-object
|
||||
name: "Integration tests"
|
||||
on:
|
||||
issue_comment:
|
||||
types: [ created ]
|
||||
# issue_comment:
|
||||
# types: [ created ]
|
||||
pull_request:
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
run-integration-tests:
|
||||
name: On-demand integration test
|
||||
if: |
|
||||
github.event.issue.pull_request && contains(github.event.comment.body, '/integration-test')
|
||||
# if: |
|
||||
# github.event.issue.pull_request && contains(github.event.comment.body, '/integration-test')
|
||||
runs-on: ubuntu-24.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
integration-test: [ "checkstyle", "metrics", "prometheus-java-client" ]
|
||||
integration-test: [ "metrics", "prometheus-java-client" ] # XXX: Dropped checkstyle.
|
||||
steps:
|
||||
- name: Install Harden-Runner
|
||||
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
|
||||
@@ -45,17 +47,18 @@ jobs:
|
||||
- name: Check out code and set up JDK and Maven
|
||||
uses: s4u/setup-maven-action@4f7fb9d9675e899ca81c6161dadbba0189a4ebb1 # v1.18.0
|
||||
with:
|
||||
checkout-ref: "refs/pull/${{ github.event.issue.number }}/head"
|
||||
# checkout-ref: "refs/pull/${{ github.event.issue.number }}/head"
|
||||
java-version: 17.0.13
|
||||
java-distribution: temurin
|
||||
maven-version: 3.9.9
|
||||
- name: Install project to local Maven repository
|
||||
run: mvn -T1C install -DskipTests -Dverification.skip
|
||||
- name: Run integration test
|
||||
continue-on-error: true
|
||||
run: xvfb-run "./integration-tests/${{ matrix.integration-test }}.sh" "${{ runner.temp }}/artifacts"
|
||||
- name: Upload artifacts on failure
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: "integration-test-${{ matrix.integration-test }}"
|
||||
path: "${{ runner.temp }}/artifacts"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>documentation-support</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-contrib</artifactId>
|
||||
|
||||
@@ -4,6 +4,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.AlsoNegation;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.google.errorprone.refaster.annotation.Repeated;
|
||||
import java.io.File;
|
||||
@@ -11,6 +12,7 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
@@ -141,4 +143,35 @@ final class FileRules {
|
||||
return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke {@link File#mkdirs()} before {@link Files#exists(Path, LinkOption...)} to avoid
|
||||
* concurrency issues.
|
||||
*/
|
||||
static final class PathToFileMkDirsFilesExists {
|
||||
@BeforeTemplate
|
||||
boolean before(Path path) {
|
||||
return Files.exists(path) || path.toFile().mkdirs();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@AlsoNegation
|
||||
boolean after(Path path) {
|
||||
return path.toFile().mkdirs() || Files.exists(path);
|
||||
}
|
||||
}
|
||||
|
||||
/** Invoke {@link File#mkdirs()} before {@link File#exists()} to avoid concurrency issues. */
|
||||
static final class FileMkDirsFileExists {
|
||||
@BeforeTemplate
|
||||
boolean before(File file) {
|
||||
return file.exists() || file.mkdirs();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@AlsoNegation
|
||||
boolean after(File file) {
|
||||
return file.mkdirs() || file.exists();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,9 +489,16 @@ final class ReactorRules {
|
||||
return Flux.range(value, 1);
|
||||
}
|
||||
|
||||
// XXX: Consider generalizing part of this template using an Error Prone check that covers any
|
||||
// sequence of explicitly enumerated values passed to an iteration order-preserving collection
|
||||
// factory method.
|
||||
@BeforeTemplate
|
||||
Flux<T> before(T value) {
|
||||
return Mono.just(value).repeat().take(1);
|
||||
return Refaster.anyOf(
|
||||
Mono.just(value).flux(),
|
||||
Mono.just(value).repeat().take(1),
|
||||
Flux.fromIterable(ImmutableList.of(value)),
|
||||
Flux.fromIterable(ImmutableSet.of(value)));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -939,7 +946,11 @@ final class ReactorRules {
|
||||
static final class MonoThen<T> {
|
||||
@BeforeTemplate
|
||||
Mono<@Nullable Void> before(Mono<T> mono) {
|
||||
return Refaster.anyOf(mono.ignoreElement().then(), mono.flux().then());
|
||||
return Refaster.anyOf(
|
||||
mono.ignoreElement().then(),
|
||||
mono.flux().then(),
|
||||
Mono.when(mono),
|
||||
Mono.whenDelayError(mono));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
@@ -1078,10 +1089,12 @@ final class ReactorRules {
|
||||
// rule. Consider introducing an Error Prone check for this.
|
||||
static final class MonoSingleOptional<T> {
|
||||
@BeforeTemplate
|
||||
Mono<Optional<T>> before(Mono<T> mono) {
|
||||
Mono<Optional<T>> before(Mono<T> mono, Optional<T> optional, Mono<Optional<T>> alternate) {
|
||||
return Refaster.anyOf(
|
||||
mono.flux().collect(toOptional()),
|
||||
mono.map(Optional::of).defaultIfEmpty(Optional.empty()),
|
||||
mono.map(Optional::of),
|
||||
mono.singleOptional().defaultIfEmpty(optional),
|
||||
mono.singleOptional().switchIfEmpty(alternate),
|
||||
mono.transform(Mono::singleOptional));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
@@ -65,16 +66,18 @@ final class SuggestedFixRules {
|
||||
}
|
||||
}
|
||||
|
||||
/** Prefer {@link SuggestedFix#swap(Tree, Tree)} over more contrived alternatives. */
|
||||
/**
|
||||
* Prefer {@link SuggestedFix#swap(Tree, Tree, VisitorState)} over more contrived alternatives.
|
||||
*/
|
||||
static final class SuggestedFixSwap {
|
||||
@BeforeTemplate
|
||||
SuggestedFix before(Tree tree1, Tree tree2) {
|
||||
return SuggestedFix.builder().swap(tree1, tree2).build();
|
||||
SuggestedFix before(Tree tree1, Tree tree2, VisitorState state) {
|
||||
return SuggestedFix.builder().swap(tree1, tree2, state).build();
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
SuggestedFix after(Tree tree1, Tree tree2) {
|
||||
return SuggestedFix.swap(tree1, tree2);
|
||||
SuggestedFix after(Tree tree1, Tree tree2, VisitorState state) {
|
||||
return SuggestedFix.swap(tree1, tree2, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,4 +39,16 @@ final class FileRulesTest implements RefasterRuleCollectionTestCase {
|
||||
File testFilesCreateTempFileInCustomDirectoryToFile() throws IOException {
|
||||
return File.createTempFile("foo", "bar", new File("baz"));
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testPathToFileMkDirsFilesExists() {
|
||||
return ImmutableSet.of(
|
||||
Files.exists(Path.of("foo")) || Path.of("foo").toFile().mkdirs(),
|
||||
!Files.exists(Path.of("bar")) && !Path.of("bar").toFile().mkdirs());
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testFileMkDirsFileExists() {
|
||||
return ImmutableSet.of(
|
||||
new File("foo").exists() || new File("foo").mkdirs(),
|
||||
!new File("bar").exists() && !new File("bar").mkdirs());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,16 @@ final class FileRulesTest implements RefasterRuleCollectionTestCase {
|
||||
File testFilesCreateTempFileInCustomDirectoryToFile() throws IOException {
|
||||
return Files.createTempFile(new File("baz").toPath(), "foo", "bar").toFile();
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testPathToFileMkDirsFilesExists() {
|
||||
return ImmutableSet.of(
|
||||
Path.of("foo").toFile().mkdirs() || Files.exists(Path.of("foo")),
|
||||
!Path.of("bar").toFile().mkdirs() && !Files.exists(Path.of("bar")));
|
||||
}
|
||||
|
||||
ImmutableSet<Boolean> testFileMkDirsFileExists() {
|
||||
return ImmutableSet.of(
|
||||
new File("foo").mkdirs() || new File("foo").exists(),
|
||||
!new File("bar").mkdirs() && !new File("bar").exists());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,12 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Flux<Integer>> testFluxJust() {
|
||||
return ImmutableSet.of(Flux.range(0, 1), Mono.just(2).repeat().take(1));
|
||||
return ImmutableSet.of(
|
||||
Flux.range(0, 1),
|
||||
Mono.just(2).flux(),
|
||||
Mono.just(3).repeat().take(1),
|
||||
Flux.fromIterable(ImmutableList.of(4)),
|
||||
Flux.fromIterable(ImmutableSet.of(5)));
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<?>> testMonoIdentity() {
|
||||
@@ -342,7 +347,11 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<Void>> testMonoThen() {
|
||||
return ImmutableSet.of(Mono.just("foo").ignoreElement().then(), Mono.just("bar").flux().then());
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").ignoreElement().then(),
|
||||
Mono.just("bar").flux().then(),
|
||||
Mono.when(Mono.just("baz")),
|
||||
Mono.whenDelayError(Mono.just("qux")));
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<Void>> testFluxThen() {
|
||||
@@ -388,8 +397,10 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
ImmutableSet<Mono<Optional<String>>> testMonoSingleOptional() {
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").flux().collect(toOptional()),
|
||||
Mono.just("bar").map(Optional::of).defaultIfEmpty(Optional.empty()),
|
||||
Mono.just("baz").transform(Mono::singleOptional));
|
||||
Mono.just("bar").map(Optional::of),
|
||||
Mono.just("baz").singleOptional().defaultIfEmpty(Optional.empty()),
|
||||
Mono.just("quux").singleOptional().switchIfEmpty(Mono.just(Optional.empty())),
|
||||
Mono.just("quuz").transform(Mono::singleOptional));
|
||||
}
|
||||
|
||||
Mono<Number> testMonoCast() {
|
||||
|
||||
@@ -192,7 +192,7 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Flux<Integer>> testFluxJust() {
|
||||
return ImmutableSet.of(Flux.just(0), Flux.just(2));
|
||||
return ImmutableSet.of(Flux.just(0), Flux.just(2), Flux.just(3), Flux.just(4), Flux.just(5));
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<?>> testMonoIdentity() {
|
||||
@@ -340,7 +340,11 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<Void>> testMonoThen() {
|
||||
return ImmutableSet.of(Mono.just("foo").then(), Mono.just("bar").then());
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").then(),
|
||||
Mono.just("bar").then(),
|
||||
Mono.just("baz").then(),
|
||||
Mono.just("qux").then());
|
||||
}
|
||||
|
||||
ImmutableSet<Mono<Void>> testFluxThen() {
|
||||
@@ -384,7 +388,9 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
|
||||
return ImmutableSet.of(
|
||||
Mono.just("foo").singleOptional(),
|
||||
Mono.just("bar").singleOptional(),
|
||||
Mono.just("baz").singleOptional());
|
||||
Mono.just("baz").singleOptional(),
|
||||
Mono.just("quux").singleOptional(),
|
||||
Mono.just("quuz").singleOptional());
|
||||
}
|
||||
|
||||
Mono<Number> testMonoCast() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
@@ -23,7 +24,9 @@ final class SuggestedFixRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
SuggestedFix testSuggestedFixSwap() {
|
||||
return SuggestedFix.builder().swap((Tree) null, (ExpressionTree) null).build();
|
||||
return SuggestedFix.builder()
|
||||
.swap((Tree) null, (ExpressionTree) null, (VisitorState) null)
|
||||
.build();
|
||||
}
|
||||
|
||||
SuggestedFix testSuggestedFixPrefixWith() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package tech.picnic.errorprone.refasterrules;
|
||||
|
||||
import com.google.errorprone.VisitorState;
|
||||
import com.google.errorprone.fixes.SuggestedFix;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
@@ -23,7 +24,7 @@ final class SuggestedFixRulesTest implements RefasterRuleCollectionTestCase {
|
||||
}
|
||||
|
||||
SuggestedFix testSuggestedFixSwap() {
|
||||
return SuggestedFix.swap((Tree) null, (ExpressionTree) null);
|
||||
return SuggestedFix.swap((Tree) null, (ExpressionTree) null, (VisitorState) null);
|
||||
}
|
||||
|
||||
SuggestedFix testSuggestedFixPrefixWith() {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-experimental</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-guidelines</artifactId>
|
||||
|
||||
@@ -46,7 +46,6 @@ import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.utils.SourceCode;
|
||||
|
||||
@@ -102,7 +101,8 @@ public final class ExhaustiveRefasterTypeMigration extends BugChecker implements
|
||||
AnnotationTree migrationAnnotation = migrationAnnotations.onlyMatchingNode();
|
||||
AnnotationMirror annotationMirror = ASTHelpers.getAnnotationMirror(migrationAnnotation);
|
||||
TypeSymbol migratedType = getMigratedType(annotationMirror);
|
||||
if (migratedType.asType().isPrimitive() || !(migratedType instanceof ClassSymbol)) {
|
||||
if (migratedType.asType().isPrimitive()
|
||||
|| !(migratedType instanceof ClassSymbol migratedClass)) {
|
||||
return buildDescription(migrationAnnotation)
|
||||
.setMessage(String.format("Migration of type '%s' is unsupported", migratedType))
|
||||
.build();
|
||||
@@ -111,7 +111,7 @@ public final class ExhaustiveRefasterTypeMigration extends BugChecker implements
|
||||
ImmutableList<String> methodsClaimedUnmigrated = getMethodsClaimedUnmigrated(annotationMirror);
|
||||
ImmutableList<String> unmigratedMethods =
|
||||
getMethodsDefinitelyUnmigrated(
|
||||
tree, (ClassSymbol) migratedType, signatureOrder(methodsClaimedUnmigrated), state);
|
||||
tree, migratedClass, signatureOrder(methodsClaimedUnmigrated), state);
|
||||
|
||||
if (unmigratedMethods.equals(methodsClaimedUnmigrated)) {
|
||||
return Description.NO_MATCH;
|
||||
@@ -160,17 +160,11 @@ public final class ExhaustiveRefasterTypeMigration extends BugChecker implements
|
||||
.getValue().stream().map(a -> a.getValue().toString()).collect(toImmutableList());
|
||||
}
|
||||
|
||||
// XXX: Once only JDK 14 and above are supported, change the
|
||||
// `m.getModifiers().contains(Modifier.PUBLIC)` check to just `m.isPublic()`.
|
||||
private static ImmutableList<String> getMethodsDefinitelyUnmigrated(
|
||||
ClassTree tree, ClassSymbol migratedType, Comparator<String> comparator, VisitorState state) {
|
||||
Set<MethodSymbol> publicMethods =
|
||||
Streams.stream(
|
||||
ASTHelpers.scope(migratedType.members())
|
||||
.getSymbols(
|
||||
m ->
|
||||
m.getModifiers().contains(Modifier.PUBLIC)
|
||||
&& m instanceof MethodSymbol))
|
||||
migratedType.members().getSymbols(m -> m.isPublic() && m instanceof MethodSymbol))
|
||||
.map(MethodSymbol.class::cast)
|
||||
.collect(toCollection(HashSet::new));
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>error-prone-utils</artifactId>
|
||||
|
||||
@@ -303,14 +303,7 @@ final class SourceCodeTest {
|
||||
|
||||
@Override
|
||||
public Description matchLiteral(LiteralTree tree, VisitorState state) {
|
||||
// XXX: The character conversion is a workaround for the fact that `ASTHelpers#constValue`
|
||||
// returns an `Integer` value for `char` constants.
|
||||
return Optional.ofNullable(ASTHelpers.constValue(tree))
|
||||
.map(
|
||||
constant ->
|
||||
ASTHelpers.isSubtype(ASTHelpers.getType(tree), state.getSymtab().charType, state)
|
||||
? (char) (int) constant
|
||||
: constant)
|
||||
.map(constant -> describeMatch(tree, addComment(tree, constant, state)))
|
||||
.orElse(Description.NO_MATCH);
|
||||
}
|
||||
|
||||
@@ -89,15 +89,63 @@
|
||||
}
|
||||
return new CollectdReporter(
|
||||
registry,
|
||||
@@ -302,7 +297,7 @@ public class CollectdReporter extends ScheduledReporter {
|
||||
@@ -177,7 +172,7 @@ public class CollectdReporter extends ScheduledReporter {
|
||||
}
|
||||
}
|
||||
|
||||
- private static final Logger LOG = LoggerFactory.getLogger(CollectdReporter.class);
|
||||
+ private static final Logger LOGGER = LoggerFactory.getLogger(CollectdReporter.class);
|
||||
private static final String REPORTER_NAME = "collectd-reporter";
|
||||
private static final String FALLBACK_HOST_NAME = "localhost";
|
||||
private static final String COLLECTD_TYPE_GAUGE = "gauge";
|
||||
@@ -224,7 +219,7 @@ public class CollectdReporter extends ScheduledReporter {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
} catch (Exception e) {
|
||||
- LOG.error("Failed to lookup local host name: {}", e.getMessage(), e);
|
||||
+ LOGGER.error("Failed to lookup local host name: {}", e.getMessage(), e);
|
||||
return FALLBACK_HOST_NAME;
|
||||
}
|
||||
}
|
||||
@@ -263,7 +258,7 @@ public class CollectdReporter extends ScheduledReporter {
|
||||
serializeTimer(metaData.plugin(entry.getKey().getKey()), entry.getValue());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
- LOG.warn("Unable to report to Collectd", e);
|
||||
+ LOGGER.warn("Unable to report to Collectd", e);
|
||||
} finally {
|
||||
disconnect(sender);
|
||||
}
|
||||
@@ -279,7 +274,7 @@ public class CollectdReporter extends ScheduledReporter {
|
||||
try {
|
||||
sender.disconnect();
|
||||
} catch (Exception e) {
|
||||
- LOG.warn("Error disconnecting from Collectd", e);
|
||||
+ LOGGER.warn("Error disconnecting from Collectd", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,9 +297,9 @@ public class CollectdReporter extends ScheduledReporter {
|
||||
try {
|
||||
writer.write(metaData, value);
|
||||
} catch (RuntimeException e) {
|
||||
- LOG.warn("Failed to process metric '" + metaData.getPlugin() + "': " + e.getMessage());
|
||||
+ LOG.warn("Failed to process metric '{}': {}", metaData.getPlugin(), e.getMessage());
|
||||
+ LOGGER.warn("Failed to process metric '{}': {}", metaData.getPlugin(), e.getMessage());
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to send metric to collectd", e);
|
||||
- LOG.error("Failed to send metric to collectd", e);
|
||||
+ LOGGER.error("Failed to send metric to collectd", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,7 +309,7 @@ public class CollectdReporter extends ScheduledReporter {
|
||||
} else if (metric.getValue() instanceof Boolean) {
|
||||
write(metaData.typeInstance("value").get(), ((Boolean) metric.getValue()) ? 1 : 0);
|
||||
} else {
|
||||
- LOG.warn(
|
||||
+ LOGGER.warn(
|
||||
"Failed to process metric '{}'. Unsupported gauge of type: {} ",
|
||||
metaData.get().getPlugin(),
|
||||
metric.getValue().getClass().getName());
|
||||
@@ -336,9 +331,9 @@ public class CollectdReporter extends ScheduledReporter {
|
||||
private void serializeHistogram(MetaData.Builder metaData, Histogram metric) {
|
||||
final Snapshot snapshot = metric.getSnapshot();
|
||||
@@ -476,26 +524,6 @@
|
||||
}
|
||||
|
||||
/**
|
||||
--- a/metrics-core/src/main/java/io/dropwizard/metrics5/CsvReporter.java
|
||||
+++ b/metrics-core/src/main/java/io/dropwizard/metrics5/CsvReporter.java
|
||||
@@ -179,7 +179,7 @@ public class CsvReporter extends ScheduledReporter {
|
||||
}
|
||||
}
|
||||
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(CsvReporter.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(CsvReporter.class);
|
||||
|
||||
private final File directory;
|
||||
private final Locale locale;
|
||||
@@ -391,7 +391,7 @@ public class CsvReporter extends ScheduledReporter {
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
- LOGGER.warn("Error writing to {}", name, e);
|
||||
+ LOG.warn("Error writing to {}", name, e);
|
||||
}
|
||||
}
|
||||
|
||||
--- a/metrics-core/src/main/java/io/dropwizard/metrics5/ExponentialMovingAverages.java
|
||||
+++ b/metrics-core/src/main/java/io/dropwizard/metrics5/ExponentialMovingAverages.java
|
||||
@@ -17,9 +17,9 @@ public class ExponentialMovingAverages implements MovingAverages {
|
||||
@@ -990,6 +1018,15 @@
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
@@ -24,7 +27,7 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public abstract class ScheduledReporter implements Closeable, Reporter {
|
||||
|
||||
- private static final Logger LOG = LoggerFactory.getLogger(ScheduledReporter.class);
|
||||
+ private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledReporter.class);
|
||||
|
||||
/** A simple named thread factory. */
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@@ -128,7 +131,7 @@ public abstract class ScheduledReporter implements Closeable, Reporter {
|
||||
durationUnit,
|
||||
executor,
|
||||
@@ -1040,6 +1077,33 @@
|
||||
protected ScheduledFuture<?> getScheduledFuture(
|
||||
long initialDelay, long period, TimeUnit unit, Runnable runnable) {
|
||||
return getScheduledFuture(initialDelay, period, unit, runnable, this.executor);
|
||||
@@ -225,7 +224,7 @@ public abstract class ScheduledReporter implements Closeable, Reporter {
|
||||
try {
|
||||
report();
|
||||
} catch (Throwable ex) {
|
||||
- LOG.error(
|
||||
+ LOGGER.error(
|
||||
"Exception thrown from {}#report. Exception was suppressed.",
|
||||
ScheduledReporter.this.getClass().getSimpleName(),
|
||||
ex);
|
||||
@@ -250,7 +249,7 @@ public abstract class ScheduledReporter implements Closeable, Reporter {
|
||||
try {
|
||||
report();
|
||||
} catch (Exception e) {
|
||||
- LOG.warn("Final reporting of metrics failed.", e);
|
||||
+ LOGGER.warn("Final reporting of metrics failed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +260,7 @@ public abstract class ScheduledReporter implements Closeable, Reporter {
|
||||
executor.shutdownNow(); // Cancel currently executing tasks
|
||||
// Wait a while for tasks to respond to being cancelled
|
||||
if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||
- LOG.warn("ScheduledExecutorService did not terminate.");
|
||||
+ LOGGER.warn("ScheduledExecutorService did not terminate.");
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
--- a/metrics-core/src/main/java/io/dropwizard/metrics5/SharedMetricRegistries.java
|
||||
+++ b/metrics-core/src/main/java/io/dropwizard/metrics5/SharedMetricRegistries.java
|
||||
@@ -1,5 +1,7 @@
|
||||
@@ -1200,32 +1264,15 @@
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -15,8 +14,8 @@ import org.junit.jupiter.api.Test;
|
||||
@@ -15,7 +14,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
-class CachedGaugeTest {
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(CachedGaugeTest.class);
|
||||
+final class CachedGaugeTest {
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(CachedGaugeTest.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CachedGaugeTest.class);
|
||||
private static final int THREAD_COUNT = 10;
|
||||
private static final long RUNNING_TIME_MILLIS = TimeUnit.SECONDS.toMillis(10);
|
||||
|
||||
@@ -100,12 +99,12 @@ class CachedGaugeTest {
|
||||
Integer newValue = shortTimeoutGauge.getValue();
|
||||
|
||||
if (newValue == null) {
|
||||
- LOGGER.warn("Cached gauge returned null value");
|
||||
+ LOG.warn("Cached gauge returned null value");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newValue < lastValue) {
|
||||
- LOGGER.error(
|
||||
+ LOG.error(
|
||||
"Cached gauge returned stale value, last: {}, new: {}",
|
||||
lastValue,
|
||||
newValue);
|
||||
@@ -122,7 +121,7 @@ class CachedGaugeTest {
|
||||
}
|
||||
|
||||
@@ -1899,29 +1946,16 @@
|
||||
assertThat(histogram.getSnapshot()).isEqualTo(snapshot);
|
||||
--- a/metrics-core/src/test/java/io/dropwizard/metrics5/InstrumentedExecutorServiceTest.java
|
||||
+++ b/metrics-core/src/test/java/io/dropwizard/metrics5/InstrumentedExecutorServiceTest.java
|
||||
@@ -19,10 +19,9 @@ import org.junit.jupiter.api.Test;
|
||||
@@ -19,7 +19,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
-class InstrumentedExecutorServiceTest {
|
||||
+final class InstrumentedExecutorServiceTest {
|
||||
|
||||
- private static final Logger LOGGER =
|
||||
- LoggerFactory.getLogger(InstrumentedExecutorServiceTest.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(InstrumentedExecutorServiceTest.class);
|
||||
private ExecutorService executor;
|
||||
private MetricRegistry registry;
|
||||
private InstrumentedExecutorService instrumentedExecutorService;
|
||||
@@ -48,7 +47,7 @@ class InstrumentedExecutorServiceTest {
|
||||
void tearDown() throws Exception {
|
||||
instrumentedExecutorService.shutdown();
|
||||
if (!instrumentedExecutorService.awaitTermination(2, TimeUnit.SECONDS)) {
|
||||
- LOGGER.error("InstrumentedExecutorService did not terminate.");
|
||||
+ LOG.error("InstrumentedExecutorService did not terminate.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,8 +114,8 @@ class InstrumentedExecutorServiceTest {
|
||||
private static final Logger LOGGER =
|
||||
LoggerFactory.getLogger(InstrumentedExecutorServiceTest.class);
|
||||
@@ -115,8 +115,8 @@ class InstrumentedExecutorServiceTest {
|
||||
assertThat(idle.getSnapshot().size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@@ -1931,7 +1965,7 @@
|
||||
void reportsTasksInformationForThreadPoolExecutor() throws Exception {
|
||||
executor =
|
||||
new ThreadPoolExecutor(4, 16, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(32));
|
||||
@@ -180,7 +179,7 @@ class InstrumentedExecutorServiceTest {
|
||||
@@ -180,7 +180,7 @@ class InstrumentedExecutorServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1940,7 +1974,7 @@
|
||||
executor =
|
||||
new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1));
|
||||
instrumentedExecutorService = new InstrumentedExecutorService(executor, registry, "tp");
|
||||
@@ -207,7 +206,7 @@ class InstrumentedExecutorServiceTest {
|
||||
@@ -207,7 +207,7 @@ class InstrumentedExecutorServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1949,7 +1983,7 @@
|
||||
executor =
|
||||
new ThreadPoolExecutor(4, 16, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(32));
|
||||
instrumentedExecutorService = new InstrumentedExecutorService(executor, registry, "stp");
|
||||
@@ -236,8 +235,8 @@ class InstrumentedExecutorServiceTest {
|
||||
@@ -236,8 +236,8 @@ class InstrumentedExecutorServiceTest {
|
||||
MetricRegistry.name("stp", "tasks.capacity"));
|
||||
}
|
||||
|
||||
@@ -1959,7 +1993,7 @@
|
||||
void reportsTasksInformationForForkJoinPool() throws Exception {
|
||||
executor = Executors.newWorkStealingPool(4);
|
||||
instrumentedExecutorService = new InstrumentedExecutorService(executor, registry, "fjp");
|
||||
@@ -291,7 +290,7 @@ class InstrumentedExecutorServiceTest {
|
||||
@@ -291,7 +291,7 @@ class InstrumentedExecutorServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1970,17 +2004,15 @@
|
||||
|
||||
--- a/metrics-core/src/test/java/io/dropwizard/metrics5/InstrumentedScheduledExecutorServiceTest.java
|
||||
+++ b/metrics-core/src/test/java/io/dropwizard/metrics5/InstrumentedScheduledExecutorServiceTest.java
|
||||
@@ -13,8 +13,8 @@ import org.junit.jupiter.api.Test;
|
||||
@@ -13,7 +13,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
-class InstrumentedScheduledExecutorServiceTest {
|
||||
- private static final Logger LOGGER =
|
||||
+final class InstrumentedScheduledExecutorServiceTest {
|
||||
+ private static final Logger LOG =
|
||||
private static final Logger LOGGER =
|
||||
LoggerFactory.getLogger(InstrumentedScheduledExecutorServiceTest.class);
|
||||
|
||||
private final ScheduledExecutorService scheduledExecutor =
|
||||
@@ -35,17 +35,17 @@ class InstrumentedScheduledExecutorServiceTest {
|
||||
private final Histogram percentOfPeriod = registry.histogram("xs.scheduled.percent-of-period");
|
||||
|
||||
@@ -2338,15 +2370,6 @@
|
||||
assertThat(completed.getCount()).isNotEqualTo(0);
|
||||
assertThat(duration.getCount()).isNotEqualTo(0);
|
||||
assertThat(duration.getSnapshot().size()).isNotEqualTo(0);
|
||||
@@ -322,7 +322,7 @@ class InstrumentedScheduledExecutorServiceTest {
|
||||
void tearDown() throws Exception {
|
||||
instrumentedScheduledExecutor.shutdown();
|
||||
if (!instrumentedScheduledExecutor.awaitTermination(2, TimeUnit.SECONDS)) {
|
||||
- LOGGER.error("InstrumentedScheduledExecutorService did not terminate.");
|
||||
+ LOG.error("InstrumentedScheduledExecutorService did not terminate.");
|
||||
}
|
||||
}
|
||||
}
|
||||
--- a/metrics-core/src/test/java/io/dropwizard/metrics5/InstrumentedThreadFactoryTest.java
|
||||
+++ b/metrics-core/src/test/java/io/dropwizard/metrics5/InstrumentedThreadFactoryTest.java
|
||||
@@ -11,7 +11,7 @@ import java.util.concurrent.TimeUnit;
|
||||
@@ -3801,15 +3824,6 @@
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
@@ -29,7 +32,7 @@ public class Graphite implements GraphiteSender {
|
||||
private Writer writer;
|
||||
private int failures;
|
||||
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(Graphite.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(Graphite.class);
|
||||
|
||||
/**
|
||||
* Creates a new client which connects to the given address using the default {@link
|
||||
@@ -63,13 +66,9 @@ public class Graphite implements GraphiteSender {
|
||||
* @param charset the character set used by the server
|
||||
*/
|
||||
@@ -3837,24 +3851,6 @@
|
||||
InetSocketAddress address = this.address;
|
||||
// the previous dns retry logic did not work, as address.getAddress would always return the
|
||||
// cached value
|
||||
@@ -178,7 +175,7 @@ public class Graphite implements GraphiteSender {
|
||||
writer.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
- LOGGER.debug("Error closing writer", ex);
|
||||
+ LOG.debug("Error closing writer", ex);
|
||||
} finally {
|
||||
this.writer = null;
|
||||
}
|
||||
@@ -188,7 +185,7 @@ public class Graphite implements GraphiteSender {
|
||||
socket.close();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
- LOGGER.debug("Error closing socket", ex);
|
||||
+ LOG.debug("Error closing socket", ex);
|
||||
} finally {
|
||||
this.socket = null;
|
||||
}
|
||||
--- a/metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteRabbitMQ.java
|
||||
+++ b/metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteRabbitMQ.java
|
||||
@@ -1,5 +1,6 @@
|
||||
@@ -3923,39 +3919,7 @@
|
||||
this.addMetricAttributesAsTags = false;
|
||||
this.floatingPointFormatter = DEFAULT_FP_FORMATTER;
|
||||
}
|
||||
@@ -249,7 +247,7 @@ public class GraphiteReporter extends ScheduledReporter {
|
||||
}
|
||||
}
|
||||
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(GraphiteReporter.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(GraphiteReporter.class);
|
||||
// the Carbon plaintext format is pretty underspecified, but it seems like it just wants
|
||||
// US-formatted digits
|
||||
private static final DoubleFunction<String> DEFAULT_FP_FORMATTER =
|
||||
@@ -430,12 +428,12 @@ public class GraphiteReporter extends ScheduledReporter {
|
||||
}
|
||||
graphite.flush();
|
||||
} catch (IOException e) {
|
||||
- LOGGER.warn("Unable to report to Graphite", graphite, e);
|
||||
+ LOG.warn("Unable to report to Graphite", graphite, e);
|
||||
} finally {
|
||||
try {
|
||||
graphite.close();
|
||||
} catch (IOException e1) {
|
||||
- LOGGER.warn("Error closing Graphite", graphite, e1);
|
||||
+ LOG.warn("Error closing Graphite", graphite, e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -448,16 +446,16 @@ public class GraphiteReporter extends ScheduledReporter {
|
||||
try {
|
||||
graphite.close();
|
||||
} catch (IOException e) {
|
||||
- LOGGER.debug("Error disconnecting from Graphite", graphite, e);
|
||||
+ LOG.debug("Error disconnecting from Graphite", graphite, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,9 +453,9 @@ public class GraphiteReporter extends ScheduledReporter {
|
||||
|
||||
private void reportTimer(MetricName name, Timer timer, long timestamp) throws IOException {
|
||||
final Snapshot snapshot = timer.getSnapshot();
|
||||
@@ -4017,15 +3981,6 @@
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
@@ -48,7 +49,7 @@ public class PickledGraphite implements GraphiteSender {
|
||||
QUOTE = '\'',
|
||||
LF = '\n';
|
||||
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(PickledGraphite.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(PickledGraphite.class);
|
||||
private static final int DEFAULT_BATCH_SIZE = 100;
|
||||
|
||||
private int batchSize;
|
||||
@@ -173,9 +174,7 @@ public class PickledGraphite implements GraphiteSender {
|
||||
|
||||
@Override
|
||||
@@ -4046,17 +4001,6 @@
|
||||
try {
|
||||
byte[] payload = pickleMetrics(metrics);
|
||||
byte[] header = ByteBuffer.allocate(4).putInt(payload.length).array();
|
||||
@@ -260,8 +259,8 @@ public class PickledGraphite implements GraphiteSender {
|
||||
outputStream.write(payload);
|
||||
outputStream.flush();
|
||||
|
||||
- if (LOGGER.isDebugEnabled()) {
|
||||
- LOGGER.debug("Wrote {} metrics", metrics.size());
|
||||
+ if (LOG.isDebugEnabled()) {
|
||||
+ LOG.debug("Wrote {} metrics", metrics.size());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.failures++;
|
||||
--- a/metrics-graphite/src/test/java/io/dropwizard/metrics5/graphite/GraphiteRabbitMQTest.java
|
||||
+++ b/metrics-graphite/src/test/java/io/dropwizard/metrics5/graphite/GraphiteRabbitMQTest.java
|
||||
@@ -8,7 +8,6 @@ import static org.mockito.Mockito.anyString;
|
||||
@@ -4475,15 +4419,6 @@
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -27,7 +29,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
/** A registry for health checks. */
|
||||
public class HealthCheckRegistry {
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(HealthCheckRegistry.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(HealthCheckRegistry.class);
|
||||
private static final int ASYNC_EXECUTOR_POOL_SIZE = 2;
|
||||
|
||||
private final ConcurrentMap<String, HealthCheck> healthChecks;
|
||||
@@ -92,9 +94,8 @@ public class HealthCheckRegistry {
|
||||
public void register(String name, HealthCheck healthCheck) {
|
||||
HealthCheck registered;
|
||||
@@ -4514,13 +4449,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,12 +218,12 @@ public class HealthCheckRegistry {
|
||||
try {
|
||||
results.put(entry.getKey(), entry.getValue().get());
|
||||
} catch (Exception e) {
|
||||
- LOGGER.warn("Error executing health check {}", entry.getKey(), e);
|
||||
+ LOG.warn("Error executing health check {}", entry.getKey(), e);
|
||||
results.put(entry.getKey(), HealthCheck.Result.unhealthy(e));
|
||||
@@ -222,7 +223,7 @@ public class HealthCheckRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5357,39 +5286,6 @@
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +196,7 @@ public class InfluxDbReporter extends GarbageFreeScheduledReporter {
|
||||
}
|
||||
}
|
||||
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(InfluxDbReporter.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(InfluxDbReporter.class);
|
||||
private static final String VALUE = "value";
|
||||
|
||||
private final Clock clock;
|
||||
@@ -279,12 +279,12 @@ public class InfluxDbReporter extends GarbageFreeScheduledReporter {
|
||||
}
|
||||
sender.flush();
|
||||
} catch (IOException e) {
|
||||
- LOGGER.warn("Unable to report to InfluxDb", sender, e);
|
||||
+ LOG.warn("Unable to report to InfluxDb", sender, e);
|
||||
} finally {
|
||||
try {
|
||||
sender.disconnect();
|
||||
} catch (IOException e) {
|
||||
- LOGGER.warn("Error disconnecting InfluxDb", sender, e);
|
||||
+ LOG.warn("Error disconnecting InfluxDb", sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,7 +297,7 @@ public class InfluxDbReporter extends GarbageFreeScheduledReporter {
|
||||
try {
|
||||
sender.close();
|
||||
} catch (IOException e) {
|
||||
- LOGGER.debug("Error disconnecting from InfluxDb", e);
|
||||
+ LOG.debug("Error disconnecting from InfluxDb", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
--- a/metrics-influxdb/src/main/java/io/dropwizard/metrics5/influxdb/InfluxDbUdpSender.java
|
||||
+++ b/metrics-influxdb/src/main/java/io/dropwizard/metrics5/influxdb/InfluxDbUdpSender.java
|
||||
@@ -1,5 +1,7 @@
|
||||
@@ -6065,15 +5961,6 @@
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -33,7 +33,7 @@ public class JCacheGaugeSet implements MetricSet {
|
||||
private static final String M_BEAN_COORDINATES =
|
||||
"javax.cache:type=CacheStatistics,CacheManager=*,Cache=*";
|
||||
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(JCacheGaugeSet.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(JCacheGaugeSet.class);
|
||||
|
||||
@Override
|
||||
public Map<MetricName, Metric> getMetrics() {
|
||||
@@ -52,7 +52,7 @@ public class JCacheGaugeSet implements MetricSet {
|
||||
}
|
||||
}
|
||||
@@ -6083,15 +5970,6 @@
|
||||
}
|
||||
|
||||
private Set<ObjectInstance> getCacheBeans() {
|
||||
@@ -60,7 +60,7 @@ public class JCacheGaugeSet implements MetricSet {
|
||||
return ManagementFactory.getPlatformMBeanServer()
|
||||
.queryMBeans(ObjectName.getInstance(M_BEAN_COORDINATES), null);
|
||||
} catch (MalformedObjectNameException e) {
|
||||
- LOGGER.error("Unable to retrieve {}. Are JCache statistics enabled?", M_BEAN_COORDINATES);
|
||||
+ LOG.error("Unable to retrieve {}. Are JCache statistics enabled?", M_BEAN_COORDINATES);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
--- a/metrics-jcache/src/test/java/JCacheGaugeSetTest.java
|
||||
+++ b/metrics-jcache/src/test/java/JCacheGaugeSetTest.java
|
||||
@@ -11,7 +11,7 @@ import org.junit.jupiter.api.AfterEach;
|
||||
@@ -8461,11 +8339,11 @@
|
||||
|
||||
private static final char[] QUOTABLE_CHARS = new char[] {',', '=', ':', '"'};
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(JmxReporter.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultObjectNameFactory.class);
|
||||
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultObjectNameFactory.class);
|
||||
|
||||
@Override
|
||||
public ObjectName createName(String type, String domain, MetricName name) {
|
||||
@@ -38,14 +38,13 @@ public class DefaultObjectNameFactory implements ObjectNameFactory {
|
||||
@@ -38,9 +38,8 @@ public class DefaultObjectNameFactory implements ObjectNameFactory {
|
||||
|| shouldQuote(objectName.getKeyProperty("type"))) {
|
||||
properties.put("type", ObjectName.quote(type));
|
||||
}
|
||||
@@ -8476,12 +8354,6 @@
|
||||
} catch (MalformedObjectNameException e) {
|
||||
try {
|
||||
return new ObjectName(domain, "name", ObjectName.quote(name.getKey()));
|
||||
} catch (MalformedObjectNameException e1) {
|
||||
- LOGGER.warn("Unable to register {} {}", type, name, e1);
|
||||
+ LOG.warn("Unable to register {} {}", type, name, e1);
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
}
|
||||
--- a/metrics-jmx/src/main/java/io/dropwizard/metrics5/jmx/JmxReporter.java
|
||||
+++ b/metrics-jmx/src/main/java/io/dropwizard/metrics5/jmx/JmxReporter.java
|
||||
@@ -1,5 +1,9 @@
|
||||
@@ -8542,147 +8414,6 @@
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(JmxReporter.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(JmxReporter.class);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public interface MetricMBean {
|
||||
@@ -570,9 +571,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
registerMBean(new JmxGauge(gauge, objectName), objectName);
|
||||
}
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
- LOGGER.debug("Unable to register gauge", e);
|
||||
+ LOG.debug("Unable to register gauge", e);
|
||||
} catch (JMException e) {
|
||||
- LOGGER.warn("Unable to register gauge", e);
|
||||
+ LOG.warn("Unable to register gauge", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,9 +583,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
final ObjectName objectName = createName("gauges", name);
|
||||
unregisterMBean(objectName);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
- LOGGER.debug("Unable to unregister gauge", e);
|
||||
+ LOG.debug("Unable to unregister gauge", e);
|
||||
} catch (MBeanRegistrationException e) {
|
||||
- LOGGER.warn("Unable to unregister gauge", e);
|
||||
+ LOG.warn("Unable to unregister gauge", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,9 +597,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
registerMBean(new JmxCounter(counter, objectName), objectName);
|
||||
}
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
- LOGGER.debug("Unable to register counter", e);
|
||||
+ LOG.debug("Unable to register counter", e);
|
||||
} catch (JMException e) {
|
||||
- LOGGER.warn("Unable to register counter", e);
|
||||
+ LOG.warn("Unable to register counter", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,9 +609,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
final ObjectName objectName = createName("counters", name);
|
||||
unregisterMBean(objectName);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
- LOGGER.debug("Unable to unregister counter", e);
|
||||
+ LOG.debug("Unable to unregister counter", e);
|
||||
} catch (MBeanRegistrationException e) {
|
||||
- LOGGER.warn("Unable to unregister counter", e);
|
||||
+ LOG.warn("Unable to unregister counter", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,9 +623,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
registerMBean(new JmxHistogram(histogram, objectName), objectName);
|
||||
}
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
- LOGGER.debug("Unable to register histogram", e);
|
||||
+ LOG.debug("Unable to register histogram", e);
|
||||
} catch (JMException e) {
|
||||
- LOGGER.warn("Unable to register histogram", e);
|
||||
+ LOG.warn("Unable to register histogram", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,9 +635,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
final ObjectName objectName = createName("histograms", name);
|
||||
unregisterMBean(objectName);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
- LOGGER.debug("Unable to unregister histogram", e);
|
||||
+ LOG.debug("Unable to unregister histogram", e);
|
||||
} catch (MBeanRegistrationException e) {
|
||||
- LOGGER.warn("Unable to unregister histogram", e);
|
||||
+ LOG.warn("Unable to unregister histogram", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,9 +650,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
new JmxMeter(meter, objectName, timeUnits.rateFor(name.getKey())), objectName);
|
||||
}
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
- LOGGER.debug("Unable to register meter", e);
|
||||
+ LOG.debug("Unable to register meter", e);
|
||||
} catch (JMException e) {
|
||||
- LOGGER.warn("Unable to register meter", e);
|
||||
+ LOG.warn("Unable to register meter", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,9 +662,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
final ObjectName objectName = createName("meters", name);
|
||||
unregisterMBean(objectName);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
- LOGGER.debug("Unable to unregister meter", e);
|
||||
+ LOG.debug("Unable to unregister meter", e);
|
||||
} catch (MBeanRegistrationException e) {
|
||||
- LOGGER.warn("Unable to unregister meter", e);
|
||||
+ LOG.warn("Unable to unregister meter", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -681,9 +682,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
objectName);
|
||||
}
|
||||
} catch (InstanceAlreadyExistsException e) {
|
||||
- LOGGER.debug("Unable to register timer", e);
|
||||
+ LOG.debug("Unable to register timer", e);
|
||||
} catch (JMException e) {
|
||||
- LOGGER.warn("Unable to register timer", e);
|
||||
+ LOG.warn("Unable to register timer", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,9 +694,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
final ObjectName objectName = createName("timers", name);
|
||||
unregisterMBean(objectName);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
- LOGGER.debug("Unable to unregister timer", e);
|
||||
+ LOG.debug("Unable to unregister timer", e);
|
||||
} catch (MBeanRegistrationException e) {
|
||||
- LOGGER.warn("Unable to unregister timer", e);
|
||||
+ LOG.warn("Unable to unregister timer", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,9 +709,9 @@ public class JmxReporter implements Reporter, Closeable {
|
||||
try {
|
||||
unregisterMBean(name);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
- LOGGER.debug("Unable to unregister metric", e);
|
||||
+ LOG.debug("Unable to unregister metric", e);
|
||||
} catch (MBeanRegistrationException e) {
|
||||
- LOGGER.warn("Unable to unregister metric", e);
|
||||
+ LOG.warn("Unable to unregister metric", e);
|
||||
}
|
||||
}
|
||||
registered.clear();
|
||||
--- a/metrics-jmx/src/test/java/io/dropwizard/metrics5/jmx/DefaultObjectNameFactoryTest.java
|
||||
+++ b/metrics-jmx/src/test/java/io/dropwizard/metrics5/jmx/DefaultObjectNameFactoryTest.java
|
||||
@@ -7,7 +7,7 @@ import io.dropwizard.metrics5.MetricName;
|
||||
@@ -9002,21 +8733,7 @@
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.management.JMException;
|
||||
@@ -19,7 +20,7 @@ import org.slf4j.LoggerFactory;
|
||||
* <p>These JMX objects are only available on Java 7 and above.
|
||||
*/
|
||||
public class BufferPoolMetricSet implements MetricSet {
|
||||
- private static final Logger LOGGER = LoggerFactory.getLogger(BufferPoolMetricSet.class);
|
||||
+ private static final Logger LOG = LoggerFactory.getLogger(BufferPoolMetricSet.class);
|
||||
private static final String[] ATTRIBUTES = {"Count", "MemoryUsed", "TotalCapacity"};
|
||||
private static final String[] NAMES = {"count", "used", "capacity"};
|
||||
private static final String[] POOLS = {"direct", "mapped"};
|
||||
@@ -43,10 +44,10 @@ public class BufferPoolMetricSet implements MetricSet {
|
||||
gauges.put(
|
||||
MetricRegistry.name(pool, name), new JmxAttributeGauge(mBeanServer, on, attribute));
|
||||
} catch (JMException ignored) {
|
||||
- LOGGER.debug("Unable to load buffer pool MBeans, possibly running on Java 6");
|
||||
+ LOG.debug("Unable to load buffer pool MBeans, possibly running on Java 6");
|
||||
@@ -47,6 +48,6 @@ public class BufferPoolMetricSet implements MetricSet {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ metrics-collectd/src/main/java/io/dropwizard/metrics5/collectd/PacketWriter.java
|
||||
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-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[431,17] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
|
||||
metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[436,19] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
|
||||
metrics-graphite/src/main/java/io/dropwizard/metrics5/graphite/GraphiteReporter.java:[449,20] [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
|
||||
@@ -26,8 +26,8 @@ metrics-httpclient5/src/main/java/io/dropwizard/metrics5/httpclient5/Instrumente
|
||||
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-influxdb/src/main/java/io/dropwizard/metrics5/influxdb/InfluxDbReporter.java:[282,17] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
|
||||
metrics-influxdb/src/main/java/io/dropwizard/metrics5/influxdb/InfluxDbReporter.java:[287,19] [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
|
||||
|
||||
@@ -8,11 +8,7 @@ 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/.*'
|
||||
shared_error_prone_flags='-XepExcludedPaths:.*/target/generated-sources/.* -XepOpt:Slf4jLoggerDeclaration:CanonicalStaticLoggerName=LOGGER'
|
||||
patch_error_prone_flags=''
|
||||
validation_error_prone_flags=''
|
||||
validation_build_flags=''
|
||||
|
||||
225
pom.xml
225
pom.xml
@@ -4,7 +4,7 @@
|
||||
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Picnic :: Error Prone Support</name>
|
||||
@@ -146,7 +146,7 @@
|
||||
<error-prone.self-check-args />
|
||||
<!-- The build timestamp is derived from the most recent commit
|
||||
timestamp in support of reproducible builds. -->
|
||||
<project.build.outputTimestamp>2025-02-02T12:19:40Z</project.build.outputTimestamp>
|
||||
<project.build.outputTimestamp>2025-03-24T10:41:07Z</project.build.outputTimestamp>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<!-- Glob pattern identifying Refaster rule definition files. These
|
||||
Java classes don't contain "regular" code, and thus require special
|
||||
@@ -205,17 +205,21 @@
|
||||
<version.auto-service>1.1.1</version.auto-service>
|
||||
<version.auto-value>1.11.0</version.auto-value>
|
||||
<version.error-prone>${version.error-prone-orig}</version.error-prone>
|
||||
<version.error-prone-fork>${version.error-prone-orig}-picnic-2</version.error-prone-fork>
|
||||
<version.error-prone-orig>2.36.0</version.error-prone-orig>
|
||||
<version.error-prone-fork>${version.error-prone-orig}-picnic-1</version.error-prone-fork>
|
||||
<version.error-prone-orig>2.37.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.jmh>1.37</version.jmh>
|
||||
<version.maven>3.9.9</version.maven>
|
||||
<version.mockito>5.15.2</version.mockito>
|
||||
<version.nopen-checker>1.0.1</version.nopen-checker>
|
||||
<version.nullaway>0.12.3</version.nullaway>
|
||||
<version.pitest-git>1.1.4</version.pitest-git>
|
||||
<version.rewrite-templating>1.22.1</version.rewrite-templating>
|
||||
<version.mockito>5.17.0</version.mockito>
|
||||
<!-- XXX: Consider providing our own implementation with similar
|
||||
functionality, and designing it such that JMH classes would not need to
|
||||
be annotated `@Open`. -->
|
||||
<version.nopen>1.0.1</version.nopen>
|
||||
<version.nullaway>0.12.5</version.nullaway>
|
||||
<version.pitest-git>2.2.0</version.pitest-git>
|
||||
<version.rewrite-templating>1.24.2</version.rewrite-templating>
|
||||
<version.surefire>3.2.3</version.surefire>
|
||||
</properties>
|
||||
|
||||
@@ -269,7 +273,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson</groupId>
|
||||
<artifactId>jackson-bom</artifactId>
|
||||
<version>2.18.2</version>
|
||||
<version>2.18.3</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -331,7 +335,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.googlejavaformat</groupId>
|
||||
<artifactId>google-java-format</artifactId>
|
||||
<version>1.25.2</version>
|
||||
<version>1.26.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
@@ -350,10 +354,15 @@
|
||||
<artifactId>truth</artifactId>
|
||||
<version>1.4.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jakewharton.nopen</groupId>
|
||||
<artifactId>nopen-annotations</artifactId>
|
||||
<version>${version.nopen}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jakewharton.nopen</groupId>
|
||||
<artifactId>nopen-checker</artifactId>
|
||||
<version>${version.nopen-checker}</version>
|
||||
<version>${version.nopen}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.uber.nullaway</groupId>
|
||||
@@ -363,14 +372,14 @@
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-bom</artifactId>
|
||||
<version>1.14.4</version>
|
||||
<version>1.14.5</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-bom</artifactId>
|
||||
<version>2024.0.3</version>
|
||||
<version>2024.0.4</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -387,7 +396,7 @@
|
||||
<dependency>
|
||||
<groupId>io.swagger.core.v3</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>2.2.28</version>
|
||||
<version>2.2.29</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
@@ -422,7 +431,7 @@
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.17.1</version>
|
||||
<version>1.17.5</version>
|
||||
</dependency>
|
||||
<!-- Specified so that Renovate will file Maven upgrade PRs, which
|
||||
subsequently will cause `maven-enforcer-plugin` to require that
|
||||
@@ -435,7 +444,7 @@
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>1.9.22.1</version>
|
||||
<version>1.9.23</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
@@ -447,7 +456,7 @@
|
||||
<dependency>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
<artifactId>checker-qual</artifactId>
|
||||
<version>3.49.0</version>
|
||||
<version>3.49.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
@@ -472,7 +481,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit</groupId>
|
||||
<artifactId>junit-bom</artifactId>
|
||||
<version>5.11.4</version>
|
||||
<version>5.12.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -485,8 +494,20 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-core</artifactId>
|
||||
<version>5.3.1</version>
|
||||
<artifactId>mongodb-driver-bom</artifactId>
|
||||
<version>5.4.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>${version.jmh}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${version.jmh}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
@@ -496,33 +517,33 @@
|
||||
<dependency>
|
||||
<groupId>org.openrewrite.recipe</groupId>
|
||||
<artifactId>rewrite-recipe-bom</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<version>3.5.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-bom</artifactId>
|
||||
<version>2.0.16</version>
|
||||
<version>2.0.17</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-framework-bom</artifactId>
|
||||
<version>6.2.3</version>
|
||||
<version>6.2.5</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test</artifactId>
|
||||
<version>3.4.2</version>
|
||||
<version>3.4.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-bom</artifactId>
|
||||
<version>6.4.2</version>
|
||||
<version>6.4.4</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
@@ -548,6 +569,16 @@
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.arcmutate</groupId>
|
||||
<artifactId>pitest-git-maven-plugin</artifactId>
|
||||
<version>${version.pitest-git}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.arcmutate</groupId>
|
||||
<artifactId>pitest-github-maven-plugin</artifactId>
|
||||
<version>${version.pitest-git}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.ekryd.sortpom</groupId>
|
||||
<artifactId>sortpom-maven-plugin</artifactId>
|
||||
@@ -575,16 +606,6 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.groupcdg</groupId>
|
||||
<artifactId>pitest-git-maven-plugin</artifactId>
|
||||
<version>${version.pitest-git}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.groupcdg</groupId>
|
||||
<artifactId>pitest-github-maven-plugin</artifactId>
|
||||
<version>${version.pitest-git}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.spotify.fmt</groupId>
|
||||
<artifactId>fmt-maven-plugin</artifactId>
|
||||
@@ -608,11 +629,10 @@
|
||||
<plugin>
|
||||
<groupId>de.thetaphi</groupId>
|
||||
<artifactId>forbiddenapis</artifactId>
|
||||
<version>3.8</version>
|
||||
<version>3.9</version>
|
||||
<configuration>
|
||||
<bundledSignatures>
|
||||
<bundledSignature>jdk-internal</bundledSignature>
|
||||
<bundledSignature>jdk-reflection</bundledSignature>
|
||||
<bundledSignature>jdk-system-out</bundledSignature>
|
||||
<!-- Other bundles are available but currently not
|
||||
enabled:
|
||||
@@ -622,6 +642,10 @@
|
||||
- jdk-deprecated: we compile with `-Xlint:all`,
|
||||
which causes the build to fail when _any_
|
||||
deprecated method is called.
|
||||
- jdk-reflection: this bundle should probably be
|
||||
enabled, but currently
|
||||
`java.lang.reflect.AccessibleObject#setAccessible`
|
||||
is still called in various places.
|
||||
- jdk-non-portable: the Error Prone integration
|
||||
crucially relies on some of these APIs.
|
||||
- jdk-unsafe: see
|
||||
@@ -923,7 +947,7 @@
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>10.21.2</version>
|
||||
<version>10.22.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.spring.nohttp</groupId>
|
||||
@@ -948,7 +972,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<version>3.14.0</version>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<!-- XXX: Inline and drop the version
|
||||
@@ -959,6 +983,11 @@
|
||||
<artifactId>auto-value</artifactId>
|
||||
<version>${version.auto-value}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.google.auto.value</groupId>
|
||||
<artifactId>auto-value</artifactId>
|
||||
<version>${version.auto-value}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service</artifactId>
|
||||
@@ -969,6 +998,10 @@
|
||||
<artifactId>rewrite-templating</artifactId>
|
||||
<version>${version.rewrite-templating}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
<compilerArgs>
|
||||
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
|
||||
@@ -1056,7 +1089,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.1.3</version>
|
||||
<version>3.1.4</version>
|
||||
<configuration>
|
||||
<retryFailedDeploymentCount>3</retryFailedDeploymentCount>
|
||||
</configuration>
|
||||
@@ -1134,7 +1167,7 @@
|
||||
<dependency>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>extra-enforcer-rules</artifactId>
|
||||
<version>1.9.0</version>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -1162,7 +1195,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>3.1.3</version>
|
||||
<version>3.1.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -1298,7 +1331,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.5.2</version>
|
||||
<version>3.5.3</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
@@ -1306,11 +1339,17 @@
|
||||
<properties>
|
||||
<configurationParameters>junit.jupiter.execution.parallel.enabled=true
|
||||
junit.jupiter.execution.parallel.mode.default=concurrent
|
||||
junit.jupiter.execution.timeout.threaddump.enabled=true
|
||||
junit.platform.stacktrace.pruning.enabled=false</configurationParameters>
|
||||
</properties>
|
||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
@@ -1408,6 +1447,7 @@
|
||||
GPL-2.0-with-classpath-exception
|
||||
| CDDL/GPLv2+CE
|
||||
| CDDL + GPLv2 with classpath exception
|
||||
| GNU General Public License (GPL), version 2, with the Classpath exception
|
||||
| GNU General Public License, version 2 (GPL2), with the classpath exception
|
||||
| GNU General Public License, version 2, with the Classpath Exception
|
||||
| GPL2 w/ CPE
|
||||
@@ -1442,7 +1482,7 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>tidy-maven-plugin</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.4.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>check-pom</id>
|
||||
@@ -1494,7 +1534,7 @@
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.8.12</version>
|
||||
<version>0.8.13</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<!-- Refaster rules are tested using a custom method
|
||||
@@ -1524,7 +1564,7 @@
|
||||
<plugin>
|
||||
<groupId>org.pitest</groupId>
|
||||
<artifactId>pitest-maven</artifactId>
|
||||
<version>1.18.1</version>
|
||||
<version>1.19.0</version>
|
||||
<configuration>
|
||||
<excludedClasses>
|
||||
<!-- AutoValue generated classes. -->
|
||||
@@ -1546,24 +1586,24 @@
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.groupcdg</groupId>
|
||||
<groupId>com.arcmutate</groupId>
|
||||
<artifactId>base</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.arcmutate</groupId>
|
||||
<artifactId>pitest-accelerator-junit5</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.arcmutate</groupId>
|
||||
<artifactId>pitest-git-plugin</artifactId>
|
||||
<version>${version.pitest-git}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.groupcdg.arcmutate</groupId>
|
||||
<artifactId>base</artifactId>
|
||||
<version>1.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.groupcdg.pitest</groupId>
|
||||
<artifactId>pitest-accelerator-junit5</artifactId>
|
||||
<version>1.0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.pitest</groupId>
|
||||
<artifactId>pitest-junit5-plugin</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<version>1.2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
@@ -1578,7 +1618,7 @@
|
||||
<plugin>
|
||||
<groupId>org.sonarsource.scanner.maven</groupId>
|
||||
<artifactId>sonar-maven-plugin</artifactId>
|
||||
<version>5.0.0.4389</version>
|
||||
<version>5.1.0.4751</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
@@ -1865,7 +1905,7 @@
|
||||
<path>
|
||||
<groupId>com.jakewharton.nopen</groupId>
|
||||
<artifactId>nopen-checker</artifactId>
|
||||
<version>${version.nopen-checker}</version>
|
||||
<version>${version.nopen}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.uber.nullaway</groupId>
|
||||
@@ -1938,9 +1978,7 @@
|
||||
-XepOpt:NullAway:AssertsEnabled=true
|
||||
-XepOpt:NullAway:CheckOptionalEmptiness=true
|
||||
-XepOpt:Nullness:Conservative=false
|
||||
-XepOpt:StatementSwitchToExpressionSwitch:EnableAssignmentSwitchConversion=true
|
||||
-XepOpt:StatementSwitchToExpressionSwitch:EnableDirectConversion=true
|
||||
-XepOpt:StatementSwitchToExpressionSwitch:EnableReturnSwitchConversion=true
|
||||
<!-- Append additional custom arguments. -->
|
||||
${error-prone.patch-args}
|
||||
${error-prone.self-check-args}
|
||||
@@ -2154,5 +2192,66 @@
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<!-- Enables execution of a JMH benchmark. Given a benchmark class
|
||||
`tech.picnic.MyBenchmark`, the following command (executed against
|
||||
the (sub)module in which the benchmark resides) will compile and
|
||||
execute said benchmark:
|
||||
|
||||
mvn process-test-classes -Dverification.skip \
|
||||
-Djmh.run-benchmark=tech.picnic.MyBenchmark
|
||||
-->
|
||||
<id>run-jmh-benchmark</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>jmh.run-benchmark</name>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-jmh-runtime-classpath</id>
|
||||
<goals>
|
||||
<goal>build-classpath</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputProperty>testClasspath</outputProperty>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-jmh-benchmark</id>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<classpathScope>test</classpathScope>
|
||||
<mainClass>${jmh.run-benchmark}</mainClass>
|
||||
<systemProperties>
|
||||
<!-- The runtime classpath is defined
|
||||
in this way so that any JVMs forked by
|
||||
JMH will have the desired classpath. -->
|
||||
<systemProperty>
|
||||
<key>java.class.path</key>
|
||||
<value>${project.build.testOutputDirectory}${path.separator}${project.build.outputDirectory}${path.separator}${testClasspath}</value>
|
||||
</systemProperty>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-compiler</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-runner</artifactId>
|
||||
@@ -26,13 +26,21 @@
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>refaster-support</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto</groupId>
|
||||
<artifactId>auto-common</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.value</groupId>
|
||||
<artifactId>auto-value-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_annotation</artifactId>
|
||||
@@ -48,6 +56,11 @@
|
||||
<artifactId>error_prone_check_api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_test_helpers</artifactId>
|
||||
@@ -58,6 +71,11 @@
|
||||
<artifactId>guava</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jakewharton.nopen</groupId>
|
||||
<artifactId>nopen-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
@@ -95,6 +113,11 @@
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
<artifactId>rewrite-core</artifactId>
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package tech.picnic.errorprone.refaster.runner;
|
||||
|
||||
import static java.util.Comparator.comparingInt;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A node in an immutable tree.
|
||||
*
|
||||
* <p>The tree's edges are string-labeled, while its leaves store values of type {@code T}.
|
||||
*/
|
||||
@AutoValue
|
||||
abstract class Node<T> {
|
||||
// XXX: Review: should this method accept a `SetMultimap<V, ? extends Set<String>>`, or should
|
||||
// there be such an overload?
|
||||
static <T> Node<T> create(
|
||||
Set<T> values, Function<? super T, ? extends Set<? extends Set<String>>> pathExtractor) {
|
||||
Builder<T> tree = Builder.create();
|
||||
tree.register(values, pathExtractor);
|
||||
return tree.build();
|
||||
}
|
||||
|
||||
abstract ImmutableMap<String, Node<T>> children();
|
||||
|
||||
abstract ImmutableList<T> values();
|
||||
|
||||
// XXX: Consider having `RefasterRuleSelector` already collect the candidate edges into a
|
||||
// `SortedSet`, as that would likely speed up `ImmutableSortedSet#copyOf`.
|
||||
// XXX: If this ^ proves worthwhile, then the test code and benchmark should be updated
|
||||
// accordingly.
|
||||
void collectReachableValues(Set<String> candidateEdges, Consumer<T> sink) {
|
||||
collectReachableValues(ImmutableSortedSet.copyOf(candidateEdges).asList(), sink);
|
||||
}
|
||||
|
||||
private void collectReachableValues(ImmutableList<String> candidateEdges, Consumer<T> sink) {
|
||||
values().forEach(sink);
|
||||
|
||||
if (candidateEdges.isEmpty() || children().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* For performance reasons we iterate over the smallest set of edges. In case there are fewer
|
||||
* children than candidate edges we iterate over the former, at the cost of not pruning the set
|
||||
* of candidate edges if a transition is made.
|
||||
*/
|
||||
int candidateEdgeCount = candidateEdges.size();
|
||||
if (children().size() < candidateEdgeCount) {
|
||||
for (Map.Entry<String, Node<T>> e : children().entrySet()) {
|
||||
if (candidateEdges.contains(e.getKey())) {
|
||||
e.getValue().collectReachableValues(candidateEdges, sink);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < candidateEdgeCount; i++) {
|
||||
Node<T> child = children().get(candidateEdges.get(i));
|
||||
if (child != null) {
|
||||
child.collectReachableValues(candidateEdges.subList(i + 1, candidateEdgeCount), sink);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
@SuppressWarnings("AutoValueImmutableFields" /* Type is used only during `Node` construction. */)
|
||||
abstract static class Builder<T> {
|
||||
private static <T> Builder<T> create() {
|
||||
return new AutoValue_Node_Builder<>(new HashMap<>(), new ArrayList<>());
|
||||
}
|
||||
|
||||
abstract Map<String, Builder<T>> children();
|
||||
|
||||
abstract List<T> values();
|
||||
|
||||
/**
|
||||
* Registers all paths to each of the given values.
|
||||
*
|
||||
* <p>Shorter paths are registered first, so that longer paths can be skipped if a strict prefix
|
||||
* leads to the same value.
|
||||
*/
|
||||
private void register(
|
||||
Set<T> values, Function<? super T, ? extends Set<? extends Set<String>>> pathsExtractor) {
|
||||
for (T value : values) {
|
||||
List<? extends Set<String>> paths = new ArrayList<>(pathsExtractor.apply(value));
|
||||
/*
|
||||
* We sort paths by length ascending, so that in case of two paths where one is an initial
|
||||
* prefix of the other, only the former is encoded (thus saving some space).
|
||||
*/
|
||||
paths.sort(comparingInt(Set::size));
|
||||
paths.forEach(path -> registerPath(value, ImmutableList.sortedCopyOf(path)));
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPath(T value, ImmutableList<String> path) {
|
||||
if (values().contains(value)) {
|
||||
/* Another (shorter) path already leads to this value. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.isEmpty()) {
|
||||
values().add(value);
|
||||
} else {
|
||||
children()
|
||||
.computeIfAbsent(path.get(0), k -> create())
|
||||
.registerPath(value, path.subList(1, path.size()));
|
||||
}
|
||||
}
|
||||
|
||||
private Node<T> build() {
|
||||
return new AutoValue_Node<>(
|
||||
ImmutableMap.copyOf(Maps.transformValues(children(), Builder::build)),
|
||||
ImmutableList.copyOf(values()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import com.google.common.collect.TreeRangeSet;
|
||||
import com.google.errorprone.BugPattern;
|
||||
import com.google.errorprone.BugPattern.SeverityLevel;
|
||||
import com.google.errorprone.CodeTransformer;
|
||||
import com.google.errorprone.CompositeCodeTransformer;
|
||||
import com.google.errorprone.ErrorProneFlags;
|
||||
import com.google.errorprone.ErrorProneOptions.Severity;
|
||||
import com.google.errorprone.SubContext;
|
||||
@@ -39,6 +38,7 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import javax.inject.Inject;
|
||||
@@ -64,8 +64,9 @@ public final class Refaster extends BugChecker implements CompilationUnitTreeMat
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// XXX: Review this suppression.
|
||||
@SuppressWarnings({"java:S1948", "serial"} /* Concrete instance will be `Serializable`. */)
|
||||
private final CodeTransformer codeTransformer;
|
||||
private final RefasterRuleSelector ruleSelector;
|
||||
|
||||
/** Instantiates a default {@link Refaster} instance. */
|
||||
public Refaster() {
|
||||
@@ -80,16 +81,29 @@ public final class Refaster extends BugChecker implements CompilationUnitTreeMat
|
||||
@Inject
|
||||
@VisibleForTesting
|
||||
public Refaster(ErrorProneFlags flags) {
|
||||
codeTransformer = createCompositeCodeTransformer(flags);
|
||||
ruleSelector = createRefasterRuleSelector(flags);
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
@Override
|
||||
public Description matchCompilationUnit(CompilationUnitTree tree, VisitorState state) {
|
||||
/* First, collect all matches. */
|
||||
List<Description> matches = new ArrayList<>();
|
||||
codeTransformer.apply(state.getPath(), new SubContext(state.context), matches::add);
|
||||
Set<CodeTransformer> candidateTransformers = ruleSelector.selectCandidateRules(tree);
|
||||
|
||||
/* First, collect all matches. */
|
||||
SubContext context = new SubContext(state.context);
|
||||
List<Description> matches = new ArrayList<>();
|
||||
for (CodeTransformer transformer : candidateTransformers) {
|
||||
try {
|
||||
transformer.apply(state.getPath(), context, matches::add);
|
||||
} catch (LinkageError e) {
|
||||
// XXX: This `try/catch` block handles the issue described and resolved in
|
||||
// https://github.com/google/error-prone/pull/2456. Drop this block once that change is
|
||||
// released.
|
||||
// XXX: Find a way to identify that we're running Picnic's Error Prone fork and disable this
|
||||
// fallback if so, as it might hide other bugs.
|
||||
return Description.NO_MATCH;
|
||||
}
|
||||
}
|
||||
/* Then apply them. */
|
||||
applyMatches(matches, ((JCCompilationUnit) tree).endPositions, state);
|
||||
|
||||
@@ -193,10 +207,12 @@ public final class Refaster extends BugChecker implements CompilationUnitTreeMat
|
||||
return description.fixes.stream().flatMap(fix -> fix.getReplacements(endPositions).stream());
|
||||
}
|
||||
|
||||
private static CodeTransformer createCompositeCodeTransformer(ErrorProneFlags flags) {
|
||||
// XXX: Add a flag to disable the optimized `RefasterRuleSelector`. That would allow us to verify
|
||||
// that we're not prematurely pruning rules.
|
||||
private static RefasterRuleSelector createRefasterRuleSelector(ErrorProneFlags flags) {
|
||||
ImmutableListMultimap<String, CodeTransformer> allTransformers =
|
||||
CodeTransformers.getAllCodeTransformers();
|
||||
return CompositeCodeTransformer.compose(
|
||||
return RefasterRuleSelector.create(
|
||||
flags
|
||||
.get(INCLUDED_RULES_PATTERN_FLAG)
|
||||
.map(Pattern::compile)
|
||||
|
||||
@@ -0,0 +1,510 @@
|
||||
package tech.picnic.errorprone.refaster.runner;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static java.util.Collections.newSetFromMap;
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.errorprone.CodeTransformer;
|
||||
import com.google.errorprone.CompositeCodeTransformer;
|
||||
import com.google.errorprone.refaster.BlockTemplate;
|
||||
import com.google.errorprone.refaster.ExpressionTemplate;
|
||||
import com.google.errorprone.refaster.RefasterRule;
|
||||
import com.google.errorprone.refaster.UAnyOf;
|
||||
import com.google.errorprone.refaster.UExpression;
|
||||
import com.google.errorprone.refaster.UStatement;
|
||||
import com.google.errorprone.refaster.UStaticIdent;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import com.sun.source.tree.AssignmentTree;
|
||||
import com.sun.source.tree.BinaryTree;
|
||||
import com.sun.source.tree.ClassTree;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.CompoundAssignmentTree;
|
||||
import com.sun.source.tree.ExpressionTree;
|
||||
import com.sun.source.tree.IdentifierTree;
|
||||
import com.sun.source.tree.MemberReferenceTree;
|
||||
import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.MethodTree;
|
||||
import com.sun.source.tree.PackageTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.UnaryTree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import tech.picnic.errorprone.refaster.AnnotatedCompositeCodeTransformer;
|
||||
|
||||
// XXX: Add some examples of which source files would match what templates in the tree.
|
||||
// XXX: Consider this text in general.
|
||||
/**
|
||||
* A {@link RefasterRuleSelector} algorithm that selects Refaster templates based on the content of
|
||||
* a {@link CompilationUnitTree}.
|
||||
*
|
||||
* <p>The algorithm consists of the following steps:
|
||||
*
|
||||
* <ol>
|
||||
* <li>Create a {@link Node tree} structure based on the provided Refaster templates.
|
||||
* <ol>
|
||||
* <li>Extract all identifiers from the {@link BeforeTemplate}s.
|
||||
* <li>Sort identifiers lexicographically and collect into a set.
|
||||
* <li>Add a path to the tree based on the sorted identifiers.
|
||||
* </ol>
|
||||
* <li>Extract all identifiers from the {@link CompilationUnitTree} and sort them
|
||||
* lexicographically.
|
||||
* <li>Traverse the tree based on the identifiers from the {@link CompilationUnitTree}. Every node
|
||||
* can contain Refaster templates. Once a node is we found a candidate Refaster template that
|
||||
* might match some code and will therefore be added to the list of candidates.
|
||||
* </ol>
|
||||
*
|
||||
* <p>This is an example to explain the algorithm. Consider the templates with identifiers; {@code
|
||||
* T1 = [A, B, C]}, {@code T2 = [B]}, and {@code T3 = [B, D]}. This will result in the following
|
||||
* tree structure:
|
||||
*
|
||||
* <pre>{@code
|
||||
* <root>
|
||||
* ├── A
|
||||
* │ └── B
|
||||
* │ └── C -- T1
|
||||
* └── B -- T2
|
||||
* └── D -- T3
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The tree is traversed based on the identifiers in the {@link CompilationUnitTree}. When a node
|
||||
* containing a template is reached, we can be certain that the identifiers from the {@link
|
||||
* BeforeTemplate} are at least present in the {@link CompilationUnitTree}.
|
||||
*
|
||||
* <p>Since the identifiers are sorted, we can skip parts of the {@link Node tree} while we are
|
||||
* traversing it. Instead of trying to match all Refaster templates against every expression in a
|
||||
* {@link CompilationUnitTree} we now only matching a subset of the templates that at least have a
|
||||
* chance of matching. As a result, the performance of Refaster increases significantly.
|
||||
*/
|
||||
final class RefasterRuleSelector {
|
||||
private final Node<CodeTransformer> codeTransformers;
|
||||
|
||||
private RefasterRuleSelector(Node<CodeTransformer> codeTransformers) {
|
||||
this.codeTransformers = codeTransformers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new {@link RefasterRuleSelector} backed by the given {@link CodeTransformer}s.
|
||||
*/
|
||||
static RefasterRuleSelector create(ImmutableCollection<CodeTransformer> refasterRules) {
|
||||
Map<CodeTransformer, ImmutableSet<ImmutableSet<String>>> ruleIdentifiersByTransformer =
|
||||
indexRuleIdentifiers(refasterRules);
|
||||
return new RefasterRuleSelector(
|
||||
Node.create(ruleIdentifiersByTransformer.keySet(), ruleIdentifiersByTransformer::get));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a set of Refaster templates that can possibly match based on a {@link
|
||||
* CompilationUnitTree}.
|
||||
*
|
||||
* @param tree The {@link CompilationUnitTree} for which candidate Refaster templates are
|
||||
* selected.
|
||||
* @return Set of Refaster templates that can possibly match in the provided {@link
|
||||
* CompilationUnitTree}.
|
||||
*/
|
||||
Set<CodeTransformer> selectCandidateRules(CompilationUnitTree tree) {
|
||||
Set<CodeTransformer> candidateRules = newSetFromMap(new IdentityHashMap<>());
|
||||
codeTransformers.collectReachableValues(extractSourceIdentifiers(tree), candidateRules::add);
|
||||
return candidateRules;
|
||||
}
|
||||
|
||||
private static Map<CodeTransformer, ImmutableSet<ImmutableSet<String>>> indexRuleIdentifiers(
|
||||
ImmutableCollection<CodeTransformer> codeTransformers) {
|
||||
IdentityHashMap<CodeTransformer, ImmutableSet<ImmutableSet<String>>> identifiers =
|
||||
new IdentityHashMap<>();
|
||||
for (CodeTransformer transformer : codeTransformers) {
|
||||
collectRuleIdentifiers(transformer, identifiers);
|
||||
}
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
private static void collectRuleIdentifiers(
|
||||
CodeTransformer codeTransformer,
|
||||
Map<CodeTransformer, ImmutableSet<ImmutableSet<String>>> identifiers) {
|
||||
if (codeTransformer instanceof CompositeCodeTransformer compositeCodeTransformer) {
|
||||
for (CodeTransformer transformer : compositeCodeTransformer.transformers()) {
|
||||
collectRuleIdentifiers(transformer, identifiers);
|
||||
}
|
||||
} else if (codeTransformer instanceof AnnotatedCompositeCodeTransformer annotatedTransformer) {
|
||||
for (Map.Entry<CodeTransformer, ImmutableSet<ImmutableSet<String>>> e :
|
||||
indexRuleIdentifiers(annotatedTransformer.transformers()).entrySet()) {
|
||||
identifiers.put(annotatedTransformer.withTransformers(e.getKey()), e.getValue());
|
||||
}
|
||||
} else if (codeTransformer instanceof RefasterRule) {
|
||||
identifiers.put(
|
||||
codeTransformer, extractRuleIdentifiers((RefasterRule<?, ?>) codeTransformer));
|
||||
} else {
|
||||
/* Unrecognized `CodeTransformer` types are indexed such that they always apply. */
|
||||
identifiers.put(codeTransformer, ImmutableSet.of(ImmutableSet.of()));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Consider decomposing `RefasterRule`s such that each rule has exactly one
|
||||
// `@BeforeTemplate`.
|
||||
private static ImmutableSet<ImmutableSet<String>> extractRuleIdentifiers(
|
||||
RefasterRule<?, ?> refasterRule) {
|
||||
ImmutableSet.Builder<ImmutableSet<String>> results = ImmutableSet.builder();
|
||||
|
||||
for (Object template : RefasterIntrospection.getBeforeTemplates(refasterRule)) {
|
||||
if (template instanceof ExpressionTemplate expressionTemplate) {
|
||||
UExpression expr = RefasterIntrospection.getExpression(expressionTemplate);
|
||||
results.addAll(extractRuleIdentifiers(ImmutableList.of(expr)));
|
||||
} else if (template instanceof BlockTemplate blockTemplate) {
|
||||
ImmutableList<UStatement> statements =
|
||||
RefasterIntrospection.getTemplateStatements(blockTemplate);
|
||||
results.addAll(extractRuleIdentifiers(statements));
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
String.format("Unexpected template type '%s'", template.getClass()));
|
||||
}
|
||||
}
|
||||
|
||||
return results.build();
|
||||
}
|
||||
|
||||
// XXX: Consider interning the strings (once a benchmark is in place).
|
||||
private static ImmutableSet<ImmutableSet<String>> extractRuleIdentifiers(
|
||||
ImmutableList<? extends Tree> trees) {
|
||||
List<Set<String>> identifierCombinations = new ArrayList<>();
|
||||
identifierCombinations.add(new HashSet<>());
|
||||
TemplateIdentifierExtractor.INSTANCE.scan(trees, identifierCombinations);
|
||||
return identifierCombinations.stream().map(ImmutableSet::copyOf).collect(toImmutableSet());
|
||||
}
|
||||
|
||||
private static Set<String> extractSourceIdentifiers(Tree tree) {
|
||||
Set<String> identifiers = new HashSet<>();
|
||||
SourceIdentifierExtractor.INSTANCE.scan(tree, identifiers);
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique string representation of the given {@link Tree.Kind}.
|
||||
*
|
||||
* @return A string representation of the operator, if known
|
||||
* @throws IllegalArgumentException If the given input is not supported.
|
||||
*/
|
||||
// XXX: Extend list to cover remaining cases; at least for any `Kind` that may appear in a
|
||||
// Refaster template. (E.g. keywords such as `if`, `instanceof`, `new`, ...)
|
||||
private static String treeKindToString(Tree.Kind kind) {
|
||||
return switch (kind) {
|
||||
case ASSIGNMENT -> "=";
|
||||
case POSTFIX_INCREMENT -> "x++";
|
||||
case PREFIX_INCREMENT -> "++x";
|
||||
case POSTFIX_DECREMENT -> "x--";
|
||||
case PREFIX_DECREMENT -> "--x";
|
||||
case UNARY_PLUS -> "+x";
|
||||
case UNARY_MINUS -> "-x";
|
||||
case BITWISE_COMPLEMENT -> "~";
|
||||
case LOGICAL_COMPLEMENT -> "!";
|
||||
case MULTIPLY -> "*";
|
||||
case DIVIDE -> "/";
|
||||
case REMAINDER -> "%";
|
||||
case PLUS -> "+";
|
||||
case MINUS -> "-";
|
||||
case LEFT_SHIFT -> "<<";
|
||||
case RIGHT_SHIFT -> ">>";
|
||||
case UNSIGNED_RIGHT_SHIFT -> ">>>";
|
||||
case LESS_THAN -> "<";
|
||||
case GREATER_THAN -> ">";
|
||||
case LESS_THAN_EQUAL -> "<=";
|
||||
case GREATER_THAN_EQUAL -> ">=";
|
||||
case EQUAL_TO -> "==";
|
||||
case NOT_EQUAL_TO -> "!=";
|
||||
case AND -> "&";
|
||||
case XOR -> "^";
|
||||
case OR -> "|";
|
||||
case CONDITIONAL_AND -> "&&";
|
||||
case CONDITIONAL_OR -> "||";
|
||||
case MULTIPLY_ASSIGNMENT -> "*=";
|
||||
case DIVIDE_ASSIGNMENT -> "/=";
|
||||
case REMAINDER_ASSIGNMENT -> "%=";
|
||||
case PLUS_ASSIGNMENT -> "+=";
|
||||
case MINUS_ASSIGNMENT -> "-=";
|
||||
case LEFT_SHIFT_ASSIGNMENT -> "<<=";
|
||||
case RIGHT_SHIFT_ASSIGNMENT -> ">>=";
|
||||
case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT -> ">>>=";
|
||||
case AND_ASSIGNMENT -> "&=";
|
||||
case XOR_ASSIGNMENT -> "^=";
|
||||
case OR_ASSIGNMENT -> "|=";
|
||||
default -> throw new IllegalStateException("Cannot convert Tree.Kind to a String: " + kind);
|
||||
};
|
||||
}
|
||||
|
||||
private static final class RefasterIntrospection {
|
||||
// XXX: Update `ErrorProneRuntimeClasspath` to not suggest inaccessible types.
|
||||
@SuppressWarnings("ErrorProneRuntimeClasspath")
|
||||
private static final String UCLASS_IDENT_FQCN = "com.google.errorprone.refaster.UClassIdent";
|
||||
|
||||
private static final Class<?> UCLASS_IDENT = getClass(UCLASS_IDENT_FQCN);
|
||||
private static final Method METHOD_REFASTER_RULE_BEFORE_TEMPLATES =
|
||||
getMethod(RefasterRule.class, "beforeTemplates");
|
||||
private static final Method METHOD_EXPRESSION_TEMPLATE_EXPRESSION =
|
||||
getMethod(ExpressionTemplate.class, "expression");
|
||||
private static final Method METHOD_BLOCK_TEMPLATE_TEMPLATE_STATEMENTS =
|
||||
getMethod(BlockTemplate.class, "templateStatements");
|
||||
private static final Method METHOD_USTATIC_IDENT_CLASS_IDENT =
|
||||
getMethod(UStaticIdent.class, "classIdent");
|
||||
private static final Method METHOD_UCLASS_IDENT_GET_TOP_LEVEL_CLASS =
|
||||
getMethod(UCLASS_IDENT, "getTopLevelClass");
|
||||
private static final Method METHOD_UANY_OF_EXPRESSIONS = getMethod(UAnyOf.class, "expressions");
|
||||
|
||||
static boolean isUClassIdent(IdentifierTree tree) {
|
||||
return UCLASS_IDENT.isInstance(tree);
|
||||
}
|
||||
|
||||
static ImmutableList<?> getBeforeTemplates(RefasterRule<?, ?> refasterRule) {
|
||||
return invokeMethod(METHOD_REFASTER_RULE_BEFORE_TEMPLATES, refasterRule);
|
||||
}
|
||||
|
||||
static UExpression getExpression(ExpressionTemplate template) {
|
||||
return invokeMethod(METHOD_EXPRESSION_TEMPLATE_EXPRESSION, template);
|
||||
}
|
||||
|
||||
static ImmutableList<UStatement> getTemplateStatements(BlockTemplate template) {
|
||||
return invokeMethod(METHOD_BLOCK_TEMPLATE_TEMPLATE_STATEMENTS, template);
|
||||
}
|
||||
|
||||
static IdentifierTree getClassIdent(UStaticIdent tree) {
|
||||
return invokeMethod(METHOD_USTATIC_IDENT_CLASS_IDENT, tree);
|
||||
}
|
||||
|
||||
// Arguments to this method must actually be of the package-private type `UClassIdent`.
|
||||
static String getTopLevelClass(IdentifierTree uClassIdent) {
|
||||
return invokeMethod(METHOD_UCLASS_IDENT_GET_TOP_LEVEL_CLASS, uClassIdent);
|
||||
}
|
||||
|
||||
static ImmutableList<UExpression> getExpressions(UAnyOf tree) {
|
||||
return invokeMethod(METHOD_UANY_OF_EXPRESSIONS, tree);
|
||||
}
|
||||
|
||||
private static Class<?> getClass(String fqcn) {
|
||||
try {
|
||||
return RefasterIntrospection.class.getClassLoader().loadClass(fqcn);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException(String.format("Failed to load class `%s`", fqcn), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getMethod(Class<?> clazz, String methodName) {
|
||||
try {
|
||||
Method method = clazz.getDeclaredMethod(methodName);
|
||||
method.setAccessible(true);
|
||||
return method;
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalStateException(
|
||||
String.format("No method `%s` on class `%s`", methodName, clazz.getName()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"})
|
||||
private static <T> T invokeMethod(Method method, Object instance) {
|
||||
try {
|
||||
return (T) method.invoke(instance);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new IllegalStateException(String.format("Failed to invoke method `%s`", method), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TemplateIdentifierExtractor
|
||||
extends TreeScanner<@Nullable Void, List<Set<String>>> {
|
||||
private static final TemplateIdentifierExtractor INSTANCE = new TemplateIdentifierExtractor();
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitIdentifier(
|
||||
IdentifierTree node, List<Set<String>> identifierCombinations) {
|
||||
// XXX: Also include the package name if not `java.lang`; it must be present.
|
||||
if (RefasterIntrospection.isUClassIdent(node)) {
|
||||
for (Set<String> ids : identifierCombinations) {
|
||||
ids.add(getSimpleName(RefasterIntrospection.getTopLevelClass(node)));
|
||||
ids.add(getIdentifier(node));
|
||||
}
|
||||
} else if (node instanceof UStaticIdent uStaticIdent) {
|
||||
IdentifierTree subNode = RefasterIntrospection.getClassIdent(uStaticIdent);
|
||||
for (Set<String> ids : identifierCombinations) {
|
||||
ids.add(getSimpleName(RefasterIntrospection.getTopLevelClass(subNode)));
|
||||
ids.add(getIdentifier(subNode));
|
||||
ids.add(node.getName().toString());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getIdentifier(IdentifierTree tree) {
|
||||
return getSimpleName(tree.getName().toString());
|
||||
}
|
||||
|
||||
private static String getSimpleName(String fqcn) {
|
||||
int index = fqcn.lastIndexOf('.');
|
||||
return index < 0 ? fqcn : fqcn.substring(index + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitMemberReference(
|
||||
MemberReferenceTree node, List<Set<String>> identifierCombinations) {
|
||||
super.visitMemberReference(node, identifierCombinations);
|
||||
String id = node.getName().toString();
|
||||
identifierCombinations.forEach(ids -> ids.add(id));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitMemberSelect(
|
||||
MemberSelectTree node, List<Set<String>> identifierCombinations) {
|
||||
super.visitMemberSelect(node, identifierCombinations);
|
||||
String id = node.getIdentifier().toString();
|
||||
identifierCombinations.forEach(ids -> ids.add(id));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitAssignment(
|
||||
AssignmentTree node, List<Set<String>> identifierCombinations) {
|
||||
registerOperator(node, identifierCombinations);
|
||||
return super.visitAssignment(node, identifierCombinations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitCompoundAssignment(
|
||||
CompoundAssignmentTree node, List<Set<String>> identifierCombinations) {
|
||||
registerOperator(node, identifierCombinations);
|
||||
return super.visitCompoundAssignment(node, identifierCombinations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitUnary(UnaryTree node, List<Set<String>> identifierCombinations) {
|
||||
registerOperator(node, identifierCombinations);
|
||||
return super.visitUnary(node, identifierCombinations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitBinary(BinaryTree node, List<Set<String>> identifierCombinations) {
|
||||
registerOperator(node, identifierCombinations);
|
||||
return super.visitBinary(node, identifierCombinations);
|
||||
}
|
||||
|
||||
private static void registerOperator(
|
||||
ExpressionTree node, List<Set<String>> identifierCombinations) {
|
||||
String id = treeKindToString(node.getKind());
|
||||
identifierCombinations.forEach(ids -> ids.add(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitOther(Tree node, List<Set<String>> identifierCombinations) {
|
||||
if (node instanceof UAnyOf uAnyOf) {
|
||||
List<Set<String>> base = copy(identifierCombinations);
|
||||
identifierCombinations.clear();
|
||||
|
||||
for (UExpression expr : RefasterIntrospection.getExpressions(uAnyOf)) {
|
||||
List<Set<String>> branch = copy(base);
|
||||
scan(expr, branch);
|
||||
identifierCombinations.addAll(branch);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<Set<String>> copy(List<Set<String>> identifierCombinations) {
|
||||
return identifierCombinations.stream()
|
||||
.map(HashSet::new)
|
||||
.collect(toCollection(ArrayList::new));
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SourceIdentifierExtractor
|
||||
extends TreeScanner<@Nullable Void, Set<String>> {
|
||||
private static final SourceIdentifierExtractor INSTANCE = new SourceIdentifierExtractor();
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitPackage(PackageTree node, Set<String> identifiers) {
|
||||
/* Refaster rules never match package declarations. */
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitClass(ClassTree node, Set<String> identifiers) {
|
||||
/*
|
||||
* Syntactic details of a class declaration other than the definition of its members do not
|
||||
* need to be reflected in a Refaster rule for it to apply to the class's code.
|
||||
*/
|
||||
return scan(node.getMembers(), identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitMethod(MethodTree node, Set<String> identifiers) {
|
||||
/*
|
||||
* Syntactic details of a method declaration other than its body do not need to be reflected
|
||||
* in a Refaster rule for it to apply to the method's code.
|
||||
*/
|
||||
return scan(node.getBody(), identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitVariable(VariableTree node, Set<String> identifiers) {
|
||||
/* A variable's modifiers and name do not influence where a Refaster rule matches. */
|
||||
return reduce(scan(node.getInitializer(), identifiers), scan(node.getType(), identifiers));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitIdentifier(IdentifierTree node, Set<String> identifiers) {
|
||||
identifiers.add(node.getName().toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitMemberReference(MemberReferenceTree node, Set<String> identifiers) {
|
||||
super.visitMemberReference(node, identifiers);
|
||||
identifiers.add(node.getName().toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitMemberSelect(MemberSelectTree node, Set<String> identifiers) {
|
||||
super.visitMemberSelect(node, identifiers);
|
||||
identifiers.add(node.getIdentifier().toString());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitAssignment(AssignmentTree node, Set<String> identifiers) {
|
||||
registerOperator(node, identifiers);
|
||||
return super.visitAssignment(node, identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitCompoundAssignment(
|
||||
CompoundAssignmentTree node, Set<String> identifiers) {
|
||||
registerOperator(node, identifiers);
|
||||
return super.visitCompoundAssignment(node, identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitUnary(UnaryTree node, Set<String> identifiers) {
|
||||
registerOperator(node, identifiers);
|
||||
return super.visitUnary(node, identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Void visitBinary(BinaryTree node, Set<String> identifiers) {
|
||||
registerOperator(node, identifiers);
|
||||
return super.visitBinary(node, identifiers);
|
||||
}
|
||||
|
||||
private static void registerOperator(ExpressionTree node, Set<String> identifiers) {
|
||||
identifiers.add(treeKindToString(node.getKind()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package tech.picnic.errorprone.refaster.runner;
|
||||
|
||||
import static com.google.common.collect.ImmutableListMultimap.flatteningToImmutableListMultimap;
|
||||
import static java.util.function.Function.identity;
|
||||
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.jakewharton.nopen.annotation.Open;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
import org.openjdk.jmh.infra.Blackhole;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.RunnerException;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
import tech.picnic.errorprone.refaster.runner.NodeTestCase.NodeTestCaseEntry;
|
||||
|
||||
@Open
|
||||
@State(Scope.Benchmark)
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@Fork(jvmArgs = {"-Xms1G", "-Xmx1G"})
|
||||
@Warmup(iterations = 5)
|
||||
@Measurement(iterations = 10)
|
||||
public class NodeBenchmark {
|
||||
@SuppressWarnings("NullAway" /* Initialized by `@Setup` method. */)
|
||||
private ImmutableListMultimap<NodeTestCase<Integer>, NodeTestCaseEntry<Integer>> testCases;
|
||||
|
||||
public static void main(String[] args) throws RunnerException {
|
||||
// XXX: Update `ErrorProneRuntimeClasspath` to allow same-package `Class` references.
|
||||
@SuppressWarnings("ErrorProneRuntimeClasspath")
|
||||
String testRegex = Pattern.quote(NodeBenchmark.class.getCanonicalName());
|
||||
new Runner(new OptionsBuilder().include(testRegex).forks(1).build()).run();
|
||||
}
|
||||
|
||||
@Setup
|
||||
public final void setUp() {
|
||||
Random random = new Random(0);
|
||||
|
||||
testCases =
|
||||
Stream.of(
|
||||
NodeTestCase.generate(100, 5, 10, 10, random),
|
||||
NodeTestCase.generate(100, 5, 10, 100, random),
|
||||
NodeTestCase.generate(100, 5, 10, 1000, random),
|
||||
NodeTestCase.generate(1000, 10, 20, 10, random),
|
||||
NodeTestCase.generate(1000, 10, 20, 100, random),
|
||||
NodeTestCase.generate(1000, 10, 20, 1000, random),
|
||||
NodeTestCase.generate(1000, 10, 20, 10000, random))
|
||||
.collect(
|
||||
flatteningToImmutableListMultimap(
|
||||
identity(), testCase -> testCase.generateTestCaseEntries(random)));
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public final void create(Blackhole bh) {
|
||||
for (NodeTestCase<Integer> testCase : testCases.keySet()) {
|
||||
bh.consume(testCase.buildTree());
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public final void collectReachableValues(Blackhole bh) {
|
||||
for (Map.Entry<NodeTestCase<Integer>, Collection<NodeTestCaseEntry<Integer>>> e :
|
||||
testCases.asMap().entrySet()) {
|
||||
Node<Integer> tree = e.getKey().buildTree();
|
||||
for (NodeTestCaseEntry<Integer> testCaseEntry : e.getValue()) {
|
||||
tree.collectReachableValues(testCaseEntry.candidateEdges(), bh::consume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package tech.picnic.errorprone.refaster.runner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
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 NodeTest {
|
||||
private static Stream<Arguments> collectReachableValuesTestCases() {
|
||||
Random random = new Random(0);
|
||||
|
||||
return Stream.of(
|
||||
NodeTestCase.generate(0, 0, 0, 0, random),
|
||||
NodeTestCase.generate(1, 1, 1, 1, random),
|
||||
NodeTestCase.generate(2, 2, 2, 10, random),
|
||||
NodeTestCase.generate(10, 2, 5, 10, random),
|
||||
NodeTestCase.generate(10, 2, 5, 100, random),
|
||||
NodeTestCase.generate(100, 5, 10, 100, random),
|
||||
NodeTestCase.generate(100, 5, 10, 1000, random))
|
||||
.flatMap(
|
||||
testCase -> {
|
||||
Node<Integer> tree = testCase.buildTree();
|
||||
return testCase
|
||||
.generateTestCaseEntries(random)
|
||||
.map(e -> arguments(tree, e.candidateEdges(), e.reachableValues()));
|
||||
});
|
||||
}
|
||||
|
||||
@MethodSource("collectReachableValuesTestCases")
|
||||
@ParameterizedTest
|
||||
void collectReachableValues(
|
||||
Node<Integer> tree,
|
||||
ImmutableSet<String> candidateEdges,
|
||||
Collection<Integer> expectedReachable) {
|
||||
List<Integer> actualReachable = new ArrayList<>();
|
||||
tree.collectReachableValues(candidateEdges, actualReachable::add);
|
||||
assertThat(actualReachable).hasSameElementsAs(expectedReachable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package tech.picnic.errorprone.refaster.runner;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.ImmutableSetMultimap.flatteningToImmutableSetMultimap;
|
||||
import static java.util.function.Function.identity;
|
||||
import static java.util.stream.Collectors.collectingAndThen;
|
||||
|
||||
import com.google.auto.value.AutoValue;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@AutoValue
|
||||
abstract class NodeTestCase<V> {
|
||||
static NodeTestCase<Integer> generate(
|
||||
int entryCount, int maxPathCount, int maxPathLength, int pathValueDomainSize, Random random) {
|
||||
return random
|
||||
.ints(entryCount)
|
||||
.boxed()
|
||||
.collect(
|
||||
collectingAndThen(
|
||||
flatteningToImmutableSetMultimap(
|
||||
identity(),
|
||||
i ->
|
||||
random
|
||||
.ints(random.nextInt(maxPathCount + 1))
|
||||
.mapToObj(
|
||||
p ->
|
||||
random
|
||||
.ints(
|
||||
random.nextInt(maxPathLength + 1),
|
||||
0,
|
||||
pathValueDomainSize)
|
||||
.mapToObj(String::valueOf)
|
||||
.collect(toImmutableSet()))),
|
||||
AutoValue_NodeTestCase::new));
|
||||
}
|
||||
|
||||
abstract ImmutableSetMultimap<V, ImmutableSet<String>> input();
|
||||
|
||||
final Node<V> buildTree() {
|
||||
return Node.create(input().keySet(), input()::get);
|
||||
}
|
||||
|
||||
final Stream<NodeTestCaseEntry<V>> generateTestCaseEntries(Random random) {
|
||||
return generatePathTestCases(input(), random);
|
||||
}
|
||||
|
||||
private static <V> Stream<NodeTestCaseEntry<V>> generatePathTestCases(
|
||||
ImmutableSetMultimap<V, ImmutableSet<String>> treeInput, Random random) {
|
||||
ImmutableSet<String> allEdges =
|
||||
treeInput.values().stream().flatMap(ImmutableSet::stream).collect(toImmutableSet());
|
||||
|
||||
return Stream.concat(
|
||||
Stream.of(ImmutableSet.<String>of()), shuffle(treeInput.values(), random).stream())
|
||||
// XXX: Use `random.nextInt(20, 100)` once we no longer target JDK 11. (And consider
|
||||
// introducing a Refaster template for this case.)
|
||||
.limit(20 + random.nextInt(80))
|
||||
.flatMap(edges -> generateVariations(edges, allEdges, "unused", random))
|
||||
.distinct()
|
||||
.map(edges -> createTestCaseEntry(treeInput, edges));
|
||||
}
|
||||
|
||||
private static <T> Stream<ImmutableSet<T>> generateVariations(
|
||||
ImmutableSet<T> baseEdges, ImmutableSet<T> allEdges, T unusedEdge, Random random) {
|
||||
Optional<T> knownEdge = selectRandomElement(allEdges, random);
|
||||
|
||||
return Stream.of(
|
||||
random.nextBoolean() ? null : baseEdges,
|
||||
random.nextBoolean() ? null : shuffle(baseEdges, random),
|
||||
random.nextBoolean() ? null : insertValue(baseEdges, unusedEdge, random),
|
||||
baseEdges.isEmpty() || random.nextBoolean()
|
||||
? null
|
||||
: randomStrictSubset(baseEdges, random),
|
||||
baseEdges.isEmpty() || random.nextBoolean()
|
||||
? null
|
||||
: insertValue(randomStrictSubset(baseEdges, random), unusedEdge, random),
|
||||
baseEdges.isEmpty() || random.nextBoolean()
|
||||
? null
|
||||
: knownEdge
|
||||
.map(edge -> insertValue(randomStrictSubset(baseEdges, random), edge, random))
|
||||
.orElse(null))
|
||||
.filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
private static <T> Optional<T> selectRandomElement(ImmutableSet<T> collection, Random random) {
|
||||
return collection.isEmpty()
|
||||
? Optional.empty()
|
||||
: Optional.of(collection.asList().get(random.nextInt(collection.size())));
|
||||
}
|
||||
|
||||
private static <T> ImmutableSet<T> shuffle(ImmutableCollection<T> values, Random random) {
|
||||
List<T> allValues = new ArrayList<>(values);
|
||||
Collections.shuffle(allValues, random);
|
||||
return ImmutableSet.copyOf(allValues);
|
||||
}
|
||||
|
||||
private static <T> ImmutableSet<T> insertValue(
|
||||
ImmutableSet<T> values, T extraValue, Random random) {
|
||||
List<T> allValues = new ArrayList<>(values);
|
||||
allValues.add(random.nextInt(values.size() + 1), extraValue);
|
||||
return ImmutableSet.copyOf(allValues);
|
||||
}
|
||||
|
||||
private static <T> ImmutableSet<T> randomStrictSubset(ImmutableSet<T> values, Random random) {
|
||||
checkArgument(!values.isEmpty(), "Cannot select strict subset of random collection");
|
||||
|
||||
List<T> allValues = new ArrayList<>(values);
|
||||
Collections.shuffle(allValues, random);
|
||||
return ImmutableSet.copyOf(allValues.subList(0, random.nextInt(allValues.size())));
|
||||
}
|
||||
|
||||
private static <V> NodeTestCaseEntry<V> createTestCaseEntry(
|
||||
ImmutableSetMultimap<V, ImmutableSet<String>> treeInput, ImmutableSet<String> edges) {
|
||||
return new AutoValue_NodeTestCase_NodeTestCaseEntry<>(
|
||||
edges,
|
||||
treeInput.asMap().entrySet().stream()
|
||||
.filter(e -> e.getValue().stream().anyMatch(edges::containsAll))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(toImmutableList()));
|
||||
}
|
||||
|
||||
@AutoValue
|
||||
abstract static class NodeTestCaseEntry<V> {
|
||||
abstract ImmutableSet<String> candidateEdges();
|
||||
|
||||
abstract ImmutableList<V> reachableValues();
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-support</artifactId>
|
||||
|
||||
@@ -46,7 +46,12 @@ public abstract class AnnotatedCompositeCodeTransformer implements CodeTransform
|
||||
|
||||
abstract String packageName();
|
||||
|
||||
abstract ImmutableList<CodeTransformer> transformers();
|
||||
/**
|
||||
* Return The {@link CodeTransformer}s to which to delegate.
|
||||
*
|
||||
* @return The ordered {@link CodeTransformer}s to which to delegate.
|
||||
*/
|
||||
public abstract ImmutableList<CodeTransformer> transformers();
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("java:S3038" /* All AutoValue properties must be specified explicitly. */)
|
||||
@@ -67,6 +72,18 @@ public abstract class AnnotatedCompositeCodeTransformer implements CodeTransform
|
||||
return new AutoValue_AnnotatedCompositeCodeTransformer(packageName, transformers, annotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link AnnotatedCompositeCodeTransformer} similar to this one, but with the
|
||||
* specified transformers.
|
||||
*
|
||||
* @param transformers The replacement transformers.
|
||||
* @return A derivative {@link AnnotatedCompositeCodeTransformer}.
|
||||
*/
|
||||
public AnnotatedCompositeCodeTransformer withTransformers(CodeTransformer... transformers) {
|
||||
return new AutoValue_AnnotatedCompositeCodeTransformer(
|
||||
packageName(), ImmutableList.copyOf(transformers), annotations());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void apply(TreePath path, Context context, DescriptionListener listener) {
|
||||
for (CodeTransformer transformer : transformers()) {
|
||||
|
||||
@@ -118,11 +118,12 @@ public final class IsEmpty implements Matcher<ExpressionTree> {
|
||||
}
|
||||
|
||||
private boolean isEmptyCollectionConstructor(ExpressionTree tree, VisitorState state) {
|
||||
if (!(tree instanceof NewClassTree) || !MUTABLE_COLLECTION_TYPE.matches(tree, state)) {
|
||||
if (!(tree instanceof NewClassTree newClassTree)
|
||||
|| !MUTABLE_COLLECTION_TYPE.matches(tree, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<? extends ExpressionTree> arguments = ((NewClassTree) tree).getArguments();
|
||||
List<? extends ExpressionTree> arguments = newClassTree.getArguments();
|
||||
if (arguments.stream().allMatch(a -> EMPTY_COLLECTION_CONSTRUCTOR_ARGUMENT.matches(a, state))) {
|
||||
/*
|
||||
* This is a default constructor, or a constructor that creates an empty collection using
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>tech.picnic.error-prone-support</groupId>
|
||||
<artifactId>error-prone-support</artifactId>
|
||||
<version>0.20.1-SNAPSHOT</version>
|
||||
<version>0.21.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>refaster-test-support</artifactId>
|
||||
|
||||
@@ -6,6 +6,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet;
|
||||
import static com.google.errorprone.BugPattern.LinkType.NONE;
|
||||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Comparator.naturalOrder;
|
||||
import static tech.picnic.errorprone.refaster.runner.Refaster.INCLUDED_RULES_PATTERN_FLAG;
|
||||
|
||||
@@ -17,6 +18,7 @@ import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Range;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||
import com.google.errorprone.BugPattern;
|
||||
@@ -38,6 +40,9 @@ import com.sun.source.util.TreeScanner;
|
||||
import com.sun.tools.javac.tree.EndPosTable;
|
||||
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
|
||||
import com.sun.tools.javac.util.Position;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -124,13 +129,15 @@ public final class RefasterRuleCollection extends BugChecker implements Compilat
|
||||
*/
|
||||
public static void validate(Class<?> clazz) {
|
||||
String className = clazz.getSimpleName();
|
||||
String inputResource = className + "TestInput.java";
|
||||
String outputResource = className + "TestOutput.java";
|
||||
|
||||
BugCheckerRefactoringTestHelper.newInstance(RefasterRuleCollection.class, clazz)
|
||||
.setArgs(
|
||||
"--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
|
||||
"-XepOpt:" + RULE_COLLECTION_FLAG + '=' + className)
|
||||
.addInput(className + "TestInput.java")
|
||||
.addOutput(className + "TestOutput.java")
|
||||
.addInputLines(inputResource, loadResource(clazz, inputResource))
|
||||
.addOutputLines(outputResource, loadResource(clazz, outputResource))
|
||||
.doTest(TestMode.TEXT_MATCH);
|
||||
}
|
||||
|
||||
@@ -247,6 +254,15 @@ public final class RefasterRuleCollection extends BugChecker implements Compilat
|
||||
return value.substring(index + 1);
|
||||
}
|
||||
|
||||
private static String loadResource(Class<?> contextClass, String resource) {
|
||||
URL url = Resources.getResource(contextClass, resource);
|
||||
try {
|
||||
return Resources.toString(url, UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException("Cannot find resource: " + url, e);
|
||||
}
|
||||
}
|
||||
|
||||
private class UnexpectedMatchReporter extends TreeScanner<@Nullable Void, VisitorState> {
|
||||
private final ImmutableRangeMap<Integer, String> indexedMatches;
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package tech.picnic.errorprone.refaster.test;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.Map;
|
||||
|
||||
/** Refaster rule collection to validate the reporting of missing test methods. */
|
||||
final class NestedRefasterAnyOfRules {
|
||||
private NestedRefasterAnyOfRules() {}
|
||||
|
||||
static final class NestedRefasterAnyOf<K, V> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings({"ImmutableMapOf1", "MapEntry"} /* Similar rules for testing purposes. */)
|
||||
Map<K, V> before(K k1, V v1) {
|
||||
return Refaster.anyOf(
|
||||
ImmutableMap.ofEntries(
|
||||
Refaster.anyOf(Map.entry(k1, v1), new SimpleImmutableEntry<>(k1, v1))),
|
||||
singletonMap(k1, v1));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(K k1, V v1) {
|
||||
return ImmutableMap.of(k1, v1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,10 @@ final class RefasterRuleCollectionTest {
|
||||
MethodWithoutPrefixRules.class,
|
||||
MisnamedTestClassRules.class,
|
||||
MissingTestAndWrongTestRules.class,
|
||||
NestedRefasterAnyOfRules.class,
|
||||
PartialTestMatchRules.class,
|
||||
RuleWithoutTestRules.class,
|
||||
SingleRefasterAnyOfRules.class,
|
||||
ValidRules.class
|
||||
})
|
||||
void verifyRefasterRuleCollections(Class<?> clazz) {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package tech.picnic.errorprone.refaster.test;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.errorprone.refaster.Refaster;
|
||||
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||
import java.util.Map;
|
||||
|
||||
/** Refaster rule collection to validate the reporting of missing test methods. */
|
||||
final class SingleRefasterAnyOfRules {
|
||||
private SingleRefasterAnyOfRules() {}
|
||||
|
||||
static final class SingleRefasterAnyOf<K, V> {
|
||||
@BeforeTemplate
|
||||
@SuppressWarnings("ImmutableMapOf1" /* Similar rule for testing purposes. */)
|
||||
Map<K, V> before(K k1, V v1) {
|
||||
return Refaster.anyOf(ImmutableMap.ofEntries(Map.entry(k1, v1)), singletonMap(k1, v1));
|
||||
}
|
||||
|
||||
@AfterTemplate
|
||||
ImmutableMap<K, V> after(K k1, V v1) {
|
||||
return ImmutableMap.of(k1, v1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package tech.picnic.errorprone.refaster.test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** Code to test the Refaster rules from {@link NestedRefasterAnyOfRules}. */
|
||||
final class NestedRefasterAnyOfRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Map<?, ?> testNestedRefasterAnyOf() {
|
||||
Map<String, String> stringStringMap = Map.of("1", "2");
|
||||
return ImmutableMap.ofEntries(Map.entry("k1", "v1"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package tech.picnic.errorprone.refaster.test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** Code to test the Refaster rules from {@link NestedRefasterAnyOfRules}. */
|
||||
final class NestedRefasterAnyOfRulesTest implements RefasterRuleCollectionTestCase {
|
||||
Map<?, ?> testNestedRefasterAnyOf() {
|
||||
Map<String, String> stringStringMap = Map.of("1", "2");
|
||||
return ImmutableMap.of("k1", "v1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package tech.picnic.errorprone.refaster.test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/** Code to test the Refaster rules from {@link SingleRefasterAnyOfRules}. */
|
||||
final class SingleRefasterAnyOfRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(Collections.class);
|
||||
}
|
||||
|
||||
Map<?, ?> testSingleRefasterAnyOf() {
|
||||
return Collections.singletonMap("k1", "v1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package tech.picnic.errorprone.refaster.test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/** Code to test the Refaster rules from {@link SingleRefasterAnyOfRules}. */
|
||||
final class SingleRefasterAnyOfRulesTest implements RefasterRuleCollectionTestCase {
|
||||
@Override
|
||||
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||
return ImmutableSet.of(Collections.class);
|
||||
}
|
||||
|
||||
Map<?, ?> testSingleRefasterAnyOf() {
|
||||
return ImmutableMap.of("k1", "v1");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
# 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.21.0
|
||||
compatible:
|
||||
- "2.37.0"
|
||||
- version: 0.20.0
|
||||
compatible:
|
||||
- "2.36.0"
|
||||
|
||||
Reference in New Issue
Block a user