Compare commits

...

187 Commits

Author SHA1 Message Date
Rick Ossendrijver
1ac65e9f53 Fix missed merge conflicts 2024-11-14 09:28:43 +01:00
Rick Ossendrijver
f793c73bba Merge master in this branch 2024-11-14 09:26:11 +01:00
Stephan Schroevers
13684ec59d Replace deprecated build-helper:remove-project-artifact goal (#1413) 2024-11-13 18:27:41 +01:00
Picnic-DevPla-Bot
a51ff4de4e Upgrade actions/checkout v4.1.6 -> v4.2.2 (#1401)
See:
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v422
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v421
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v420
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v417
2024-11-12 11:11:52 +01:00
Phil Werli
da9b313ff7 Introduce assorted Reactor StepVerifier Refaster rules (#1132) 2024-11-11 14:08:05 +01:00
Phil Werli
6a50fe2d9c Introduce Instant{Identity,TruncatedTo{Milliseconds,Seconds}} Refaster rules (#1395)
While there, have `IdentityConversion` support `Instant#from`.
2024-11-11 10:42:05 +01:00
Stephan Schroevers
ed32cbae06 Update step-security/harden-runner configuration (#1412)
By allowing access to Open Source Insights.
2024-11-11 08:46:49 +01:00
Picnic-DevPla-Bot
00549a3ba6 Upgrade org.openrewrite:rewrite-java-17 8.38.1 -> 8.40.0 (#1390)
See:
- https://github.com/openrewrite/rewrite/releases/tag/v8.40.0
- https://github.com/openrewrite/rewrite/releases/tag/v8.39.0
- https://github.com/openrewrite/rewrite/releases/tag/v8.38.3
- https://github.com/openrewrite/rewrite/releases/tag/v8.38.2
- https://github.com/openrewrite/rewrite/compare/v8.38.1...v8.40.0
2024-11-11 07:54:49 +01:00
Picnic-DevPla-Bot
13f1fa3167 Upgrade ossf/scorecard-action v2.3.3 -> v2.4.0 (#1403)
See:
- https://github.com/ossf/scorecard-action/releases/tag/v2.4.0
- https://github.com/ossf/scorecard-action/compare/v2.3.3...v2.4.0
2024-11-11 07:44:12 +01:00
Picnic-DevPla-Bot
6396def588 Upgrade sonar-maven-plugin 4.0.0.4121 -> 5.0.0.4389 (#1405)
See:
- https://github.com/SonarSource/sonar-scanner-maven/releases/tag/5.0.0.4389
- https://github.com/SonarSource/sonar-scanner-maven/compare/4.0.0.4121...5.0.0.4389
2024-11-10 22:04:47 +01:00
Picnic-DevPla-Bot
7599b0f22f Upgrade step-security/harden-runner v2.8.0 -> v2.10.1 (#1404)
See:
- https://github.com/step-security/harden-runner/releases/tag/v2.10.1
- https://github.com/step-security/harden-runner/releases/tag/v2.10.0
- https://github.com/step-security/harden-runner/releases/tag/v2.9.1
- https://github.com/step-security/harden-runner/releases/tag/v2.9.0
- https://github.com/step-security/harden-runner/releases/tag/v2.8.1
2024-11-10 21:33:56 +01:00
Picnic-DevPla-Bot
08eb7e7699 Upgrade OpenRewrite Templating 1.16.3 -> 1.17.0 (#1409)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.17.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.16.3...v1.17.0
2024-11-10 18:38:30 +01:00
Stephan Schroevers
89f918c23e Update step-security/harden-runner configuration (#1411)
By allowing Docker Hub and Maven Central access.
2024-11-10 18:26:40 +01:00
Stephan Schroevers
f08fc344f5 Track StreamFlatMapOptional Refaster rule caveat (#1410) 2024-11-10 15:14:08 +01:00
Picnic-DevPla-Bot
99aa656a1e Upgrade s4u/setup-maven-action v1.13.0 -> v1.16.0 (#1400)
See:
- https://github.com/s4u/setup-maven-action/releases/tag/v1.16.0
- https://github.com/s4u/setup-maven-action/releases/tag/v1.15.0
- https://github.com/s4u/setup-maven-action/releases/tag/v1.14.0
2024-11-09 10:27:57 +01:00
Picnic-DevPla-Bot
86fbaf7403 Upgrade Checkstyle 10.20.0 -> 10.20.1 (#1407)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.20.1
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.20.0...checkstyle-10.20.1
2024-11-08 19:37:12 +01:00
Picnic-DevPla-Bot
563012549a Upgrade pitest-maven-plugin 1.17.0 -> 1.17.1 (#1397)
See:
- https://github.com/hcoles/pitest/releases/tag/1.17.1
- https://github.com/hcoles/pitest/compare/1.17.0...1.17.1
2024-11-07 21:29:39 +01:00
Picnic-DevPla-Bot
4f46eb30d2 Upgrade actions/upload-artifact v4.3.3 -> v4.4.3 (#1402)
See:
- https://github.com/actions/upload-artifact/releases/tag/v4.4.3
- https://github.com/actions/upload-artifact/releases/tag/v4.4.2
- https://github.com/actions/upload-artifact/releases/tag/v4.4.1
- https://github.com/actions/upload-artifact/releases/tag/v4.4.0
- https://github.com/actions/upload-artifact/releases/tag/v4.3.6
- https://github.com/actions/upload-artifact/releases/tag/v4.3.5
- https://github.com/actions/upload-artifact/releases/tag/v4.3.4
2024-11-07 16:39:05 +01:00
Picnic-DevPla-Bot
2f30082127 Upgrade maven-javadoc-plugin 3.10.1 -> 3.11.1 (#1398)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MJAVADOC%20AND%20fixVersion%20%3E%203.10.1%20AND%20fixVersion%20%3C%3D%203.11.1
- https://github.com/apache/maven-javadoc-plugin/releases/tag/maven-javadoc-plugin-3.11.0
- https://github.com/apache/maven-javadoc-plugin/releases/tag/maven-javadoc-plugin-3.11.1
- https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.1...maven-javadoc-plugin-3.11.1
2024-11-07 12:48:15 +01:00
Stephan Schroevers
548506fbbb Update Error Prone compatibility matrix (#1406) 2024-11-07 10:54:08 +01:00
Picnic-DevPla-Bot
bdef83bce5 Upgrade Byte Buddy 1.15.7 -> 1.15.10 (#1388)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.8
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.9
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.10
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.15.7...byte-buddy-1.15.10
2024-11-06 09:03:44 +01:00
Picnic-DevPla-Bot
f7f665681d Upgrade Surefire 3.5.1 -> 3.5.2 (#1396)
See:
- https://github.com/apache/maven-surefire/releases/tag/surefire-3.5.2
- https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.2
2024-11-05 11:36:11 +01:00
Picnic-DevPla-Bot
7c0d544cf8 Upgrade Checker Framework Annotations 3.48.1 -> 3.48.2 (#1389)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.48.2
- https://github.com/typetools/checker-framework/compare/checker-framework-3.48.1...checker-framework-3.48.2
2024-11-04 14:51:00 +01:00
Stephan Schroevers
9390b6f571 Run GitHub Actions workflows on ubuntu-24.04 (#1391)
See https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
2024-11-03 18:36:54 +01:00
Stephan Schroevers
176a833d89 Upgrade ruby/setup-ruby v1.174.0 -> v1.199.0 (#1392)
See:
- https://github.com/ruby/setup-ruby/releases/tag/v1.175.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.176.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.177.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.178.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.179.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.180.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.181.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.182.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.183.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.184.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.185.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.186.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.187.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.188.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.189.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.190.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.191.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.192.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.193.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.194.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.195.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.196.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.197.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.198.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.199.0
- https://github.com/ruby/setup-ruby/compare/v1.174.0...v1.199.0
2024-11-03 18:17:38 +01:00
Stephan Schroevers
3cacd27248 [maven-release-plugin] prepare for next development iteration 2024-11-03 16:58:19 +01:00
Stephan Schroevers
f06a2e4d43 [maven-release-plugin] prepare release v0.19.1 2024-11-03 16:58:19 +01:00
Stephan Schroevers
cd06288f5b Fix error-prone-contrib runtime classpath (#1387) 2024-11-03 16:53:15 +01:00
Picnic-DevPla-Bot
4b458e01bd Upgrade Checkstyle 10.19.0 -> 10.20.0 (#1386)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.20.0
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.19.0...checkstyle-10.20.0
2024-11-01 09:37:37 +01:00
Stephan Schroevers
eccfc34c78 [maven-release-plugin] prepare for next development iteration 2024-10-31 20:57:03 +01:00
Stephan Schroevers
0317cb73d6 [maven-release-plugin] prepare release v0.19.0 2024-10-31 20:57:03 +01:00
Mohamed Sameh
ce6931cc36 Ignore primitive casts in ClassCastLambdaUsage check (#1385) 2024-10-30 15:37:40 +01:00
Stephan Schroevers
9940576ea8 Introduce NameContentEquals Refaster rule (#1379) 2024-10-29 10:55:55 +01:00
Mohamed Sameh
caf2a86922 Introduce ClassCastLambdaUsage check (#1381)
This new check replaces the `ClassLiteralCast` Refaster rule, as the 
latter produced invalid code by suggesting expressions of the form
`T.class::cast` for generic `T`.
2024-10-29 10:35:36 +01:00
Stephan Schroevers
507d759d02 Upgrade JDKs used by GitHub Actions builds (#1329)
Summary of changes:
- Use JDK 17.0.13 instead of 17.0.10.
- Use JDK 21.0.5 instead of 21.0.2.
- Use JDK 23.0.1 instead of 22.0.2.
- Have GitHub issue template reference more recent version numbers.

See:
- https://adoptium.net/temurin/release-notes/?version=jdk-17.0.11+9
- https://adoptium.net/temurin/release-notes/?version=jdk-17.0.12+7
- https://adoptium.net/temurin/release-notes/?version=jdk-17.0.13+11
- https://adoptium.net/temurin/release-notes/?version=jdk-21.0.3+9
- https://adoptium.net/temurin/release-notes/?version=jdk-21.0.4+7
- https://adoptium.net/temurin/release-notes/?version=jdk-21.0.5+11
- https://adoptium.net/temurin/release-notes/?version=jdk-23+37
- https://adoptium.net/temurin/release-notes/?version=jdk-23.0.1+11
2024-10-29 10:26:04 +01:00
Picnic-DevPla-Bot
8ec4936980 Upgrade NullAway 0.12.0 -> 0.12.1 (#1383)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.12.1
- https://github.com/uber/NullAway/compare/v0.12.0...v0.12.1
2024-10-29 10:16:33 +01:00
Picnic-DevPla-Bot
0f0b27abb7 Upgrade Jackson 2.18.0 -> 2.18.1 (#1382)
See:
- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.18.1
- https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.18.0...jackson-bom-2.18.1
2024-10-29 09:43:59 +01:00
Mohamed Sameh
2b1dbd98cd Introduce Slf4jLoggerDeclaration check (#783) 2024-10-28 12:37:10 +01:00
Picnic-DevPla-Bot
e0583a8f0a Upgrade OpenRewrite Templating 1.16.2 -> 1.16.3 (#1380)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.16.3
- https://github.com/openrewrite/rewrite-templating/compare/v1.16.2...v1.16.3
2024-10-28 08:44:43 +01:00
Mohamed Sameh
21437a43aa Introduce ConstantNaming check (#794)
This check flags static constants that do not follow the upper snake
case naming convention.

While there, introduce the `Flags#getSet` utility method, and use it to
replace `Flags#getList` in relevant places.
2024-10-27 14:23:59 +01:00
Stephan Schroevers
cf8af8c5cf Use dynamic Reproducible Builds badge (#1378) 2024-10-27 13:19:46 +01:00
Picnic-DevPla-Bot
07bd4b0b54 Upgrade maven-checkstyle-plugin 3.5.0 -> 3.6.0 (#1377)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MCHECKSTYLE%20AND%20fixVersion%20%3E%203.5.0%20AND%20fixVersion%20%3C%3D%203.6.0
- https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.5.0...maven-checkstyle-plugin-3.6.0
2024-10-27 12:46:41 +01:00
Picnic-DevPla-Bot
d1765fea0e Upgrade maven-dependency-plugin 3.8.0 -> 3.8.1 (#1375)
See:
- https://github.com/apache/maven-dependency-plugin/releases/tag/maven-dependency-plugin-3.8.1
- https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.8.0...maven-dependency-plugin-3.8.1
2024-10-27 12:37:15 +01:00
Picnic-DevPla-Bot
5922c5b032 Upgrade Checkstyle 10.18.2 -> 10.19.0 (#1376)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.19.0
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.18.2...checkstyle-10.19.0
2024-10-27 12:12:35 +01:00
Danylo Naumenko
56b60f5cf6 Introduce MicrometerRules Refaster rule collection (#1365) 2024-10-26 14:56:11 +02:00
Mohamed Sameh
be6b17b7dc Introduce ImmutableEnumSetRules Refaster rule collection (#1302) 2024-10-26 14:01:25 +02:00
Picnic-DevPla-Bot
f782ec2d8f Upgrade Spring Boot 3.3.4 -> 3.3.5 (#1374)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.5
- https://github.com/spring-projects/spring-boot/compare/v3.3.4...v3.3.5
2024-10-26 13:36:32 +02:00
Picnic-DevPla-Bot
6e88e3cea8 Upgrade Error Prone 2.33.0 -> 2.35.1 (#1363)
See:
- https://github.com/google/error-prone/releases/tag/v2.34.0
- https://github.com/google/error-prone/releases/tag/v2.35.0
- https://github.com/google/error-prone/releases/tag/v2.35.1
- https://github.com/google/error-prone/compare/v2.33.0...v2.35.1
- https://github.com/PicnicSupermarket/error-prone/compare/v2.33.0-picnic-2...v2.35.1-picnic-1
2024-10-26 13:20:13 +02:00
Picnic-DevPla-Bot
09fb21358a Upgrade Project Reactor 2023.0.10 -> 2023.0.11 (#1359)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.11
- https://github.com/reactor/reactor/compare/2023.0.10...2023.0.11
2024-10-26 11:53:55 +02:00
Picnic-DevPla-Bot
c27a626042 Upgrade OpenRewrite 2.21.0 -> 2.21.1 (#1369)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.21.1
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.21.0...v2.21.1
2024-10-26 11:33:07 +02:00
Picnic-DevPla-Bot
da33e800fa Upgrade Spring Security 6.3.3 -> 6.3.4 (#1367)
See:
- https://github.com/spring-projects/spring-security/releases/tag/6.3.4
- https://github.com/spring-projects/spring-security/compare/6.3.3...6.3.4
2024-10-25 23:50:12 +02:00
Picnic-DevPla-Bot
bc13976cc7 Upgrade OpenRewrite Templating 1.16.1 -> 1.16.2 (#1370)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.16.2
- https://github.com/openrewrite/rewrite-templating/compare/v1.16.1...v1.16.2
2024-10-25 23:36:02 +02:00
Picnic-DevPla-Bot
7f1f0656fd Upgrade maven-site-plugin 3.20.0 -> 3.21.0 (#1371)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MSITE%20AND%20fixVersion%20%3E%203.20.0%20AND%20fixVersion%20%3C%3D%203.21.0
- https://github.com/apache/maven-site-plugin/compare/maven-site-plugin-3.20.0...maven-site-plugin-3.21.0
2024-10-25 23:26:57 +02:00
Picnic-DevPla-Bot
4e99382f42 Upgrade pomchecker-maven-plugin 1.13.0 -> 1.14.0 (#1372)
See:
- https://github.com/kordamp/pomchecker/releases/tag/v1.14.0
- https://github.com/kordamp/pomchecker/compare/v1.13.0...v1.14.0
2024-10-25 22:50:26 +02:00
Picnic-DevPla-Bot
9aa03aa842 Upgrade JUnit 5 5.11.2 -> 5.11.3 (#1366)
See:
- https://junit.org/junit5/docs/current/release-notes/
- https://github.com/junit-team/junit5/releases/tag/r5.11.3
- https://github.com/junit-team/junit5/compare/r5.11.2...r5.11.3
2024-10-25 22:39:48 +02:00
Picnic-DevPla-Bot
71cc09a7e7 Upgrade Spring 6.1.13 -> 6.1.14 (#1362)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.14
- https://github.com/spring-projects/spring-framework/compare/v6.1.13...v6.1.14
2024-10-25 17:07:18 +02:00
Picnic-DevPla-Bot
9b4cbfb84d Upgrade Byte Buddy 1.15.5 -> 1.15.7 (#1368)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.6
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.7
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.15.5...byte-buddy-1.15.7
2024-10-24 09:01:49 +02:00
Picnic-DevPla-Bot
f2238c779c Upgrade Guava 33.3.0-jre -> 33.3.1-jre (#1336)
And drop some Refaster rules now covered by `@InlineMe` instructions.

See:
- https://guava.dev/releases/33.3.1-jre/api/diffs/
- https://github.com/google/guava/releases/tag/v33.3.1
- https://github.com/google/guava/compare/v33.3.0...v33.3.1
2024-10-23 10:06:19 +02:00
Picnic-DevPla-Bot
6e893e9869 Upgrade fmt-maven-plugin 2.24 -> 2.25 (#1356)
See:
- https://github.com/spotify/fmt-maven-plugin/releases/tag/2.25
- https://github.com/spotify/fmt-maven-plugin/compare/2.24...2.25
2024-10-23 09:30:41 +02:00
Picnic-DevPla-Bot
7ee8826e96 Upgrade NullAway 0.11.3 -> 0.12.0 (#1364)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.12.0
- https://github.com/uber/NullAway/compare/v0.11.3...v0.12.0
2024-10-20 12:35:33 +02:00
Picnic-DevPla-Bot
a0689f62b4 Upgrade Byte Buddy 1.15.4 -> 1.15.5 (#1360)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.5
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.15.4...byte-buddy-1.15.5
2024-10-18 13:53:23 +02:00
Picnic-DevPla-Bot
1b00c87b2f Upgrade Mockito 5.14.0 -> 5.14.2 (#1361)
See:
- https://github.com/mockito/mockito/releases/tag/v5.14.1
- https://github.com/mockito/mockito/releases/tag/v5.14.2
- https://github.com/mockito/mockito/compare/v5.14.0...v5.14.2
2024-10-18 13:23:57 +02:00
Picnic-DevPla-Bot
0bce1a0e29 Upgrade Mockito 5.13.0 -> 5.14.0 (#1345)
And configure its Java agent such that Byte Buddy does not need to use
the deprecated self-attach mechanism.

See:
- https://github.com/mockito/mockito/releases/tag/v5.14.0
- https://github.com/mockito/mockito/compare/v5.13.0...v5.14.0
2024-10-17 15:11:27 +02:00
Picnic-DevPla-Bot
ce18b0c058 Upgrade Google Java Format 1.23.0 -> 1.24.0 (#1352)
See:
- https://github.com/google/google-java-format/releases/tag/v1.24.0
- https://github.com/google/google-java-format/compare/v1.23.0...v1.24.0
2024-10-16 20:53:44 +02:00
Picnic-DevPla-Bot
4f2c143b9c Upgrade maven-gpg-plugin 3.2.6 -> 3.2.7 (#1344)
See:
- https://github.com/apache/maven-gpg-plugin/releases/tag/maven-gpg-plugin-3.2.7
- https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.6...maven-gpg-plugin-3.2.7
2024-10-16 19:07:41 +02:00
Picnic-DevPla-Bot
f4740e0e64 Upgrade JUnit 5 5.11.1 -> 5.11.2 (#1351)
See:
- https://junit.org/junit5/docs/current/release-notes/
- https://github.com/junit-team/junit5/releases/tag/r5.11.2
- https://github.com/junit-team/junit5/compare/r5.11.1...r5.11.2
2024-10-15 09:07:40 +02:00
Picnic-DevPla-Bot
3a155169ef Upgrade MongoDB driver 5.1.4 -> 5.2.0 (#1341)
See:
- https://jira.mongodb.org/issues/?jql=project%20%3D%20JAVA%20AND%20fixVersion%20%3E%205.1.4%20AND%20fixVersion%20%3C%3D%205.2.0
- https://github.com/mongodb/mongo-java-driver/releases/tag/r5.2.0
- https://github.com/mongodb/mongo-java-driver/compare/r5.1.4...r5.2.0
2024-10-14 14:22:27 +02:00
Picnic-DevPla-Bot
13847f6d2c Upgrade Jackson 2.17.2 -> 2.18.0 (#1343)
See:
- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.18
- https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.17.2...jackson-bom-2.18.0
2024-10-14 13:26:24 +02:00
Picnic-DevPla-Bot
6a81b92e11 Upgrade Surefire 3.5.0 -> 3.5.1 (#1354)
See:
- https://github.com/apache/maven-surefire/releases/tag/surefire-3.5.1
- https://github.com/apache/maven-surefire/compare/surefire-3.5.0...surefire-3.5.1
2024-10-14 12:06:14 +02:00
Stephan Schroevers
5794b404f2 Update Error Prone compatibility matrix (#1358) 2024-10-14 09:53:24 +02:00
Picnic-DevPla-Bot
b2d7ed4dc7 Upgrade Forbidden APIs plugin 3.7 -> 3.8 (#1355)
See:
- https://github.com/policeman-tools/forbidden-apis/wiki/Changes
- https://github.com/policeman-tools/forbidden-apis/compare/3.7...3.8
2024-10-14 07:03:03 +02:00
Picnic-DevPla-Bot
0fdc102aa5 Upgrade Swagger 2.2.23 -> 2.2.25 (#1337)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.24
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.25
- https://github.com/swagger-api/swagger-core/compare/v2.2.23...v2.2.25
2024-10-13 20:52:45 +02:00
Picnic-DevPla-Bot
ce3cf6a2d0 Upgrade maven-javadoc-plugin 3.10.0 -> 3.10.1 (#1349)
See:
- https://github.com/apache/maven-javadoc-plugin/releases/tag/maven-javadoc-plugin-3.10.1
- https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.0...maven-javadoc-plugin-3.10.1
2024-10-13 18:22:35 +02:00
Picnic-DevPla-Bot
0f657f8835 Upgrade OpenRewrite 2.19.0 -> 2.21.0 (#1338)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.20.0
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.21.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.19.0...v2.21.0
2024-10-13 16:52:43 +02:00
Picnic-DevPla-Bot
5f56f43c40 Upgrade OpenRewrite Templating 1.15.0 -> 1.16.1 (#1339)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.16.0
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.16.1
- https://github.com/openrewrite/rewrite-templating/compare/v1.15.0...v1.16.1
2024-10-13 16:03:59 +02:00
Picnic-DevPla-Bot
ef6faf518a Upgrade Checker Framework Annotations 3.47.0 -> 3.48.1 (#1350)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.48.0
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.48.1
- https://github.com/typetools/checker-framework/compare/checker-framework-3.47.0...checker-framework-3.48.1
2024-10-13 15:55:12 +02:00
Picnic-DevPla-Bot
aa08d954a0 Upgrade Byte Buddy 1.15.1 -> 1.15.4 (#1340)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.2
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.3
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.4
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.15.1...byte-buddy-1.15.4
2024-10-13 15:43:21 +02:00
Picnic-DevPla-Bot
e4d1818ed0 Upgrade Error Prone 2.32.0 -> 2.33.0 (#1348)
See:
- https://github.com/google/error-prone/releases/tag/v2.33.0
- https://github.com/google/error-prone/compare/v2.32.0...v2.33.0
- https://github.com/PicnicSupermarket/error-prone/compare/v2.32.0-picnic-1...v2.33.0-picnic-2
2024-10-13 15:27:01 +02:00
Mohamed Sameh
beb96f0f4b Introduce CollectionIterator Refaster rule (#1347)
This rule supersedes the more specific `ImmutableCollectionIterator` rule.
2024-10-01 10:05:33 +02:00
Picnic-DevPla-Bot
4d1eeb2be1 Upgrade Checkstyle 10.18.1 -> 10.18.2 (#1346)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.18.2
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.18.1...checkstyle-10.18.2
2024-09-30 14:04:53 +02:00
Stephan Schroevers
9cbc6f875c Have LexicographicalAnnotationAttributeListing also sort booleans and chars (#1334) 2024-09-30 06:38:44 +02:00
Picnic-DevPla-Bot
5583630fb4 Upgrade JUnit 5 5.11.0 -> 5.11.1 (#1342)
See:
- https://junit.org/junit5/docs/current/release-notes/
- https://github.com/junit-team/junit5/releases/tag/r5.11.1
- https://github.com/junit-team/junit5/compare/r5.11.0...r5.11.1
2024-09-27 14:17:50 +02:00
Picnic-DevPla-Bot
91e841ce12 Upgrade maven-gpg-plugin 3.2.5 -> 3.2.6 (#1331)
See:
- https://github.com/apache/maven-gpg-plugin/releases/tag/maven-gpg-plugin-3.2.6
- https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.5...maven-gpg-plugin-3.2.6
2024-09-24 11:40:34 +02:00
Picnic-DevPla-Bot
3956a82cd5 Upgrade extra-enforcer-rules 1.8.0 -> 1.9.0 (#1335)
See:
- https://github.com/mojohaus/extra-enforcer-rules/releases/tag/1.9.0
- https://github.com/mojohaus/extra-enforcer-rules/compare/1.8.0...1.9.0
2024-09-23 10:26:57 +02:00
Picnic-DevPla-Bot
c57debdc25 Upgrade maven-site-plugin 3.12.1 -> 3.20.0 (#1296)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MSITE%20AND%20fixVersion%20%3E%203.12.1%20AND%20fixVersion%20%3C%3D%203.20.0
- https://github.com/apache/maven-site-plugin/releases/tag/maven-site-plugin-3.20.0
- https://github.com/apache/maven-site-plugin/compare/maven-site-plugin-3.12.1...maven-site-plugin-3.20.0
2024-09-23 09:46:35 +02:00
Picnic-DevPla-Bot
6a13efded8 Upgrade Spring Boot 3.3.3 -> 3.3.4 (#1333)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.4
- https://github.com/spring-projects/spring-boot/compare/v3.3.3...v3.3.4
2024-09-20 22:27:00 +02:00
Picnic-DevPla-Bot
432cf4560d Upgrade pitest-maven-plugin 1.16.1 -> 1.17.0 (#1313)
See:
- https://github.com/hcoles/pitest/releases/tag/1.16.2
- https://github.com/hcoles/pitest/releases/tag/1.16.3
- https://github.com/hcoles/pitest/releases/tag/1.17.0
- https://github.com/hcoles/pitest/compare/1.16.1...1.17.0
2024-09-19 13:03:04 +02:00
Picnic-DevPla-Bot
966fb36ac9 Upgrade Spring 6.1.12 -> 6.1.13 (#1328)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.13
- https://github.com/spring-projects/spring-framework/compare/v6.1.12...v6.1.13
2024-09-17 11:55:54 +02:00
Picnic-DevPla-Bot
c63d9350d2 Upgrade OpenRewrite Templating 1.14.1 -> 1.15.0 (#1327)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.15.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.14.1...v1.15.0
2024-09-17 11:37:37 +02:00
Picnic-DevPla-Bot
e74874b04c Upgrade OpenRewrite 2.18.0 -> 2.19.0 (#1326)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.19.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.18.0...v2.19.0
2024-09-17 11:17:35 +02:00
Picnic-DevPla-Bot
f821d3775b Upgrade NullAway 0.11.2 -> 0.11.3 (#1332)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.11.3
- https://github.com/uber/NullAway/compare/v0.11.2...v0.11.3
2024-09-17 10:48:58 +02:00
Stephan Schroevers
3d5ee10d93 Introduce Refaster rules for Sonar's java:S4635 rule (#1320)
As well as two related expressions that can be optimized.

See:
- https://sonarcloud.io/organizations/picnic-technologies/rules?open=java%3AS4635&rule_key=java%3AS4635
- 2615792731/java-checks/src/main/java/org/sonar/java/checks/StringOffsetMethodsCheck.java
2024-09-16 09:15:12 +02:00
Stephan Schroevers
26da67d1f5 Use rewrite-java-17 rather than rewrite-java-11 (#1330) 2024-09-16 08:02:56 +02:00
Stephan Schroevers
b3ca01a6c7 Introduce RefasterRuleTestExtractor for documentation generation (#1317)
This new `Extractor` implementation collects Refaster example input and 
output code from rule collection tests.

This change also introduces explicit compilation steps for the test
code. As a side-effect this produces faster feedback in case of invalid
input or output code.
2024-09-14 12:02:37 +02:00
Picnic-DevPla-Bot
9f222e9efe Upgrade Error Prone 2.31.0 -> 2.32.0 (#1325)
See:
- https://github.com/google/error-prone/releases/tag/v2.32.0
- https://github.com/google/error-prone/compare/v2.31.0...v2.32.0
- https://github.com/PicnicSupermarket/error-prone/compare/v2.31.0-picnic-1...v2.32.0-picnic-1
2024-09-13 09:44:18 +02:00
Picnic-DevPla-Bot
097af51a3e Upgrade Project Reactor 2023.0.9 -> 2023.0.10 (#1323)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.10
- https://github.com/reactor/reactor/compare/2023.0.9...2023.0.10
2024-09-11 15:00:08 +02:00
Picnic-DevPla-Bot
c62e6c1127 Upgrade errorprone-slf4j 0.1.25 -> 0.1.28 (#1324)
See:
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.28
- https://github.com/KengoTODA/errorprone-slf4j/compare/v0.1.25...v0.1.28
2024-09-11 12:55:23 +02:00
Picnic-DevPla-Bot
5960423c4e Upgrade maven-dependency-plugin 3.7.1 -> 3.8.0 (#1304)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MDEP%20AND%20fixVersion%20%3E%203.7.1%20AND%20fixVersion%20%3C%3D%203.8.0
- https://github.com/apache/maven-dependency-plugin/releases/tag/maven-dependency-plugin-3.8.0
- https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.7.1...maven-dependency-plugin-3.8.0
2024-09-11 09:42:34 +02:00
Picnic-DevPla-Bot
188715c3c0 Upgrade Checkstyle 10.18.0 -> 10.18.1 (#1318)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.18.1
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.18.0...checkstyle-10.18.1
2024-09-11 09:25:26 +02:00
Picnic-DevPla-Bot
fb45bb00ed Upgrade maven-javadoc-plugin 3.8.0 -> 3.10.0 (#1310)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MJAVADOC%20AND%20fixVersion%20%3E%203.8.0%20AND%20fixVersion%20%3C%3D%203.10.0
- https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.8.0...maven-javadoc-plugin-3.10.0
2024-09-10 19:55:17 +02:00
Picnic-DevPla-Bot
fd5fc913ce Upgrade maven-install-plugin 3.1.2 -> 3.1.3 (#1301)
See:
- https://github.com/apache/maven-install-plugin/releases/tag/maven-install-plugin-3.1.3
- https://github.com/apache/maven-install-plugin/compare/maven-install-plugin-3.1.2...maven-install-plugin-3.1.3
2024-09-10 19:44:45 +02:00
Picnic-DevPla-Bot
ae20c6069d Upgrade OpenRewrite 2.17.0 -> 2.18.0 (#1315)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.18.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.17.0...v2.18.0
2024-09-10 19:14:25 +02:00
Picnic-DevPla-Bot
8457bd5026 Upgrade MongoDB driver 5.1.3 -> 5.1.4 (#1321)
See:
- https://jira.mongodb.org/issues/?jql=project%20%3D%20JAVA%20AND%20fixVersion%20%3E%204.11.3%20AND%20fixVersion%20%3C%3D%204.11.4
- https://github.com/mongodb/mongo-java-driver/releases/tag/r5.1.4
- https://github.com/mongodb/mongo-java-driver/compare/r5.1.3...r5.1.4
2024-09-10 18:07:43 +02:00
Picnic-DevPla-Bot
fcfb97b0e0 Upgrade maven-deploy-plugin 3.1.2 -> 3.1.3 (#1300)
See:
- https://github.com/apache/maven-deploy-plugin/releases/tag/maven-deploy-plugin-3.1.3
- https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-3.1.2...maven-deploy-plugin-3.1.3
2024-09-10 17:57:22 +02:00
Picnic-DevPla-Bot
15680b4cb3 Upgrade Surefire 3.3.1 -> 3.5.0 (#1298)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20SUREFIRE%20AND%20fixVersion%20%3E%203.3.1%20AND%20fixVersion%20%3C%3D%203.5.0
- https://github.com/apache/maven-surefire/releases/tag/surefire-3.4.0
- https://github.com/apache/maven-surefire/releases/tag/surefire-3.5.0
- https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.5.0
2024-09-10 17:05:51 +02:00
Picnic-DevPla-Bot
afebfbf478 Upgrade pomchecker-maven-plugin 1.11.0 -> 1.13.0 (#1319)
See:
- https://github.com/kordamp/pomchecker/releases/tag/v1.12.0
- https://github.com/kordamp/pomchecker/releases/tag/v1.13.0
- https://github.com/kordamp/pomchecker/compare/v1.11.0...v1.13.0
2024-09-10 13:32:08 +02:00
Picnic-DevPla-Bot
fe2ac938f3 Upgrade Checker Framework Annotations 3.46.0 -> 3.47.0 (#1322)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.47.0
- https://github.com/typetools/checker-framework/compare/checker-framework-3.46.0...checker-framework-3.47.0
2024-09-10 10:55:36 +02:00
Picnic-DevPla-Bot
078d8c16fa Upgrade OpenRewrite Templating 1.14.0 -> 1.14.1 (#1311)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.14.1
- https://github.com/openrewrite/rewrite-templating/compare/v1.14.0...v1.14.1
2024-09-04 15:01:36 +02:00
Stephan Schroevers
c679a3fc0c Improve Optional#orElse{,Get} support (#1283)
Summary of changes:
- Consolidate the `OptionalOrElseGet` Refaster rule and the 
  `OptionalOrElse` bug checker into the latter, keeping the best of
  both.
- Rename the `OptionalOrElse` bug checker to `OptionalOrElseGet` to
  avoid confusion.
- Replace the `IsLikelyTrivialComputation` matcher with the inverse
  `RequiresComputation` variant.
- Introduce an `OptionalOrElse` Refaster rule that simplifies
  expressions in the "opposite direction".
2024-09-03 16:00:33 +02:00
Stephan Schroevers
de54b4bf64 Introduce assorted unsigned int/long Refaster rules (#1291) 2024-09-03 15:35:15 +02:00
Picnic-DevPla-Bot
ea60241782 Upgrade Maven 3.9.8 -> 3.9.9 (#1295)
See:
- https://maven.apache.org/release-notes-all.html
- https://github.com/apache/maven/compare/maven-3.9.8...maven-3.9.9
2024-09-03 15:26:41 +02:00
Picnic-Bot
e4f928addb Upgrade fmt-maven-plugin 2.22.1 -> 2.24 (#1069)
See:
- https://github.com/spotify/fmt-maven-plugin/releases/tag/2.23
- https://github.com/spotify/fmt-maven-plugin/releases/tag/2.24
- https://github.com/spotify/fmt-maven-plugin/compare/2.22.1...2.24
2024-09-03 13:13:18 +02:00
Picnic-DevPla-Bot
059cc9e2db Upgrade Error Prone 2.30.0 -> 2.31.0 (#1314)
See:
- https://github.com/google/error-prone/releases/tag/v2.31.0
- https://github.com/google/error-prone/compare/v2.30.0...v2.31.0
2024-09-03 12:19:04 +02:00
Picnic-DevPla-Bot
1e43c28c95 Upgrade Byte Buddy 1.15.0 -> 1.15.1 (#1316)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.1
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.15.0...byte-buddy-1.15.1
2024-09-02 21:10:41 +02:00
Picnic-DevPla-Bot
a07e9b3115 Upgrade Swagger 2.2.22 -> 2.2.23 (#1312)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.23
- https://github.com/swagger-api/swagger-core/compare/v2.2.22...v2.2.23
2024-08-29 09:23:09 +02:00
Picnic-DevPla-Bot
aec38d2e33 Upgrade Mockito 5.12.0 -> 5.13.0 (#1309)
See:
- https://github.com/mockito/mockito/releases/tag/v5.13.0
- https://github.com/mockito/mockito/compare/v5.12.0...v5.13.0
2024-08-28 09:32:16 +02:00
Picnic-DevPla-Bot
5b77663288 Upgrade Spring 6.1.11 -> 6.1.12 (#1288)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.12
- https://github.com/spring-projects/spring-framework/compare/v6.1.11...v6.1.12
2024-08-27 15:48:14 +02:00
Stephan Schroevers
97c2bbd4b1 Introduce MonoFromFutureAsyncLoadingCacheGet Refaster rule (#1290) 2024-08-26 16:33:57 +02:00
Picnic-DevPla-Bot
9c8fbfd36a Upgrade OpenRewrite Templating 1.13.0 -> 1.14.0 (#1294)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.14.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.13.0...v1.14.0
2024-08-26 13:42:53 +02:00
Picnic-DevPla-Bot
38e6c3fdb5 Upgrade OpenRewrite 2.16.0 -> 2.17.0 (#1286)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.17.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.16.0...v2.17.0
2024-08-26 13:24:42 +02:00
Picnic-DevPla-Bot
5b1d82cfeb Upgrade Guava 33.2.1-jre -> 33.3.0-jre (#1293)
And drop some Refaster rules now covered by `@InlineMe` instructions.

See:
- https://guava.dev/releases/33.3.0-jre/api/diffs/
- https://github.com/google/guava/releases/tag/v33.3.0
- https://github.com/google/guava/compare/v33.2.0...v33.3.0
2024-08-26 13:02:15 +02:00
Picnic-DevPla-Bot
0821a95fcc Upgrade Spring Security 6.3.1 -> 6.3.3 (#1303)
See:
- https://github.com/spring-projects/spring-security/releases/tag/6.3.2
- https://github.com/spring-projects/spring-security/releases/tag/6.3.3
- https://github.com/spring-projects/spring-security/compare/6.3.1...6.3.3
2024-08-26 12:50:25 +02:00
Picnic-DevPla-Bot
f4afe457cb Upgrade Checkstyle 10.17.0 -> 10.18.0 (#1308)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.18.0
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.17.0...checkstyle-10.18.0
2024-08-26 09:19:52 +02:00
Picnic-DevPla-Bot
fd56ca8b6e Upgrade Spring Boot 3.3.2 -> 3.3.3 (#1305)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.3
- https://github.com/spring-projects/spring-boot/compare/v3.3.2...v3.3.3
2024-08-26 09:04:43 +02:00
Picnic-DevPla-Bot
882794d63b Upgrade maven-checkstyle-plugin 3.4.0 -> 3.5.0 (#1307)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MCHECKSTYLE%20AND%20fixVersion%20%3E%203.4.0%20AND%20fixVersion%20%3C%3D%203.5.0
- https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.4.0...maven-checkstyle-plugin-3.5.0
2024-08-26 08:22:34 +02:00
Mohamed Sameh
73ed6e32c7 Introduce Collections{Max,Min,Sort} Refaster rules (#1297)
While there, rename `{Max,Min}OfCollection` to
`Collections{Max,Min}WithComparator`.
2024-08-26 07:38:26 +02:00
Picnic-DevPla-Bot
ca5c3dd3b4 Upgrade Byte Buddy 1.14.19 -> 1.15.0 (#1306)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.15.0
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.19...byte-buddy-1.15.0
2024-08-26 07:28:00 +02:00
Picnic-DevPla-Bot
f6e9dbb996 Upgrade Byte Buddy 1.14.18 -> 1.14.19 (#1292)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.19
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.18...byte-buddy-1.14.19
2024-08-23 19:39:59 +02:00
Picnic-DevPla-Bot
260021c961 Upgrade NullAway 0.11.1 -> 0.11.2 (#1299)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.11.2
- https://github.com/uber/NullAway/compare/v0.11.1...v0.11.2
2024-08-23 19:31:03 +02:00
Stephan Schroevers
ec54e79f3e Introduce {Max,Min}Of{Array,Collection} Refaster rules (#1276)
While there, generalize the `{Max,Min}OfVarargs` rules.
2024-08-23 08:47:35 +02:00
Stephan Schroevers
4cbfdba521 Introduce additional File and Path Refaster rules (#1282) 2024-08-22 09:58:09 +02:00
Picnic-DevPla-Bot
d94f65a1f0 Upgrade JUnit 5 5.10.3 -> 5.11.0 (#1289)
See:
- https://junit.org/junit5/docs/current/release-notes/
- https://github.com/junit-team/junit5/releases/tag/r5.11.0-M1
- https://github.com/junit-team/junit5/releases/tag/r5.11.0-M2
- https://github.com/junit-team/junit5/releases/tag/r5.11.0-RC1
- https://github.com/junit-team/junit5/releases/tag/r5.11.0
- https://github.com/junit-team/junit5/compare/r5.10.3...r5.11.0
2024-08-15 09:21:45 +02:00
Picnic-DevPla-Bot
9afdf2ddf3 Upgrade OpenRewrite Templating 1.12.3 -> 1.13.0 (#1287)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.13.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.12.3...v1.13.0
2024-08-14 11:35:36 +02:00
Picnic-DevPla-Bot
060c901479 Upgrade maven-gpg-plugin 3.2.4 -> 3.2.5 (#1284)
See:
- https://github.com/apache/maven-gpg-plugin/releases/tag/maven-gpg-plugin-3.2.5
- https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.4...maven-gpg-plugin-3.2.5
2024-08-14 08:56:02 +02:00
Picnic-DevPla-Bot
1feee4f64a Upgrade Project Reactor 2023.0.8 -> 2023.0.9 (#1285)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.9
- https://github.com/reactor/reactor/compare/2023.0.8...2023.0.9
2024-08-14 08:26:16 +02:00
Picnic-Bot
552ddf6a7d Upgrade Maven API 3.9.5 -> 3.9.8 (#701)
See:
- https://maven.apache.org/release-notes-all.html
- https://github.com/apache/maven/releases/tag/maven-3.9.6
- https://github.com/apache/maven/releases/tag/maven-3.9.7
- https://github.com/apache/maven/releases/tag/maven-3.9.8
- https://github.com/apache/maven/compare/maven-3.9.5...maven-3.9.8
2024-08-12 16:14:46 +02:00
Stephan Schroevers
5d92c6c6ce Update Error Prone compatibility matrix (#1281) 2024-08-12 08:28:56 +02:00
Stephan Schroevers
fa8ca80040 [maven-release-plugin] prepare for next development iteration 2024-08-11 15:05:54 +02:00
Stephan Schroevers
b733179cd0 [maven-release-plugin] prepare release v0.18.0 2024-08-11 15:05:54 +02:00
Mohamed Sameh
3d9aab7c5b Introduce Class{Literal,Reference}Cast Refaster rules (#1269) 2024-08-11 15:01:53 +02:00
Picnic-DevPla-Bot
366cdda3d8 Upgrade Error Prone 2.29.2 -> 2.30.0 (#1280)
See:
- https://github.com/google/error-prone/releases/tag/v2.30.0
- https://github.com/google/error-prone/compare/v2.29.2...v2.30.0
- https://github.com/PicnicSupermarket/error-prone/compare/v2.29.2-picnic-1...v2.30.0-picnic-1
2024-08-11 12:48:15 +02:00
Picnic-DevPla-Bot
5b6dd147ef Upgrade MongoDB driver 5.1.2 -> 5.1.3 (#1274)
See:
- https://jira.mongodb.org/issues/?jql=project%20%3D%20JAVA%20AND%20fixVersion%20%3E%204.11.2%20AND%20fixVersion%20%3C%3D%204.11.3
- https://github.com/mongodb/mongo-java-driver/releases/tag/r4.11.3
- https://github.com/mongodb/mongo-java-driver/compare/r4.11.2...r4.11.3
2024-08-11 12:23:58 +02:00
Picnic-DevPla-Bot
a868b03130 Upgrade SLF4J 2.0.15 -> 2.0.16 (#1279)
See:
- https://www.slf4j.org/news.html
- https://github.com/qos-ch/slf4j/compare/v_2.0.15...v_2.0.16
2024-08-11 12:11:31 +02:00
Stephan Schroevers
fdf9bb5d25 Make the build JDK 22-compatible (#1277)
And verify the build with JDK 22.0.2.
2024-08-10 23:13:23 +02:00
Mohamed Sameh
363b0c22c7 Introduce ArraysAsList Refaster rule (#1275) 2024-08-10 16:49:44 +02:00
Picnic-DevPla-Bot
32ec35a354 Upgrade SLF4J 2.0.13 -> 2.0.15 (#1272)
See:
- https://www.slf4j.org/news.html
- https://github.com/qos-ch/slf4j/compare/v_2.0.13...v_2.0.15
2024-08-09 14:37:40 +02:00
Picnic-DevPla-Bot
635fe280f8 Upgrade OpenRewrite Templating 1.12.1 -> 1.12.3 (#1273)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.12.2
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.12.3
- https://github.com/openrewrite/rewrite-templating/compare/v1.12.1...v1.12.3
2024-08-09 09:49:34 +02:00
Stephan Schroevers
aac9b6bf10 Package OpenRewrite recipes in separate JAR, targeting Java 8 (#1270)
This is a prerequisite for openrewrite/rewrite-third-party#11. The new JAR has
classifier `recipes`.
2024-08-07 23:21:35 +02:00
Rick Ossendrijver
c322ea1bbc Introduce generic run-integration-test.sh script (#1141)
This new script contains reusable logic extracted from
`integration-tests/checkstyle.sh`, facilitating the introduction of additional
integration tests.
2024-08-07 23:12:55 +02:00
Stephan Schroevers
a433a90673 Introduce FilesCreateTempFileToFile Refaster rule (#1162) 2024-08-07 15:41:45 +02:00
Picnic-DevPla-Bot
5a37d65632 Upgrade Checker Framework Annotations 3.45.0 -> 3.46.0 (#1268)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.46.0
- https://github.com/typetools/checker-framework/compare/checker-framework-3.45.0...checker-framework-3.46.0
2024-08-07 11:46:32 +02:00
Rick Ossendrijver
77d183f8fd Introduce FluxFromStreamSupplier Refaster rule (#1261) 2024-08-07 10:44:41 +02:00
Picnic-DevPla-Bot
2eb4e853c5 Upgrade OpenRewrite Templating 1.12.0 -> 1.12.1 (#1265)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.12.1
- https://github.com/openrewrite/rewrite-templating/compare/v1.12.0...v1.12.1
2024-08-06 16:34:53 +02:00
Picnic-DevPla-Bot
45a7242cf5 Upgrade OpenRewrite 2.15.0 -> 2.16.0 (#1266)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.16.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.15.0...v2.16.0
2024-08-06 16:17:43 +02:00
Picnic-DevPla-Bot
c85070ba23 Upgrade org.hamcrest:hamcrest-core 2.2 -> 3.0 (#1267)
See:
- https://github.com/hamcrest/JavaHamcrest/releases/tag/v3.0-rc1
- https://github.com/hamcrest/JavaHamcrest/releases/tag/v3.0
- https://github.com/hamcrest/JavaHamcrest/compare/v2.2...v3.0
2024-08-06 14:34:47 +02:00
Mohamed Sameh
a687f09bf0 Introduce SetStream Refaster rule (#1264) 2024-08-06 14:05:53 +02:00
Picnic-DevPla-Bot
2e4fdcb0db Upgrade maven-javadoc-plugin 3.7.0 -> 3.8.0 (#1259)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MJAVADOC%20AND%20fixVersion%20%3E%203.7.0%20AND%20fixVersion%20%3C%3D%203.8.0
- https://github.com/apache/maven-javadoc-plugin/releases/tag/maven-javadoc-plugin-3.8.0
- https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.7.0...maven-javadoc-plugin-3.8.0
2024-08-06 08:53:06 +02:00
Stephan Schroevers
1005d93b7e Update step-security/harden-runner configuration (#1271)
While apparently the build doesn't fail without this, it is reasonable
for SonarCloud analysis to access the two additional domains.

While there, introduce subdomain wildcards for `sigstore.dev` and
`sonarcloud.io`.
2024-08-05 09:31:25 +02:00
Picnic-DevPla-Bot
136123f6b4 Upgrade NullAway 0.11.0 -> 0.11.1 (#1262)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.11.1
- https://github.com/uber/NullAway/compare/v0.11.0...v0.11.1
2024-08-05 09:03:14 +02:00
Picnic-DevPla-Bot
4cb5f0079d Upgrade Google Java Format 1.22.0 -> 1.23.0 (#1263)
See:
- https://github.com/google/google-java-format/releases/tag/v1.23.0
- https://github.com/google/google-java-format/compare/v1.22.0...v1.23.0
2024-08-05 08:15:16 +02:00
Stephan Schroevers
290ddf1972 [maven-release-plugin] prepare for next development iteration 2024-07-20 14:15:44 +02:00
Gijs de Jong
cc69b87b89 Try different refaster name patterns 2024-03-20 12:01:29 +01:00
Gijs de Jong
8b4cba4ac9 Fix metrics init patch 2024-03-20 10:47:07 +01:00
Rick Ossendrijver
ee0018114d Dont analyse generated files 2024-03-20 09:35:15 +01:00
Rick Ossendrijver
51ec7bcbd4 Try to run both variants 2024-03-20 09:35:15 +01:00
Rick Ossendrijver
1ff1d5705b Try to trigger metrics 2024-03-20 09:35:15 +01:00
Rick Ossendrijver
78cac86a28 Only run on GH comment 2024-03-20 09:35:15 +01:00
Gijs de Jong
b9836c6017 sync metrics 2024-03-20 09:35:15 +01:00
Rick Ossendrijver
75eb8d27e1 Typo 2024-03-20 09:35:15 +01:00
Rick Ossendrijver
041778308b Style improvements 2024-03-20 09:35:15 +01:00
Rick Ossendrijver
dddb602869 Rename metrics files to drop the version 2024-03-20 09:35:15 +01:00
Rick Ossendrijver
4dafc7e6ee Post-rebase fix 2024-03-20 09:35:15 +01:00
Gijs de Jong
79931df780 disable new checks as they cause errors 2024-03-20 09:35:15 +01:00
Gijs de Jong
4dcfb10dd9 temporarily remove condition 2024-03-20 09:35:15 +01:00
Gijs de Jong
97989c6294 trigger integration-test action 2024-03-20 09:35:15 +01:00
Gijs de Jong
5825498bec apply suggestions in init patch 2024-03-20 09:35:15 +01:00
Gijs de Jong
713853dfe1 suggestions 2024-03-20 09:35:15 +01:00
Gijs de Jong
3b2a0b4563 add matrix to integration test workflow 2024-03-20 09:35:15 +01:00
Gijs de Jong
b6bed8698a fix checkstyle integration test script 2024-03-20 09:35:15 +01:00
Gijs de Jong
2ebd53050c add additional_src_directories flag 2024-03-20 09:35:15 +01:00
Gijs de Jong
952451c877 clarify reason for check exclusion 2024-03-20 09:35:15 +01:00
Gijs de Jong
36f8b01add run metrics 2024-03-20 09:35:15 +01:00
Gijs de Jong
be6d3e555b Run metrics on java 17 2024-03-20 09:35:15 +01:00
Gijs de Jong
d7a3fbe9af Use integration-test.sh relative to test dir 2024-03-20 09:35:15 +01:00
Gijs de Jong
d18dd8af52 Use integration-test.sh in checkstyle 2024-03-20 09:35:15 +01:00
Gijs de Jong
11d02d468e Integration test script 2024-03-20 09:35:15 +01:00
Gijs de Jong
4ec0678147 Initial metrics integration test 2024-03-20 09:35:15 +01:00
106 changed files with 4492 additions and 773 deletions

View File

@@ -42,9 +42,9 @@ Please replace this sentence with log output, if applicable.
<!-- Please complete the following information: -->
- Operating system (e.g. MacOS Monterey).
- Java version (i.e. `java --version`, e.g. `17.0.10`).
- Error Prone version (e.g. `2.25.0`).
- Error Prone Support version (e.g. `0.15.0`).
- Java version (i.e. `java --version`, e.g. `17.0.13`).
- Error Prone version (e.g. `2.35.1`).
- Error Prone Support version (e.g. `0.19.0`).
### Additional context

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,24 +2,29 @@
# against the project, using the code found on the pull request branch.
# XXX: Generalize this to a matrix build of multiple integration tests,
# possibly using multiple JDK or OS versions.
# XXX: Investigate whether the comment can specify which integration tests run
# run. See this example of a dynamic build matrix:
# XXX: Investigate whether the comment can specify which integration tests run.
# See this example of a dynamic build matrix:
# https://docs.github.com/en/actions/learn-github-actions/expressions#example-returning-a-json-object
name: "Integration tests"
on:
pull_request:
branches: [ master ]
issue_comment:
types: [ created ]
permissions:
contents: read
jobs:
run-integration-tests:
runs-on: ubuntu-24.04
# if: github.event.issue.pull_request && contains(github.event.comment.body, '/integration-test')
# XXX: Configure permissions.
strategy:
matrix:
integration-test: [ "metrics", "checkstyle" ]
name: On-demand integration test
if: |
github.event.issue.pull_request && contains(github.event.comment.body, '/integration-test')
runs-on: ubuntu-22.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
@@ -33,21 +38,22 @@ jobs:
repo.maven.apache.org:443
repository.sonatype.org:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
uses: s4u/setup-maven-action@382542f77617f34e56bf83868920a4d45b7451e7 # v1.16.0
with:
# checkout-ref: "refs/pull/894/head"
checkout-ref: "refs/pull/${{ github.event.issue.number }}/head"
java-version: 17.0.10
java-version: 17.0.13
java-distribution: temurin
maven-version: 3.9.6
maven-version: 3.9.9
- name: Install project to local Maven repository
run: mvn -T1C install -DskipTests -Dverification.skip
- name: Run integration test
run: xvfb-run ./integration-tests/checkstyle.sh "${{ runner.temp }}/artifacts"
run: xvfb-run "./integration-tests/${{ matrix.integration-test }}.sh" "${{ runner.temp }}/artifacts"
- name: Upload artifacts on failure
if: ${{ failure() }}
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: integration-test-checkstyle
name: "integration-test-${{ matrix.integration-test }}"
path: "${{ runner.temp }}/artifacts"
- name: Remove installed project artifacts
run: mvn build-helper:remove-project-artifact
run: mvn dependency:purge-local-repository -DmanualInclude='${project.groupId}' -DresolutionFuzziness=groupId

View File

@@ -16,30 +16,31 @@ jobs:
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
permissions:
contents: read
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
analysis-sensorcache-eu-central-1-prod.s3.amazonaws.com:443
api.adoptium.net:443
api.sonarcloud.io:443
api.nuget.org:443
ea6ne4j2sb.execute-api.eu-central-1.amazonaws.com:443
github.com:443
objects.githubusercontent.com:443
repo.maven.apache.org:443
sc-cleancode-sensorcache-eu-central-1-prod.s3.amazonaws.com:443
scanner.sonarcloud.io:443
*.sonarcloud.io:443
sonarcloud.io:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
uses: s4u/setup-maven-action@382542f77617f34e56bf83868920a4d45b7451e7 # v1.16.0
with:
checkout-fetch-depth: 0
java-version: 17.0.10
java-version: 17.0.13
java-distribution: temurin
maven-version: 3.9.6
maven-version: 3.9.9
- name: Create missing `test` directory
# XXX: Drop this step in favour of actually having a test.
run: mkdir refaster-compiler/src/test

View File

@@ -302,7 +302,7 @@ channel; please see our [security policy][security] for details.
[refaster]: https://errorprone.info/docs/refaster
[refaster-rules-bigdecimal]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/BigDecimalRules.java
[refaster-rules]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/error-prone-contrib/src/main/java/tech/picnic/errorprone/refasterrules/
[reproducible-builds-badge]: https://img.shields.io/badge/Reproducible_Builds-ok-success?labelColor=1e5b96
[reproducible-builds-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/jvm-repo-rebuild/reproducible-central/master/content/tech/picnic/error-prone-support/error-prone-support/badge.json
[reproducible-builds-report]: https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/content/tech/picnic/error-prone-support/error-prone-support/README.md
[script-apply-error-prone-suggestions]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/apply-error-prone-suggestions.sh
[script-run-branch-mutation-tests]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/run-branch-mutation-tests.sh

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.17.0</version>
<version>0.19.2-SNAPSHOT</version>
</parent>
<artifactId>documentation-support</artifactId>
@@ -33,6 +33,15 @@
<artifactId>error_prone_test_helpers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>error-prone-utils</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>

View File

@@ -27,7 +27,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.TestCases;
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.BugPatternTestCases;
/**
* An {@link Extractor} that describes how to extract data from classes that test a {@code
@@ -40,7 +40,7 @@ import tech.picnic.errorprone.documentation.BugPatternTestExtractor.TestCases;
@Immutable
@AutoService(Extractor.class)
@SuppressWarnings("rawtypes" /* See https://github.com/google/auto/issues/870. */)
public final class BugPatternTestExtractor implements Extractor<TestCases> {
public final class BugPatternTestExtractor implements Extractor<BugPatternTestCases> {
/** Instantiates a new {@link BugPatternTestExtractor} instance. */
public BugPatternTestExtractor() {}
@@ -50,7 +50,7 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
}
@Override
public Optional<TestCases> tryExtract(ClassTree tree, VisitorState state) {
public Optional<BugPatternTestCases> tryExtract(ClassTree tree, VisitorState state) {
BugPatternTestCollector collector = new BugPatternTestCollector();
collector.scan(tree, state);
@@ -59,7 +59,7 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
.filter(not(ImmutableList::isEmpty))
.map(
tests ->
new AutoValue_BugPatternTestExtractor_TestCases(
new AutoValue_BugPatternTestExtractor_BugPatternTestCases(
state.getPath().getCompilationUnit().getSourceFile().toUri(),
ASTHelpers.getSymbol(tree).className(),
tests));
@@ -95,10 +95,10 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
.onDescendantOf("com.google.errorprone.BugCheckerRefactoringTestHelper.ExpectOutput")
.namedAnyOf("addOutputLines", "expectUnchanged");
private final List<TestCase> collectedTestCases = new ArrayList<>();
private final List<BugPatternTestCase> collectedBugPatternTestCases = new ArrayList<>();
private ImmutableList<TestCase> getCollectedTests() {
return ImmutableList.copyOf(collectedTestCases);
private ImmutableList<BugPatternTestCase> getCollectedTests() {
return ImmutableList.copyOf(collectedBugPatternTestCases);
}
@Override
@@ -110,14 +110,14 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
classUnderTest -> {
List<TestEntry> entries = new ArrayList<>();
if (isReplacementTest) {
extractReplacementTestCases(node, entries, state);
extractReplacementBugPatternTestCases(node, entries, state);
} else {
extractIdentificationTestCases(node, entries, state);
extractIdentificationBugPatternTestCases(node, entries, state);
}
if (!entries.isEmpty()) {
collectedTestCases.add(
new AutoValue_BugPatternTestExtractor_TestCase(
collectedBugPatternTestCases.add(
new AutoValue_BugPatternTestExtractor_BugPatternTestCase(
classUnderTest, ImmutableList.copyOf(entries).reverse()));
}
});
@@ -140,7 +140,7 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
: Optional.empty();
}
private static void extractIdentificationTestCases(
private static void extractIdentificationBugPatternTestCases(
MethodInvocationTree tree, List<TestEntry> sink, VisitorState state) {
if (IDENTIFICATION_SOURCE_LINES.matches(tree, state)) {
String path = ASTHelpers.constValue(tree.getArguments().get(0), String.class);
@@ -155,11 +155,11 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
if (receiver instanceof MethodInvocationTree methodInvocation) {
extractIdentificationTestCases(methodInvocation, sink, state);
extractIdentificationBugPatternTestCases(methodInvocation, sink, state);
}
}
private static void extractReplacementTestCases(
private static void extractReplacementBugPatternTestCases(
MethodInvocationTree tree, List<TestEntry> sink, VisitorState state) {
if (REPLACEMENT_OUTPUT_SOURCE_LINES.matches(tree, state)) {
/*
@@ -185,7 +185,7 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
if (receiver instanceof MethodInvocationTree methodInvocation) {
extractReplacementTestCases(methodInvocation, sink, state);
extractReplacementBugPatternTestCases(methodInvocation, sink, state);
}
}
@@ -208,24 +208,26 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
}
@AutoValue
@JsonDeserialize(as = AutoValue_BugPatternTestExtractor_TestCases.class)
abstract static class TestCases {
static TestCases create(URI source, String testClass, ImmutableList<TestCase> testCases) {
return new AutoValue_BugPatternTestExtractor_TestCases(source, testClass, testCases);
@JsonDeserialize(as = AutoValue_BugPatternTestExtractor_BugPatternTestCases.class)
abstract static class BugPatternTestCases {
static BugPatternTestCases create(
URI source, String testClass, ImmutableList<BugPatternTestCase> testCases) {
return new AutoValue_BugPatternTestExtractor_BugPatternTestCases(
source, testClass, testCases);
}
abstract URI source();
abstract String testClass();
abstract ImmutableList<TestCase> testCases();
abstract ImmutableList<BugPatternTestCase> testCases();
}
@AutoValue
@JsonDeserialize(as = AutoValue_BugPatternTestExtractor_TestCase.class)
abstract static class TestCase {
static TestCase create(String classUnderTest, ImmutableList<TestEntry> entries) {
return new AutoValue_BugPatternTestExtractor_TestCase(classUnderTest, entries);
@JsonDeserialize(as = AutoValue_BugPatternTestExtractor_BugPatternTestCase.class)
abstract static class BugPatternTestCase {
static BugPatternTestCase create(String classUnderTest, ImmutableList<TestEntry> entries) {
return new AutoValue_BugPatternTestExtractor_BugPatternTestCase(classUnderTest, entries);
}
abstract String classUnderTest();

View File

@@ -14,7 +14,6 @@ import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ServiceLoader;
import javax.tools.JavaFileObject;
@@ -87,6 +86,6 @@ final class DocumentationGeneratorTaskListener implements TaskListener {
}
private static String getSimpleClassName(URI path) {
return Paths.get(path).getFileName().toString().replace(".java", "");
return Path.of(path).getFileName().toString().replace(".java", "");
}
}

View File

@@ -0,0 +1,176 @@
package tech.picnic.errorprone.documentation;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
import static java.util.stream.Collectors.joining;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.auto.service.AutoService;
import com.google.auto.value.AutoValue;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.VisitorState;
import com.google.errorprone.annotations.FormatMethod;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.matchers.Matcher;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import java.net.URI;
import java.util.Optional;
import java.util.regex.Pattern;
import tech.picnic.errorprone.documentation.RefasterRuleCollectionTestExtractor.RefasterTestCases;
import tech.picnic.errorprone.utils.SourceCode;
/**
* An {@link Extractor} that describes how to extract data from Refaster rule input and output test
* classes.
*/
// XXX: Drop this extractor if/when the Refaster test framework is reimplemented such that tests can
// be located alongside rules, rather than in two additional resource files as currently required by
// `RefasterRuleCollection`.
@Immutable
@AutoService(Extractor.class)
@SuppressWarnings("rawtypes" /* See https://github.com/google/auto/issues/870. */)
public final class RefasterRuleCollectionTestExtractor implements Extractor<RefasterTestCases> {
private static final Matcher<ClassTree> IS_REFASTER_RULE_COLLECTION_TEST_CASE =
isSubtypeOf("tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase");
private static final Pattern TEST_CLASS_NAME_PATTERN = Pattern.compile("(.*)Test");
private static final Pattern TEST_CLASS_FILE_NAME_PATTERN =
Pattern.compile(".*(Input|Output)\\.java");
private static final Pattern TEST_METHOD_NAME_PATTERN = Pattern.compile("test(.*)");
private static final String LINE_SEPARATOR = "\n";
private static final Splitter LINE_SPLITTER = Splitter.on(LINE_SEPARATOR);
/** Instantiates a new {@link RefasterRuleCollectionTestExtractor} instance. */
public RefasterRuleCollectionTestExtractor() {}
@Override
public String identifier() {
return "refaster-rule-collection-test";
}
@Override
public Optional<RefasterTestCases> tryExtract(ClassTree tree, VisitorState state) {
if (!IS_REFASTER_RULE_COLLECTION_TEST_CASE.matches(tree, state)) {
return Optional.empty();
}
URI sourceFile = state.getPath().getCompilationUnit().getSourceFile().toUri();
return Optional.of(
RefasterTestCases.create(
sourceFile,
getRuleCollectionName(tree),
isInputFile(sourceFile),
getRefasterTestCases(tree, state)));
}
private static String getRuleCollectionName(ClassTree tree) {
String className = tree.getSimpleName().toString();
// XXX: Instead of throwing an error here, it'd be nicer to have a bug checker validate key
// aspects of `RefasterRuleCollectionTestCase` subtypes.
return tryExtractPatternGroup(className, TEST_CLASS_NAME_PATTERN)
.orElseThrow(
violation(
"Refaster rule collection test class name '%s' does not match '%s'",
className, TEST_CLASS_NAME_PATTERN));
}
private static boolean isInputFile(URI sourceFile) {
String path = sourceFile.getPath();
// XXX: Instead of throwing an error here, it'd be nicer to have a bug checker validate key
// aspects of `RefasterRuleCollectionTestCase` subtypes.
return "Input"
.equals(
tryExtractPatternGroup(path, TEST_CLASS_FILE_NAME_PATTERN)
.orElseThrow(
violation(
"Refaster rule collection test file name '%s' does not match '%s'",
path, TEST_CLASS_FILE_NAME_PATTERN)));
}
private static ImmutableList<RefasterTestCase> getRefasterTestCases(
ClassTree tree, VisitorState state) {
return tree.getMembers().stream()
.filter(MethodTree.class::isInstance)
.map(MethodTree.class::cast)
.flatMap(m -> tryExtractRefasterTestCase(m, state).stream())
.collect(toImmutableList());
}
private static Optional<RefasterTestCase> tryExtractRefasterTestCase(
MethodTree method, VisitorState state) {
return tryExtractPatternGroup(method.getName().toString(), TEST_METHOD_NAME_PATTERN)
.map(name -> RefasterTestCase.create(name, getFormattedSource(method, state)));
}
/**
* Returns the source code for the specified method.
*
* @implNote This operation attempts to trim leading whitespace, such that the start and end of
* the method declaration are aligned. The implemented heuristic assumes that the code is
* formatted using Google Java Format.
*/
// XXX: Leading Javadoc and other comments are currently not extracted. Consider fixing this.
private static String getFormattedSource(MethodTree method, VisitorState state) {
String source = SourceCode.treeToString(method, state);
int finalNewline = source.lastIndexOf(LINE_SEPARATOR);
if (finalNewline < 0) {
return source;
}
int indentation = Math.max(0, source.lastIndexOf(' ') - finalNewline);
String prefixToStrip = " ".repeat(indentation);
return LINE_SPLITTER
.splitToStream(source)
.map(line -> line.startsWith(prefixToStrip) ? line.substring(indentation) : line)
.collect(joining(LINE_SEPARATOR));
}
private static Optional<String> tryExtractPatternGroup(String input, Pattern pattern) {
java.util.regex.Matcher matcher = pattern.matcher(input);
return matcher.matches() ? Optional.of(matcher.group(1)) : Optional.empty();
}
@FormatMethod
private static Supplier<VerifyException> violation(String format, Object... args) {
return () -> new VerifyException(String.format(format, args));
}
@AutoValue
@JsonDeserialize(as = AutoValue_RefasterRuleCollectionTestExtractor_RefasterTestCases.class)
abstract static class RefasterTestCases {
static RefasterTestCases create(
URI source,
String ruleCollection,
boolean isInput,
ImmutableList<RefasterTestCase> testCases) {
return new AutoValue_RefasterRuleCollectionTestExtractor_RefasterTestCases(
source, ruleCollection, isInput, testCases);
}
abstract URI source();
abstract String ruleCollection();
abstract boolean isInput();
abstract ImmutableList<RefasterTestCase> testCases();
}
@AutoValue
@JsonDeserialize(as = AutoValue_RefasterRuleCollectionTestExtractor_RefasterTestCase.class)
abstract static class RefasterTestCase {
static RefasterTestCase create(String name, String content) {
return new AutoValue_RefasterRuleCollectionTestExtractor_RefasterTestCase(name, content);
}
abstract String name();
abstract String content();
}
}

View File

@@ -7,10 +7,10 @@ import java.net.URI;
import java.nio.file.Path;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.BugPatternTestCase;
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.BugPatternTestCases;
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.IdentificationTestEntry;
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.ReplacementTestEntry;
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.TestCase;
import tech.picnic.errorprone.documentation.BugPatternTestExtractor.TestCases;
final class BugPatternTestExtractorTest {
@Test
@@ -269,11 +269,11 @@ final class BugPatternTestExtractorTest {
verifyGeneratedFileContent(
outputDirectory,
"SingleFileCompilationTestHelperTest",
TestCases.create(
BugPatternTestCases.create(
URI.create("file:///SingleFileCompilationTestHelperTest.java"),
"SingleFileCompilationTestHelperTest",
ImmutableList.of(
TestCase.create(
BugPatternTestCase.create(
"SingleFileCompilationTestHelperTest.TestChecker",
ImmutableList.of(
IdentificationTestEntry.create(
@@ -302,11 +302,11 @@ final class BugPatternTestExtractorTest {
verifyGeneratedFileContent(
outputDirectory,
"SingleFileCompilationTestHelperWithSetArgsTest",
TestCases.create(
BugPatternTestCases.create(
URI.create("file:///SingleFileCompilationTestHelperWithSetArgsTest.java"),
"SingleFileCompilationTestHelperWithSetArgsTest",
ImmutableList.of(
TestCase.create(
BugPatternTestCase.create(
"SingleFileCompilationTestHelperWithSetArgsTest.TestChecker",
ImmutableList.of(
IdentificationTestEntry.create(
@@ -335,11 +335,11 @@ final class BugPatternTestExtractorTest {
verifyGeneratedFileContent(
outputDirectory,
"MultiFileCompilationTestHelperTest",
TestCases.create(
BugPatternTestCases.create(
URI.create("file:///MultiFileCompilationTestHelperTest.java"),
"MultiFileCompilationTestHelperTest",
ImmutableList.of(
TestCase.create(
BugPatternTestCase.create(
"MultiFileCompilationTestHelperTest.TestChecker",
ImmutableList.of(
IdentificationTestEntry.create(
@@ -370,11 +370,11 @@ final class BugPatternTestExtractorTest {
verifyGeneratedFileContent(
outputDirectory,
"SingleFileBugCheckerRefactoringTestHelperTest",
TestCases.create(
BugPatternTestCases.create(
URI.create("file:///SingleFileBugCheckerRefactoringTestHelperTest.java"),
"SingleFileBugCheckerRefactoringTestHelperTest",
ImmutableList.of(
TestCase.create(
BugPatternTestCase.create(
"SingleFileBugCheckerRefactoringTestHelperTest.TestChecker",
ImmutableList.of(
ReplacementTestEntry.create(
@@ -408,12 +408,12 @@ final class BugPatternTestExtractorTest {
verifyGeneratedFileContent(
outputDirectory,
"SingleFileBugCheckerRefactoringTestHelperWithSetArgsFixChooserAndCustomTestModeTest",
TestCases.create(
BugPatternTestCases.create(
URI.create(
"file:///SingleFileBugCheckerRefactoringTestHelperWithSetArgsFixChooserAndCustomTestModeTest.java"),
"SingleFileBugCheckerRefactoringTestHelperWithSetArgsFixChooserAndCustomTestModeTest",
ImmutableList.of(
TestCase.create(
BugPatternTestCase.create(
"SingleFileBugCheckerRefactoringTestHelperWithSetArgsFixChooserAndCustomTestModeTest.TestChecker",
ImmutableList.of(
ReplacementTestEntry.create(
@@ -444,11 +444,11 @@ final class BugPatternTestExtractorTest {
verifyGeneratedFileContent(
outputDirectory,
"MultiFileBugCheckerRefactoringTestHelperTest",
TestCases.create(
BugPatternTestCases.create(
URI.create("file:///MultiFileBugCheckerRefactoringTestHelperTest.java"),
"MultiFileBugCheckerRefactoringTestHelperTest",
ImmutableList.of(
TestCase.create(
BugPatternTestCase.create(
"MultiFileBugCheckerRefactoringTestHelperTest.TestChecker",
ImmutableList.of(
ReplacementTestEntry.create(
@@ -484,16 +484,16 @@ final class BugPatternTestExtractorTest {
verifyGeneratedFileContent(
outputDirectory,
"CompilationAndBugCheckerRefactoringTestHelpersTest",
TestCases.create(
BugPatternTestCases.create(
URI.create("file:///CompilationAndBugCheckerRefactoringTestHelpersTest.java"),
"CompilationAndBugCheckerRefactoringTestHelpersTest",
ImmutableList.of(
TestCase.create(
BugPatternTestCase.create(
"CompilationAndBugCheckerRefactoringTestHelpersTest.TestChecker",
ImmutableList.of(
IdentificationTestEntry.create(
"A.java", "// BUG: Diagnostic contains:\nclass A {}\n"))),
TestCase.create(
BugPatternTestCase.create(
"CompilationAndBugCheckerRefactoringTestHelpersTest.TestChecker",
ImmutableList.of(
ReplacementTestEntry.create(
@@ -532,17 +532,17 @@ final class BugPatternTestExtractorTest {
verifyGeneratedFileContent(
outputDirectory,
"CompilationAndBugCheckerRefactoringTestHelpersWithCustomCheckerPackageAndNamesTest",
TestCases.create(
BugPatternTestCases.create(
URI.create(
"file:///CompilationAndBugCheckerRefactoringTestHelpersWithCustomCheckerPackageAndNamesTest.java"),
"pkg.CompilationAndBugCheckerRefactoringTestHelpersWithCustomCheckerPackageAndNamesTest",
ImmutableList.of(
TestCase.create(
BugPatternTestCase.create(
"pkg.CompilationAndBugCheckerRefactoringTestHelpersWithCustomCheckerPackageAndNamesTest.CustomTestChecker",
ImmutableList.of(
IdentificationTestEntry.create(
"A.java", "// BUG: Diagnostic contains:\nclass A {}\n"))),
TestCase.create(
BugPatternTestCase.create(
"pkg.CompilationAndBugCheckerRefactoringTestHelpersWithCustomCheckerPackageAndNamesTest.CustomTestChecker2",
ImmutableList.of(
ReplacementTestEntry.create(
@@ -550,9 +550,9 @@ final class BugPatternTestExtractorTest {
}
private static void verifyGeneratedFileContent(
Path outputDirectory, String testClass, TestCases expected) {
Path outputDirectory, String testClass, BugPatternTestCases expected) {
assertThat(outputDirectory.resolve(String.format("bugpattern-test-%s.json", testClass)))
.exists()
.returns(expected, path -> Json.read(path, TestCases.class));
.returns(expected, path -> Json.read(path, BugPatternTestCases.class));
}
}

View File

@@ -10,7 +10,6 @@ import static org.junit.jupiter.api.condition.OS.WINDOWS;
import com.google.auto.service.AutoService;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.errorprone.VisitorState;
@@ -41,7 +40,8 @@ final class DocumentationGeneratorTaskListenerTest {
entry ->
AclEntry.newBuilder(entry)
.setPermissions(
Sets.difference(entry.permissions(), ImmutableSet.of(ADD_SUBDIRECTORY)))
Sets.difference(
entry.permissions(), Sets.immutableEnumSet(ADD_SUBDIRECTORY)))
.build())
.collect(toImmutableList()));

View File

@@ -0,0 +1,166 @@
package tech.picnic.errorprone.documentation;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import java.net.URI;
import java.nio.file.Path;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import tech.picnic.errorprone.documentation.RefasterRuleCollectionTestExtractor.RefasterTestCase;
import tech.picnic.errorprone.documentation.RefasterRuleCollectionTestExtractor.RefasterTestCases;
final class RefasterRuleCollectionTestExtractorTest {
@Test
void noRefasterRuleTest(@TempDir Path outputDirectory) {
Compilation.compileWithDocumentationGenerator(
outputDirectory, "NoRefasterRuleTest.java", "public final class NoRefasterRuleTest {}");
assertThat(outputDirectory.toAbsolutePath()).isEmptyDirectory();
}
@Test
void invalidTestClassName(@TempDir Path outputDirectory) {
assertThatThrownBy(
() ->
Compilation.compileWithDocumentationGenerator(
outputDirectory,
"InvalidTestClassNameInput.java",
"import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;",
"",
"final class InvalidTestClassName implements RefasterRuleCollectionTestCase {}"))
.cause()
.isInstanceOf(VerifyException.class)
.hasMessage(
"Refaster rule collection test class name 'InvalidTestClassName' does not match '(.*)Test'");
}
@Test
void invalidFileName(@TempDir Path outputDirectory) {
assertThatThrownBy(
() ->
Compilation.compileWithDocumentationGenerator(
outputDirectory,
"InvalidFileNameTest.java",
"import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;",
"",
"final class InvalidFileNameTest implements RefasterRuleCollectionTestCase {}"))
.cause()
.isInstanceOf(VerifyException.class)
.hasMessage(
"Refaster rule collection test file name '/InvalidFileNameTest.java' does not match '.*(Input|Output)\\.java'");
}
@Test
void emptyRefasterRuleCollectionTestInput(@TempDir Path outputDirectory) {
Compilation.compileWithDocumentationGenerator(
outputDirectory,
"EmptyRefasterRuleCollectionTestInput.java",
"import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;",
"",
"final class EmptyRefasterRuleCollectionTest implements RefasterRuleCollectionTestCase {}");
verifyGeneratedFileContent(
outputDirectory,
"EmptyRefasterRuleCollectionTestInput",
RefasterTestCases.create(
URI.create("file:///EmptyRefasterRuleCollectionTestInput.java"),
"EmptyRefasterRuleCollection",
/* isInput= */ true,
ImmutableList.of()));
}
@Test
void singletonRefasterRuleCollectionTestOutput(@TempDir Path outputDirectory) {
Compilation.compileWithDocumentationGenerator(
outputDirectory,
"SingletonRefasterRuleCollectionTestOutput.java",
"import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;",
"",
"final class SingletonRefasterRuleCollectionTest implements RefasterRuleCollectionTestCase {",
" int testMyRule() {",
" return 42;",
" }",
"}");
verifyGeneratedFileContent(
outputDirectory,
"SingletonRefasterRuleCollectionTestOutput",
RefasterTestCases.create(
URI.create("file:///SingletonRefasterRuleCollectionTestOutput.java"),
"SingletonRefasterRuleCollection",
/* isInput= */ false,
ImmutableList.of(
RefasterTestCase.create(
"MyRule",
"""
int testMyRule() {
return 42;
}"""))));
}
@Test
void complexRefasterRuleCollectionTestOutput(@TempDir Path outputDirectory) {
Compilation.compileWithDocumentationGenerator(
outputDirectory,
"pkg/ComplexRefasterRuleCollectionTestInput.java",
"package pkg;",
"",
"import com.google.common.collect.ImmutableSet;",
"import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;",
"",
"final class ComplexRefasterRuleCollectionTest implements RefasterRuleCollectionTestCase {",
" private static final String IGNORED_CONSTANT = \"constant\";",
"",
" @Override",
" public ImmutableSet<Object> elidedTypesAndStaticImports() {",
" return ImmutableSet.of();",
" }",
"",
" /** Javadoc. */",
" String testFirstRule() {",
" return \"Don't panic\";",
" }",
"",
" // Comment.",
" String testSecondRule() {",
" return \"Carry a towel\";",
" }",
"",
" void testEmptyRule() {}",
"}");
verifyGeneratedFileContent(
outputDirectory,
"ComplexRefasterRuleCollectionTestInput",
RefasterTestCases.create(
URI.create("file:///pkg/ComplexRefasterRuleCollectionTestInput.java"),
"ComplexRefasterRuleCollection",
/* isInput= */ true,
ImmutableList.of(
RefasterTestCase.create(
"FirstRule",
"""
String testFirstRule() {
return "Don't panic";
}"""),
RefasterTestCase.create(
"SecondRule",
"""
String testSecondRule() {
return "Carry a towel";
}"""),
RefasterTestCase.create("EmptyRule", "void testEmptyRule() {}"))));
}
private static void verifyGeneratedFileContent(
Path outputDirectory, String testIdentifier, RefasterTestCases expected) {
assertThat(
outputDirectory.resolve(
String.format("refaster-rule-collection-test-%s.json", testIdentifier)))
.exists()
.returns(expected, path -> Json.read(path, RefasterTestCases.class));
}
}

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.17.0</version>
<version>0.19.2-SNAPSHOT</version>
</parent>
<artifactId>error-prone-contrib</artifactId>
@@ -55,7 +55,12 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-support</artifactId>
<scope>provided</scope>
<!-- XXX: One would expect this to be a `provided` dependency (as
Refaster rules are interpreted by the `refaster-runner` module),
but the `OptionalOrElseGet` bug checker defined by this module
depends on the `RequiresComputation` matcher that
`refaster-support` primarily exposes for use by Refaster rules.
Review this setup. (Should the matchers be moved elsewhere?) -->
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
@@ -67,6 +72,11 @@
<artifactId>jackson-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service-annotations</artifactId>
@@ -82,6 +92,11 @@
<artifactId>guava</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
@@ -196,7 +211,7 @@
</dependency>
<dependency>
<groupId>org.openrewrite</groupId>
<artifactId>rewrite-java-11</artifactId>
<artifactId>rewrite-java-17</artifactId>
<scope>test</scope>
</dependency>
<dependency>
@@ -287,6 +302,55 @@
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
</compilerArgs>
</configuration>
<executions>
<!-- The Refaster input/output test classes used by
`RefasterRuleCollection` are modelled as classpath
resources, and thus not subject to the default test
compilation step. These two custom compilation steps
serve two purposes:
- To provide early feedback in case of syntax errors.
- To enable the `DocumentationGenerator` compiler
plugin to extract documentation metadata from them.
Note that the input and output files must be compiled
separately and to distinct output directories, as they
define the same set of class names. -->
<!-- XXX: Drop these executions if/when the Refaster
test framework is reimplemented such that tests can be
located alongside rules, rather than in two additional
resource files. -->
<execution>
<id>compile-refaster-test-input</id>
<goals>
<goal>testCompile</goal>
</goals>
<phase>process-test-resources</phase>
<configuration>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/test/resources</compileSourceRoot>
</compileSourceRoots>
<testIncludes>
<testInclude>**/*Input.java</testInclude>
</testIncludes>
<outputDirectory>${project.build.directory}/refaster-test-input</outputDirectory>
</configuration>
</execution>
<execution>
<id>compile-refaster-test-output</id>
<goals>
<goal>testCompile</goal>
</goals>
<phase>process-test-resources</phase>
<configuration>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/test/resources</compileSourceRoot>
</compileSourceRoots>
<testIncludes>
<testInclude>**/*Output.java</testInclude>
</testIncludes>
<outputDirectory>${project.build.directory}/refaster-test-output</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>

View File

@@ -0,0 +1,72 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
import com.google.common.collect.Iterables;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.LambdaExpressionTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Type;
import tech.picnic.errorprone.utils.SourceCode;
/**
* A {@link BugChecker} that flags lambda expressions that can be replaced with a method reference
* of the form {@code T.class::cast}.
*/
// XXX: Consider folding this logic into the `MethodReferenceUsage` check of the
// `error-prone-experimental` module.
// XXX: This check and its tests are structurally nearly identical to `IsInstanceLambdaUsage`.
// Unless folded into `MethodReferenceUsage`, consider merging the two.
@AutoService(BugChecker.class)
@BugPattern(
summary = "Prefer `Class::cast` method reference over equivalent lambda expression",
link = BUG_PATTERNS_BASE_URL + "ClassCastLambdaUsage",
linkType = CUSTOM,
severity = SUGGESTION,
tags = SIMPLIFICATION)
public final class ClassCastLambdaUsage extends BugChecker implements LambdaExpressionTreeMatcher {
private static final long serialVersionUID = 1L;
/** Instantiates a new {@link ClassCastLambdaUsage} instance. */
public ClassCastLambdaUsage() {}
@Override
public Description matchLambdaExpression(LambdaExpressionTree tree, VisitorState state) {
if (tree.getParameters().size() != 1 || !(tree.getBody() instanceof TypeCastTree typeCast)) {
return Description.NO_MATCH;
}
Type type = ASTHelpers.getType(typeCast);
if (type == null || type.isParameterized() || type.isPrimitive()) {
/*
* The method reference syntax does not support casting to parameterized types. Additionally,
* `Class#cast` does not support the same range of type conversions between (boxed) primitive
* types as the cast operator.
*/
// XXX: Depending on the declared type of the value being cast, in some cases we _can_ rewrite
// primitive casts. Add support for this.
return Description.NO_MATCH;
}
VariableTree param = Iterables.getOnlyElement(tree.getParameters());
if (!ASTHelpers.getSymbol(param).equals(ASTHelpers.getSymbol(typeCast.getExpression()))) {
return Description.NO_MATCH;
}
return describeMatch(
tree,
SuggestedFix.replace(
tree, SourceCode.treeToString(typeCast.getType(), state) + ".class::cast"));
}
}

View File

@@ -0,0 +1,125 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.BugPattern.StandardTags.STYLE;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.hasModifier;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.errorprone.BugPattern;
import com.google.errorprone.ErrorProneFlags;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreeScanner;
import java.util.Locale;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.lang.model.element.Modifier;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.utils.Flags;
/**
* A {@link BugChecker} that flags static constants that do not follow the upper snake case naming
* convention.
*/
@AutoService(BugChecker.class)
@BugPattern(
summary = "Constant variables should adhere to the `UPPER_SNAKE_CASE` naming convention",
link = BUG_PATTERNS_BASE_URL + "ConstantNaming",
linkType = CUSTOM,
severity = WARNING,
tags = STYLE)
@SuppressWarnings("java:S2160" /* Super class equality definition suffices. */)
public final class ConstantNaming extends BugChecker implements VariableTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Matcher<VariableTree> IS_CONSTANT =
allOf(hasModifier(Modifier.STATIC), hasModifier(Modifier.FINAL));
private static final Matcher<VariableTree> IS_PRIVATE = hasModifier(Modifier.PRIVATE);
private static final Pattern SNAKE_CASE = Pattern.compile("([a-z])([A-Z])");
private static final ImmutableSet<String> DEFAULT_EXEMPTED_NAMES =
ImmutableSet.of("serialVersionUID");
/**
* Flag using which constant names that must not be flagged (in addition to those defined by
* {@link #DEFAULT_EXEMPTED_NAMES}) can be specified.
*/
private static final String ADDITIONAL_EXEMPTED_NAMES_FLAG =
"CanonicalConstantNaming:ExemptedNames";
private final ImmutableSet<String> exemptedNames;
/** Instantiates a default {@link ConstantNaming} instance. */
public ConstantNaming() {
this(ErrorProneFlags.empty());
}
/**
* Instantiates a customized {@link ConstantNaming}.
*
* @param flags Any provided command line flags.
*/
@Inject
ConstantNaming(ErrorProneFlags flags) {
exemptedNames =
Sets.union(DEFAULT_EXEMPTED_NAMES, Flags.getSet(flags, ADDITIONAL_EXEMPTED_NAMES_FLAG))
.immutableCopy();
}
@Override
public Description matchVariable(VariableTree tree, VisitorState state) {
String variableName = tree.getName().toString();
if (!IS_CONSTANT.matches(tree, state) || exemptedNames.contains(variableName)) {
return Description.NO_MATCH;
}
String replacement = toUpperSnakeCase(variableName);
if (replacement.equals(variableName)) {
return Description.NO_MATCH;
}
Description.Builder description = buildDescription(tree);
if (!IS_PRIVATE.matches(tree, state)) {
description.setMessage(
"%s; consider renaming to '%s', though note that this is not a private constant"
.formatted(message(), replacement));
} else if (isVariableNameInUse(replacement, state)) {
description.setMessage(
"%s; consider renaming to '%s', though note that a variable with this name is already declared"
.formatted(message(), replacement));
} else {
description.addFix(SuggestedFixes.renameVariable(tree, replacement, state));
}
return description.build();
}
private static String toUpperSnakeCase(String variableName) {
return SNAKE_CASE.matcher(variableName).replaceAll("$1_$2").toUpperCase(Locale.ROOT);
}
private static boolean isVariableNameInUse(String name, VisitorState state) {
return Boolean.TRUE.equals(
new TreeScanner<Boolean, @Nullable Void>() {
@Override
public Boolean visitVariable(VariableTree tree, @Nullable Void unused) {
return ASTHelpers.getSymbol(tree).getSimpleName().contentEquals(name)
|| super.visitVariable(tree, null);
}
@Override
public Boolean reduce(Boolean r1, Boolean r2) {
return Boolean.TRUE.equals(r1) || Boolean.TRUE.equals(r2);
}
}.scan(state.getPath().getCompilationUnit(), null));
}
}

View File

@@ -62,7 +62,7 @@ public final class EmptyMethod extends BugChecker implements MethodTreeMatcher {
}
private static boolean isInPossibleTestHelperClass(VisitorState state) {
return Optional.ofNullable(ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class))
return Optional.ofNullable(state.findEnclosing(ClassTree.class))
.map(ClassTree::getSimpleName)
.filter(name -> name.toString().contains("Test"))
.isPresent();

View File

@@ -36,6 +36,7 @@ import java.util.Formatter;
import java.util.List;
import java.util.Optional;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.utils.MoreASTHelpers;
import tech.picnic.errorprone.utils.SourceCode;
/**
@@ -203,14 +204,10 @@ public final class FormatStringConcatenation extends BugChecker
ExpressionTree argument = ASTHelpers.stripParentheses(arguments.get(argPosition));
return argument instanceof BinaryTree
&& isStringTyped(argument, state)
&& MoreASTHelpers.isStringTyped(argument, state)
&& ASTHelpers.constValue(argument, String.class) == null;
}
private static boolean isStringTyped(ExpressionTree tree, VisitorState state) {
return ASTHelpers.isSameType(ASTHelpers.getType(tree), state.getSymtab().stringType, state);
}
private static class ReplacementArgumentsConstructor
extends SimpleTreeVisitor<@Nullable Void, VisitorState> {
private final StringBuilder formatString = new StringBuilder();
@@ -223,7 +220,7 @@ public final class FormatStringConcatenation extends BugChecker
@Override
public @Nullable Void visitBinary(BinaryTree tree, VisitorState state) {
if (tree.getKind() == Kind.PLUS && isStringTyped(tree, state)) {
if (tree.getKind() == Kind.PLUS && MoreASTHelpers.isStringTyped(tree, state)) {
tree.getLeftOperand().accept(this, state);
tree.getRightOperand().accept(this, state);
} else {

View File

@@ -39,6 +39,7 @@ import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Types;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import tech.picnic.errorprone.utils.SourceCode;
@@ -51,6 +52,7 @@ import tech.picnic.errorprone.utils.SourceCode;
// is effectively the identity operation.
// XXX: Also flag nullary instance method invocations that represent an identity conversion, such as
// `Boolean#booleanValue()`, `Byte#byteValue()` and friends.
// XXX: Also flag redundant round-trip conversions such as `path.toFile().toPath()`.
@AutoService(BugChecker.class)
@BugPattern(
summary = "Avoid or clarify identity conversions",
@@ -83,6 +85,7 @@ public final class IdentityConversion extends BugChecker implements MethodInvoca
ImmutableSetMultimap.class.getCanonicalName(),
ImmutableTable.class.getCanonicalName())
.named("copyOf"),
staticMethod().onClass(Instant.class.getCanonicalName()).namedAnyOf("from"),
staticMethod().onClass(Matchers.class.getCanonicalName()).namedAnyOf("allOf", "anyOf"),
staticMethod().onClass("reactor.adapter.rxjava.RxJava2Adapter"),
staticMethod()

View File

@@ -25,6 +25,8 @@ import tech.picnic.errorprone.utils.SourceCode;
*/
// XXX: Consider folding this logic into the `MethodReferenceUsage` check of the
// `error-prone-experimental` module.
// XXX: This check and its tests are structurally nearly identical to `ClassCastLambdaUsage`. Unless
// folded into `MethodReferenceUsage`, consider merging the two.
@AutoService(BugChecker.class)
@BugPattern(
summary = "Prefer `Class::isInstance` method reference over equivalent lambda expression",

View File

@@ -16,7 +16,7 @@ import static tech.picnic.errorprone.utils.MoreJUnitMatchers.TEST_METHOD;
import static tech.picnic.errorprone.utils.MoreMatchers.hasMetaAnnotation;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
@@ -70,7 +70,7 @@ public final class JUnitClassModifiers extends BugChecker implements ClassTreeMa
SuggestedFixes.removeModifiers(
tree.getModifiers(),
state,
ImmutableSet.of(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC))
Sets.immutableEnumSet(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC))
.ifPresent(fixBuilder::merge);
if (!HAS_SPRING_CONFIGURATION_ANNOTATION.matches(tree, state)) {

View File

@@ -14,6 +14,7 @@ import com.google.common.base.Splitter;
import com.google.common.collect.Comparators;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.errorprone.BugPattern;
import com.google.errorprone.ErrorProneFlags;
import com.google.errorprone.VisitorState;
@@ -34,10 +35,8 @@ import com.sun.source.tree.Tree;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import javax.inject.Inject;
import org.jspecify.annotations.Nullable;
@@ -163,7 +162,12 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
/* For now we don't force sorting on numeric types. */
return Stream.of(
symtab.annotationType, symtab.classType, symtab.enumSym.type, symtab.stringType)
symtab.annotationType,
symtab.booleanType,
symtab.charType,
symtab.classType,
symtab.enumSym.type,
symtab.stringType)
.anyMatch(t -> ASTHelpers.isSubtype(elemType, t, state));
}
@@ -225,10 +229,8 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
excludedAnnotations(flags));
}
private static ImmutableList<String> excludedAnnotations(ErrorProneFlags flags) {
Set<String> exclusions = new HashSet<>();
exclusions.addAll(Flags.getList(flags, EXCLUDED_ANNOTATIONS_FLAG));
exclusions.addAll(BLACKLISTED_ANNOTATIONS);
return ImmutableList.copyOf(exclusions);
private static ImmutableSet<String> excludedAnnotations(ErrorProneFlags flags) {
return Sets.union(BLACKLISTED_ANNOTATIONS, Flags.getSet(flags, EXCLUDED_ANNOTATIONS_FLAG))
.immutableCopy();
}
}

View File

@@ -18,14 +18,12 @@ import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import java.util.Optional;
import java.util.function.Supplier;
import tech.picnic.errorprone.refaster.matchers.RequiresComputation;
import tech.picnic.errorprone.utils.SourceCode;
/**
@@ -36,12 +34,12 @@ import tech.picnic.errorprone.utils.SourceCode;
* it does, the suggested fix changes the program's semantics. Such fragile code must instead be
* refactored such that the side-effectful code does not appear accidental.
*/
// XXX: Consider also implementing the inverse, in which `.orElseGet(() -> someConstant)` is
// flagged.
// XXX: Once the `MethodReferenceUsageCheck` becomes generally usable, consider leaving the method
// reference cleanup to that check, and express the remainder of the logic in this class using a
// Refaster template, i.c.w. a `@Matches` constraint that implements the `requiresComputation`
// logic.
// XXX: This rule may introduce a compilation error: the `value` expression may reference a
// non-effectively final variable, which is not allowed in the replacement lambda expression.
// Review whether a `@Matcher` can be used to avoid this.
// XXX: Once the `MethodReferenceUsageCheck` bug checker becomes generally usable, consider leaving
// the method reference cleanup to that check, and express the remainder of the logic in this class
// using a Refaster template, i.c.w. a `@NotMatches(RequiresComputation.class)` constraint.
@AutoService(BugChecker.class)
@BugPattern(
summary =
@@ -51,16 +49,17 @@ import tech.picnic.errorprone.utils.SourceCode;
linkType = NONE,
severity = WARNING,
tags = PERFORMANCE)
public final class OptionalOrElse extends BugChecker implements MethodInvocationTreeMatcher {
public final class OptionalOrElseGet extends BugChecker implements MethodInvocationTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> REQUIRES_COMPUTATION = new RequiresComputation();
private static final Matcher<ExpressionTree> OPTIONAL_OR_ELSE_METHOD =
instanceMethod().onExactClass(Optional.class.getCanonicalName()).namedAnyOf("orElse");
// XXX: Also exclude invocations of `@Placeholder`-annotated methods.
private static final Matcher<ExpressionTree> REFASTER_METHOD =
staticMethod().onClass(Refaster.class.getCanonicalName());
/** Instantiates a new {@link OptionalOrElse} instance. */
public OptionalOrElse() {}
/** Instantiates a new {@link OptionalOrElseGet} instance. */
public OptionalOrElseGet() {}
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
@@ -69,7 +68,8 @@ public final class OptionalOrElse extends BugChecker implements MethodInvocation
}
ExpressionTree argument = Iterables.getOnlyElement(tree.getArguments());
if (!requiresComputation(argument) || REFASTER_METHOD.matches(argument, state)) {
if (!REQUIRES_COMPUTATION.matches(argument, state)
|| REFASTER_METHOD.matches(argument, state)) {
return Description.NO_MATCH;
}
@@ -91,18 +91,6 @@ public final class OptionalOrElse extends BugChecker implements MethodInvocation
return describeMatch(tree, fix);
}
/**
* Tells whether the given expression contains anything other than a literal or a (possibly
* dereferenced) variable or constant.
*/
private static boolean requiresComputation(ExpressionTree tree) {
return !(tree instanceof IdentifierTree
|| tree instanceof LiteralTree
|| (tree instanceof MemberSelectTree memberSelect
&& !requiresComputation(memberSelect.getExpression()))
|| ASTHelpers.constValue(tree) != null);
}
/** Returns the nullary method reference matching the given expression, if any. */
private static Optional<String> tryMethodReferenceConversion(
ExpressionTree tree, VisitorState state) {
@@ -118,7 +106,7 @@ public final class OptionalOrElse extends BugChecker implements MethodInvocation
return Optional.empty();
}
if (requiresComputation(memberSelect.getExpression())) {
if (REQUIRES_COMPUTATION.matches(memberSelect.getExpression(), state)) {
return Optional.empty();
}

View File

@@ -378,11 +378,11 @@ public final class RedundantStringConversion extends BugChecker
private static Matcher<MethodInvocationTree> createConversionMethodMatcher(
ErrorProneFlags flags) {
// XXX: ErrorProneFlags#getList splits by comma, but method signatures may also contain commas.
// For this class methods accepting more than one argument are not valid, but still: not nice.
// XXX: `Flags#getSet` splits by comma, but method signatures may also contain commas. For this
// class methods accepting more than one argument are not valid, but still: not nice.
return anyOf(
WELL_KNOWN_STRING_CONVERSION_METHODS,
new MethodMatcherFactory()
.create(Flags.getList(flags, EXTRA_STRING_CONVERSION_METHODS_FLAG)));
.create(Flags.getSet(flags, EXTRA_STRING_CONVERSION_METHODS_FLAG)));
}
}

View File

@@ -15,8 +15,8 @@ import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.BugPattern;
import com.google.errorprone.ErrorProneFlags;
import com.google.errorprone.VisitorState;
@@ -74,10 +74,10 @@ public final class RequestParamType extends BugChecker implements VariableTreeMa
return allOf(
annotations(AT_LEAST_ONE, isType("org.springframework.web.bind.annotation.RequestParam")),
anyOf(isSubtypeOf(ImmutableCollection.class), isSubtypeOf(ImmutableMap.class)),
not(isSubtypeOfAny(Flags.getList(flags, SUPPORTED_CUSTOM_TYPES_FLAG))));
not(isSubtypeOfAny(Flags.getSet(flags, SUPPORTED_CUSTOM_TYPES_FLAG))));
}
private static Matcher<Tree> isSubtypeOfAny(ImmutableList<String> inclusions) {
private static Matcher<Tree> isSubtypeOfAny(ImmutableSet<String> inclusions) {
return anyOf(
inclusions.stream()
.map(inclusion -> isSubtypeOf(Suppliers.typeFromString(inclusion)))

View File

@@ -0,0 +1,185 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.common.base.Verify.verify;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.BugPattern.StandardTags.STYLE;
import static com.google.errorprone.matchers.Matchers.allOf;
import static com.google.errorprone.matchers.Matchers.classLiteral;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
import static com.google.errorprone.matchers.Matchers.staticMethod;
import static com.google.errorprone.matchers.Matchers.toType;
import static java.util.Objects.requireNonNull;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
import com.google.common.base.CaseFormat;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.errorprone.BugPattern;
import com.google.errorprone.ErrorProneFlags;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Symbol;
import java.util.EnumSet;
import javax.inject.Inject;
import javax.lang.model.element.Modifier;
import tech.picnic.errorprone.utils.MoreASTHelpers;
/** A {@link BugChecker} that flags non-canonical SLF4J logger declarations. */
@AutoService(BugChecker.class)
@BugPattern(
summary = "SLF4J logger declarations should follow established best-practices",
link = BUG_PATTERNS_BASE_URL + "Slf4jLoggerDeclaration",
linkType = CUSTOM,
severity = WARNING,
tags = STYLE)
@SuppressWarnings("java:S2160" /* Super class equality definition suffices. */)
public final class Slf4jLoggerDeclaration extends BugChecker implements VariableTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Matcher<ExpressionTree> IS_GET_LOGGER =
staticMethod().onDescendantOf("org.slf4j.LoggerFactory").named("getLogger");
private static final String CANONICAL_STATIC_LOGGER_NAME_FLAG =
"Slf4jLogDeclaration:CanonicalStaticLoggerName";
private static final String DEFAULT_CANONICAL_LOGGER_NAME = "LOG";
private static final Matcher<ExpressionTree> IS_STATIC_ENCLOSING_CLASS_REFERENCE =
classLiteral(Slf4jLoggerDeclaration::isEnclosingClassReference);
private static final Matcher<ExpressionTree> IS_DYNAMIC_ENCLOSING_CLASS_REFERENCE =
toType(
MethodInvocationTree.class,
allOf(
instanceMethod().anyClass().named("getClass").withNoParameters(),
Slf4jLoggerDeclaration::getClassReceiverIsEnclosingClassInstance));
private static final ImmutableSet<Modifier> INSTANCE_DECLARATION_MODIFIERS =
Sets.immutableEnumSet(Modifier.PRIVATE, Modifier.FINAL);
private static final ImmutableSet<Modifier> STATIC_DECLARATION_MODIFIERS =
Sets.immutableEnumSet(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL);
private final String canonicalStaticFieldName;
private final String canonicalInstanceFieldName;
/** Instantiates a default {@link Slf4jLoggerDeclaration} instance. */
public Slf4jLoggerDeclaration() {
this(ErrorProneFlags.empty());
}
/**
* Instantiates a customized {@link Slf4jLoggerDeclaration}.
*
* @param flags Any provided command line flags.
*/
@Inject
Slf4jLoggerDeclaration(ErrorProneFlags flags) {
canonicalStaticFieldName =
flags.get(CANONICAL_STATIC_LOGGER_NAME_FLAG).orElse(DEFAULT_CANONICAL_LOGGER_NAME);
canonicalInstanceFieldName =
CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, canonicalStaticFieldName);
}
@Override
public Description matchVariable(VariableTree tree, VisitorState state) {
ExpressionTree initializer = tree.getInitializer();
if (!IS_GET_LOGGER.matches(initializer, state)) {
return Description.NO_MATCH;
}
ClassTree clazz = getEnclosingClass(state);
ExpressionTree factoryArg =
Iterables.getOnlyElement(((MethodInvocationTree) initializer).getArguments());
SuggestedFix.Builder fix = SuggestedFix.builder();
if (clazz.getModifiers().getFlags().contains(Modifier.ABSTRACT)
&& IS_DYNAMIC_ENCLOSING_CLASS_REFERENCE.matches(factoryArg, state)) {
/*
* While generally we prefer `Logger` declarations to be static and named after their
* enclosing class, we allow one exception: loggers in abstract classes with a name derived
* from `getClass()`.
*/
suggestModifiers(tree, INSTANCE_DECLARATION_MODIFIERS, fix, state);
suggestRename(tree, canonicalInstanceFieldName, fix, state);
} else {
suggestModifiers(
tree,
clazz.getKind() == Kind.INTERFACE ? ImmutableSet.of() : STATIC_DECLARATION_MODIFIERS,
fix,
state);
suggestRename(tree, canonicalStaticFieldName, fix, state);
if (!MoreASTHelpers.isStringTyped(factoryArg, state)
&& !IS_STATIC_ENCLOSING_CLASS_REFERENCE.matches(factoryArg, state)) {
/*
* Loggers with a custom string name are generally "special", but those with a name derived
* from a class other than the one that encloses it are likely in error.
*/
fix.merge(SuggestedFix.replace(factoryArg, clazz.getSimpleName() + ".class"));
}
}
return fix.isEmpty() ? Description.NO_MATCH : describeMatch(tree, fix.build());
}
private static void suggestModifiers(
VariableTree tree,
ImmutableSet<Modifier> modifiers,
SuggestedFix.Builder fixBuilder,
VisitorState state) {
ModifiersTree modifiersTree =
requireNonNull(ASTHelpers.getModifiers(tree), "`VariableTree` must have modifiers");
SuggestedFixes.addModifiers(tree, modifiersTree, state, modifiers).ifPresent(fixBuilder::merge);
SuggestedFixes.removeModifiers(
modifiersTree, state, Sets.difference(EnumSet.allOf(Modifier.class), modifiers))
.ifPresent(fixBuilder::merge);
}
private static void suggestRename(
VariableTree variableTree, String name, SuggestedFix.Builder fixBuilder, VisitorState state) {
if (!variableTree.getName().contentEquals(name)) {
fixBuilder.merge(SuggestedFixes.renameVariable(variableTree, name, state));
}
}
private static boolean isEnclosingClassReference(ExpressionTree tree, VisitorState state) {
return ASTHelpers.getSymbol(getEnclosingClass(state)).equals(ASTHelpers.getSymbol(tree));
}
private static boolean getClassReceiverIsEnclosingClassInstance(
MethodInvocationTree getClassInvocationTree, VisitorState state) {
ExpressionTree receiver = ASTHelpers.getReceiver(getClassInvocationTree);
if (receiver == null) {
/*
* Method invocations without an explicit receiver either involve static methods (possibly
* statically imported), or instance methods invoked on the enclosing class. As the given
* `getClassInvocationTree` is guaranteed to be a nullary `#getClass()` invocation, the latter
* must be the case.
*/
return true;
}
Symbol symbol = ASTHelpers.getSymbol(receiver);
return symbol != null
&& symbol.asType().tsym.equals(ASTHelpers.getSymbol(getEnclosingClass(state)));
}
private static ClassTree getEnclosingClass(VisitorState state) {
ClassTree clazz = state.findEnclosing(ClassTree.class);
// XXX: Review whether we should relax this constraint in the face of so-called anonymous
// classes. See
// https://docs.oracle.com/en/java/javase/23/language/implicitly-declared-classes-and-instance-main-methods.html
verify(clazz != null, "Variable not defined inside class");
return clazz;
}
}

View File

@@ -1,8 +1,6 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Sets.toImmutableEnumSet;
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
import static java.util.Collections.disjoint;
import static java.util.Objects.checkIndex;
@@ -70,28 +68,6 @@ final class AssortedRules {
}
}
/**
* Use {@link Sets#toImmutableEnumSet()} when possible, as it is more efficient than {@link
* ImmutableSet#toImmutableSet()} and produces a more compact object.
*
* <p><strong>Warning:</strong> this rewrite rule is not completely behavior preserving: while the
* original code produces a set that iterates over the elements in encounter order, the
* replacement code iterates over the elements in enum definition order.
*/
// XXX: ^ Consider emitting a comment warning about this fact?
static final class StreamToImmutableEnumSet<T extends Enum<T>> {
@BeforeTemplate
ImmutableSet<T> before(Stream<T> stream) {
return stream.collect(toImmutableSet());
}
@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
ImmutableSet<T> after(Stream<T> stream) {
return stream.collect(toImmutableEnumSet());
}
}
/** Prefer {@link Iterators#getNext(Iterator, Object)} over more contrived alternatives. */
static final class IteratorGetNextOrDefault<T> {
@BeforeTemplate

View File

@@ -9,6 +9,7 @@ import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.sun.tools.javac.util.Constants;
import com.sun.tools.javac.util.Convert;
import javax.lang.model.element.Name;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
/** Refaster rules related to {@link com.google.errorprone.bugpatterns.BugChecker} classes. */
@@ -67,4 +68,22 @@ final class BugCheckerRules {
return Constants.format(value);
}
}
/** Prefer {@link Name#contentEquals(CharSequence)} over more verbose alternatives. */
static final class NameContentEquals {
@BeforeTemplate
boolean before(Name name, CharSequence string) {
return name.toString().equals(string.toString());
}
@BeforeTemplate
boolean before(Name name, String string) {
return name.toString().equals(string);
}
@AfterTemplate
boolean after(Name name, CharSequence string) {
return name.contentEquals(string);
}
}
}

View File

@@ -3,6 +3,7 @@ package tech.picnic.errorprone.refasterrules;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import java.util.function.Function;
import java.util.function.Predicate;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
@@ -37,7 +38,12 @@ final class ClassRules {
}
}
/** Prefer {@link Class#isInstance(Object)} method references over more verbose alternatives. */
/**
* Prefer {@link Class#isInstance(Object)} method references over lambda expressions that require
* naming a variable.
*/
// XXX: Once the `ClassReferenceIsInstancePredicate` rule is dropped, rename this rule to just
// `ClassIsInstancePredicate`.
static final class ClassLiteralIsInstancePredicate<T, S> {
@BeforeTemplate
Predicate<S> before() {
@@ -50,7 +56,11 @@ final class ClassRules {
}
}
/** Prefer {@link Class#isInstance(Object)} method references over more verbose alternatives. */
/**
* Prefer {@link Class#isInstance(Object)} method references over lambda expressions that require
* naming a variable.
*/
// XXX: Drop this rule once the `MethodReferenceUsage` rule is enabled by default.
static final class ClassReferenceIsInstancePredicate<T, S> {
@BeforeTemplate
Predicate<S> before(Class<T> clazz) {
@@ -62,4 +72,21 @@ final class ClassRules {
return clazz::isInstance;
}
}
/**
* Prefer {@link Class#cast(Object)} method references over lambda expressions that require naming
* a variable.
*/
// XXX: Drop this rule once the `MethodReferenceUsage` rule is enabled by default.
static final class ClassReferenceCast<T, S> {
@BeforeTemplate
Function<T, S> before(Class<? extends S> clazz) {
return o -> clazz.cast(o);
}
@AfterTemplate
Function<T, S> after(Class<? extends S> clazz) {
return clazz::cast;
}
}
}

View File

@@ -8,7 +8,9 @@ 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.NotMatches;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -21,6 +23,7 @@ import java.util.function.Consumer;
import java.util.function.IntFunction;
import java.util.stream.Stream;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
import tech.picnic.errorprone.refaster.matchers.IsRefasterAsVarargs;
/** Refaster rules related to expressions dealing with (arbitrary) collections. */
// XXX: There are other Guava `Iterables` methods that should not be called if the input is known to
@@ -184,6 +187,24 @@ final class CollectionRules {
}
}
/** Don't unnecessarily call {@link Stream#distinct()} on an already-unique stream of elements. */
// XXX: This rule assumes that the `Set` relies on `Object#equals`, rather than a custom
// equivalence relation.
// XXX: Expressions that drop or reorder elements from the stream, such as `.filter`, `.skip` and
// `sorted`, can similarly be simplified. Covering all cases is better done using an Error Prone
// check.
static final class SetStream<T> {
@BeforeTemplate
Stream<?> before(Set<T> set) {
return set.stream().distinct();
}
@AfterTemplate
Stream<?> after(Set<T> set) {
return set.stream();
}
}
/** Prefer {@link ArrayList#ArrayList(Collection)} over the Guava alternative. */
@SuppressWarnings(
"NonApiType" /* Matching against `List` would unnecessarily constrain the rule. */)
@@ -276,6 +297,23 @@ final class CollectionRules {
}
}
/** Prefer {@link Arrays#asList(Object[])} over more contrived alternatives. */
// XXX: Consider moving this rule to `ImmutableListRules` and having it suggest
// `ImmutableList#copyOf`. That would retain immutability, at the cost of no longer handling
// `null`s.
static final class ArraysAsList<T> {
// XXX: This expression produces an unmodifiable list, while the alternative doesn't.
@BeforeTemplate
List<T> before(@NotMatches(IsRefasterAsVarargs.class) T[] array) {
return Arrays.stream(array).toList();
}
@AfterTemplate
List<T> after(T[] array) {
return Arrays.asList(array);
}
}
/** Prefer calling {@link Collection#toArray()} over more contrived alternatives. */
static final class CollectionToArray<T> {
@BeforeTemplate
@@ -327,18 +365,20 @@ final class CollectionRules {
}
}
/**
* Don't call {@link ImmutableCollection#asList()} if {@link ImmutableCollection#iterator()} is
* called on the result; call it directly.
*/
static final class ImmutableCollectionIterator<T> {
/** Prefer {@link Collection#iterator()} over more contrived or less efficient alternatives. */
static final class CollectionIterator<T> {
@BeforeTemplate
Iterator<T> before(Collection<T> collection) {
return collection.stream().iterator();
}
@BeforeTemplate
Iterator<T> before(ImmutableCollection<T> collection) {
return collection.asList().iterator();
}
@AfterTemplate
Iterator<T> after(ImmutableCollection<T> collection) {
Iterator<T> after(Collection<T> collection) {
return collection.iterator();
}
}

View File

@@ -24,8 +24,10 @@ import com.google.errorprone.refaster.annotation.Placeholder;
import com.google.errorprone.refaster.annotation.Repeated;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.function.Function;
@@ -243,18 +245,77 @@ final class ComparatorRules {
}
}
/** Prefer {@link Collections#sort(List)} over more verbose alternatives. */
static final class CollectionsSort<T extends Comparable<? super T>> {
@BeforeTemplate
void before(List<T> collection) {
Collections.sort(collection, naturalOrder());
}
@AfterTemplate
void after(List<T> collection) {
Collections.sort(collection);
}
}
/** Prefer {@link Collections#min(Collection)} over more verbose alternatives. */
static final class CollectionsMin<T extends Comparable<? super T>> {
@BeforeTemplate
T before(Collection<T> collection) {
return Refaster.anyOf(
Collections.min(collection, naturalOrder()), Collections.max(collection, reverseOrder()));
}
@AfterTemplate
T after(Collection<T> collection) {
return Collections.min(collection);
}
}
/**
* Avoid unnecessary creation of a {@link Stream} to determine the minimum of a known collection
* of values.
*/
static final class MinOfVarargs<T> {
static final class MinOfArray<S, T extends S> {
@BeforeTemplate
T before(@Repeated T value, Comparator<T> cmp) {
T before(T[] array, Comparator<S> cmp) {
return Arrays.stream(array).min(cmp).orElseThrow();
}
@AfterTemplate
T after(T[] array, Comparator<S> cmp) {
return Collections.min(Arrays.asList(array), cmp);
}
}
/**
* Avoid unnecessary creation of a {@link Stream} to determine the minimum of a known collection
* of values.
*/
static final class CollectionsMinWithComparator<S, T extends S> {
@BeforeTemplate
T before(Collection<T> collection, Comparator<S> cmp) {
return collection.stream().min(cmp).orElseThrow();
}
@AfterTemplate
T after(Collection<T> collection, Comparator<S> cmp) {
return Collections.min(collection, cmp);
}
}
/**
* Avoid unnecessary creation of a {@link Stream} to determine the minimum of a known collection
* of values.
*/
static final class MinOfVarargs<S, T extends S> {
@BeforeTemplate
T before(@Repeated T value, Comparator<S> cmp) {
return Stream.of(Refaster.asVarargs(value)).min(cmp).orElseThrow();
}
@AfterTemplate
T after(@Repeated T value, Comparator<T> cmp) {
T after(@Repeated T value, Comparator<S> cmp) {
return Collections.min(Arrays.asList(value), cmp);
}
}
@@ -310,18 +371,64 @@ final class ComparatorRules {
}
}
/** Prefer {@link Collections#max(Collection)} over more verbose alternatives. */
static final class CollectionsMax<T extends Comparable<? super T>> {
@BeforeTemplate
T before(Collection<T> collection) {
return Refaster.anyOf(
Collections.max(collection, naturalOrder()), Collections.min(collection, reverseOrder()));
}
@AfterTemplate
T after(Collection<T> collection) {
return Collections.max(collection);
}
}
/**
* Avoid unnecessary creation of a {@link Stream} to determine the maximum of a known collection
* of values.
*/
static final class MaxOfVarargs<T> {
static final class MaxOfArray<S, T extends S> {
@BeforeTemplate
T before(@Repeated T value, Comparator<T> cmp) {
T before(T[] array, Comparator<S> cmp) {
return Arrays.stream(array).max(cmp).orElseThrow();
}
@AfterTemplate
T after(T[] array, Comparator<S> cmp) {
return Collections.max(Arrays.asList(array), cmp);
}
}
/**
* Avoid unnecessary creation of a {@link Stream} to determine the maximum of a known collection
* of values.
*/
static final class CollectionsMaxWithComparator<S, T extends S> {
@BeforeTemplate
T before(Collection<T> collection, Comparator<S> cmp) {
return collection.stream().max(cmp).orElseThrow();
}
@AfterTemplate
T after(Collection<T> collection, Comparator<S> cmp) {
return Collections.max(collection, cmp);
}
}
/**
* Avoid unnecessary creation of a {@link Stream} to determine the maximum of a known collection
* of values.
*/
static final class MaxOfVarargs<S, T extends S> {
@BeforeTemplate
T before(@Repeated T value, Comparator<S> cmp) {
return Stream.of(Refaster.asVarargs(value)).max(cmp).orElseThrow();
}
@AfterTemplate
T after(@Repeated T value, Comparator<T> cmp) {
T after(@Repeated T value, Comparator<S> cmp) {
return Collections.max(Arrays.asList(value), cmp);
}
}

View File

@@ -2,12 +2,18 @@ package tech.picnic.errorprone.refasterrules;
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.BeforeTemplate;
import com.google.errorprone.refaster.annotation.Repeated;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
/** Refaster rules related to expressions dealing with files. */
@@ -15,6 +21,49 @@ import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
final class FileRules {
private FileRules() {}
/** Prefer the more idiomatic {@link Path#of(URI)} over {@link Paths#get(URI)}. */
static final class PathOfUri {
@BeforeTemplate
Path before(URI uri) {
return Paths.get(uri);
}
@AfterTemplate
Path after(URI uri) {
return Path.of(uri);
}
}
/**
* Prefer the more idiomatic {@link Path#of(String, String...)} over {@link Paths#get(String,
* String...)}.
*/
static final class PathOfString {
@BeforeTemplate
Path before(String first, @Repeated String more) {
return Paths.get(first, more);
}
@AfterTemplate
Path after(String first, @Repeated String more) {
return Path.of(first, more);
}
}
/** Avoid redundant conversions from {@link Path} to {@link File}. */
// XXX: Review whether a rule such as this one is better handled by the `IdentityConversion` rule.
static final class PathInstance {
@BeforeTemplate
Path before(Path path) {
return path.toFile().toPath();
}
@AfterTemplate
Path after(Path path) {
return path;
}
}
/** Prefer {@link Files#readString(Path, Charset)} over more contrived alternatives. */
static final class FilesReadStringWithCharset {
@BeforeTemplate
@@ -40,4 +89,44 @@ final class FileRules {
return Files.readString(path);
}
}
/**
* Prefer {@link Files#createTempFile(String, String, FileAttribute[])} over alternatives that
* create files with more liberal permissions.
*/
static final class FilesCreateTempFileToFile {
@BeforeTemplate
@SuppressWarnings({
"FilesCreateTempFileInCustomDirectoryToFile" /* This is a more specific template. */,
"java:S5443" /* This violation will be rewritten. */,
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
})
File before(String prefix, String suffix) throws IOException {
return Refaster.anyOf(
File.createTempFile(prefix, suffix), File.createTempFile(prefix, suffix, null));
}
@AfterTemplate
@SuppressWarnings(
"java:S5443" /* On POSIX systems the file will only have user read-write permissions. */)
File after(String prefix, String suffix) throws IOException {
return Files.createTempFile(prefix, suffix).toFile();
}
}
/**
* Prefer {@link Files#createTempFile(Path, String, String, FileAttribute[])} over alternatives
* that create files with more liberal permissions.
*/
static final class FilesCreateTempFileInCustomDirectoryToFile {
@BeforeTemplate
File before(File directory, String prefix, String suffix) throws IOException {
return File.createTempFile(prefix, suffix, directory);
}
@AfterTemplate
File after(File directory, String prefix, String suffix) throws IOException {
return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
}
}
}

View File

@@ -0,0 +1,246 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Sets.toImmutableEnumSet;
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.refaster.annotation.Repeated;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.stream.Stream;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
/**
* Refaster rules related to expressions dealing with {@code
* com.google.common.collect.ImmutableEnumSet}s.
*/
// XXX: Some of the rules defined here impact iteration order. That's a rather subtle change. Should
// we emit a comment warning about this fact? (This may produce a lot of noise. A bug checker could
// in some cases determine whether iteration order is important.)
// XXX: Consider replacing the `SetsImmutableEnumSet[N]` Refaster rules with a bug checker, such
// that call to `ImmutableSet#of(Object, Object, Object, Object, Object, Object, Object[])` with
// enum-typed values can also be rewritten.
@OnlineDocumentation
final class ImmutableEnumSetRules {
private ImmutableEnumSetRules() {}
/**
* Prefer {@link Sets#immutableEnumSet(Iterable)} for enum collections to take advantage of the
* internally used {@link EnumSet}.
*
* <p><strong>Warning:</strong> this rule is not completely behavior preserving: while the
* original code produces a set that iterates over its elements in the same order as the input
* {@link Iterable}, the replacement code iterates over the elements in enum definition order.
*/
static final class SetsImmutableEnumSetIterable<T extends Enum<T>> {
@BeforeTemplate
ImmutableSet<T> before(Iterable<T> elements) {
return ImmutableSet.copyOf(elements);
}
@BeforeTemplate
ImmutableSet<T> before(Collection<T> elements) {
return ImmutableSet.copyOf(elements);
}
@AfterTemplate
ImmutableSet<T> after(Iterable<T> elements) {
return Sets.immutableEnumSet(elements);
}
}
/**
* Prefer {@link Sets#immutableEnumSet(Iterable)} for enum collections to take advantage of the
* internally used {@link EnumSet}.
*
* <p><strong>Warning:</strong> this rule is not completely behavior preserving: while the
* original code produces a set that iterates over its elements in the same order as defined in
* the array, the replacement code iterates over the elements in enum definition order.
*/
static final class SetsImmutableEnumSetArraysAsList<T extends Enum<T>> {
@BeforeTemplate
ImmutableSet<T> before(T[] elements) {
return ImmutableSet.copyOf(elements);
}
@AfterTemplate
ImmutableSet<T> after(T[] elements) {
return Sets.immutableEnumSet(Arrays.asList(elements));
}
}
/**
* Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of
* the internally used {@link EnumSet}.
*/
static final class SetsImmutableEnumSet1<T extends Enum<T>> {
@BeforeTemplate
@SuppressWarnings("SetsImmutableEnumSetIterable" /* This is a more specific template. */)
ImmutableSet<T> before(T e1) {
return Refaster.anyOf(ImmutableSet.of(e1), ImmutableSet.copyOf(EnumSet.of(e1)));
}
@AfterTemplate
@SuppressWarnings("unchecked")
ImmutableSet<T> after(T e1) {
return Sets.immutableEnumSet(e1);
}
}
/**
* Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of
* the internally used {@link EnumSet}.
*
* <p><strong>Warning:</strong> this rule is not completely behavior preserving: while the {@link
* ImmutableSet#of} expression produces a set that iterates over its elements in the listed order,
* the replacement code iterates over the elements in enum definition order.
*/
static final class SetsImmutableEnumSet2<T extends Enum<T>> {
@BeforeTemplate
@SuppressWarnings("SetsImmutableEnumSetIterable" /* This is a more specific template. */)
ImmutableSet<T> before(T e1, T e2) {
return Refaster.anyOf(ImmutableSet.of(e1, e2), ImmutableSet.copyOf(EnumSet.of(e1, e2)));
}
@AfterTemplate
@SuppressWarnings("unchecked")
ImmutableSet<T> after(T e1, T e2) {
return Sets.immutableEnumSet(e1, e2);
}
}
/**
* Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of
* the internally used {@link EnumSet}.
*
* <p><strong>Warning:</strong> this rule is not completely behavior preserving: while the {@link
* ImmutableSet#of} expression produces a set that iterates over its elements in the listed order,
* the replacement code iterates over the elements in enum definition order.
*/
static final class SetsImmutableEnumSet3<T extends Enum<T>> {
@BeforeTemplate
@SuppressWarnings("SetsImmutableEnumSetIterable" /* This is a more specific template. */)
ImmutableSet<T> before(T e1, T e2, T e3) {
return Refaster.anyOf(
ImmutableSet.of(e1, e2, e3), ImmutableSet.copyOf(EnumSet.of(e1, e2, e3)));
}
@AfterTemplate
@SuppressWarnings("unchecked")
ImmutableSet<T> after(T e1, T e2, T e3) {
return Sets.immutableEnumSet(e1, e2, e3);
}
}
/**
* Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of
* the internally used {@link EnumSet}.
*
* <p><strong>Warning:</strong> this rule is not completely behavior preserving: while the {@link
* ImmutableSet#of} expression produces a set that iterates over its elements in the listed order,
* the replacement code iterates over the elements in enum definition order.
*/
static final class SetsImmutableEnumSet4<T extends Enum<T>> {
@BeforeTemplate
@SuppressWarnings("SetsImmutableEnumSetIterable" /* This is a more specific template. */)
ImmutableSet<T> before(T e1, T e2, T e3, T e4) {
return Refaster.anyOf(
ImmutableSet.of(e1, e2, e3, e4), ImmutableSet.copyOf(EnumSet.of(e1, e2, e3, e4)));
}
@AfterTemplate
@SuppressWarnings("unchecked")
ImmutableSet<T> after(T e1, T e2, T e3, T e4) {
return Sets.immutableEnumSet(e1, e2, e3, e4);
}
}
/**
* Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of
* the internally used {@link EnumSet}.
*
* <p><strong>Warning:</strong> this rule is not completely behavior preserving: while the {@link
* ImmutableSet#of} expression produces a set that iterates over its elements in the listed order,
* the replacement code iterates over the elements in enum definition order.
*/
static final class SetsImmutableEnumSet5<T extends Enum<T>> {
@BeforeTemplate
@SuppressWarnings("SetsImmutableEnumSetIterable" /* This is a more specific template. */)
ImmutableSet<T> before(T e1, T e2, T e3, T e4, T e5) {
return Refaster.anyOf(
ImmutableSet.of(e1, e2, e3, e4, e5), ImmutableSet.copyOf(EnumSet.of(e1, e2, e3, e4, e5)));
}
@AfterTemplate
@SuppressWarnings("unchecked")
ImmutableSet<T> after(T e1, T e2, T e3, T e4, T e5) {
return Sets.immutableEnumSet(e1, e2, e3, e4, e5);
}
}
/**
* Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of
* the internally used {@link EnumSet}.
*
* <p><strong>Warning:</strong> this rule is not completely behavior preserving: while the
* original code produces a set that iterates over its elements in the listed order, the
* replacement code iterates over the elements in enum definition order.
*/
static final class SetsImmutableEnumSet6<T extends Enum<T>> {
@BeforeTemplate
ImmutableSet<T> before(T e1, T e2, T e3, T e4, T e5, T e6) {
return ImmutableSet.of(e1, e2, e3, e4, e5, e6);
}
@AfterTemplate
@SuppressWarnings("unchecked")
ImmutableSet<T> after(T e1, T e2, T e3, T e4, T e5, T e6) {
return Sets.immutableEnumSet(e1, e2, e3, e4, e5, e6);
}
}
/**
* Prefer {@link Sets#immutableEnumSet(Enum, Enum[])} for enum collections to take advantage of
* the internally used {@link EnumSet}.
*/
static final class SetsImmutableEnumSetVarArgs<T extends Enum<T>> {
@BeforeTemplate
@SuppressWarnings("SetsImmutableEnumSetIterable" /* This is a more specific template. */)
ImmutableSet<T> before(T e1, @Repeated T elements) {
return ImmutableSet.copyOf(EnumSet.of(e1, Refaster.asVarargs(elements)));
}
@AfterTemplate
ImmutableSet<T> after(T e1, @Repeated T elements) {
return Sets.immutableEnumSet(e1, Refaster.asVarargs(elements));
}
}
/**
* Use {@link Sets#toImmutableEnumSet()} when possible, as it is more efficient than {@link
* ImmutableSet#toImmutableSet()} and produces a more compact object.
*
* <p><strong>Warning:</strong> this rule is not completely behavior preserving: while the
* original code produces a set that iterates over its elements in encounter order, the
* replacement code iterates over the elements in enum definition order.
*/
static final class StreamToImmutableEnumSet<T extends Enum<T>> {
@BeforeTemplate
ImmutableSet<T> before(Stream<T> stream) {
return stream.collect(toImmutableSet());
}
@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
ImmutableSet<T> after(Stream<T> stream) {
return stream.collect(toImmutableEnumSet());
}
}
}

View File

@@ -0,0 +1,88 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
/** Refaster rules related to expressions dealing with Micrometer. */
// XXX: Consider replacing the `TagsOf[N]` rules with a bug checker, so that various other
// expressions (e.g. those creating other collection types, those passing in tags some other way, or
// those passing in more tags) can be replaced as wel.
@OnlineDocumentation
final class MicrometerRules {
private MicrometerRules() {}
/** Prefer using {@link Tags} over other immutable collections. */
static final class TagsOf1 {
@BeforeTemplate
ImmutableCollection<Tag> before(Tag tag) {
return Refaster.anyOf(ImmutableSet.of(tag), ImmutableList.of(tag));
}
@AfterTemplate
Iterable<Tag> after(Tag tag) {
return Tags.of(tag);
}
}
/** Prefer using {@link Tags} over other immutable collections. */
static final class TagsOf2 {
@BeforeTemplate
ImmutableCollection<Tag> before(Tag tag1, Tag tag2) {
return Refaster.anyOf(ImmutableSet.of(tag1, tag2), ImmutableList.of(tag1, tag2));
}
@AfterTemplate
Iterable<Tag> after(Tag tag1, Tag tag2) {
return Tags.of(tag1, tag2);
}
}
/** Prefer using {@link Tags} over other immutable collections. */
static final class TagsOf3 {
@BeforeTemplate
ImmutableCollection<Tag> before(Tag tag1, Tag tag2, Tag tag3) {
return Refaster.anyOf(ImmutableSet.of(tag1, tag2, tag3), ImmutableList.of(tag1, tag2, tag3));
}
@AfterTemplate
Iterable<Tag> after(Tag tag1, Tag tag2, Tag tag3) {
return Tags.of(tag1, tag2, tag3);
}
}
/** Prefer using {@link Tags} over other immutable collections. */
static final class TagsOf4 {
@BeforeTemplate
ImmutableCollection<Tag> before(Tag tag1, Tag tag2, Tag tag3, Tag tag4) {
return Refaster.anyOf(
ImmutableSet.of(tag1, tag2, tag3, tag4), ImmutableList.of(tag1, tag2, tag3, tag4));
}
@AfterTemplate
Iterable<Tag> after(Tag tag1, Tag tag2, Tag tag3, Tag tag4) {
return Tags.of(tag1, tag2, tag3, tag4);
}
}
/** Prefer using {@link Tags} over other immutable collections. */
static final class TagsOf5 {
@BeforeTemplate
ImmutableCollection<Tag> before(Tag tag1, Tag tag2, Tag tag3, Tag tag4, Tag tag5) {
return Refaster.anyOf(
ImmutableSet.of(tag1, tag2, tag3, tag4, tag5),
ImmutableList.of(tag1, tag2, tag3, tag4, tag5));
}
@AfterTemplate
Iterable<Tag> after(Tag tag1, Tag tag2, Tag tag3, Tag tag4, Tag tag5) {
return Tags.of(tag1, tag2, tag3, tag4, tag5);
}
}
}

View File

@@ -20,7 +20,7 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
import tech.picnic.errorprone.refaster.matchers.IsLikelyTrivialComputation;
import tech.picnic.errorprone.refaster.matchers.RequiresComputation;
/** Refaster rules related to expressions dealing with {@link Optional}s. */
@OnlineDocumentation
@@ -255,24 +255,21 @@ final class OptionalRules {
}
/**
* Prefer {@link Optional#orElseGet(Supplier)} over {@link Optional#orElse(Object)} if the
* fallback value is not the result of a trivial computation.
* Prefer {@link Optional#orElse(Object)} over {@link Optional#orElseGet(Supplier)} if the
* fallback value does not require non-trivial computation.
*/
// XXX: This rule may introduce a compilation error: the `value` expression may reference a
// non-effectively final variable, which is not allowed in the replacement lambda expression.
// Review whether a `@Matcher` can be used to avoid this.
// XXX: Once `MethodReferenceUsage` is "production ready", replace
// `@NotMatches(IsLikelyTrivialComputation.class)` with `@Matches(RequiresComputation.class)` (and
// reimplement the matcher accordingly).
static final class OptionalOrElseGet<T> {
// XXX: This rule is the counterpart to the `OptionalOrElseGet` bug checker. Once the
// `MethodReferenceUsage` bug checker is "production ready", that bug checker may similarly be
// replaced with a Refaster rule.
static final class OptionalOrElse<T> {
@BeforeTemplate
T before(Optional<T> optional, @NotMatches(IsLikelyTrivialComputation.class) T value) {
return optional.orElse(value);
T before(Optional<T> optional, @NotMatches(RequiresComputation.class) T value) {
return optional.orElseGet(() -> value);
}
@AfterTemplate
T after(Optional<T> optional, T value) {
return optional.orElseGet(() -> value);
return optional.orElse(value);
}
}
@@ -282,6 +279,9 @@ final class OptionalRules {
*/
// XXX: Do we need the `.filter(Optional::isPresent)`? If it's absent the caller probably assumed
// that the values are present. (If we drop it, we should rewrite vacuous filter steps.)
// XXX: The rewritten `filter`/`map` expression may be more performant than its replacement. See
// https://github.com/palantir/gradle-baseline/pull/2946. (There are plans to pair Refaster rules
// with JMH benchmarks; this would be a great use case.)
static final class StreamFlatMapOptional<T> {
@BeforeTemplate
Stream<T> before(Stream<Optional<T>> stream) {
@@ -373,7 +373,12 @@ final class OptionalRules {
/** Prefer {@link Optional#or(Supplier)} over more verbose alternatives. */
static final class OptionalOrOtherOptional<T> {
@BeforeTemplate
@SuppressWarnings("NestedOptionals")
@SuppressWarnings({
"LexicographicalAnnotationAttributeListing" /* `key-*` entry must remain last. */,
"NestedOptionals" /* This violation will be rewritten. */,
"OptionalOrElse" /* Parameters represent expressions that may require computation. */,
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
})
Optional<T> before(Optional<T> optional1, Optional<T> optional2) {
// XXX: Note that rewriting the first and third variant will change the code's behavior if
// `optional2` has side-effects.
@@ -393,10 +398,7 @@ final class OptionalRules {
}
}
/**
* Avoid unnecessary operations on an {@link Optional} that ultimately result in that very same
* {@link Optional}.
*/
/** Don't unnecessarily transform an {@link Optional} to an equivalent instance. */
static final class OptionalIdentity<T> {
@BeforeTemplate
@SuppressWarnings("NestedOptionals")

View File

@@ -8,6 +8,8 @@ import com.google.common.primitives.Floats;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.google.common.primitives.UnsignedInts;
import com.google.common.primitives.UnsignedLongs;
import com.google.errorprone.refaster.Refaster;
import com.google.errorprone.refaster.annotation.AfterTemplate;
import com.google.errorprone.refaster.annotation.AlsoNegation;
@@ -76,6 +78,8 @@ final class PrimitiveRules {
}
/** Prefer {@link Math#toIntExact(long)} over the Guava alternative. */
// XXX: This rule changes the exception possibly thrown from `IllegalArgumentException` to
// `ArithmeticException`.
static final class LongToIntExact {
@BeforeTemplate
int before(long l) {
@@ -192,97 +196,6 @@ final class PrimitiveRules {
}
}
/** Prefer {@link Boolean#compare(boolean, boolean)} over the Guava alternative. */
static final class BooleanCompare {
@BeforeTemplate
int before(boolean a, boolean b) {
return Booleans.compare(a, b);
}
@AfterTemplate
int after(boolean a, boolean b) {
return Boolean.compare(a, b);
}
}
/** Prefer {@link Character#compare(char, char)} over the Guava alternative. */
static final class CharacterCompare {
@BeforeTemplate
int before(char a, char b) {
return Chars.compare(a, b);
}
@AfterTemplate
int after(char a, char b) {
return Character.compare(a, b);
}
}
/** Prefer {@link Short#compare(short, short)} over the Guava alternative. */
static final class ShortCompare {
@BeforeTemplate
int before(short a, short b) {
return Shorts.compare(a, b);
}
@AfterTemplate
int after(short a, short b) {
return Short.compare(a, b);
}
}
/** Prefer {@link Integer#compare(int, int)} over the Guava alternative. */
static final class IntegerCompare {
@BeforeTemplate
int before(int a, int b) {
return Ints.compare(a, b);
}
@AfterTemplate
int after(int a, int b) {
return Integer.compare(a, b);
}
}
/** Prefer {@link Long#compare(long, long)} over the Guava alternative. */
static final class LongCompare {
@BeforeTemplate
int before(long a, long b) {
return Longs.compare(a, b);
}
@AfterTemplate
int after(long a, long b) {
return Long.compare(a, b);
}
}
/** Prefer {@link Float#compare(float, float)} over the Guava alternative. */
static final class FloatCompare {
@BeforeTemplate
int before(float a, float b) {
return Floats.compare(a, b);
}
@AfterTemplate
int after(float a, float b) {
return Float.compare(a, b);
}
}
/** Prefer {@link Double#compare(double, double)} over the Guava alternative. */
static final class DoubleCompare {
@BeforeTemplate
int before(double a, double b) {
return Doubles.compare(a, b);
}
@AfterTemplate
int after(double a, double b) {
return Double.compare(a, b);
}
}
/** Prefer {@link Character#BYTES} over the Guava alternative. */
static final class CharacterBytes {
@BeforeTemplate
@@ -442,4 +355,205 @@ final class PrimitiveRules {
return Long.signum(l) == -1;
}
}
/** Prefer JDK's {@link Integer#compareUnsigned(int, int)} over third-party alternatives. */
static final class IntegerCompareUnsigned {
@BeforeTemplate
int before(int x, int y) {
return UnsignedInts.compare(x, y);
}
@AfterTemplate
int after(int x, int y) {
return Integer.compareUnsigned(x, y);
}
}
/** Prefer JDK's {@link Long#compareUnsigned(long, long)} over third-party alternatives. */
static final class LongCompareUnsigned {
@BeforeTemplate
long before(long x, long y) {
return UnsignedLongs.compare(x, y);
}
@AfterTemplate
long after(long x, long y) {
return Long.compareUnsigned(x, y);
}
}
/** Prefer JDK's {@link Integer#divideUnsigned(int, int)} over third-party alternatives. */
static final class IntegerDivideUnsigned {
@BeforeTemplate
int before(int x, int y) {
return UnsignedInts.divide(x, y);
}
@AfterTemplate
int after(int x, int y) {
return Integer.divideUnsigned(x, y);
}
}
/** Prefer JDK's {@link Long#divideUnsigned(long, long)} over third-party alternatives. */
static final class LongDivideUnsigned {
@BeforeTemplate
long before(long x, long y) {
return UnsignedLongs.divide(x, y);
}
@AfterTemplate
long after(long x, long y) {
return Long.divideUnsigned(x, y);
}
}
/** Prefer JDK's {@link Integer#remainderUnsigned(int, int)} over third-party alternatives. */
static final class IntegerRemainderUnsigned {
@BeforeTemplate
int before(int x, int y) {
return UnsignedInts.remainder(x, y);
}
@AfterTemplate
int after(int x, int y) {
return Integer.remainderUnsigned(x, y);
}
}
/** Prefer JDK's {@link Long#remainderUnsigned(long, long)} over third-party alternatives. */
static final class LongRemainderUnsigned {
@BeforeTemplate
long before(long x, long y) {
return UnsignedLongs.remainder(x, y);
}
@AfterTemplate
long after(long x, long y) {
return Long.remainderUnsigned(x, y);
}
}
/**
* Prefer JDK's {@link Integer#parseUnsignedInt(String)} over third-party or more verbose
* alternatives.
*/
static final class IntegerParseUnsignedInt {
@BeforeTemplate
int before(String string) {
return Refaster.anyOf(
UnsignedInts.parseUnsignedInt(string), Integer.parseUnsignedInt(string, 10));
}
@AfterTemplate
int after(String string) {
return Integer.parseUnsignedInt(string);
}
}
/**
* Prefer JDK's {@link Long#parseUnsignedLong(String)} over third-party or more verbose
* alternatives.
*/
static final class LongParseUnsignedLong {
@BeforeTemplate
long before(String string) {
return Refaster.anyOf(
UnsignedLongs.parseUnsignedLong(string), Long.parseUnsignedLong(string, 10));
}
@AfterTemplate
long after(String string) {
return Long.parseUnsignedLong(string);
}
}
/** Prefer JDK's {@link Integer#parseUnsignedInt(String, int)} over third-party alternatives. */
static final class IntegerParseUnsignedIntWithRadix {
@BeforeTemplate
int before(String string, int radix) {
return UnsignedInts.parseUnsignedInt(string, radix);
}
@AfterTemplate
int after(String string, int radix) {
return Integer.parseUnsignedInt(string, radix);
}
}
/** Prefer JDK's {@link Long#parseUnsignedLong(String, int)} over third-party alternatives. */
static final class LongParseUnsignedLongWithRadix {
@BeforeTemplate
long before(String string, int radix) {
return UnsignedLongs.parseUnsignedLong(string, radix);
}
@AfterTemplate
long after(String string, int radix) {
return Long.parseUnsignedLong(string, radix);
}
}
/**
* Prefer JDK's {@link Integer#toUnsignedString(int)} over third-party or more verbose
* alternatives.
*/
static final class IntegerToUnsignedString {
@BeforeTemplate
String before(int i) {
return Refaster.anyOf(UnsignedInts.toString(i), Integer.toUnsignedString(i, 10));
}
@AfterTemplate
String after(int i) {
return Integer.toUnsignedString(i);
}
}
/**
* Prefer JDK's {@link Long#toUnsignedString(long)} over third-party or more verbose alternatives.
*/
static final class LongToUnsignedString {
@BeforeTemplate
String before(long i) {
return Refaster.anyOf(UnsignedLongs.toString(i), Long.toUnsignedString(i, 10));
}
@AfterTemplate
String after(long i) {
return Long.toUnsignedString(i);
}
}
/**
* Prefer JDK's {@link Integer#toUnsignedString(int,int)} over third-party or more verbose
* alternatives.
*/
static final class IntegerToUnsignedStringWithRadix {
@BeforeTemplate
String before(int i, int radix) {
return UnsignedInts.toString(i, radix);
}
@AfterTemplate
String after(int i, int radix) {
return Integer.toUnsignedString(i, radix);
}
}
/**
* Prefer JDK's {@link Long#toUnsignedString(long,int)} over third-party or more verbose
* alternatives.
*/
static final class LongToUnsignedStringWithRadix {
@BeforeTemplate
String before(long i, int radix) {
return UnsignedLongs.toString(i, radix);
}
@AfterTemplate
String after(long i, int radix) {
return Long.toUnsignedString(i, radix);
}
}
}

View File

@@ -13,6 +13,7 @@ import static java.util.stream.Collectors.toCollection;
import static org.assertj.core.api.Assertions.assertThat;
import static reactor.function.TupleUtils.function;
import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -41,6 +42,7 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
@@ -1204,10 +1206,17 @@ final class ReactorRules {
}
/** Prefer {@link Flux#fromIterable(Iterable)} over less efficient alternatives. */
// XXX: Once the `FluxFromStreamSupplier` rule is constrained using
// `@NotMatches(IsIdentityOperation.class)`, this rule should also cover
// `Flux.fromStream(collection.stream())`.
static final class FluxFromIterable<T> {
// XXX: Once the `MethodReferenceUsage` check is generally enabled, drop the second
// `Refaster.anyOf` variant.
@BeforeTemplate
Flux<T> before(Collection<T> collection) {
return Flux.fromStream(collection.stream());
return Flux.fromStream(
Refaster.<Supplier<Stream<? extends T>>>anyOf(
collection::stream, () -> collection.stream()));
}
@AfterTemplate
@@ -1759,6 +1768,60 @@ final class ReactorRules {
}
}
/**
* Prefer {@link StepVerifier#verify()} over a dangling {@link
* StepVerifier#verifyThenAssertThat()}.
*/
// XXX: Application of this rule (and several others in this class) will cause invalid code if the
// result of the rewritten expression is dereferenced. Consider introducing a bug checker that
// identifies rules that change the return type of an expression and annotates them accordingly.
// The associated annotation can then be used to instruct an annotation processor to generate
// corresponding `void` rules that match only statements. This would allow the `Refaster` check to
// conditionally skip "not fully safe" rules. This allows conditionally flagging more dubious
// code, at the risk of compilation failures. With this rule, for example, we want to explicitly
// nudge users towards `StepVerifier.Step#assertNext(Consumer)` or
// `StepVerifier.Step#expectNext(Object)`, together with `Step#verifyComplete()`.
static final class StepVerifierVerify {
@BeforeTemplate
StepVerifier.Assertions before(StepVerifier stepVerifier) {
return stepVerifier.verifyThenAssertThat();
}
@AfterTemplate
Duration after(StepVerifier stepVerifier) {
return stepVerifier.verify();
}
}
/**
* Prefer {@link StepVerifier#verify(Duration)} over a dangling {@link
* StepVerifier#verifyThenAssertThat(Duration)}.
*/
static final class StepVerifierVerifyDuration {
@BeforeTemplate
StepVerifier.Assertions before(StepVerifier stepVerifier, Duration duration) {
return stepVerifier.verifyThenAssertThat(duration);
}
@AfterTemplate
Duration after(StepVerifier stepVerifier, Duration duration) {
return stepVerifier.verify(duration);
}
}
/** Don't unnecessarily invoke {@link StepVerifier#verifyLater()} multiple times. */
static final class StepVerifierVerifyLater {
@BeforeTemplate
StepVerifier before(StepVerifier stepVerifier) {
return stepVerifier.verifyLater().verifyLater();
}
@AfterTemplate
StepVerifier after(StepVerifier stepVerifier) {
return stepVerifier.verifyLater();
}
}
/** Don't unnecessarily have {@link StepVerifier.Step} expect no elements. */
static final class StepVerifierStepIdentity<T> {
@BeforeTemplate
@@ -1859,6 +1922,12 @@ final class ReactorRules {
return step.expectErrorMatches(predicate).verify();
}
@BeforeTemplate
@SuppressWarnings("StepVerifierVerify" /* This is a more specific template. */)
StepVerifier.Assertions before2(StepVerifier.LastStep step, Predicate<Throwable> predicate) {
return step.expectError().verifyThenAssertThat().hasOperatorErrorMatching(predicate);
}
@AfterTemplate
Duration after(StepVerifier.LastStep step, Predicate<Throwable> predicate) {
return step.verifyErrorMatches(predicate);
@@ -1881,6 +1950,30 @@ final class ReactorRules {
}
}
/**
* Prefer {@link StepVerifier.LastStep#verifyErrorSatisfies(Consumer)} with AssertJ over more
* contrived alternatives.
*/
static final class StepVerifierLastStepVerifyErrorSatisfiesAssertJ<T extends Throwable> {
@BeforeTemplate
@SuppressWarnings("StepVerifierVerify" /* This is a more specific template. */)
StepVerifier.Assertions before(StepVerifier.LastStep step, Class<T> clazz, String message) {
return Refaster.anyOf(
step.expectError()
.verifyThenAssertThat()
.hasOperatorErrorOfType(clazz)
.hasOperatorErrorWithMessage(message),
step.expectError(clazz).verifyThenAssertThat().hasOperatorErrorWithMessage(message),
step.expectErrorMessage(message).verifyThenAssertThat().hasOperatorErrorOfType(clazz));
}
@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
Duration after(StepVerifier.LastStep step, Class<T> clazz, String message) {
return step.verifyErrorSatisfies(t -> assertThat(t).isInstanceOf(clazz).hasMessage(message));
}
}
/**
* Prefer {@link StepVerifier.LastStep#verifyErrorMessage(String)} over more verbose alternatives.
*/
@@ -1913,7 +2006,7 @@ final class ReactorRules {
/**
* Prefer {@link Mono#fromFuture(Supplier)} over {@link Mono#fromFuture(CompletableFuture)}, as
* the former may defer initiation of the asynchornous computation until subscription.
* the former may defer initiation of the asynchronous computation until subscription.
*/
static final class MonoFromFutureSupplier<T> {
// XXX: Constrain the `future` parameter using `@NotMatches(IsIdentityOperation.class)` once
@@ -1932,7 +2025,7 @@ final class ReactorRules {
/**
* Prefer {@link Mono#fromFuture(Supplier, boolean)} over {@link
* Mono#fromFuture(CompletableFuture, boolean)}, as the former may defer initiation of the
* asynchornous computation until subscription.
* asynchronous computation until subscription.
*/
static final class MonoFromFutureSupplierBoolean<T> {
// XXX: Constrain the `future` parameter using `@NotMatches(IsIdentityOperation.class)` once
@@ -1947,4 +2040,39 @@ final class ReactorRules {
return Mono.fromFuture(() -> future, suppressCancel);
}
}
/**
* Don't propagate {@link Mono} cancellations to an upstream cache value computation, as
* completion of such computations may benefit concurrent or subsequent cache usages.
*/
static final class MonoFromFutureAsyncLoadingCacheGet<K, V> {
@BeforeTemplate
Mono<V> before(AsyncLoadingCache<K, V> cache, K key) {
return Mono.fromFuture(() -> cache.get(key));
}
@AfterTemplate
Mono<V> after(AsyncLoadingCache<K, V> cache, K key) {
return Mono.fromFuture(() -> cache.get(key), /* suppressCancel= */ true);
}
}
/**
* Prefer {@link Flux#fromStream(Supplier)} over {@link Flux#fromStream(Stream)}, as the former
* yields a {@link Flux} that is more likely to behave as expected when subscribed to more than
* once.
*/
static final class FluxFromStreamSupplier<T> {
// XXX: Constrain the `stream` parameter using `@NotMatches(IsIdentityOperation.class)` once
// `IsIdentityOperation` no longer matches nullary method invocations.
@BeforeTemplate
Flux<T> before(Stream<T> stream) {
return Flux.fromStream(stream);
}
@AfterTemplate
Flux<T> after(Stream<T> stream) {
return Flux.fromStream(() -> stream);
}
}
}

View File

@@ -244,4 +244,105 @@ final class StringRules {
return Utf8.encodedLength(str);
}
}
/** Prefer {@link String#indexOf(int, int)} over less efficient alternatives. */
static final class StringIndexOfChar {
@BeforeTemplate
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
int before(String string, int ch, int fromIndex) {
return string.substring(fromIndex).indexOf(ch);
}
@AfterTemplate
int after(String string, int ch, int fromIndex) {
return Math.max(-1, string.indexOf(ch, fromIndex) - fromIndex);
}
}
/** Prefer {@link String#indexOf(String, int)} over less efficient alternatives. */
static final class StringIndexOfString {
@BeforeTemplate
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
int before(String string, String substring, int fromIndex) {
return string.substring(fromIndex).indexOf(substring);
}
@AfterTemplate
int after(String string, String substring, int fromIndex) {
return Math.max(-1, string.indexOf(substring, fromIndex) - fromIndex);
}
}
// XXX: Once we compile Refaster templates with JDK 21 also suggest `String#indexOf(int, int,
// int)` and `String#indexOf(String, int, int)`.
/** Prefer {@link String#lastIndexOf(int, int)} over less efficient alternatives. */
static final class StringLastIndexOfChar {
@BeforeTemplate
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
int before(String string, int ch, int fromIndex) {
return string.substring(fromIndex).lastIndexOf(ch);
}
@AfterTemplate
int after(String string, int ch, int fromIndex) {
return Math.max(-1, string.lastIndexOf(ch) - fromIndex);
}
}
/** Prefer {@link String#lastIndexOf(String, int)} over less efficient alternatives. */
static final class StringLastIndexOfString {
@BeforeTemplate
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
int before(String string, String substring, int fromIndex) {
return string.substring(fromIndex).lastIndexOf(substring);
}
@AfterTemplate
int after(String string, String substring, int fromIndex) {
return Math.max(-1, string.lastIndexOf(substring) - fromIndex);
}
}
/** Prefer {@link String#lastIndexOf(int, int)} over less efficient alternatives. */
static final class StringLastIndexOfCharWithIndex {
@BeforeTemplate
int before(String string, int ch, int fromIndex) {
return string.substring(0, fromIndex).lastIndexOf(ch);
}
@AfterTemplate
int after(String string, int ch, int fromIndex) {
return string.lastIndexOf(ch, fromIndex - 1);
}
}
/** Prefer {@link String#lastIndexOf(String, int)} over less efficient alternatives. */
// XXX: The replacement expression isn't fully equivalent: in case `substring` is empty, then
// the replacement yields `fromIndex - 1` rather than `fromIndex`.
static final class StringLastIndexOfStringWithIndex {
@BeforeTemplate
int before(String string, String substring, int fromIndex) {
return string.substring(0, fromIndex).lastIndexOf(substring);
}
@AfterTemplate
int after(String string, String substring, int fromIndex) {
return string.lastIndexOf(substring, fromIndex - 1);
}
}
/** Prefer {@link String#startsWith(String, int)} over less efficient alternatives. */
static final class StringStartsWith {
@BeforeTemplate
@SuppressWarnings("java:S4635" /* This violation will be rewritten. */)
boolean before(String string, String prefix, int fromIndex) {
return string.substring(fromIndex).startsWith(prefix);
}
@AfterTemplate
boolean after(String string, String prefix, int fromIndex) {
return string.startsWith(prefix, fromIndex);
}
}
}

View File

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

View File

@@ -0,0 +1,70 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class ClassCastLambdaUsageTest {
@Test
void identification() {
CompilationTestHelper.newInstance(ClassCastLambdaUsage.class, getClass())
.addSourceLines(
"A.java",
"import com.google.common.collect.ImmutableSet;",
"import java.util.stream.IntStream;",
"import java.util.stream.Stream;",
"",
"class A {",
" void m() {",
" Number localVariable = 0;",
"",
" Stream.of(0).map(i -> i);",
" Stream.of(1).map(i -> i + 1);",
" Stream.of(2).map(Integer.class::cast);",
" Stream.of(3).map(i -> (Integer) 2);",
" Stream.of(4).map(i -> (Integer) localVariable);",
" // XXX: Ideally this case is also flagged. Pick this up in the context of merging the",
" // `ClassCastLambdaUsage` and `MethodReferenceUsage` checks, or introduce a separate check that",
" // simplifies unnecessary block lambda expressions.",
" Stream.of(5)",
" .map(",
" i -> {",
" return (Integer) i;",
" });",
" Stream.<ImmutableSet>of(ImmutableSet.of(5)).map(s -> (ImmutableSet<Number>) s);",
" Stream.of(ImmutableSet.of(6)).map(s -> (ImmutableSet<?>) s);",
" Stream.of(7).reduce((a, b) -> (Integer) a);",
" IntStream.of(8).mapToObj(i -> (char) i);",
"",
" // BUG: Diagnostic contains:",
" Stream.of(8).map(i -> (Integer) i);",
" }",
"}")
.doTest();
}
@Test
void replacement() {
BugCheckerRefactoringTestHelper.newInstance(ClassCastLambdaUsage.class, getClass())
.addInputLines(
"A.java",
"import java.util.stream.Stream;",
"",
"class A {",
" void m() {",
" Stream.of(1).map(i -> (Integer) i);",
" }",
"}")
.addOutputLines(
"A.java",
"import java.util.stream.Stream;",
"",
"class A {",
" void m() {",
" Stream.of(1).map(Integer.class::cast);",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -0,0 +1,78 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class ConstantNamingTest {
@Test
void identification() {
CompilationTestHelper.newInstance(ConstantNaming.class, getClass())
.addSourceLines(
"A.java",
"class A {",
" private static final long serialVersionUID = 1L;",
" private static final int FOO = 1;",
" // BUG: Diagnostic contains: consider renaming to 'BAR', though note that this is not a private",
" // constant",
" static final int bar = 2;",
" // BUG: Diagnostic contains:",
" private static final int baz = 3;",
" // BUG: Diagnostic contains: consider renaming to 'QUX_QUUX', though note that a variable with",
" // this name is already declared",
" private static final int qux_QUUX = 4;",
" // BUG: Diagnostic contains: consider renaming to 'QUUZ', though note that a variable with",
" // this name is already declared",
" private static final int quuz = 3;",
"",
" private final int foo = 4;",
" private final Runnable QUX_QUUX =",
" new Runnable() {",
" private static final int QUUZ = 1;",
"",
" @Override",
" public void run() {}",
" };",
"}")
.doTest();
}
@Test
void identificationWithCustomExemption() {
CompilationTestHelper.newInstance(ConstantNaming.class, getClass())
.setArgs("-XepOpt:CanonicalConstantNaming:ExemptedNames=foo,baz")
.addSourceLines(
"A.java",
"class A {",
" private static final long serialVersionUID = 1L;",
" private static final int foo = 1;",
" // BUG: Diagnostic contains:",
" private static final int bar = 2;",
" private static final int baz = 3;",
"}")
.doTest();
}
@Test
void replacement() {
BugCheckerRefactoringTestHelper.newInstance(ConstantNaming.class, getClass())
.addInputLines(
"A.java",
"class A {",
" static final int foo = 1;",
" private static final int bar = 2;",
" private static final int baz = 3;",
" private static final int BAZ = 4;",
"}")
.addOutputLines(
"A.java",
"class A {",
" static final int foo = 1;",
" private static final int BAR = 2;",
" private static final int baz = 3;",
" private static final int BAZ = 4;",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

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

View File

@@ -18,22 +18,23 @@ final class IsInstanceLambdaUsageTest {
" void m() {",
" Integer localVariable = 0;",
"",
" Stream.of(0).map(i -> i + 1);",
" Stream.of(1).filter(Integer.class::isInstance);",
" Stream.of(2).filter(i -> i.getClass() instanceof Class);",
" Stream.of(3).filter(i -> localVariable instanceof Integer);",
" Stream.of(0).map(i -> i);",
" Stream.of(1).map(i -> i + 1);",
" Stream.of(2).filter(Integer.class::isInstance);",
" Stream.of(3).filter(i -> i.getClass() instanceof Class);",
" Stream.of(4).filter(i -> localVariable instanceof Integer);",
" // XXX: Ideally this case is also flagged. Pick this up in the context of merging the",
" // `IsInstanceLambdaUsage` and `MethodReferenceUsage` checks, or introduce a separate check that",
" // simplifies unnecessary block lambda expressions.",
" Stream.of(4)",
" Stream.of(5)",
" .filter(",
" i -> {",
" return localVariable instanceof Integer;",
" return i instanceof Integer;",
" });",
" Flux.just(5, \"foo\").distinctUntilChanged(v -> v, (a, b) -> a instanceof Integer);",
" Flux.just(6, \"foo\").distinctUntilChanged(v -> v, (a, b) -> a instanceof Integer);",
"",
" // BUG: Diagnostic contains:",
" Stream.of(6).filter(i -> i instanceof Integer);",
" Stream.of(7).filter(i -> i instanceof Integer);",
" }",
"}")
.doTest();

View File

@@ -29,6 +29,10 @@ final class LexicographicalAnnotationAttributeListingTest {
" @interface Foo {",
" String[] value() default {};",
"",
" boolean[] bools() default {};",
"",
" char[] chars() default {};",
"",
" int[] ints() default {};",
"",
" Class<?>[] cls() default {};",
@@ -69,6 +73,32 @@ final class LexicographicalAnnotationAttributeListingTest {
" @Foo({\"a\", \"A\"})",
" A unsortedStringCaseInsensitiveWithTotalOrderFallback();",
"",
" @Foo(bools = {})",
" A noBools();",
"",
" @Foo(bools = {false})",
" A oneBool();",
"",
" @Foo(bools = {false, true})",
" A sortedBools();",
"",
" // BUG: Diagnostic contains:",
" @Foo(bools = {true, false})",
" A unsortedBools();",
"",
" @Foo(chars = {})",
" A noChars();",
"",
" @Foo(chars = {'a'})",
" A oneChar();",
"",
" @Foo(chars = {'a', 'b'})",
" A sortedChars();",
"",
" // BUG: Diagnostic contains:",
" @Foo(chars = {'b', 'a'})",
" A unsortedChars();",
"",
" @Foo(ints = {})",
" A noInts();",
"",
@@ -173,6 +203,10 @@ final class LexicographicalAnnotationAttributeListingTest {
" @interface Foo {",
" String[] value() default {};",
"",
" boolean[] bools() default {};",
"",
" char[] chars() default {};",
"",
" Class<?>[] cls() default {};",
"",
" RoundingMode[] enums() default {};",
@@ -185,7 +219,13 @@ final class LexicographicalAnnotationAttributeListingTest {
" }",
"",
" @Foo({\" \", \"\", \"b\", \"a\"})",
" A unsortedString();",
" A unsortedStrings();",
"",
" @Foo(bools = {true, false})",
" A unsortedBooleans();",
"",
" @Foo(chars = {'b', 'a'})",
" A unsortedChars();",
"",
" @Foo(cls = {long.class, int.class})",
" A unsortedClasses();",
@@ -210,6 +250,10 @@ final class LexicographicalAnnotationAttributeListingTest {
" @interface Foo {",
" String[] value() default {};",
"",
" boolean[] bools() default {};",
"",
" char[] chars() default {};",
"",
" Class<?>[] cls() default {};",
"",
" RoundingMode[] enums() default {};",
@@ -222,7 +266,13 @@ final class LexicographicalAnnotationAttributeListingTest {
" }",
"",
" @Foo({\"\", \" \", \"a\", \"b\"})",
" A unsortedString();",
" A unsortedStrings();",
"",
" @Foo(bools = {false, true})",
" A unsortedBooleans();",
"",
" @Foo(chars = {'a', 'b'})",
" A unsortedChars();",
"",
" @Foo(cls = {int.class, long.class})",
" A unsortedClasses();",

View File

@@ -5,14 +5,15 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class OptionalOrElseTest {
final class OptionalOrElseGetTest {
@Test
void identification() {
CompilationTestHelper.newInstance(OptionalOrElse.class, getClass())
CompilationTestHelper.newInstance(OptionalOrElseGet.class, getClass())
.addSourceLines(
"A.java",
"import com.google.errorprone.refaster.Refaster;",
"import java.util.Optional;",
"import java.util.function.Supplier;",
"",
"class A {",
" private final Optional<Object> optional = Optional.empty();",
@@ -27,6 +28,7 @@ final class OptionalOrElseTest {
" optional.orElse(string);",
" optional.orElse(this.string);",
" optional.orElse(Refaster.anyOf(\"constant\", \"another\"));",
" Optional.<Supplier<String>>empty().orElse(() -> \"constant\");",
"",
" // BUG: Diagnostic contains:",
" Optional.empty().orElse(string + \"constant\");",
@@ -67,7 +69,7 @@ final class OptionalOrElseTest {
@Test
void replacement() {
BugCheckerRefactoringTestHelper.newInstance(OptionalOrElse.class, getClass())
BugCheckerRefactoringTestHelper.newInstance(OptionalOrElseGet.class, getClass())
.addInputLines(
"A.java",
"import java.util.Optional;",

View File

@@ -0,0 +1,219 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class Slf4jLoggerDeclarationTest {
@Test
void identification() {
CompilationTestHelper.newInstance(Slf4jLoggerDeclaration.class, getClass())
.addSourceLines(
"A.java",
"import static java.lang.Class.forName;",
"",
"import org.slf4j.Logger;",
"import org.slf4j.LoggerFactory;",
"",
"class A {",
" private static final long serialVersionUID = 1L;",
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
"",
" abstract static class DynamicLogger {",
" private final Logger log = LoggerFactory.getLogger(getClass());",
" }",
"",
" abstract static class DynamicLoggerWithExplicitThis {",
" private final Logger log = LoggerFactory.getLogger(this.getClass());",
" }",
"",
" static final class StaticLogger {",
" private static final Logger LOG = LoggerFactory.getLogger(StaticLogger.class);",
" }",
"",
" static final class StaticLoggerWithCustomIdentifier {",
" private static final Logger LOG = LoggerFactory.getLogger(\"custom-identifier\");",
" }",
"",
" interface StaticLoggerForInterface {",
" Logger LOG = LoggerFactory.getLogger(StaticLoggerForInterface.class);",
" }",
"",
" abstract static class DynamicLoggerForWrongTypeWithoutReceiver {",
" // BUG: Diagnostic contains:",
" private final Logger log = LoggerFactory.getLogger(forName(\"A.class\"));",
"",
" DynamicLoggerForWrongTypeWithoutReceiver() throws ClassNotFoundException {}",
" }",
"",
" abstract static class DynamicLoggerForWrongTypeWithoutSymbol {",
" // BUG: Diagnostic contains:",
" private final Logger log = LoggerFactory.getLogger(\"foo\".getClass());",
" }",
"",
" abstract static class DynamicLoggerForWrongTypeWithSymbol {",
" // BUG: Diagnostic contains:",
" private final Logger log = LoggerFactory.getLogger(new A().getClass());",
" }",
"",
" static final class NonAbstractDynamicLogger {",
" // BUG: Diagnostic contains:",
" private final Logger log = LoggerFactory.getLogger(getClass());",
" }",
"",
" abstract static class DynamicLoggerWithMissingModifier {",
" // BUG: Diagnostic contains:",
" final Logger log = LoggerFactory.getLogger(getClass());",
" }",
"",
" abstract static class DynamicLoggerWithExcessModifier {",
" // BUG: Diagnostic contains:",
" private final transient Logger log = LoggerFactory.getLogger(getClass());",
" }",
"",
" abstract static class MisnamedDynamicLogger {",
" // BUG: Diagnostic contains:",
" private final Logger LOG = LoggerFactory.getLogger(getClass());",
" }",
"",
" static final class StaticLoggerWithMissingModifier {",
" // BUG: Diagnostic contains:",
" static final Logger LOG = LoggerFactory.getLogger(StaticLoggerWithMissingModifier.class);",
" }",
"",
" static final class StaticLoggerWithExcessModifier {",
" // BUG: Diagnostic contains:",
" private static final transient Logger LOG =",
" LoggerFactory.getLogger(StaticLoggerWithExcessModifier.class);",
" }",
"",
" static final class MisnamedStaticLogger {",
" // BUG: Diagnostic contains:",
" private static final Logger log = LoggerFactory.getLogger(MisnamedStaticLogger.class);",
" }",
"",
" static final class StaticLoggerWithIncorrectIdentifier {",
" // BUG: Diagnostic contains:",
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
" }",
"",
" static final class StaticLoggerWithCustomIdentifierAndMissingModifier {",
" // BUG: Diagnostic contains:",
" static final Logger LOG = LoggerFactory.getLogger(\"custom-identifier\");",
" }",
"",
" static final class StaticLoggerWithCustomIdentifierAndExcessModifier {",
" // BUG: Diagnostic contains:",
" private static final transient Logger LOG = LoggerFactory.getLogger(\"custom-identifier\");",
" }",
"",
" static final class MisnamedStaticLoggerWithCustomIdentifier {",
" // BUG: Diagnostic contains:",
" private static final Logger log = LoggerFactory.getLogger(\"custom-identifier\");",
" }",
"",
" interface StaticLoggerForInterfaceWithExcessModifier {",
" // BUG: Diagnostic contains:",
" static Logger LOG = LoggerFactory.getLogger(StaticLoggerForInterfaceWithExcessModifier.class);",
" }",
"",
" interface MisnamedStaticLoggerForInterface {",
" // BUG: Diagnostic contains:",
" Logger log = LoggerFactory.getLogger(MisnamedStaticLoggerForInterface.class);",
" }",
"",
" interface StaticLoggerForInterfaceWithIncorrectIdentifier {",
" // BUG: Diagnostic contains:",
" Logger LOG = LoggerFactory.getLogger(A.class);",
" }",
"}")
.doTest();
}
@Test
void replacement() {
BugCheckerRefactoringTestHelper.newInstance(Slf4jLoggerDeclaration.class, getClass())
.addInputLines(
"A.java",
"import org.slf4j.Logger;",
"import org.slf4j.LoggerFactory;",
"",
"class A {",
" static Logger foo = LoggerFactory.getLogger(Logger.class);",
"",
" abstract static class DynamicLogger {",
" transient Logger BAR = LoggerFactory.getLogger(getClass());",
" }",
"",
" static final class StaticLogger {",
" transient Logger baz = LoggerFactory.getLogger(LoggerFactory.class);",
" }",
"",
" static final class StaticLoggerWithCustomIdentifier {",
" transient Logger qux = LoggerFactory.getLogger(\"custom-identifier\");",
" }",
"",
" interface StaticLoggerForInterface {",
" public static final Logger quux = LoggerFactory.getLogger(A.class);",
" }",
"}")
.addOutputLines(
"A.java",
"import org.slf4j.Logger;",
"import org.slf4j.LoggerFactory;",
"",
"class A {",
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
"",
" abstract static class DynamicLogger {",
" private final Logger log = LoggerFactory.getLogger(getClass());",
" }",
"",
" static final class StaticLogger {",
" private static final Logger LOG = LoggerFactory.getLogger(StaticLogger.class);",
" }",
"",
" static final class StaticLoggerWithCustomIdentifier {",
" private static final Logger LOG = LoggerFactory.getLogger(\"custom-identifier\");",
" }",
"",
" interface StaticLoggerForInterface {",
" Logger LOG = LoggerFactory.getLogger(StaticLoggerForInterface.class);",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
@Test
void replacementWithCustomLoggerName() {
BugCheckerRefactoringTestHelper.newInstance(Slf4jLoggerDeclaration.class, getClass())
.setArgs(ImmutableList.of("-XepOpt:Slf4jLogDeclaration:CanonicalStaticLoggerName=FOO_BAR"))
.addInputLines(
"A.java",
"import org.slf4j.Logger;",
"import org.slf4j.LoggerFactory;",
"",
"class A {",
" transient Logger LOG = LoggerFactory.getLogger(Logger.class);",
"",
" abstract static class DynamicLogger {",
" transient Logger log = LoggerFactory.getLogger(getClass());",
" }",
"}")
.addOutputLines(
"A.java",
"import org.slf4j.Logger;",
"import org.slf4j.LoggerFactory;",
"",
"class A {",
" private static final Logger FOO_BAR = LoggerFactory.getLogger(A.class);",
"",
" abstract static class DynamicLogger {",
" private final Logger fooBar = LoggerFactory.getLogger(getClass());",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -43,6 +43,7 @@ final class RefasterRulesTest {
EqualityRules.class,
FileRules.class,
InputStreamRules.class,
ImmutableEnumSetRules.class,
ImmutableListRules.class,
ImmutableListMultimapRules.class,
ImmutableMapRules.class,
@@ -58,6 +59,7 @@ final class RefasterRulesTest {
LongStreamRules.class,
MapEntryRules.class,
MapRules.class,
MicrometerRules.class,
MockitoRules.class,
MultimapRules.class,
NullRules.class,

View File

@@ -1,10 +1,7 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.BoundType;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -24,8 +21,7 @@ final class AssortedRulesTest implements RefasterRuleCollectionTestCase {
Preconditions.class,
Sets.class,
Splitter.class,
Streams.class,
toImmutableSet());
Streams.class);
}
int testCheckIndex() {
@@ -38,10 +34,6 @@ final class AssortedRulesTest implements RefasterRuleCollectionTestCase {
}
}
ImmutableSet<BoundType> testStreamToImmutableEnumSet() {
return Stream.of(BoundType.OPEN).collect(toImmutableSet());
}
ImmutableSet<String> testIteratorGetNextOrDefault() {
return ImmutableSet.of(
ImmutableList.of("a").iterator().hasNext()

View File

@@ -1,12 +1,9 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Sets.toImmutableEnumSet;
import static java.util.Objects.checkIndex;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.BoundType;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -27,8 +24,7 @@ final class AssortedRulesTest implements RefasterRuleCollectionTestCase {
Preconditions.class,
Sets.class,
Splitter.class,
Streams.class,
toImmutableSet());
Streams.class);
}
int testCheckIndex() {
@@ -39,10 +35,6 @@ final class AssortedRulesTest implements RefasterRuleCollectionTestCase {
checkIndex(1, 2);
}
ImmutableSet<BoundType> testStreamToImmutableEnumSet() {
return Stream.of(BoundType.OPEN).collect(toImmutableEnumSet());
}
ImmutableSet<String> testIteratorGetNextOrDefault() {
return ImmutableSet.of(
Iterators.getNext(ImmutableList.of("a").iterator(), "foo"),

View File

@@ -5,6 +5,7 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper;
import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;
import com.google.errorprone.bugpatterns.BugChecker;
import com.sun.tools.javac.util.Convert;
import javax.lang.model.element.Name;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
@@ -31,4 +32,10 @@ final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
String testConstantsFormat() {
return String.format("\"%s\"", Convert.quote("foo"));
}
ImmutableSet<Boolean> testNameContentEquals() {
return ImmutableSet.of(
((Name) null).toString().equals("foo".subSequence(0, 1).toString()),
((com.sun.tools.javac.util.Name) null).toString().equals("bar"));
}
}

View File

@@ -6,6 +6,7 @@ import com.google.errorprone.BugCheckerRefactoringTestHelper.FixChoosers;
import com.google.errorprone.bugpatterns.BugChecker;
import com.sun.tools.javac.util.Constants;
import com.sun.tools.javac.util.Convert;
import javax.lang.model.element.Name;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
@@ -30,4 +31,10 @@ final class BugCheckerRulesTest implements RefasterRuleCollectionTestCase {
String testConstantsFormat() {
return Constants.format("foo");
}
ImmutableSet<Boolean> testNameContentEquals() {
return ImmutableSet.of(
((Name) null).contentEquals("foo".subSequence(0, 1)),
((com.sun.tools.javac.util.Name) null).contentEquals("bar"));
}
}

View File

@@ -1,26 +1,30 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.function.Function;
import java.util.function.Predicate;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class ClassRulesTest implements RefasterRuleCollectionTestCase {
boolean testClassIsInstance() throws IOException {
boolean testClassIsInstance() {
return CharSequence.class.isAssignableFrom("foo".getClass());
}
ImmutableSet<Boolean> testInstanceof() throws IOException {
ImmutableSet<Boolean> testInstanceof() {
Class<?> clazz = CharSequence.class;
return ImmutableSet.of(CharSequence.class.isInstance("foo"), clazz.isInstance("bar"));
}
Predicate<String> testClassLiteralIsInstancePredicate() throws IOException {
Predicate<String> testClassLiteralIsInstancePredicate() {
return s -> s instanceof CharSequence;
}
Predicate<String> testClassReferenceIsInstancePredicate() throws IOException {
Predicate<String> testClassReferenceIsInstancePredicate() {
Class<?> clazz = CharSequence.class;
return s -> clazz.isInstance(s);
}
Function<Number, Integer> testClassReferenceCast() {
return i -> Integer.class.cast(i);
}
}

View File

@@ -1,26 +1,30 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.function.Function;
import java.util.function.Predicate;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class ClassRulesTest implements RefasterRuleCollectionTestCase {
boolean testClassIsInstance() throws IOException {
boolean testClassIsInstance() {
return CharSequence.class.isInstance("foo");
}
ImmutableSet<Boolean> testInstanceof() throws IOException {
ImmutableSet<Boolean> testInstanceof() {
Class<?> clazz = CharSequence.class;
return ImmutableSet.of("foo" instanceof CharSequence, clazz.isInstance("bar"));
}
Predicate<String> testClassLiteralIsInstancePredicate() throws IOException {
Predicate<String> testClassLiteralIsInstancePredicate() {
return CharSequence.class::isInstance;
}
Predicate<String> testClassReferenceIsInstancePredicate() throws IOException {
Predicate<String> testClassReferenceIsInstancePredicate() {
Class<?> clazz = CharSequence.class;
return clazz::isInstance;
}
Function<Number, Integer> testClassReferenceCast() {
return Integer.class::cast;
}
}

View File

@@ -6,9 +6,11 @@ import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.TreeSet;
import java.util.stream.Stream;
@@ -70,6 +72,10 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
}
}
Stream<Integer> testSetStream() {
return ImmutableSet.of(1).stream().distinct();
}
ArrayList<String> testNewArrayListFromCollection() {
return Lists.newArrayList(ImmutableList.of("foo"));
}
@@ -94,6 +100,10 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(1).asList().toString();
}
List<String> testArraysAsList() {
return Arrays.stream(new String[0]).toList();
}
ImmutableSet<Object[]> testCollectionToArray() {
return ImmutableSet.of(
ImmutableSet.of(1).toArray(new Object[1]),
@@ -109,8 +119,9 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(1).asList().toArray(Integer[]::new);
}
Iterator<Integer> testImmutableCollectionIterator() {
return ImmutableSet.of(1).asList().iterator();
ImmutableSet<Iterator<Integer>> testCollectionIterator() {
return ImmutableSet.of(
ImmutableSet.of(1).stream().iterator(), ImmutableSet.of(2).asList().iterator());
}
ImmutableSet<Optional<Integer>> testOptionalFirstCollectionElement() {

View File

@@ -6,9 +6,11 @@ import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.TreeSet;
import java.util.stream.Stream;
@@ -62,6 +64,10 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
new HashSet<Number>().removeAll(ImmutableSet.of(2));
}
Stream<Integer> testSetStream() {
return ImmutableSet.of(1).stream();
}
ArrayList<String> testNewArrayListFromCollection() {
return new ArrayList<>(ImmutableList.of("foo"));
}
@@ -86,6 +92,10 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(1).toString();
}
List<String> testArraysAsList() {
return Arrays.asList(new String[0]);
}
ImmutableSet<Object[]> testCollectionToArray() {
return ImmutableSet.of(
ImmutableSet.of(1).toArray(), ImmutableSet.of(2).toArray(), ImmutableSet.of(3).toArray());
@@ -99,8 +109,8 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(1).toArray(Integer[]::new);
}
Iterator<Integer> testImmutableCollectionIterator() {
return ImmutableSet.of(1).iterator();
ImmutableSet<Iterator<Integer>> testCollectionIterator() {
return ImmutableSet.of(ImmutableSet.of(1).iterator(), ImmutableSet.of(2).iterator());
}
ImmutableSet<Optional<Integer>> testOptionalFirstCollectionElement() {

View File

@@ -107,6 +107,24 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
Comparator.<String>reverseOrder().compare("baz", "qux"));
}
void testCollectionsSort() {
Collections.sort(ImmutableList.of("foo", "bar"), naturalOrder());
}
ImmutableSet<String> testCollectionsMin() {
return ImmutableSet.of(
Collections.min(ImmutableList.of("foo"), naturalOrder()),
Collections.max(ImmutableList.of("bar"), reverseOrder()));
}
String testMinOfArray() {
return Arrays.stream(new String[0]).min(naturalOrder()).orElseThrow();
}
String testCollectionsMinWithComparator() {
return ImmutableSet.of("foo", "bar").stream().min(naturalOrder()).orElseThrow();
}
int testMinOfVarargs() {
return Stream.of(1, 2).min(naturalOrder()).orElseThrow();
}
@@ -135,6 +153,20 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
Collections.min(ImmutableSet.of("a", "b"), (a, b) -> 1));
}
ImmutableSet<String> testCollectionsMax() {
return ImmutableSet.of(
Collections.max(ImmutableList.of("foo"), naturalOrder()),
Collections.min(ImmutableList.of("bar"), reverseOrder()));
}
String testMaxOfArray() {
return Arrays.stream(new String[0]).max(naturalOrder()).orElseThrow();
}
String testCollectionsMaxWithComparator() {
return ImmutableSet.of("foo", "bar").stream().max(naturalOrder()).orElseThrow();
}
int testMaxOfVarargs() {
return Stream.of(1, 2).max(naturalOrder()).orElseThrow();
}

View File

@@ -98,6 +98,23 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of("foo".compareTo("bar"), "qux".compareTo("baz"));
}
void testCollectionsSort() {
Collections.sort(ImmutableList.of("foo", "bar"));
}
ImmutableSet<String> testCollectionsMin() {
return ImmutableSet.of(
Collections.min(ImmutableList.of("foo")), Collections.min(ImmutableList.of("bar")));
}
String testMinOfArray() {
return Collections.min(Arrays.asList(new String[0]), naturalOrder());
}
String testCollectionsMinWithComparator() {
return Collections.min(ImmutableSet.of("foo", "bar"), naturalOrder());
}
int testMinOfVarargs() {
return Collections.min(Arrays.asList(1, 2), naturalOrder());
}
@@ -126,6 +143,19 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
Comparators.min("a", "b", (a, b) -> 1));
}
ImmutableSet<String> testCollectionsMax() {
return ImmutableSet.of(
Collections.max(ImmutableList.of("foo")), Collections.max(ImmutableList.of("bar")));
}
String testMaxOfArray() {
return Collections.max(Arrays.asList(new String[0]), naturalOrder());
}
String testCollectionsMaxWithComparator() {
return Collections.max(ImmutableSet.of("foo", "bar"), naturalOrder());
}
int testMaxOfVarargs() {
return Collections.max(Arrays.asList(1, 2), naturalOrder());
}

View File

@@ -1,12 +1,28 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class FileRulesTest implements RefasterRuleCollectionTestCase {
Path testPathOfUri() {
return Paths.get(URI.create("foo"));
}
ImmutableSet<Path> testPathOfString() {
return ImmutableSet.of(Paths.get("foo"), Paths.get("bar", "baz", "qux"));
}
Path testPathInstance() {
return Path.of("foo").toFile().toPath();
}
String testFilesReadStringWithCharset() throws IOException {
return new String(Files.readAllBytes(Paths.get("foo")), StandardCharsets.ISO_8859_1);
}
@@ -14,4 +30,13 @@ final class FileRulesTest implements RefasterRuleCollectionTestCase {
String testFilesReadString() throws IOException {
return Files.readString(Paths.get("foo"), StandardCharsets.UTF_8);
}
ImmutableSet<File> testFilesCreateTempFileToFile() throws IOException {
return ImmutableSet.of(
File.createTempFile("foo", "bar"), File.createTempFile("baz", "qux", null));
}
File testFilesCreateTempFileInCustomDirectoryToFile() throws IOException {
return File.createTempFile("foo", "bar", new File("baz"));
}
}

View File

@@ -1,12 +1,28 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class FileRulesTest implements RefasterRuleCollectionTestCase {
Path testPathOfUri() {
return Path.of(URI.create("foo"));
}
ImmutableSet<Path> testPathOfString() {
return ImmutableSet.of(Path.of("foo"), Path.of("bar", "baz", "qux"));
}
Path testPathInstance() {
return Path.of("foo");
}
String testFilesReadStringWithCharset() throws IOException {
return Files.readString(Paths.get("foo"), StandardCharsets.ISO_8859_1);
}
@@ -14,4 +30,13 @@ final class FileRulesTest implements RefasterRuleCollectionTestCase {
String testFilesReadString() throws IOException {
return Files.readString(Paths.get("foo"));
}
ImmutableSet<File> testFilesCreateTempFileToFile() throws IOException {
return ImmutableSet.of(
Files.createTempFile("foo", "bar").toFile(), Files.createTempFile("baz", "qux").toFile());
}
File testFilesCreateTempFileInCustomDirectoryToFile() throws IOException {
return Files.createTempFile(new File("baz").toPath(), "foo", "bar").toFile();
}
}

View File

@@ -0,0 +1,96 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import com.google.common.collect.BoundType;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import java.math.RoundingMode;
import java.util.EnumSet;
import java.util.stream.Stream;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class ImmutableEnumSetRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(EnumSet.class, toImmutableSet());
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSetIterable() {
return ImmutableSet.of(
ImmutableSet.copyOf(Iterables.cycle(RoundingMode.UP)),
ImmutableSet.copyOf(EnumSet.allOf(RoundingMode.class)));
}
ImmutableSet<RoundingMode> testSetsImmutableEnumSetArraysAsList() {
return ImmutableSet.copyOf(RoundingMode.values());
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet1() {
return ImmutableSet.of(
ImmutableSet.of(RoundingMode.UP), ImmutableSet.copyOf(EnumSet.of(RoundingMode.UP)));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet2() {
return ImmutableSet.of(
ImmutableSet.of(RoundingMode.UP, RoundingMode.DOWN),
ImmutableSet.copyOf(EnumSet.of(RoundingMode.UP, RoundingMode.DOWN)));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet3() {
return ImmutableSet.of(
ImmutableSet.of(RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING),
ImmutableSet.copyOf(EnumSet.of(RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING)));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet4() {
return ImmutableSet.of(
ImmutableSet.of(
RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR),
ImmutableSet.copyOf(
EnumSet.of(
RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR)));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet5() {
return ImmutableSet.of(
ImmutableSet.of(
RoundingMode.UP,
RoundingMode.DOWN,
RoundingMode.CEILING,
RoundingMode.FLOOR,
RoundingMode.UNNECESSARY),
ImmutableSet.copyOf(
EnumSet.of(
RoundingMode.UP,
RoundingMode.DOWN,
RoundingMode.CEILING,
RoundingMode.FLOOR,
RoundingMode.UNNECESSARY)));
}
ImmutableSet<RoundingMode> testSetsImmutableEnumSet6() {
return ImmutableSet.of(
RoundingMode.UP,
RoundingMode.DOWN,
RoundingMode.CEILING,
RoundingMode.FLOOR,
RoundingMode.UNNECESSARY,
RoundingMode.HALF_EVEN);
}
ImmutableSet<RoundingMode> testSetsImmutableEnumSetVarArgs() {
return ImmutableSet.copyOf(
EnumSet.of(
RoundingMode.UP,
RoundingMode.DOWN,
RoundingMode.CEILING,
RoundingMode.FLOOR,
RoundingMode.UNNECESSARY,
RoundingMode.HALF_EVEN));
}
ImmutableSet<BoundType> testStreamToImmutableEnumSet() {
return Stream.of(BoundType.OPEN).collect(toImmutableSet());
}
}

View File

@@ -0,0 +1,96 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Sets.toImmutableEnumSet;
import com.google.common.collect.BoundType;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.stream.Stream;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class ImmutableEnumSetRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(EnumSet.class, toImmutableSet());
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSetIterable() {
return ImmutableSet.of(
Sets.immutableEnumSet(Iterables.cycle(RoundingMode.UP)),
Sets.immutableEnumSet(EnumSet.allOf(RoundingMode.class)));
}
ImmutableSet<RoundingMode> testSetsImmutableEnumSetArraysAsList() {
return Sets.immutableEnumSet(Arrays.asList(RoundingMode.values()));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet1() {
return ImmutableSet.of(
Sets.immutableEnumSet(RoundingMode.UP), Sets.immutableEnumSet(RoundingMode.UP));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet2() {
return ImmutableSet.of(
Sets.immutableEnumSet(RoundingMode.UP, RoundingMode.DOWN),
Sets.immutableEnumSet(RoundingMode.UP, RoundingMode.DOWN));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet3() {
return ImmutableSet.of(
Sets.immutableEnumSet(RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING),
Sets.immutableEnumSet(RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet4() {
return ImmutableSet.of(
Sets.immutableEnumSet(
RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR),
Sets.immutableEnumSet(
RoundingMode.UP, RoundingMode.DOWN, RoundingMode.CEILING, RoundingMode.FLOOR));
}
ImmutableSet<ImmutableSet<RoundingMode>> testSetsImmutableEnumSet5() {
return ImmutableSet.of(
Sets.immutableEnumSet(
RoundingMode.UP,
RoundingMode.DOWN,
RoundingMode.CEILING,
RoundingMode.FLOOR,
RoundingMode.UNNECESSARY),
Sets.immutableEnumSet(
RoundingMode.UP,
RoundingMode.DOWN,
RoundingMode.CEILING,
RoundingMode.FLOOR,
RoundingMode.UNNECESSARY));
}
ImmutableSet<RoundingMode> testSetsImmutableEnumSet6() {
return Sets.immutableEnumSet(
RoundingMode.UP,
RoundingMode.DOWN,
RoundingMode.CEILING,
RoundingMode.FLOOR,
RoundingMode.UNNECESSARY,
RoundingMode.HALF_EVEN);
}
ImmutableSet<RoundingMode> testSetsImmutableEnumSetVarArgs() {
return Sets.immutableEnumSet(
RoundingMode.UP,
RoundingMode.DOWN,
RoundingMode.CEILING,
RoundingMode.FLOOR,
RoundingMode.UNNECESSARY,
RoundingMode.HALF_EVEN);
}
ImmutableSet<BoundType> testStreamToImmutableEnumSet() {
return Stream.of(BoundType.OPEN).collect(toImmutableEnumSet());
}
}

View File

@@ -26,6 +26,7 @@ final class ImmutableMultisetRulesTest implements RefasterRuleCollectionTestCase
Stream.<Integer>empty().collect(toImmutableMultiset()));
}
@SuppressWarnings("unchecked")
ImmutableMultiset<ImmutableMultiset<Integer>> testIterableToImmutableMultiset() {
return ImmutableMultiset.of(
ImmutableList.of(1).stream().collect(toImmutableMultiset()),

View File

@@ -24,6 +24,7 @@ final class ImmutableMultisetRulesTest implements RefasterRuleCollectionTestCase
return ImmutableMultiset.of(ImmutableMultiset.of(), ImmutableMultiset.of());
}
@SuppressWarnings("unchecked")
ImmutableMultiset<ImmutableMultiset<Integer>> testIterableToImmutableMultiset() {
return ImmutableMultiset.of(
ImmutableMultiset.copyOf(ImmutableList.of(1)),

View File

@@ -37,6 +37,7 @@ final class ImmutableSortedMultisetRulesTest implements RefasterRuleCollectionTe
Stream.<Integer>empty().collect(toImmutableSortedMultiset(naturalOrder())));
}
@SuppressWarnings("unchecked")
ImmutableMultiset<ImmutableSortedMultiset<Integer>> testIterableToImmutableSortedMultiset() {
return ImmutableMultiset.of(
ImmutableSortedMultiset.copyOf(naturalOrder(), ImmutableList.of(1)),

View File

@@ -35,6 +35,7 @@ final class ImmutableSortedMultisetRulesTest implements RefasterRuleCollectionTe
return ImmutableMultiset.of(ImmutableSortedMultiset.of(), ImmutableSortedMultiset.of());
}
@SuppressWarnings("unchecked")
ImmutableMultiset<ImmutableSortedMultiset<Integer>> testIterableToImmutableSortedMultiset() {
return ImmutableMultiset.of(
ImmutableSortedMultiset.copyOf(ImmutableList.of(1)),

View File

@@ -0,0 +1,57 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import io.micrometer.core.instrument.Tag;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class MicrometerRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(ImmutableList.class);
}
ImmutableSet<Iterable<Tag>> testTagsOf1() {
return ImmutableSet.of(
ImmutableSet.of(Tag.of("foo", "v1")), ImmutableList.of(Tag.of("bar", "v2")));
}
ImmutableSet<Iterable<Tag>> testTagsOf2() {
return ImmutableSet.of(
ImmutableSet.of(Tag.of("foo", "v1"), Tag.of("bar", "v2")),
ImmutableList.of(Tag.of("baz", "v3"), Tag.of("qux", "v4")));
}
ImmutableSet<Iterable<Tag>> testTagsOf3() {
return ImmutableSet.of(
ImmutableSet.of(Tag.of("foo", "v1"), Tag.of("bar", "v2"), Tag.of("baz", "v3")),
ImmutableList.of(Tag.of("qux", "v4"), Tag.of("quux", "v5"), Tag.of("corge", "v6")));
}
ImmutableSet<Iterable<Tag>> testTagsOf4() {
return ImmutableSet.of(
ImmutableSet.of(
Tag.of("foo", "v1"), Tag.of("bar", "v2"), Tag.of("baz", "v3"), Tag.of("qux", "v4")),
ImmutableList.of(
Tag.of("quux", "v5"),
Tag.of("corge", "v6"),
Tag.of("grault", "v7"),
Tag.of("garply", "v8")));
}
ImmutableSet<Iterable<Tag>> testTagsOf5() {
return ImmutableSet.of(
ImmutableSet.of(
Tag.of("foo", "v1"),
Tag.of("bar", "v2"),
Tag.of("baz", "v3"),
Tag.of("qux", "v4"),
Tag.of("quux", "v5")),
ImmutableList.of(
Tag.of("corge", "v6"),
Tag.of("grault", "v7"),
Tag.of("garply", "v8"),
Tag.of("waldo", "v9"),
Tag.of("fred", "v10")));
}
}

View File

@@ -0,0 +1,56 @@
package tech.picnic.errorprone.refasterrules;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class MicrometerRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(ImmutableList.class);
}
ImmutableSet<Iterable<Tag>> testTagsOf1() {
return ImmutableSet.of(Tags.of(Tag.of("foo", "v1")), Tags.of(Tag.of("bar", "v2")));
}
ImmutableSet<Iterable<Tag>> testTagsOf2() {
return ImmutableSet.of(
Tags.of(Tag.of("foo", "v1"), Tag.of("bar", "v2")),
Tags.of(Tag.of("baz", "v3"), Tag.of("qux", "v4")));
}
ImmutableSet<Iterable<Tag>> testTagsOf3() {
return ImmutableSet.of(
Tags.of(Tag.of("foo", "v1"), Tag.of("bar", "v2"), Tag.of("baz", "v3")),
Tags.of(Tag.of("qux", "v4"), Tag.of("quux", "v5"), Tag.of("corge", "v6")));
}
ImmutableSet<Iterable<Tag>> testTagsOf4() {
return ImmutableSet.of(
Tags.of(Tag.of("foo", "v1"), Tag.of("bar", "v2"), Tag.of("baz", "v3"), Tag.of("qux", "v4")),
Tags.of(
Tag.of("quux", "v5"),
Tag.of("corge", "v6"),
Tag.of("grault", "v7"),
Tag.of("garply", "v8")));
}
ImmutableSet<Iterable<Tag>> testTagsOf5() {
return ImmutableSet.of(
Tags.of(
Tag.of("foo", "v1"),
Tag.of("bar", "v2"),
Tag.of("baz", "v3"),
Tag.of("qux", "v4"),
Tag.of("quux", "v5")),
Tags.of(
Tag.of("corge", "v6"),
Tag.of("grault", "v7"),
Tag.of("garply", "v8"),
Tag.of("waldo", "v9"),
Tag.of("fred", "v10")));
}
}

View File

@@ -83,11 +83,9 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
return Optional.of("foo").orElseGet(() -> Optional.of("bar").orElseThrow());
}
ImmutableSet<String> testOptionalOrElseGet() {
ImmutableSet<String> testOptionalOrElse() {
return ImmutableSet.of(
Optional.of("foo").orElse("bar"),
Optional.of("baz").orElse(toString()),
Optional.of("qux").orElse(String.valueOf(true)));
Optional.of("foo").orElseGet(() -> "bar"), Optional.of("baz").orElseGet(() -> toString()));
}
ImmutableSet<Object> testStreamFlatMapOptional() {

View File

@@ -80,11 +80,9 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
return Optional.of("foo").or(() -> Optional.of("bar")).orElseThrow();
}
ImmutableSet<String> testOptionalOrElseGet() {
ImmutableSet<String> testOptionalOrElse() {
return ImmutableSet.of(
Optional.of("foo").orElse("bar"),
Optional.of("baz").orElse(toString()),
Optional.of("qux").orElseGet(() -> String.valueOf(true)));
Optional.of("foo").orElse("bar"), Optional.of("baz").orElseGet(() -> toString()));
}
ImmutableSet<Object> testStreamFlatMapOptional() {

View File

@@ -9,6 +9,8 @@ import com.google.common.primitives.Floats;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.google.common.primitives.UnsignedInts;
import com.google.common.primitives.UnsignedLongs;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
@@ -22,7 +24,9 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
Floats.class,
Ints.class,
Longs.class,
Shorts.class);
Shorts.class,
UnsignedInts.class,
UnsignedLongs.class);
}
ImmutableSet<Boolean> testLessThan() {
@@ -105,34 +109,6 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
return Doubles.hashCode(1);
}
int testBooleanCompare() {
return Booleans.compare(false, true);
}
int testCharacterCompare() {
return Chars.compare('a', 'b');
}
int testShortCompare() {
return Shorts.compare((short) 1, (short) 2);
}
int testIntegerCompare() {
return Ints.compare(1, 2);
}
int testLongCompare() {
return Longs.compare(1, 2);
}
int testFloatCompare() {
return Floats.compare(1, 2);
}
int testDoubleCompare() {
return Doubles.compare(1, 2);
}
int testCharacterBytes() {
return Chars.BYTES;
}
@@ -190,4 +166,60 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(
Long.signum(1L) < 0, Long.signum(2L) <= -1, Long.signum(3L) >= 0, Long.signum(4L) > -1);
}
int testIntegerCompareUnsigned() {
return UnsignedInts.compare(1, 2);
}
long testLongCompareUnsigned() {
return UnsignedLongs.compare(1, 2);
}
int testIntegerDivideUnsigned() {
return UnsignedInts.divide(1, 2);
}
long testLongDivideUnsigned() {
return UnsignedLongs.divide(1, 2);
}
int testIntegerRemainderUnsigned() {
return UnsignedInts.remainder(1, 2);
}
long testLongRemainderUnsigned() {
return UnsignedLongs.remainder(1, 2);
}
ImmutableSet<Integer> testIntegerParseUnsignedInt() {
return ImmutableSet.of(UnsignedInts.parseUnsignedInt("1"), Integer.parseUnsignedInt("2", 10));
}
ImmutableSet<Long> testLongParseUnsignedLong() {
return ImmutableSet.of(UnsignedLongs.parseUnsignedLong("1"), Long.parseUnsignedLong("2", 10));
}
int testIntegerParseUnsignedIntWithRadix() {
return UnsignedInts.parseUnsignedInt("1", 2);
}
long testLongParseUnsignedLongWithRadix() {
return UnsignedLongs.parseUnsignedLong("1", 2);
}
ImmutableSet<String> testIntegerToUnsignedString() {
return ImmutableSet.of(UnsignedInts.toString(1), Integer.toUnsignedString(2, 10));
}
ImmutableSet<String> testLongToUnsignedString() {
return ImmutableSet.of(UnsignedLongs.toString(1), Long.toUnsignedString(2, 10));
}
String testIntegerToUnsignedStringWithRadix() {
return UnsignedInts.toString(1, 2);
}
String testLongToUnsignedStringWithRadix() {
return UnsignedLongs.toString(1, 2);
}
}

View File

@@ -9,6 +9,8 @@ import com.google.common.primitives.Floats;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import com.google.common.primitives.UnsignedInts;
import com.google.common.primitives.UnsignedLongs;
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
@@ -22,7 +24,9 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
Floats.class,
Ints.class,
Longs.class,
Shorts.class);
Shorts.class,
UnsignedInts.class,
UnsignedLongs.class);
}
ImmutableSet<Boolean> testLessThan() {
@@ -105,34 +109,6 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
return Double.hashCode(1);
}
int testBooleanCompare() {
return Boolean.compare(false, true);
}
int testCharacterCompare() {
return Character.compare('a', 'b');
}
int testShortCompare() {
return Short.compare((short) 1, (short) 2);
}
int testIntegerCompare() {
return Integer.compare(1, 2);
}
int testLongCompare() {
return Long.compare(1, 2);
}
int testFloatCompare() {
return Float.compare(1, 2);
}
int testDoubleCompare() {
return Double.compare(1, 2);
}
int testCharacterBytes() {
return Character.BYTES;
}
@@ -190,4 +166,60 @@ final class PrimitiveRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(
Long.signum(1L) == -1, Long.signum(2L) == -1, Long.signum(3L) != -1, Long.signum(4L) != -1);
}
int testIntegerCompareUnsigned() {
return Integer.compareUnsigned(1, 2);
}
long testLongCompareUnsigned() {
return Long.compareUnsigned(1, 2);
}
int testIntegerDivideUnsigned() {
return Integer.divideUnsigned(1, 2);
}
long testLongDivideUnsigned() {
return Long.divideUnsigned(1, 2);
}
int testIntegerRemainderUnsigned() {
return Integer.remainderUnsigned(1, 2);
}
long testLongRemainderUnsigned() {
return Long.remainderUnsigned(1, 2);
}
ImmutableSet<Integer> testIntegerParseUnsignedInt() {
return ImmutableSet.of(Integer.parseUnsignedInt("1"), Integer.parseUnsignedInt("2"));
}
ImmutableSet<Long> testLongParseUnsignedLong() {
return ImmutableSet.of(Long.parseUnsignedLong("1"), Long.parseUnsignedLong("2"));
}
int testIntegerParseUnsignedIntWithRadix() {
return Integer.parseUnsignedInt("1", 2);
}
long testLongParseUnsignedLongWithRadix() {
return Long.parseUnsignedLong("1", 2);
}
ImmutableSet<String> testIntegerToUnsignedString() {
return ImmutableSet.of(Integer.toUnsignedString(1), Integer.toUnsignedString(2));
}
ImmutableSet<String> testLongToUnsignedString() {
return ImmutableSet.of(Long.toUnsignedString(1), Long.toUnsignedString(2));
}
String testIntegerToUnsignedStringWithRadix() {
return Integer.toUnsignedString(1, 2);
}
String testLongToUnsignedStringWithRadix() {
return Long.toUnsignedString(1, 2);
}
}

View File

@@ -10,6 +10,7 @@ import static java.util.stream.Collectors.minBy;
import static java.util.stream.Collectors.toCollection;
import static org.assertj.core.api.Assertions.assertThat;
import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -23,6 +24,7 @@ import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import java.util.stream.Stream;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.math.MathFlux;
@@ -434,8 +436,10 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Flux.just(ImmutableList.of("bar")).concatMap(Flux::fromIterable, 2));
}
Flux<String> testFluxFromIterable() {
return Flux.fromStream(ImmutableList.of("foo").stream());
ImmutableSet<Flux<String>> testFluxFromIterable() {
return ImmutableSet.of(
Flux.fromStream(ImmutableList.of("foo")::stream),
Flux.fromStream(() -> ImmutableList.of("bar").stream()));
}
ImmutableSet<Mono<Integer>> testFluxCountMapMathToIntExact() {
@@ -594,6 +598,18 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
return StepVerifier.create(Flux.just(1));
}
Object testStepVerifierVerify() {
return Mono.empty().as(StepVerifier::create).expectError().verifyThenAssertThat();
}
Object testStepVerifierVerifyDuration() {
return Mono.empty().as(StepVerifier::create).expectError().verifyThenAssertThat(Duration.ZERO);
}
StepVerifier testStepVerifierVerifyLater() {
return Mono.empty().as(StepVerifier::create).expectError().verifyLater().verifyLater();
}
ImmutableSet<StepVerifier.Step<Integer>> testStepVerifierStepIdentity() {
return ImmutableSet.of(
Mono.just(1).as(StepVerifier::create).expectNext(),
@@ -634,17 +650,43 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
.verifyErrorSatisfies(t -> assertThat(t).isInstanceOf(AssertionError.class)));
}
Duration testStepVerifierLastStepVerifyErrorMatches() {
return Mono.empty()
.as(StepVerifier::create)
.expectErrorMatches(IllegalArgumentException.class::equals)
.verify();
ImmutableSet<?> testStepVerifierLastStepVerifyErrorMatches() {
return ImmutableSet.of(
Mono.empty()
.as(StepVerifier::create)
.expectErrorMatches(IllegalArgumentException.class::equals)
.verify(),
Mono.empty()
.as(StepVerifier::create)
.expectError()
.verifyThenAssertThat()
.hasOperatorErrorMatching(IllegalStateException.class::equals));
}
Duration testStepVerifierLastStepVerifyErrorSatisfies() {
return Mono.empty().as(StepVerifier::create).expectErrorSatisfies(t -> {}).verify();
}
ImmutableSet<?> testStepVerifierLastStepVerifyErrorSatisfiesAssertJ() {
return ImmutableSet.of(
Mono.empty()
.as(StepVerifier::create)
.expectError()
.verifyThenAssertThat()
.hasOperatorErrorOfType(IllegalArgumentException.class)
.hasOperatorErrorWithMessage("foo"),
Mono.empty()
.as(StepVerifier::create)
.expectError(IllegalStateException.class)
.verifyThenAssertThat()
.hasOperatorErrorWithMessage("bar"),
Mono.empty()
.as(StepVerifier::create)
.expectErrorMessage("baz")
.verifyThenAssertThat()
.hasOperatorErrorOfType(AssertionError.class));
}
Duration testStepVerifierLastStepVerifyErrorMessage() {
return Mono.empty().as(StepVerifier::create).expectErrorMessage("foo").verify();
}
@@ -660,4 +702,12 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Mono<Void> testMonoFromFutureSupplierBoolean() {
return Mono.fromFuture(CompletableFuture.completedFuture(null), true);
}
Mono<String> testMonoFromFutureAsyncLoadingCacheGet() {
return Mono.fromFuture(() -> ((AsyncLoadingCache<Integer, String>) null).get(0));
}
Flux<Integer> testFluxFromStreamSupplier() {
return Flux.fromStream(Stream.of(1));
}
}

View File

@@ -12,6 +12,7 @@ import static java.util.stream.Collectors.toCollection;
import static org.assertj.core.api.Assertions.assertThat;
import static reactor.function.TupleUtils.function;
import com.github.benmanes.caffeine.cache.AsyncLoadingCache;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -25,6 +26,7 @@ import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import java.util.stream.Stream;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.function.TupleUtils;
@@ -429,8 +431,9 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Flux.just(ImmutableList.of("bar")).concatMapIterable(identity(), 2));
}
Flux<String> testFluxFromIterable() {
return Flux.fromIterable(ImmutableList.of("foo"));
ImmutableSet<Flux<String>> testFluxFromIterable() {
return ImmutableSet.of(
Flux.fromIterable(ImmutableList.of("foo")), Flux.fromIterable(ImmutableList.of("bar")));
}
ImmutableSet<Mono<Integer>> testFluxCountMapMathToIntExact() {
@@ -583,6 +586,18 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
return Flux.just(1).as(StepVerifier::create);
}
Object testStepVerifierVerify() {
return Mono.empty().as(StepVerifier::create).expectError().verify();
}
Object testStepVerifierVerifyDuration() {
return Mono.empty().as(StepVerifier::create).expectError().verify(Duration.ZERO);
}
StepVerifier testStepVerifierVerifyLater() {
return Mono.empty().as(StepVerifier::create).expectError().verifyLater();
}
ImmutableSet<StepVerifier.Step<Integer>> testStepVerifierStepIdentity() {
return ImmutableSet.of(
Mono.just(1).as(StepVerifier::create),
@@ -616,16 +631,36 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Mono.empty().as(StepVerifier::create).verifyError(AssertionError.class));
}
Duration testStepVerifierLastStepVerifyErrorMatches() {
return Mono.empty()
.as(StepVerifier::create)
.verifyErrorMatches(IllegalArgumentException.class::equals);
ImmutableSet<?> testStepVerifierLastStepVerifyErrorMatches() {
return ImmutableSet.of(
Mono.empty()
.as(StepVerifier::create)
.verifyErrorMatches(IllegalArgumentException.class::equals),
Mono.empty()
.as(StepVerifier::create)
.verifyErrorMatches(IllegalStateException.class::equals));
}
Duration testStepVerifierLastStepVerifyErrorSatisfies() {
return Mono.empty().as(StepVerifier::create).verifyErrorSatisfies(t -> {});
}
ImmutableSet<?> testStepVerifierLastStepVerifyErrorSatisfiesAssertJ() {
return ImmutableSet.of(
Mono.empty()
.as(StepVerifier::create)
.verifyErrorSatisfies(
t -> assertThat(t).isInstanceOf(IllegalArgumentException.class).hasMessage("foo")),
Mono.empty()
.as(StepVerifier::create)
.verifyErrorSatisfies(
t -> assertThat(t).isInstanceOf(IllegalStateException.class).hasMessage("bar")),
Mono.empty()
.as(StepVerifier::create)
.verifyErrorSatisfies(
t -> assertThat(t).isInstanceOf(AssertionError.class).hasMessage("baz")));
}
Duration testStepVerifierLastStepVerifyErrorMessage() {
return Mono.empty().as(StepVerifier::create).verifyErrorMessage("foo");
}
@@ -641,4 +676,12 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Mono<Void> testMonoFromFutureSupplierBoolean() {
return Mono.fromFuture(() -> CompletableFuture.completedFuture(null), true);
}
Mono<String> testMonoFromFutureAsyncLoadingCacheGet() {
return Mono.fromFuture(() -> ((AsyncLoadingCache<Integer, String>) null).get(0), true);
}
Flux<Integer> testFluxFromStreamSupplier() {
return Flux.fromStream(() -> Stream.of(1));
}
}

View File

@@ -96,4 +96,32 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
int testUtf8EncodedLength() {
return "foo".getBytes(UTF_8).length;
}
int testStringIndexOfChar() {
return "foo".substring(1).indexOf('a');
}
int testStringIndexOfString() {
return "foo".substring(1).indexOf("bar");
}
int testStringLastIndexOfChar() {
return "foo".substring(1).lastIndexOf('a');
}
int testStringLastIndexOfString() {
return "foo".substring(1).lastIndexOf("bar");
}
int testStringLastIndexOfCharWithIndex() {
return "foo".substring(0, 2).lastIndexOf('a');
}
int testStringLastIndexOfStringWithIndex() {
return "foo".substring(0, 2).lastIndexOf("bar");
}
boolean testStringStartsWith() {
return "foo".substring(1).startsWith("bar");
}
}

View File

@@ -96,4 +96,32 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
int testUtf8EncodedLength() {
return Utf8.encodedLength("foo");
}
int testStringIndexOfChar() {
return Math.max(-1, "foo".indexOf('a', 1) - 1);
}
int testStringIndexOfString() {
return Math.max(-1, "foo".indexOf("bar", 1) - 1);
}
int testStringLastIndexOfChar() {
return Math.max(-1, "foo".lastIndexOf('a') - 1);
}
int testStringLastIndexOfString() {
return Math.max(-1, "foo".lastIndexOf("bar") - 1);
}
int testStringLastIndexOfCharWithIndex() {
return "foo".lastIndexOf('a', 2 - 1);
}
int testStringLastIndexOfStringWithIndex() {
return "foo".lastIndexOf("bar", 2 - 1);
}
boolean testStringStartsWith() {
return "foo".startsWith("bar", 1);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
package tech.picnic.errorprone.utils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.ErrorProneFlags;
/** Helper methods for working with {@link ErrorProneFlags}. */
@@ -19,4 +20,19 @@ public final class Flags {
ImmutableList<String> list = errorProneFlags.getListOrEmpty(name);
return list.equals(ImmutableList.of("")) ? ImmutableList.of() : list;
}
/**
* Returns the set of (comma-separated) arguments passed using the given Error Prone flag.
*
* @param errorProneFlags The full set of flags provided.
* @param name The name of the flag of interest.
* @return A non-{@code null} set of provided arguments; this set is empty if the flag was not
* provided, or if the flag's value is the empty string.
* @implNote This method does not delegate to {@link ErrorProneFlags#getSetOrEmpty(String)}, as
* that method wouldn't allow us to identify a non-singleton set of empty strings; such a set
* should not be treated as empty.
*/
public static ImmutableSet<String> getSet(ErrorProneFlags errorProneFlags, String name) {
return ImmutableSet.copyOf(getList(errorProneFlags, name));
}
}

View File

@@ -78,4 +78,16 @@ public final class MoreASTHelpers {
public static boolean areSameType(Tree treeA, Tree treeB, VisitorState state) {
return ASTHelpers.isSameType(ASTHelpers.getType(treeA), ASTHelpers.getType(treeB), state);
}
/**
* Tells whether the given tree is of type {@link String}.
*
* @param tree The tree of interest.
* @param state The {@link VisitorState} describing the context in which the given tree was found.
* @return Whether the specified tree has the same type as {@link
* com.sun.tools.javac.code.Symtab#stringType}.
*/
public static boolean isStringTyped(Tree tree, VisitorState state) {
return ASTHelpers.isSameType(ASTHelpers.getType(tree), state.getSymtab().stringType, state);
}
}

View File

@@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.ErrorProneOptions;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
@@ -11,21 +12,29 @@ import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
final class FlagsTest {
private static Stream<Arguments> getListTestCases() {
/* { args, flag, expected } */
private static Stream<Arguments> getCollectionTestCases() {
/* { args, flag, listed } */
return Stream.of(
arguments(ImmutableList.of(), "Foo", ImmutableList.of()),
arguments(ImmutableList.of("-XepOpt:Foo=bar,baz"), "Qux", ImmutableList.of()),
arguments(ImmutableList.of("-XepOpt:Foo="), "Foo", ImmutableList.of()),
arguments(ImmutableList.of("-XepOpt:Foo=bar"), "Foo", ImmutableList.of("bar")),
arguments(ImmutableList.of("-XepOpt:Foo=bar,bar"), "Foo", ImmutableList.of("bar", "bar")),
arguments(ImmutableList.of("-XepOpt:Foo=bar,baz"), "Foo", ImmutableList.of("bar", "baz")),
arguments(ImmutableList.of("-XepOpt:Foo=,"), "Foo", ImmutableList.of("", "")));
}
@MethodSource("getListTestCases")
@MethodSource("getCollectionTestCases")
@ParameterizedTest
void getList(ImmutableList<String> args, String flag, ImmutableList<String> expected) {
void getList(ImmutableList<String> args, String flag, ImmutableList<String> listed) {
assertThat(Flags.getList(ErrorProneOptions.processArgs(args).getFlags(), flag))
.containsExactlyElementsOf(expected);
.containsExactlyElementsOf(listed);
}
@MethodSource("getCollectionTestCases")
@ParameterizedTest
void getSet(ImmutableList<String> args, String flag, ImmutableList<String> listed) {
assertThat(Flags.getSet(ErrorProneOptions.processArgs(args).getFlags(), flag))
.containsExactlyElementsOf(ImmutableSet.copyOf(listed));
}
}

View File

@@ -9,10 +9,13 @@ import com.google.errorprone.CompilationTestHelper;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.ExpressionStatementTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.ReturnTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher;
import com.google.errorprone.matchers.Description;
import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.Tree;
@@ -137,6 +140,25 @@ final class MoreASTHelpersTest {
.doTest();
}
@Test
void isStringTyped() {
CompilationTestHelper.newInstance(IsStringTypedTestChecker.class, getClass())
.addSourceLines(
"A.java",
"class A {",
" void m() {",
" int foo = 1;",
" // BUG: Diagnostic contains:",
" String s = \"foo\";",
"",
" hashCode();",
" // BUG: Diagnostic contains:",
" toString();",
" }",
"}")
.doTest();
}
private static String createMethodSearchDiagnosticsMessage(
BiFunction<String, VisitorState, Object> valueFunction, VisitorState state) {
return Maps.toMap(ImmutableSet.of("foo", "bar", "baz"), key -> valueFunction.apply(key, state))
@@ -224,4 +246,28 @@ final class MoreASTHelpersTest {
: Description.NO_MATCH;
}
}
/**
* A {@link BugChecker} that delegates to {@link MoreASTHelpers#isStringTyped(Tree,
* VisitorState)}.
*/
@BugPattern(summary = "Interacts with `MoreASTHelpers` for testing purposes", severity = ERROR)
public static final class IsStringTypedTestChecker extends BugChecker
implements MethodInvocationTreeMatcher, VariableTreeMatcher {
private static final long serialVersionUID = 1L;
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
return getDescription(tree, state);
}
@Override
public Description matchVariable(VariableTree tree, VisitorState state) {
return getDescription(tree, state);
}
private Description getDescription(Tree tree, VisitorState state) {
return MoreASTHelpers.isStringTyped(tree, state) ? describeMatch(tree) : Description.NO_MATCH;
}
}
}

View File

@@ -73,7 +73,7 @@ final class ThirdPartyLibraryTest {
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
@ValueSource(booleans = {false, true})
void isIntroductionAllowedIgnoreClasspathCompat(boolean ignoreClassPath) {
CompilationTestHelper.newInstance(IsIntroductionAllowedTestChecker.class, getClass())
.setArgs("-XepOpt:ErrorProneSupport:IgnoreClasspathCompat=" + ignoreClassPath)

View File

@@ -2,205 +2,35 @@
set -e -u -o pipefail
integration_test_root="$(cd "$(dirname -- "${0}")" && pwd)"
error_prone_support_root="${integration_test_root}/.."
repos_root="${integration_test_root}/.repos"
test_name="$(basename "${0}" .sh)"
project=checkstyle
repository=https://github.com/checkstyle/checkstyle.git
revision=checkstyle-10.14.0
if [ "${#}" -gt 2 ] || ([ "${#}" = 2 ] && [ "${1:---sync}" != '--sync' ]); then
echo "Usage: ${0} [--sync] [<report_directory>]"
exit 1
fi
do_sync="$([ "${#}" = 0 ] || [ "${1:-}" != '--sync' ] || echo 1)"
report_directory="$([ "${#}" = 0 ] || ([ -z "${do_sync}" ] && echo "${1}") || ([ "${#}" = 1 ] || echo "${2}"))"
if [ -n "${report_directory}" ]; then
mkdir -p "${report_directory}"
else
report_directory="$(mktemp -d)"
trap 'rm -rf -- "${report_directory}"' INT TERM HUP EXIT
fi
case "$(uname -s)" in
Linux*)
grep_command=grep
sed_command=sed
;;
Darwin*)
grep_command=ggrep
sed_command=gsed
;;
*)
echo "Unsupported distribution $(uname -s) for this script."
exit 1
;;
esac
project='checkstyle'
repository='https://github.com/checkstyle/checkstyle.git'
revision='checkstyle-10.14.0'
# XXX: Configure Renovate to manage the AssertJ version declared here.
shared_build_flags="
-Perror-prone-compile,error-prone-test-compile
-Dassertj.version=3.24.2
-Derror-prone.version=$(
mvn -f "${error_prone_support_root}" help:evaluate -Dexpression=version.error-prone -q -DforceStdout
)
-Derror-prone-support.version=$(
mvn -f "${error_prone_support_root}" help:evaluate -Dexpression=project.version -q -DforceStdout
)
-DadditionalSourceDirectories=\${project.basedir}\${file.separator}src\${file.separator}it\${file.separator}java,\${project.basedir}\${file.separator}src\${file.separator}xdocs-examples\${file.separator}java
"
# XXX: Configure Renovate to manage the fmt-maven-plugin version declared here.
# XXX: Once GitHub actions uses Maven 3.9.2+, we can inline this variable with
# version reference `${fmt.version}`, and `-Dfmt.version=2.21.1` added to
# `shared_build_flags`.
format_goal='com.spotify.fmt:fmt-maven-plugin:2.21.1:format'
error_prone_shared_flags='-XepExcludedPaths:(\Q${project.basedir}${file.separator}src${file.separator}\E(it|test|xdocs-examples)\Q${file.separator}resources\E|\Q${project.build.directory}${file.separator}\E).*'
error_prone_patch_flags="${error_prone_shared_flags} -XepPatchLocation:IN_PLACE -XepPatchChecks:$(
find "${error_prone_support_root}" \
-path "*/META-INF/services/com.google.errorprone.bugpatterns.BugChecker" \
-not -path "*/error-prone-experimental/*" \
-not -path "*/error-prone-guidelines/*" \
-print0 \
| xargs -0 "${grep_command}" -hoP '[^.]+$' \
| paste -s -d ',' -
)"
error_prone_validation_flags="${error_prone_shared_flags} -XepDisableAllChecks $(
find "${error_prone_support_root}" \
-path "*/META-INF/services/com.google.errorprone.bugpatterns.BugChecker" \
-not -path "*/error-prone-experimental/*" \
-not -path "*/error-prone-guidelines/*" \
-print0 \
| xargs -0 "${grep_command}" -hoP '[^.]+$' \
| "${sed_command}" -r 's,(.*),-Xep:\1:WARN,' \
| paste -s -d ' ' -
)"
echo "Shared build flags: ${shared_build_flags}"
echo "Error Prone patch flags: ${error_prone_patch_flags}"
echo "Error Prone validation flags: ${error_prone_validation_flags}"
mkdir -p "${repos_root}"
# Make sure that the targeted tag of the project's Git repository is checked
# out.
project_root="${repos_root}/${project}"
if [ ! -d "${project_root}" ]; then
# The repository has not yet been cloned; create a shallow clone.
git clone --branch "${revision}" --depth 1 "${repository}" "${project_root}"
else
# The repository does already appear to exist. Try to check out the requested
# tag if possible, and fetch it otherwise.
#
# Under certain circumstances this does not cause the relevant tag to be
# created, so if necessary we manually create it.
git -C "${project_root}" checkout --force "${revision}" 2>/dev/null \
|| (
git -C "${project_root}" fetch --depth 1 "${repository}" "${revision}" \
&& git -C "${project_root}" checkout --force FETCH_HEAD \
&& (git -C "${project_root}" tag "${revision}" || true)
)
fi
pushd "${project_root}"
# Make sure that Git is sufficiently configured to enable committing to the
# project's Git repository.
git config user.email || git config user.email "integration-test@example.com"
git config user.name || git config user.name "Integration Test"
# Prepare the code for analysis by (a) applying the minimal set of changes
# required to run Error Prone with Error Prone Support and (b) formatting the
# code using the same method by which it will be formatted after each
# compilation round. The initial formatting operation ensures that subsequent
# modifications can be rendered in a clean manner.
git clean -fdx
git apply < "${integration_test_root}/${test_name}-init.patch"
git commit -m 'dependency: Introduce Error Prone Support' .
mvn ${shared_build_flags} "${format_goal}"
git commit -m 'minor: Reformat using Google Java Format' .
diff_base="$(git rev-parse HEAD)"
# Apply Error Prone Support-suggested changes until a fixed point is reached.
function apply_patch() {
local extra_build_args="${1}"
mvn ${shared_build_flags} ${extra_build_args} \
package "${format_goal}" \
-Derror-prone.configuration-args="${error_prone_patch_flags}" \
-DskipTests
if ! git diff --exit-code; then
git commit -m 'minor: Apply patches' .
# Changes were applied, so another compilation round may apply yet more
# changes. For performance reasons we perform incremental compilation,
# enabled using a misleading flag. (See
# https://issues.apache.org/jira/browse/MCOMPILER-209 for details.)
apply_patch '-Dmaven.compiler.useIncrementalCompilation=false'
elif [ "${extra_build_args}" != 'clean' ]; then
# No changes were applied. We'll attempt one more round in which all files
# are recompiled, because there are cases in which violations are missed
# during incremental compilation.
apply_patch 'clean'
fi
}
apply_patch ''
# Run one more full build and log the output.
#
# By also running the tests, we validate that the (majority of) applied changes
# are behavior preserving. Some tests are skipped:
additional_build_flags='-Dassertj.version=3.24.2'
additional_source_directories='${project.basedir}${file.separator}src${file.separator}it${file.separator}java,${project.basedir}${file.separator}src${file.separator}xdocs-examples${file.separator}java'
patch_error_prone_flags=''
validation_error_prone_flags=''
# Validation skips some tests:
# - The `metadataFilesGenerationAllFiles` test is skipped because it makes line
# number assertions that will fail when the code is formatted or patched.
# - The `allCheckSectionJavaDocs` test is skipped because is validates that
# - The `allCheckSectionJavaDocs` test is skipped because it validates that
# Javadoc has certain closing tags that are removed by Google Java Format.
validation_build_log="${report_directory}/${test_name}-validation-build-log.txt"
mvn ${shared_build_flags} \
clean package \
-Derror-prone.configuration-args="${error_prone_validation_flags}" \
-Dtest='
!MetadataGeneratorUtilTest#metadataFilesGenerationAllFiles,
!XdocsJavaDocsTest#allCheckSectionJavaDocs' \
| tee "${validation_build_log}" \
|| failure=1
validation_build_flags='-Dtest=!MetadataGeneratorUtilTest#metadataFilesGenerationAllFiles,!XdocsJavaDocsTest#allCheckSectionJavaDocs'
# Collect the applied changes.
expected_changes="${integration_test_root}/${test_name}-expected-changes.patch"
actual_changes="${report_directory}/${test_name}-changes.patch"
(git diff "${diff_base}"..HEAD | "${grep_command}" -vP '^(diff|index)' || true) > "${actual_changes}"
# Collect the warnings reported by Error Prone Support checks.
expected_warnings="${integration_test_root}/${test_name}-expected-warnings.txt"
actual_warnings="${report_directory}/${test_name}-validation-build-warnings.txt"
("${grep_command}" -oP "(?<=^\\Q[WARNING] ${PWD}/\\E).*" "${validation_build_log}" | "${grep_command}" -P '\] \[' || true) | LC_ALL=C sort > "${actual_warnings}"
# Persist or validate the applied changes and reported warnings.
if [ -n "${do_sync}" ]; then
echo 'Saving changes...'
cp "${actual_changes}" "${expected_changes}"
cp "${actual_warnings}" "${expected_warnings}"
else
echo 'Inspecting changes...'
# XXX: This "diff of diffs" also contains vacuous sections, introduced due to
# line offset differences. Try to omit those from the final output.
if ! diff -u "${expected_changes}" "${actual_changes}"; then
echo 'There are unexpected changes. Inspect the preceding output for details.'
failure=1
fi
echo 'Inspecting emitted warnings...'
if ! diff -u "${expected_warnings}" "${actual_warnings}"; then
echo 'Diagnostics output changed. Inspect the preceding output for details.'
failure=1
fi
fi
if [ -n "${failure:-}" ]; then
if [ "${#}" -gt 2 ] || ([ "${#}" = 2 ] && [ "${1:---sync}" != '--sync' ]); then
>&2 echo "Usage: ${0} [--sync] [<report_directory>]"
exit 1
fi
"$(dirname "${0}")/run-integration-test.sh" \
"${test_name}" \
"${project}" \
"${repository}" \
"${revision}" \
"${additional_build_flags}" \
"${additional_source_directories}" \
"${patch_error_prone_flags}" \
"${validation_error_prone_flags}" \
"${validation_build_flags}" \
$@

View File

@@ -0,0 +1,287 @@
metrics-annotation/src/main/java/com/codahale/metrics/annotation/CachedGauge.java:[32,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/CachedGauge.java:[37,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/CachedGauge.java:[43,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/CachedGauge.java:[48,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Counted.java:[39,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Counted.java:[44,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Counted.java:[51,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/ExceptionMetered.java:[55,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/ExceptionMetered.java:[61,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/ExceptionMetered.java:[68,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Gauge.java:[27,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Gauge.java:[32,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Metered.java:[36,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Metered.java:[41,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Metric.java:[39,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Metric.java:[44,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/ResponseMetered.java:[37,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/ResponseMetered.java:[42,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/ResponseMetered.java:[49,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Timed.java:[36,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-annotation/src/main/java/com/codahale/metrics/annotation/Timed.java:[41,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-benchmarks/src/main/java/com/codahale/metrics/benchmarks/SlidingTimeWindowReservoirsBenchmark.java:[21,3] [MissingSummary] A summary line is required on public/protected Javadocs.
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,15] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,21] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,27] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,33] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,39] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,45] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,51] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,57] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,63] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,69] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,75] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,81] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,87] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,93] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,99] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[3,9] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,15] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,21] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,27] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,33] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,39] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,45] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,51] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,57] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,63] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,69] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,75] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,81] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,87] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,93] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,99] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[4,9] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,15] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,21] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,27] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,33] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,39] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,45] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,51] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,57] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,63] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,69] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,75] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,81] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,87] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,93] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,99] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[5,9] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,15] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,21] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,27] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,33] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,39] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,45] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,51] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,57] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,63] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,69] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,75] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,81] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,87] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,93] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,99] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[6,9] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,15] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,21] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,27] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,33] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,39] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,45] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,51] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,57] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,63] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,69] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,75] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,81] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,87] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,93] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,99] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[7,9] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,15] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,21] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,27] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,33] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,39] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,45] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,51] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,57] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,63] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,69] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,75] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,81] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,87] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,93] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,99] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[8,9] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[9,15] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-benchmarks/target/generated-sources/annotations/com/codahale/metrics/benchmarks/jmh_generated/ReservoirBenchmark_jmhType_B3.java:[9,9] [HidingField] Hiding fields of superclasses may cause confusion and errors. This field is hiding a field of the same name in superclass: ReservoirBenchmark_jmhType_B1
metrics-caffeine/src/test/java/com/codahale/metrics/caffeine/MetricsStatsCounterTest.java:[89,9] [deprecation] recordEviction() in MetricsStatsCounter has been deprecated
metrics-caffeine/src/test/java/com/codahale/metrics/caffeine/MetricsStatsCounterTest.java:[96,9] [deprecation] recordEviction(int) in MetricsStatsCounter has been deprecated
metrics-collectd/src/main/java/com/codahale/metrics/collectd/CollectdReporter.java:[193,13] [InconsistentCapitalization] Found the field 'hostName' with the same name as the parameter 'hostname' but with different capitalization.
metrics-collectd/src/main/java/com/codahale/metrics/collectd/CollectdReporter.java:[305,14] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-collectd/src/main/java/com/codahale/metrics/collectd/PacketWriter.java:[160,12] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/com/codahale/metrics/collectd/PacketWriter.java:[165,11] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/com/codahale/metrics/collectd/PacketWriter.java:[171,17] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/com/codahale/metrics/collectd/PacketWriter.java:[196,8] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/com/codahale/metrics/collectd/PacketWriter.java:[199,21] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/com/codahale/metrics/collectd/PacketWriter.java:[202,11] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/com/codahale/metrics/collectd/PacketWriter.java:[248,36] [cast] redundant cast to ByteBuffer
metrics-collectd/src/main/java/com/codahale/metrics/collectd/Sanitize.java:[7,3] [MissingSummary] A summary fragment is required; consider using the value of the @see block as a summary fragment instead.
metrics-collectd/src/test/java/com/codahale/metrics/collectd/Receiver.java:[51,16] [CatchAndPrintStackTrace] Logging or rethrowing exceptions should usually be preferred to catching and calling printStackTrace
metrics-collectd/src/test/java/com/codahale/metrics/collectd/SanitizeTest.java:[26,41] [UnnecessaryParentheses] These grouping parentheses are unnecessary; it is unlikely the code will be misinterpreted without them
metrics-core/src/main/java/com/codahale/metrics/ConsoleReporter.java:[239,46] [JavaUtilDate] Date has a bad API that leads to bugs; prefer java.time.Instant or LocalDate.
metrics-core/src/main/java/com/codahale/metrics/ConsoleReporter.java:[406,43] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/main/java/com/codahale/metrics/ConsoleReporter.java:[413,43] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/main/java/com/codahale/metrics/CsvReporter.java:[310,39] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/main/java/com/codahale/metrics/CsvReporter.java:[312,39] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/main/java/com/codahale/metrics/CsvReporter.java:[382,35] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-core/src/main/java/com/codahale/metrics/InstrumentedExecutorService.java:[196,25] [try] auto-closeable resource durationContext is never referenced in body of corresponding try statement
metrics-core/src/main/java/com/codahale/metrics/InstrumentedExecutorService.java:[218,25] [try] auto-closeable resource context is never referenced in body of corresponding try statement
metrics-core/src/main/java/com/codahale/metrics/MetricRegistry.java:[329,29] [TypeParameterUnusedInFormals] Declaring a type parameter that is only used in the return type is a misuse of generics: operations on the type parameter are unchecked, it hides unsafe casts at invocations of the method, and it interacts badly with method overload resolution.
metrics-core/src/main/java/com/codahale/metrics/MovingAverages.java:[26,5] [EmptyBlockTag] A block tag (@param, @return, @throws, @deprecated) has an empty description. Block tags without descriptions don't add much value for future readers of the code; consider removing the tag entirely or adding a description.
metrics-core/src/main/java/com/codahale/metrics/NoopMetricRegistry.java:[102,29] [TypeParameterUnusedInFormals] Declaring a type parameter that is only used in the return type is a misuse of generics: operations on the type parameter are unchecked, it hides unsafe casts at invocations of the method, and it interacts badly with method overload resolution.
metrics-core/src/main/java/com/codahale/metrics/ScheduledReporter.java:[37,12] [removal] SecurityManager in java.lang has been deprecated and marked for removal
metrics-core/src/main/java/com/codahale/metrics/ScheduledReporter.java:[37,38] [removal] getSecurityManager() in System has been deprecated and marked for removal
metrics-core/src/main/java/com/codahale/metrics/ScheduledReporter.java:[47,21] [ThreadPriorityCheck] Relying on the thread scheduler is discouraged.
metrics-core/src/main/java/com/codahale/metrics/Slf4jReporter.java:[183,29] [InvalidInlineTag] Curly braces should be used for inline Javadoc tags: {@link ...}
metrics-core/src/main/java/com/codahale/metrics/WeightedSnapshot.java:[76,26] [UnnecessaryParentheses] These grouping parentheses are unnecessary; it is unlikely the code will be misinterpreted without them
metrics-core/src/test/java/com/codahale/metrics/ClockTest.java:[14,75] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/test/java/com/codahale/metrics/ClockTest.java:[16,66] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/test/java/com/codahale/metrics/MeterApproximationTest.java:[37,19] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/test/java/com/codahale/metrics/MeterApproximationTest.java:[48,19] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/test/java/com/codahale/metrics/MeterApproximationTest.java:[59,19] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-core/src/test/java/com/codahale/metrics/ScheduledReporterTest.java:[230,41] [DirectInvocationOnMock] Methods should not be directly invoked on the mock `mockExecutor`. Should this be part of a verify(..) call?
metrics-core/src/test/java/com/codahale/metrics/ScheduledReporterTest.java:[231,39] [DirectInvocationOnMock] Methods should not be directly invoked on the mock `mockExecutor`. Should this be part of a verify(..) call?
metrics-core/src/test/java/com/codahale/metrics/SharedMetricRegistriesTest.java:[12,62] [deprecation] none() in ExpectedException has been deprecated
metrics-core/src/test/java/com/codahale/metrics/SlidingTimeWindowArrayReservoirTest.java:[88,15] [UnnecessaryAsync] Variables which are initialized and do not escape the current scope do not need to worry about concurrency. Using the non-concurrent type will reduce overhead and verbosity.
metrics-core/src/test/java/com/codahale/metrics/UniformSnapshotTest.java:[128,30] [DefaultCharset] Implicit use of the platform default charset, which can result in differing behaviour between JVM executions or incorrect behavior if the encoding of the data source doesn't match expectations.
metrics-core/src/test/java/com/codahale/metrics/WeightedSnapshotTest.java:[136,30] [DefaultCharset] Implicit use of the platform default charset, which can result in differing behaviour between JVM executions or incorrect behavior if the encoding of the data source doesn't match expectations.
metrics-graphite/src/main/java/com/codahale/metrics/graphite/Graphite.java:[129,57] [OperatorPrecedence] Use grouping parenthesis to make the operator precedence explicit
metrics-graphite/src/main/java/com/codahale/metrics/graphite/GraphiteReporter.java:[253,46] [UnnecessaryLambda] Returning a lambda from a helper method or saving it in a constant is unnecessary; prefer to implement the functional interface method directly and use a method reference instead.
metrics-graphite/src/main/java/com/codahale/metrics/graphite/GraphiteReporter.java:[431,17] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
metrics-graphite/src/main/java/com/codahale/metrics/graphite/GraphiteReporter.java:[436,19] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
metrics-graphite/src/main/java/com/codahale/metrics/graphite/GraphiteReporter.java:[449,20] [Slf4jLogStatement] Log statement contains 0 placeholders, but specifies 1 matching argument(s)
metrics-graphite/src/main/java/com/codahale/metrics/graphite/GraphiteReporter.java:[456,60] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-graphite/src/main/java/com/codahale/metrics/graphite/GraphiteReporter.java:[458,60] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-graphite/src/test/java/com/codahale/metrics/graphite/GraphiteTest.java:[140,65] [AddressSelection] Prefer InetAddress.getAllByName to APIs that convert a hostname to a single IP address
metrics-graphite/src/test/java/com/codahale/metrics/graphite/GraphiteTest.java:[30,66] [AddressSelection] Prefer InetAddress.getAllByName to APIs that convert a hostname to a single IP address
metrics-graphite/src/test/java/com/codahale/metrics/graphite/GraphiteTest.java:[59,26] [DirectInvocationOnMock] Methods should not be directly invoked on the mock `socket`. Should this be part of a verify(..) call?
metrics-graphite/src/test/java/com/codahale/metrics/graphite/GraphiteUDPTest.java:[25,73] [AddressSelection] Prefer InetAddress.getAllByName to APIs that convert a hostname to a single IP address
metrics-graphite/src/test/java/com/codahale/metrics/graphite/GraphiteUDPTest.java:[35,49] [AddressSelection] Prefer InetAddress.getAllByName to APIs that convert a hostname to a single IP address
metrics-graphite/src/test/java/com/codahale/metrics/graphite/GraphiteUDPTest.java:[40,60] [StringCharset] StringCharset
metrics-graphite/src/test/java/com/codahale/metrics/graphite/GraphiteUDPTest.java:[41,34] [AddressSelection] Prefer InetAddress.getAllByName to APIs that convert a hostname to a single IP address
metrics-graphite/src/test/java/com/codahale/metrics/graphite/PickledGraphiteTest.java:[36,66] [AddressSelection] Prefer InetAddress.getAllByName to APIs that convert a hostname to a single IP address
metrics-graphite/src/test/java/com/codahale/metrics/graphite/PickledGraphiteTest.java:[68,26] [DirectInvocationOnMock] Methods should not be directly invoked on the mock `socket`. Should this be part of a verify(..) call?
metrics-healthchecks/src/main/java/com/codahale/metrics/health/HealthCheck.java:[203,19] [EqualsGetClass] Prefer instanceof to getClass when implementing Object#equals.
metrics-healthchecks/src/main/java/com/codahale/metrics/health/HealthCheck.java:[222,32] [UnnecessaryParentheses] These grouping parentheses are unnecessary; it is unlikely the code will be misinterpreted without them
metrics-healthchecks/src/main/java/com/codahale/metrics/health/HealthCheck.java:[318,25] [AnnotateFormatMethod] This method uses a pair of parameters as a format string and its arguments, but the enclosing method wasn't annotated @FormatMethod. Doing so gives compile-time rather than run-time protection against malformed format strings.
metrics-healthchecks/src/main/java/com/codahale/metrics/health/HealthCheck.java:[55,25] [AnnotateFormatMethod] This method uses a pair of parameters as a format string and its arguments, but the enclosing method wasn't annotated @FormatMethod. Doing so gives compile-time rather than run-time protection against malformed format strings.
metrics-healthchecks/src/main/java/com/codahale/metrics/health/HealthCheck.java:[79,25] [AnnotateFormatMethod] This method uses a pair of parameters as a format string and its arguments, but the enclosing method wasn't annotated @FormatMethod. Doing so gives compile-time rather than run-time protection against malformed format strings.
metrics-healthchecks/src/main/java/com/codahale/metrics/health/HealthCheckRegistry.java:[269,32] [removal] getSecurityManager() in System has been deprecated and marked for removal
metrics-healthchecks/src/main/java/com/codahale/metrics/health/HealthCheckRegistry.java:[269,6] [removal] SecurityManager in java.lang has been deprecated and marked for removal
metrics-healthchecks/src/main/java/com/codahale/metrics/health/HealthCheckRegistry.java:[278,64] [ThreadPriorityCheck] Relying on the thread scheduler is discouraged.
metrics-healthchecks/src/test/java/com/codahale/metrics/health/HealthCheckTest.java:[189,46] [JavaTimeDefaultTimeZone] ZonedDateTime.now() is not allowed because it silently uses the system default time-zone. You must pass an explicit time-zone (e.g., ZoneId.of("America/Los_Angeles")) to this method.
metrics-healthchecks/src/test/java/com/codahale/metrics/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/com/codahale/metrics/health/HealthCheckTest.java:[203,46] [JavaTimeDefaultTimeZone] ZonedDateTime.now() is not allowed because it silently uses the system default time-zone. You must pass an explicit time-zone (e.g., ZoneId.of("America/Los_Angeles")) to this method.
metrics-healthchecks/src/test/java/com/codahale/metrics/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-healthchecks/src/test/java/com/codahale/metrics/health/SharedHealthCheckRegistriesTest.java:[13,70] [deprecation] none() in ExpectedException has been deprecated
metrics-httpasyncclient/src/test/java/com/codahale/metrics/httpasyncclient/HttpClientTestBase.java:[24,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-httpclient/src/main/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategies.java:[43,59] [StringCaseLocaleUsage] Specify a `Locale` when calling `String#to{Lower,Upper}Case`. (Note: there are multiple suggested fixes; the third may be most appropriate if you're dealing with ASCII Strings.)
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[101,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[112,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[120,22] [deprecation] rewriteURI(URI,HttpHost,boolean) in URIUtils has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[31,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[38,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[45,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[54,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[63,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[70,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[78,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[86,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient/src/test/java/com/codahale/metrics/httpclient/HttpClientMetricNameStrategiesTest.java:[94,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[23,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[30,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[37,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[44,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[53,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[62,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[69,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[80,4] [deprecation] <T>assertThat(T,Matcher<? super T>) in Assert has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/HttpClientMetricNameStrategiesTest.java:[88,22] [deprecation] rewriteURI(URI,HttpHost,boolean) in URIUtils has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/InstrumentedHttpAsyncClientsTest.java:[126,8] [deprecation] SimpleHttpRequests in org.apache.hc.client5.http.async.methods has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/InstrumentedHttpAsyncClientsTest.java:[182,10] [deprecation] SimpleHttpRequests in org.apache.hc.client5.http.async.methods has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/InstrumentedHttpAsyncClientsTest.java:[26,47] [deprecation] SimpleHttpRequests in org.apache.hc.client5.http.async.methods has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/InstrumentedHttpAsyncClientsTest.java:[77,8] [deprecation] SimpleHttpRequests in org.apache.hc.client5.http.async.methods has been deprecated
metrics-httpclient5/src/test/java/com/codahale/metrics/httpclient5/InstrumentedHttpClientsTest.java:[68,12] [deprecation] execute(ClassicHttpRequest) in HttpClient has been deprecated
metrics-jakarta-servlet/src/main/java/io/dropwizard/metrics/servlet/InstrumentedFilterContextListener.java:[14,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/AdminServlet.java:[32,30] [InlineFormatString] Prefer to create format strings inline, instead of extracting them to a single-use constant
metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/HealthCheckServlet.java:[26,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/HealthCheckServlet.java:[31,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/HealthCheckServlet.java:[40,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/MetricsServlet.java:[32,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/MetricsServlet.java:[37,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/MetricsServlet.java:[46,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/MetricsServlet.java:[55,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-jakarta-servlets/src/test/java/io/dropwizard/metrics/servlets/HealthCheckServletTest.java:[104,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-jakarta-servlets/src/test/java/io/dropwizard/metrics/servlets/HealthCheckServletTest.java:[145,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-jakarta-servlets/src/test/java/io/dropwizard/metrics/servlets/HealthCheckServletTest.java:[219,25] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-jakarta-servlets/src/test/java/io/dropwizard/metrics/servlets/HealthCheckServletTest.java:[30,67] [JavaTimeDefaultTimeZone] ZonedDateTime.now() is not allowed because it silently uses the system default time-zone. You must pass an explicit time-zone (e.g., ZoneId.of("America/Los_Angeles")) to this method.
metrics-jakarta-servlets/src/test/java/io/dropwizard/metrics/servlets/HealthCheckServletTest.java:[30,67] [TimeZoneUsage] Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone
metrics-jakarta-servlets/src/test/java/io/dropwizard/metrics/servlets/MetricsServletTest.java:[130,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-jcache/src/test/java/JCacheGaugeSetTest.java:[1] [DefaultPackage] Java classes shouldn't use default package
metrics-jdbi3/src/main/java/com/codahale/metrics/jdbi3/InstrumentedTimingCollector.java:[9,33] [deprecation] TimingCollector in org.jdbi.v3.core.statement has been deprecated
metrics-jdbi3/src/test/java/com/codahale/metrics/jdbi3/strategies/SmartNameStrategyTest.java:[17,10] [deprecation] InstrumentedTimingCollector in com.codahale.metrics.jdbi3 has been deprecated
metrics-jdbi3/src/test/java/com/codahale/metrics/jdbi3/strategies/SmartNameStrategyTest.java:[23,20] [deprecation] InstrumentedTimingCollector in com.codahale.metrics.jdbi3 has been deprecated
metrics-jdbi3/src/test/java/com/codahale/metrics/jdbi3/strategies/SmartNameStrategyTest.java:[8,33] [deprecation] InstrumentedTimingCollector in com.codahale.metrics.jdbi3 has been deprecated
metrics-jersey2/src/main/java/com/codahale/metrics/jersey2/InstrumentedResourceMethodApplicationListener.java:[582,19] [EqualsGetClass] Prefer instanceof to getClass when implementing Object#equals.
metrics-jersey3/src/main/java/com/codahale/metrics/jersey3/InstrumentedResourceMethodApplicationListener.java:[582,19] [EqualsGetClass] Prefer instanceof to getClass when implementing Object#equals.
metrics-jersey31/src/main/java/io/dropwizard/metrics/jersey31/InstrumentedResourceMethodApplicationListener.java:[582,19] [EqualsGetClass] Prefer instanceof to getClass when implementing Object#equals.
metrics-jetty10/src/test/java/io/dropwizard/metrics/jetty10/InstrumentedHandlerTest.java:[134,44] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jetty10/src/test/java/io/dropwizard/metrics/jetty10/InstrumentedHandlerTest.java:[138,44] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jetty11/src/test/java/io/dropwizard/metrics/jetty11/InstrumentedHandlerTest.java:[136,44] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jetty11/src/test/java/io/dropwizard/metrics/jetty11/InstrumentedHandlerTest.java:[140,44] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jetty9/src/test/java/com/codahale/metrics/jetty9/InstrumentedHandlerTest.java:[136,44] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jetty9/src/test/java/com/codahale/metrics/jetty9/InstrumentedHandlerTest.java:[140,44] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jmx/src/main/java/com/codahale/metrics/jmx/DefaultObjectNameFactory.java:[18,45] [JdkObsolete] Hashtable performs synchronization this is usually unnecessary; prefer LinkedHashMap.
metrics-json/src/test/java/com/codahale/metrics/json/HealthCheckModuleTest.java:[131,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-json/src/test/java/com/codahale/metrics/json/HealthCheckModuleTest.java:[20,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-json/src/test/java/com/codahale/metrics/json/HealthCheckModuleTest.java:[28,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-json/src/test/java/com/codahale/metrics/json/HealthCheckModuleTest.java:[43,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-json/src/test/java/com/codahale/metrics/json/HealthCheckModuleTest.java:[62,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-json/src/test/java/com/codahale/metrics/json/HealthCheckModuleTest.java:[90,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-jvm/src/main/java/com/codahale/metrics/jvm/FileDescriptorRatioGauge.java:[42,55] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/main/java/com/codahale/metrics/jvm/FileDescriptorRatioGauge.java:[42,91] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/main/java/com/codahale/metrics/jvm/MemoryUsageGaugeSet.java:[107,31] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/main/java/com/codahale/metrics/jvm/MemoryUsageGaugeSet.java:[107,56] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/main/java/com/codahale/metrics/jvm/MemoryUsageGaugeSet.java:[77,41] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/main/java/com/codahale/metrics/jvm/MemoryUsageGaugeSet.java:[77,57] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/main/java/com/codahale/metrics/jvm/MemoryUsageGaugeSet.java:[93,29] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/main/java/com/codahale/metrics/jvm/MemoryUsageGaugeSet.java:[93,54] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/main/java/com/codahale/metrics/jvm/ThreadStatesGaugeSet.java:[47,43] [StringCaseLocaleUsage] Specify a `Locale` when calling `String#to{Lower,Upper}Case`. (Note: there are multiple suggested fixes; the third may be most appropriate if you're dealing with ASCII Strings.)
metrics-jvm/src/test/java/com/codahale/metrics/jvm/CpuTimeClockTest.java:[15,75] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/test/java/com/codahale/metrics/jvm/CpuTimeClockTest.java:[19,71] [LongDoubleConversion] Conversion from long to double may lose precision; use an explicit cast to double if this was intentional
metrics-jvm/src/test/java/com/codahale/metrics/jvm/FileDescriptorRatioGaugeSunManagementNotExistsTest.java:[55,10] [removal] AccessController in java.security has been deprecated and marked for removal
metrics-jvm/src/test/java/com/codahale/metrics/jvm/FileDescriptorRatioGaugeSunManagementNotExistsTest.java:[67,36] [URLEqualsHashCode] Avoid hash-based containers of java.net.URL--the containers rely on equals() and hashCode(), which cause java.net.URL to make blocking internet connections.
metrics-jvm/src/test/java/com/codahale/metrics/jvm/FileDescriptorRatioGaugeSunManagementNotExistsTest.java:[9,20] [removal] AccessController in java.security has been deprecated and marked for removal
metrics-jvm/src/test/java/com/codahale/metrics/jvm/ThreadDumpTest.java:[42,30] [DefaultCharset] Implicit use of the platform default charset, which can result in differing behaviour between JVM executions or incorrect behavior if the encoding of the data source doesn't match expectations.
metrics-log4j2/src/main/java/com/codahale/metrics/log4j2/InstrumentedAppender.java:[85,4] [deprecation] AbstractAppender(String,Filter,Layout<? extends Serializable>,boolean) in AbstractAppender has been deprecated
metrics-log4j2/src/main/java/com/codahale/metrics/log4j2/InstrumentedAppender.java:[96,4] [deprecation] AbstractAppender(String,Filter,Layout<? extends Serializable>,boolean) in AbstractAppender has been deprecated
metrics-servlet/src/main/java/com/codahale/metrics/servlet/InstrumentedFilterContextListener.java:[14,5] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/main/java/com/codahale/metrics/servlets/AdminServlet.java:[32,30] [InlineFormatString] Prefer to create format strings inline, instead of extracting them to a single-use constant
metrics-servlets/src/main/java/com/codahale/metrics/servlets/HealthCheckServlet.java:[26,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/main/java/com/codahale/metrics/servlets/HealthCheckServlet.java:[31,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/main/java/com/codahale/metrics/servlets/HealthCheckServlet.java:[40,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/main/java/com/codahale/metrics/servlets/HealthCheckServlet.java:[48,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java:[32,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java:[37,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java:[46,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java:[55,7] [MissingSummary] A summary fragment is required; consider using the value of the @return block as a summary fragment instead.
metrics-servlets/src/test/java/com/codahale/metrics/servlets/HealthCheckServletTest.java:[112,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-servlets/src/test/java/com/codahale/metrics/servlets/HealthCheckServletTest.java:[170,25] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-servlets/src/test/java/com/codahale/metrics/servlets/HealthCheckServletTest.java:[31,67] [JavaTimeDefaultTimeZone] ZonedDateTime.now() is not allowed because it silently uses the system default time-zone. You must pass an explicit time-zone (e.g., ZoneId.of("America/Los_Angeles")) to this method.
metrics-servlets/src/test/java/com/codahale/metrics/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-servlets/src/test/java/com/codahale/metrics/servlets/HealthCheckServletTest.java:[96,18] [FormatStringConcatenation] Defer string concatenation to the invoked method
metrics-servlets/src/test/java/com/codahale/metrics/servlets/MetricsServletTest.java:[130,18] [FormatStringConcatenation] Defer string concatenation to the invoked method

View File

@@ -0,0 +1,203 @@
diff --git a/metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/MetricsServlet.java b/metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/MetricsServlet.java
index a248dd8..4e7f053 100644
--- a/metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/MetricsServlet.java
+++ b/metrics-jakarta-servlets/src/main/java/io/dropwizard/metrics/servlets/MetricsServlet.java
@@ -188,6 +188,7 @@ public class MetricsServlet extends HttpServlet {
return mapper.writer();
}
+ @SuppressWarnings("IdentityConversion")
protected TimeUnit parseTimeUnit(String value, TimeUnit defaultValue) {
try {
return TimeUnit.valueOf(String.valueOf(value).toUpperCase(Locale.US));
diff --git a/metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java b/metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java
index 0bd1297..7c69a08 100644
--- a/metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java
+++ b/metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java
@@ -189,6 +189,7 @@ public class MetricsServlet extends HttpServlet {
return mapper.writer();
}
+ @SuppressWarnings("IdentityConversion")
protected TimeUnit parseTimeUnit(String value, TimeUnit defaultValue) {
try {
return TimeUnit.valueOf(String.valueOf(value).toUpperCase(Locale.US));
diff --git a/pom.xml b/pom.xml
index 6192b52..8c312b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -68,7 +68,8 @@
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<errorprone.version>2.19.1</errorprone.version>
<errorprone.javac.version>9+181-r4173-1</errorprone.javac.version>
-
+ <error-prone-support.flags>-Xplugin:ErrorProne -XepDisableWarningsInGeneratedCode ${error-prone.configuration-args}</error-prone-support.flags>
+ <java.version>8</java.version>
<sonar.projectKey>dropwizard_metrics</sonar.projectKey>
<sonar.organization>dropwizard</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
@@ -166,10 +167,9 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <compilerArgs>
+ <compilerArgs combine.children="append">
<arg>-Xlint:all</arg>
<arg>-XDcompilePolicy=simple</arg>
- <arg>-Xplugin:ErrorProne -XepExcludedPaths:.*/target/generated-sources/.*</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
<arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
@@ -181,18 +181,129 @@
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
</compilerArgs>
- <annotationProcessorPaths>
- <path>
- <groupId>com.google.errorprone</groupId>
- <artifactId>error_prone_core</artifactId>
- <version>${errorprone.version}</version>
- </path>
- </annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</profile>
+ <profile>
+ <id>error-prone-compile</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <executions>
+ <!-- Skip the `default-compile` execution as we don't want to execute the compile goal twice -->
+ <execution>
+ <id>default-compile</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <skipMain>true</skipMain>
+ </configuration>
+ </execution>
+ <execution>
+ <id>error-prone-compile</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <failOnError>true</failOnError>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
+ <compilerArgs combine.children="append">
+ <arg>-Xpkginfo:always</arg>
+ <arg>-XDcompilePolicy=simple</arg>
+ <arg>${error-prone-support.flags}</arg>
+ </compilerArgs>
+ <annotationProcessorPaths combine.children="append">
+ <path>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_core</artifactId>
+ <version>${error-prone.version}</version>
+ </path>
+ <path>
+ <groupId>tech.picnic.error-prone-support</groupId>
+ <artifactId>error-prone-contrib</artifactId>
+ <version>${error-prone-support.version}</version>
+ </path>
+ <path>
+ <groupId>tech.picnic.error-prone-support</groupId>
+ <artifactId>refaster-runner</artifactId>
+ <version>${error-prone-support.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>error-prone-test-compile</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <executions>
+ <!-- Skip the `default-testCompile` execution as we don't want to execute the compile goal twice -->
+ <execution>
+ <id>default-testCompile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </execution>
+ <execution>
+ <id>error-prone-test-compile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ <configuration>
+ <failOnError>true</failOnError>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
+ <compilerArgs combine.children="append">
+ <arg>-Xpkginfo:always</arg>
+ <arg>-XDcompilePolicy=simple</arg>
+ <arg>${error-prone-support.flags}</arg>
+ </compilerArgs>
+ <annotationProcessorPaths combine.children="append">
+ <path>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_core</artifactId>
+ <version>${error-prone.version}</version>
+ </path>
+ <path>
+ <groupId>tech.picnic.error-prone-support</groupId>
+ <artifactId>error-prone-contrib</artifactId>
+ <version>${error-prone-support.version}</version>
+ </path>
+ <path>
+ <groupId>tech.picnic.error-prone-support</groupId>
+ <artifactId>refaster-runner</artifactId>
+ <version>${error-prone-support.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
<profile>
<id>release-sign-artifacts</id>
<activation>
@@ -323,15 +434,7 @@
<compilerArgs>
<arg>-Xlint:all</arg>
<arg>-XDcompilePolicy=simple</arg>
- <arg>-Xplugin:ErrorProne -XepExcludedPaths:.*/target/generated-sources/.*</arg>
</compilerArgs>
- <annotationProcessorPaths>
- <path>
- <groupId>com.google.errorprone</groupId>
- <artifactId>error_prone_core</artifactId>
- <version>${errorprone.version}</version>
- </path>
- </annotationProcessorPaths>
</configuration>
</plugin>
<plugin>

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

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -e -u -o pipefail
test_name="$(basename "${0}" .sh)"
project=metrics
repository=https://github.com/dropwizard/metrics.git
revision=v4.2.19
if [ "${#}" -gt 2 ] || ([ "${#}" = 2 ] && [ "${1:---sync}" != '--sync' ]); then
echo "Usage: ${0} [--sync] [<report_directory>]"
exit 1
fi
do_sync="$([ "${#}" = 0 ] || [ "${1:-}" != '--sync' ] || echo 1)"
report_directory="$([ "${#}" = 0 ] || ([ -z "${do_sync}" ] && echo "${1}") || ([ "${#}" = 1 ] || echo "${2}"))"
# XXX: We exclude the `CollectorMutability` and the `Immutable*|Preconditions*|StringRules.StringIsNullOrEmpty` Refaster rules
# as they introduce changes that expect Guava to be on the classpath.
patch_flags="-Xep:CollectorMutability:OFF -XepOpt:Refaster:NamePattern=^(?!ImmutableSetRules\$ImmutableSetOf).*"
"$(dirname "${0}")"/run-integration-test.sh \
"${test_name}" \
"${project}" \
"${repository}" \
"${revision}" \
"" \
"" \
"${patch_flags}" \
"" \
"" \
"${do_sync}" \
"${report_directory}"

View File

@@ -0,0 +1,210 @@
#!/usr/bin/env bash
# Integration test framework for Maven builds.
#
# This script is not meant to be invoked manually. Instead it should be invoked
# through one of the top-level integration test scripts, such as
# `checkstyle.sh`.
set -e -u -o pipefail
integration_test_root="$(cd "$(dirname -- "${0}")" && pwd)"
error_prone_support_root="${integration_test_root}/.."
repos_root="${integration_test_root}/.repos"
if [ "${#}" -lt 9 ] || [ "${#}" -gt 11 ] || ([ "${#}" = 11 ] && [ "${10:---sync}" != '--sync' ]); then
>&2 echo "Usage: $(basename "${0}") <test_name> <project> <repository> <revision> <additional_build_flags> <additional_source_directories> <patch_error_prone_flags> <validation_error_prone_flags> <validation_build_flags> [--sync] [<report_directory>]"
exit 1
fi
test_name="${1}"
project="${2}"
repository="${3}"
revision="${4}"
additional_build_flags="${5}"
additional_source_directories="${6}"
patch_error_prone_flags="${7}"
validation_error_prone_flags="${8}"
validation_build_flags="${9}"
do_sync="$([ "${#}" = 9 ] || [ "${10:-}" != '--sync' ] || echo 1)"
report_directory="$([ "${#}" = 9 ] || ([ -z "${do_sync}" ] && echo "${10}") || ([ "${#}" = 10 ] || echo "${11}"))"
if [ -n "${report_directory}" ]; then
mkdir -p "${report_directory}"
else
report_directory="$(mktemp -d)"
trap 'rm -rf -- "${report_directory}"' INT TERM HUP EXIT
fi
case "$(uname -s)" in
Linux*)
grep_command=grep
sed_command=sed
;;
Darwin*)
grep_command=ggrep
sed_command=gsed
;;
*)
echo "Unsupported distribution $(uname -s) for this script."
exit 1
;;
esac
shared_build_flags="
-Perror-prone-compile,error-prone-test-compile
-Derror-prone.version=$(
mvn -f "${error_prone_support_root}" help:evaluate -Dexpression=version.error-prone -q -DforceStdout
)
-Derror-prone-support.version=$(
mvn -f "${error_prone_support_root}" help:evaluate -Dexpression=project.version -q -DforceStdout
)
-DadditionalSourceDirectories=${additional_source_directories}
${additional_build_flags}
"
# XXX: Configure Renovate to manage the fmt-maven-plugin version declared here.
# XXX: Once GitHub actions uses Maven 3.9.2+, we can inline this variable with
# version reference `${fmt.version}`, and `-Dfmt.version=2.21.1` added to
# `shared_build_flags`.
format_goal='com.spotify.fmt:fmt-maven-plugin:2.21.1:format'
error_prone_shared_flags='-XepExcludedPaths:(\Q${project.basedir}${file.separator}src${file.separator}\E(it|test|xdocs-examples)\Q${file.separator}resources\E|\Q${project.build.directory}${file.separator}\E).*'
error_prone_patch_flags="${error_prone_shared_flags} -XepPatchLocation:IN_PLACE -XepPatchChecks:$(
find "${error_prone_support_root}" \
-path "*/META-INF/services/com.google.errorprone.bugpatterns.BugChecker" \
-not -path "*/error-prone-experimental/*" \
-not -path "*/error-prone-guidelines/*" \
-print0 \
| xargs -0 "${grep_command}" -hoP '[^.]+$' \
| paste -s -d ',' -
) ${patch_error_prone_flags}"
error_prone_validation_flags="${error_prone_shared_flags} -XepDisableAllChecks $(
find "${error_prone_support_root}" \
-path "*/META-INF/services/com.google.errorprone.bugpatterns.BugChecker" \
-not -path "*/error-prone-experimental/*" \
-not -path "*/error-prone-guidelines/*" \
-print0 \
| xargs -0 "${grep_command}" -hoP '[^.]+$' \
| "${sed_command}" -r 's,(.*),-Xep:\1:WARN,' \
| paste -s -d ' ' -
) ${validation_error_prone_flags}"
echo "Shared build flags: ${shared_build_flags}"
echo "Error Prone patch flags: ${error_prone_patch_flags}"
echo "Error Prone validation flags: ${error_prone_validation_flags}"
mkdir -p "${repos_root}"
# Make sure that the targeted tag of the project's Git repository is checked
# out.
project_root="${repos_root}/${project}"
if [ ! -d "${project_root}" ]; then
# The repository has not yet been cloned; create a shallow clone.
git clone --branch "${revision}" --depth 1 "${repository}" "${project_root}"
else
# The repository does already appear to exist. Try to check out the requested
# tag if possible, and fetch it otherwise.
#
# Under certain circumstances this does not cause the relevant tag to be
# created, so if necessary we manually create it.
git -C "${project_root}" checkout --force "${revision}" 2>/dev/null \
|| (
git -C "${project_root}" fetch --depth 1 "${repository}" "${revision}" \
&& git -C "${project_root}" checkout --force FETCH_HEAD \
&& (git -C "${project_root}" tag "${revision}" || true)
)
fi
pushd "${project_root}"
# Make sure that Git is sufficiently configured to enable committing to the
# project's Git repository.
git config user.email || git config user.email 'integration-test@example.com'
git config user.name || git config user.name 'Integration Test'
# Prepare the code for analysis by (a) applying the minimal set of changes
# required to run Error Prone with Error Prone Support and (b) formatting the
# code using the same method by which it will be formatted after each
# compilation round. The initial formatting operation ensures that subsequent
# modifications can be rendered in a clean manner.
git clean -fdx
git apply < "${integration_test_root}/${test_name}-init.patch"
git commit -m 'dependency: Introduce Error Prone Support' .
mvn ${shared_build_flags} "${format_goal}"
git commit -m 'minor: Reformat using Google Java Format' .
diff_base="$(git rev-parse HEAD)"
# Apply Error Prone Support-suggested changes until a fixed point is reached.
function apply_patch() {
local extra_build_args="${1}"
mvn ${shared_build_flags} ${extra_build_args} \
package "${format_goal}" \
-Derror-prone.configuration-args="${error_prone_patch_flags}" \
-DskipTests
if ! git diff --exit-code; then
git commit -m 'minor: Apply patches' .
# Changes were applied, so another compilation round may apply yet more
# changes. For performance reasons we perform incremental compilation,
# enabled using a misleading flag. (See
# https://issues.apache.org/jira/browse/MCOMPILER-209 for details.)
apply_patch '-Dmaven.compiler.useIncrementalCompilation=false'
elif [ "${extra_build_args}" != 'clean' ]; then
# No changes were applied. We'll attempt one more round in which all files
# are recompiled, because there are cases in which violations are missed
# during incremental compilation.
apply_patch 'clean'
fi
}
apply_patch ''
# Run one more full build and log the output.
#
# By also running the tests, we validate that the (majority of) applied changes
# are behavior preserving.
validation_build_log="${report_directory}/${test_name}-validation-build-log.txt"
mvn ${shared_build_flags} \
clean package \
-Derror-prone.configuration-args="${error_prone_validation_flags}" \
${validation_build_flags} \
| tee "${validation_build_log}" \
|| failure=1
# Collect the applied changes.
expected_changes="${integration_test_root}/${test_name}-expected-changes.patch"
actual_changes="${report_directory}/${test_name}-changes.patch"
(git diff "${diff_base}"..HEAD | "${grep_command}" -vP '^(diff|index)' || true) > "${actual_changes}"
# Collect the warnings reported by Error Prone Support checks.
expected_warnings="${integration_test_root}/${test_name}-expected-warnings.txt"
actual_warnings="${report_directory}/${test_name}-validation-build-warnings.txt"
("${grep_command}" -oP "(?<=^\\Q[WARNING] ${PWD}/\\E).*" "${validation_build_log}" | "${grep_command}" -P '\] \[' || true) | LC_ALL=C sort > "${actual_warnings}"
# Persist or validate the applied changes and reported warnings.
if [ -n "${do_sync}" ]; then
echo 'Saving changes...'
cp "${actual_changes}" "${expected_changes}"
cp "${actual_warnings}" "${expected_warnings}"
else
echo 'Inspecting changes...'
# XXX: This "diff of diffs" also contains vacuous sections, introduced due to
# line offset differences. Try to omit those from the final output.
if ! diff -u "${expected_changes}" "${actual_changes}"; then
echo 'There are unexpected changes. Inspect the preceding output for details.'
failure=1
fi
echo 'Inspecting emitted warnings...'
if ! diff -u "${expected_warnings}" "${actual_warnings}"; then
echo 'Diagnostics output changed. Inspect the preceding output for details.'
failure=1
fi
fi
if [ -n "${failure:-}" ]; then
exit 1
fi

197
pom.xml
View File

@@ -4,7 +4,7 @@
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.17.0</version>
<version>0.19.2-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Picnic :: Error Prone Support</name>
@@ -52,7 +52,7 @@
<scm child.scm.developerConnection.inherit.append.path="false" child.scm.url.inherit.append.path="false">
<developerConnection>scm:git:git@github.com:PicnicSupermarket/error-prone-support.git</developerConnection>
<tag>v0.17.0</tag>
<tag>HEAD</tag>
<url>https://github.com/PicnicSupermarket/error-prone-support</url>
</scm>
<issueManagement>
@@ -111,6 +111,9 @@
but also prevents excessive memory usage by heavily parallelized
local builds. -->
-Xmx${argLine.xmx}
<!-- Configure the Byte Buddy Java agent used by Mockito to create
mocks. -->
-javaagent:${org.mockito:mockito-core:jar}
<!-- This argument cannot be set through Surefire's
'systemPropertyVariables' configuration setting. Setting the file
encoding is necessary because forked unit test invocations
@@ -148,7 +151,7 @@
<groupId.error-prone>com.google.errorprone</groupId.error-prone>
<!-- The build timestamp is derived from the most recent commit
timestamp in support of reproducible builds. -->
<project.build.outputTimestamp>2024-07-20T12:12:19Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2024-11-03T15:58:19Z</project.build.outputTimestamp>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Glob pattern identifying Refaster rule definition files. These
Java classes don't contain "regular" code, and thus require special
@@ -208,16 +211,16 @@
<version.auto-value>1.11.0</version.auto-value>
<version.error-prone>${version.error-prone-orig}</version.error-prone>
<version.error-prone-fork>v${version.error-prone-orig}-picnic-1</version.error-prone-fork>
<version.error-prone-orig>2.29.2</version.error-prone-orig>
<version.error-prone-slf4j>0.1.25</version.error-prone-slf4j>
<version.error-prone-orig>2.35.1</version.error-prone-orig>
<version.error-prone-slf4j>0.1.28</version.error-prone-slf4j>
<version.guava-beta-checker>1.0</version.guava-beta-checker>
<version.jdk>17</version.jdk>
<version.maven>3.9.5</version.maven>
<version.mockito>5.12.0</version.mockito>
<version.maven>3.9.9</version.maven>
<version.mockito>5.14.2</version.mockito>
<version.nopen-checker>1.0.1</version.nopen-checker>
<version.nullaway>0.11.0</version.nullaway>
<version.nullaway>0.12.1</version.nullaway>
<version.pitest-git>1.1.4</version.pitest-git>
<version.rewrite-templating>1.12.0</version.rewrite-templating>
<version.rewrite-templating>1.17.0</version.rewrite-templating>
<version.surefire>3.2.3</version.surefire>
</properties>
@@ -296,10 +299,15 @@
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>2.17.2</version>
<version>2.18.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>
<dependency>
<groupId>com.google.auto</groupId>
<artifactId>auto-common</artifactId>
@@ -328,7 +336,7 @@
<dependency>
<groupId>com.google.googlejavaformat</groupId>
<artifactId>google-java-format</artifactId>
<version>1.22.0</version>
<version>1.24.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
@@ -338,7 +346,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-bom</artifactId>
<version>33.2.1-jre</version>
<version>33.3.1-jre</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -357,10 +365,15 @@
<artifactId>nullaway</artifactId>
<version>${version.nullaway}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.13.6</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-bom</artifactId>
<version>2023.0.8</version>
<version>2023.0.11</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -377,7 +390,7 @@
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.2.22</version>
<version>2.2.25</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
@@ -412,7 +425,7 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.14.18</version>
<version>1.15.10</version>
</dependency>
<!-- Specified so that Renovate will file Maven upgrade PRs, which
subsequently will cause `maven-enforcer-plugin` to require that
@@ -437,12 +450,12 @@
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.45.0</version>
<version>3.48.2</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.2</version>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.immutables</groupId>
@@ -457,7 +470,7 @@
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.10.3</version>
<version>5.11.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -471,7 +484,14 @@
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-core</artifactId>
<version>5.1.2</version>
<version>5.2.0</version>
</dependency>
<!-- XXX: Drop this `rewrite-java-17` version declaration once
`rewrite-recipe-bom` pulls in version 8.39.1 or greater. -->
<dependency>
<groupId>org.openrewrite</groupId>
<artifactId>rewrite-java-17</artifactId>
<version>8.40.0</version>
</dependency>
<dependency>
<groupId>org.openrewrite</groupId>
@@ -481,33 +501,33 @@
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-recipe-bom</artifactId>
<version>2.15.0</version>
<version>2.21.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-bom</artifactId>
<version>2.0.13</version>
<version>2.0.16</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>6.1.11</version>
<version>6.1.14</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>3.3.2</version>
<version>3.3.5</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-bom</artifactId>
<version>6.3.1</version>
<version>6.3.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -518,6 +538,17 @@
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- To avoid repetition of fairly complex configuration, Surefire
is configured to always load Mockito's Java agent. Declaring the
associated dependency here avoids additional repetition, and prevents
a slightly obscure error that happens if the dependency is absent. -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
@@ -562,7 +593,7 @@
<plugin>
<groupId>com.spotify.fmt</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<version>2.22.1</version>
<version>2.25</version>
<configuration>
<additionalSourceDirectories>
<additionalSourceDirectory>${basedir}/src/test/resources</additionalSourceDirectory>
@@ -582,7 +613,7 @@
<plugin>
<groupId>de.thetaphi</groupId>
<artifactId>forbiddenapis</artifactId>
<version>3.7</version>
<version>3.8</version>
<configuration>
<bundledSignatures>
<bundledSignature>jdk-internal</bundledSignature>
@@ -648,7 +679,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.4.0</version>
<version>3.6.0</version>
<configuration>
<checkstyleRules>
<!-- We only enable rules that are not enforced by
@@ -897,7 +928,7 @@
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>10.17.0</version>
<version>10.20.1</version>
</dependency>
<dependency>
<groupId>io.spring.nohttp</groupId>
@@ -965,11 +996,43 @@
https://issues.apache.org/jira/browse/MCOMPILER-209. -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
<executions>
<!-- OpenRewrite recipe sources, generated by the
`rewrite-templating` annotation processor and
identified as classes whose name ends in `Recipes`, are
compiled to target Java 8 for compatibility with the
wider OpenRewrite ecosystem. The `maven-jar-plugin` is
configured to package these files into a separate JAR. -->
<execution>
<id>compile-recipes</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<compilerArgs combine.self="override">
<!-- When Java 8 is targeted we can't use
the `add-exports` flag. And since this goal
only recompiles already-compiled code,
static analysis is irrelevant. As such we
clear all compiler arguments, and only
suppress source/target/bootstrap classpath
warnings. -->
<arg>-Xlint:-options</arg>
</compilerArgs>
<source>8</source>
<target>8</target>
<includes>
<include>**/*Recipes.java</include>
</includes>
<outputDirectory>${project.build.directory}/openrewrite-recipes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.7.1</version>
<version>3.8.1</version>
<configuration>
<!-- XXX: Drop `ignoreAllNonTestScoped` once
https://issues.apache.org/jira/browse/MNG-6058 is
@@ -980,11 +1043,19 @@
<ignoreDirect>false</ignoreDirect>
<ignoreNonCompile>true</ignoreNonCompile>
</configuration>
<executions>
<execution>
<id>set-additional-properties</id>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.2</version>
<version>3.1.3</version>
<configuration>
<retryFailedDeploymentCount>3</retryFailedDeploymentCount>
</configuration>
@@ -1062,7 +1133,7 @@
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.8.0</version>
<version>1.9.0</version>
</dependency>
</dependencies>
<executions>
@@ -1077,7 +1148,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.2.4</version>
<version>3.2.7</version>
<executions>
<execution>
<id>sign-artifacts</id>
@@ -1090,7 +1161,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.2</version>
<version>3.1.3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -1112,6 +1183,39 @@
</archive>
</configuration>
<executions>
<execution>
<id>default-jar</id>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<!-- These Java 17 bytecode classes are omitted
from the default JAR, as instead we produce a
separate artifact with Java 8 bytecode variants. -->
<excludes>
<excludes>**/*Recipe$*.class</excludes>
<excludes>**/*Recipe.class</excludes>
<excludes>**/*Recipes.class</excludes>
</excludes>
</configuration>
</execution>
<execution>
<!-- Creates a custom JAR with Java 8-compatible
OpenRewrite recipe classes. -->
<id>create-openrewrite-recipes-jar</id>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>${project.build.directory}/openrewrite-recipes</classesDirectory>
<classifier>recipes</classifier>
<includes>
<includes>**/*Recipe$*.class</includes>
<includes>**/*Recipe.class</includes>
<includes>**/*Recipes.class</includes>
</includes>
</configuration>
</execution>
<execution>
<id>create-test-jar</id>
<goals>
@@ -1123,7 +1227,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.7.0</version>
<version>3.11.1</version>
<configuration>
<additionalJOptions>
<additionalJOption>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</additionalJOption>
@@ -1174,7 +1278,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
<version>3.21.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -1193,7 +1297,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.1</version>
<version>3.5.2</version>
<configuration>
<includes>
<include>**/*Test.java</include>
@@ -1206,11 +1310,6 @@
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.6.0</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
@@ -1404,7 +1503,7 @@
<plugin>
<groupId>org.kordamp.maven</groupId>
<artifactId>pomchecker-maven-plugin</artifactId>
<version>1.11.0</version>
<version>1.14.0</version>
<configuration>
<failOnError>false</failOnError>
<release>false</release>
@@ -1422,7 +1521,7 @@
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.16.1</version>
<version>1.17.1</version>
<configuration>
<excludedClasses>
<!-- AutoValue generated classes. -->
@@ -1476,7 +1575,7 @@
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>4.0.0.4121</version>
<version>5.0.0.4389</version>
</plugin>
</plugins>
</pluginManagement>
@@ -1485,6 +1584,10 @@
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
@@ -1864,6 +1967,12 @@
<!-- XXX: Enable this once we open-source
this library. -->
-Xep:BetaApi:OFF
<!-- This check flags bad member names, but
also type names that we may want to accept.
Consider contributing a flag to toggle this
behavior. See
https://github.com/google/error-prone/issues/4616 -->
-Xep:IdentifierName:OFF
<!-- We don't target JDK 7. -->
-Xep:Java7ApiChecker:OFF
<!-- We don't target JDK 8. -->

View File

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

View File

@@ -21,7 +21,6 @@ import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Name;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
@@ -137,10 +136,10 @@ final class RefasterRuleCompilerTaskListener implements TaskListener {
return enclosingPackage == null ? "" : enclosingPackage.toString();
}
private static CharSequence toSimpleFlatName(ClassSymbol symbol) {
Name flatName = symbol.flatName();
private static String toSimpleFlatName(ClassSymbol symbol) {
String flatName = symbol.flatName().toString();
int lastDot = flatName.lastIndexOf((byte) '.');
return lastDot < 0 ? flatName : flatName.subSequence(lastDot + 1, flatName.length());
return lastDot < 0 ? flatName : flatName.substring(lastDot + 1);
}
private static void outputCodeTransformer(CodeTransformer codeTransformer, FileObject target)

View File

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

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.17.0</version>
<version>0.19.2-SNAPSHOT</version>
</parent>
<artifactId>refaster-support</artifactId>
@@ -88,10 +88,5 @@
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

Some files were not shown because too many files have changed in this diff Show More