Compare commits

...

287 Commits

Author SHA1 Message Date
Rick Ossendrijver
8ba4f872be Add tests and more context in the StringRules file 2024-09-03 16:45:28 +02:00
Rick Ossendrijver
3d5678e20e Introduce comment for the String#copyValueOf rewrite 2024-09-03 16:45:27 +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
Stephan Schroevers
5a163ce2e9 [maven-release-plugin] prepare release v0.17.0 2024-07-20 14:15:43 +02:00
Picnic-DevPla-Bot
4eb0aae452 Upgrade versions-maven-plugin 2.17.0 -> 2.17.1 (#1250)
See:
- https://github.com/mojohaus/versions/releases/tag/2.17.1
- https://github.com/mojohaus/versions-maven-plugin/compare/2.17.0...2.17.1
2024-07-20 14:09:49 +02:00
Picnic-DevPla-Bot
b5b98d899b Upgrade OpenRewrite Templating 1.11.2 -> 1.12.0 (#1252)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.12.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.11.2...v1.12.0
2024-07-20 14:00:07 +02:00
Picnic-DevPla-Bot
bbf3d79d9a Upgrade Error Prone 2.29.1 -> 2.29.2 (#1258)
See:
- https://github.com/google/error-prone/releases/tag/v2.29.2
- https://github.com/google/error-prone/compare/v2.29.1...v2.29.2
- https://github.com/PicnicSupermarket/error-prone/compare/v2.29.1-picnic-1...v2.29.2-picnic-1
2024-07-20 13:52:09 +02:00
Picnic-DevPla-Bot
1164270589 Upgrade OpenRewrite 2.14.0 -> 2.15.0 (#1251)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.15.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.14.0...v2.15.0
2024-07-20 13:39:50 +02:00
Picnic-DevPla-Bot
f03d72388a Upgrade JSpecify 0.3.0 -> 1.0.0 (#1256)
See:
- https://github.com/jspecify/jspecify/releases/tag/v1.0.0
- https://github.com/jspecify/jspecify/compare/v0.3.0...v1.0.0
2024-07-20 13:08:33 +02:00
tijana-ninkovic
2e5d1f1e87 Extend FluxJust Refaster rule (#1253) 2024-07-20 12:57:45 +02:00
Vincent Koeman
4b1c892f04 Introduce MonoFromFutureSupplier{,Boolean} Refaster rules (#1244) 2024-07-20 12:44:37 +02:00
Picnic-DevPla-Bot
2b6b8de150 Upgrade Spring Boot 3.3.1 -> 3.3.2 (#1257)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.2
- https://github.com/spring-projects/spring-boot/compare/v3.3.1...v3.3.2
2024-07-20 00:10:21 +02:00
Picnic-DevPla-Bot
b275a33eb8 Upgrade Error Prone 2.28.0 -> 2.29.1 (#1255)
See:
- https://github.com/google/error-prone/releases/tag/v2.29.0
- https://github.com/google/error-prone/releases/tag/v2.29.1
- https://github.com/google/error-prone/compare/v2.28.0...v2.29.1
- https://github.com/PicnicSupermarket/error-prone/compare/v2.28.0-picnic-1...v2.29.1-picnic-1
2024-07-19 23:57:01 +02:00
Picnic-DevPla-Bot
7a9aeca248 Upgrade AssertJ 3.26.0 -> 3.26.3 (#1254)
See:
- https://github.com/assertj/assertj/releases/tag/assertj-build-3.26.3
- https://github.com/assertj/assertj/compare/assertj-build-3.26.0...assertj-build-3.26.3
2024-07-18 09:59:17 +02:00
Picnic-DevPla-Bot
bd5cdefea9 Upgrade maven-release-plugin 3.1.0 -> 3.1.1 (#1249)
See:
- https://github.com/apache/maven-release/releases/tag/maven-release-3.1.1
- https://github.com/apache/maven-release/compare/maven-release-3.1.0...maven-release-3.1.1
2024-07-18 07:37:50 +02:00
Picnic-Bot
a265a450f9 Upgrade AssertJ 3.25.3 -> 3.26.0 (#1197)
See:
- https://github.com/assertj/assertj/releases/tag/assertj-build-3.26.0
- https://github.com/assertj/assertj/compare/assertj-build-3.25.3...assertj-build-3.26.0
2024-07-17 16:14:56 +02:00
Stephan Schroevers
5fbb0636aa Suppress new SonarCloud warning (#1248) 2024-07-15 09:53:49 +02:00
Picnic-DevPla-Bot
6eb22da201 Upgrade MongoDB driver 5.1.1 -> 5.1.2 (#1241)
See:
- https://github.com/mongodb/mongo-java-driver/releases/tag/r5.1.2
- https://github.com/mongodb/mongo-java-driver/compare/r5.1.1...r5.1.2
2024-07-15 08:29:54 +02:00
Picnic-DevPla-Bot
781b4d0c57 Upgrade Truth 1.4.3 -> 1.4.4 (#1247)
See:
- https://github.com/google/truth/releases/tag/v1.4.4
- https://github.com/google/truth/compare/v1.4.3...v1.4.4
2024-07-15 07:34:33 +02:00
Picnic-DevPla-Bot
5234fca96d Upgrade Spring 6.1.10 -> 6.1.11 (#1245)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.11
- https://github.com/spring-projects/spring-framework/compare/v6.1.10...v6.1.11
2024-07-14 15:01:43 +02:00
Stephan Schroevers
8daedccaea Update step-security/harden-runner configuration (#1246)
While apparently the build doesn't fail without this, it is reasonable
for SonarCloud analysis to access the `api.sonarcloud.io` domain.
2024-07-14 14:11:41 +02:00
Mohamed Sameh
886e65d7ac Introduce EnumReferenceEqualityLambda Refaster rule (#1239) 2024-07-14 14:00:18 +02:00
Picnic-DevPla-Bot
ec502cef20 Upgrade Surefire 3.3.0 -> 3.3.1 (#1243)
See:
- https://github.com/apache/maven-surefire/releases/tag/surefire-3.3.1
- https://github.com/apache/maven-surefire/compare/surefire-3.3.0...surefire-3.3.1
2024-07-11 15:59:36 +02:00
Picnic-DevPla-Bot
f3ff515271 Upgrade Project Reactor 2023.0.7 -> 2023.0.8 (#1242)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.8
- https://github.com/reactor/reactor/compare/2023.0.7...2023.0.8
2024-07-11 10:25:38 +02:00
Picnic-DevPla-Bot
d662eb1cbc Upgrade git-commit-id-maven-plugin 9.0.0 -> 9.0.1 (#1235)
See:
- https://github.com/git-commit-id/git-commit-id-maven-plugin/releases/tag/v9.0.1
- https://github.com/git-commit-id/git-commit-id-maven-plugin/compare/v9.0.0...v9.0.1
2024-07-10 10:08:46 +02:00
Picnic-DevPla-Bot
c40b73186b Upgrade OpenRewrite 2.13.2 -> 2.14.0 (#1236)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.14.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.13.2...v2.14.0See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.14.0
2024-07-09 11:20:17 +02:00
Picnic-DevPla-Bot
6734af6742 Upgrade Jackson 2.17.1 -> 2.17.2 (#1238)
See:
- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.17.2
- https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.17.1...jackson-bom-2.17.2
2024-07-09 10:54:57 +02:00
Picnic-DevPla-Bot
c5ec2a552d Upgrade OpenRewrite Templating 1.11.1 -> 1.11.2 (#1234)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.11.2
- https://github.com/openrewrite/rewrite-templating/compare/v1.11.1...v1.11.2
2024-07-09 10:37:50 +02:00
Picnic-DevPla-Bot
a3e3a32332 Upgrade Byte Buddy 1.14.17 -> 1.14.18 (#1240)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.18
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.17...byte-buddy-1.14.18
2024-07-09 08:38:51 +02:00
Picnic-DevPla-Bot
8c3756c4f7 Upgrade versions-maven-plugin 2.16.2 -> 2.17.0 (#1232)
See:
- https://github.com/mojohaus/versions/releases/tag/2.17.0
- https://github.com/mojohaus/versions-maven-plugin/compare/2.16.2...2.17.0
2024-07-03 08:59:39 +02:00
Picnic-DevPla-Bot
c472225f9c Upgrade Checker Framework Annotations 3.44.0 -> 3.45.0 (#1233)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.45.0
- https://github.com/typetools/checker-framework/compare/checker-framework-3.44.0...checker-framework-3.45.0
2024-07-03 08:45:02 +02:00
Picnic-DevPla-Bot
7a8538a87a Upgrade Truth 1.4.2 -> 1.4.3 (#1230)
See:
- https://github.com/google/truth/releases/tag/v1.4.3
- https://github.com/google/truth/compare/v1.4.2...v1.4.3
2024-07-02 15:36:18 +02:00
Picnic-DevPla-Bot
dba37a3f23 Upgrade JUnit 5 5.10.2 -> 5.10.3 (#1231)
See:
- https://junit.org/junit5/docs/current/release-notes/
- https://github.com/junit-team/junit5/releases/tag/r5.10.3
- https://github.com/junit-team/junit5/compare/r5.10.2...r5.10.3
2024-07-01 14:35:22 +02:00
Picnic-DevPla-Bot
e89cfe0aef Upgrade Error Prone 2.27.1 -> 2.28.0 (#1200)
See:
- https://github.com/google/error-prone/releases/tag/v2.28.0
- https://github.com/google/error-prone/compare/v2.27.1...v2.28.0
- https://github.com/PicnicSupermarket/error-prone/compare/v2.27.1-picnic-1...v2.28.0-picnic-1
2024-06-30 11:55:32 +02:00
Picnic-DevPla-Bot
9c1993e5a7 Upgrade maven-jar-plugin 3.4.1 -> 3.4.2 (#1224)
See:
- https://github.com/apache/maven-jar-plugin/releases/tag/maven-jar-plugin-3.4.2
- https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.1...maven-jar-plugin-3.4.2
2024-06-28 10:18:53 +02:00
Picnic-DevPla-Bot
d586014379 Upgrade Spring Boot 3.3.0 -> 3.3.1 (#1228)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.1
- https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.1
2024-06-27 09:23:36 +02:00
Picnic-DevPla-Bot
3a441487a3 Upgrade Spring 6.1.8 -> 6.1.10 (#1219)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.9
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.10
- https://github.com/spring-projects/spring-framework/compare/v6.1.8...v6.1.10
2024-06-26 11:14:09 +02:00
Picnic-DevPla-Bot
6f6a4c481e Upgrade Project Reactor 2023.0.6 -> 2023.0.7 (#1215)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.7
- https://github.com/reactor/reactor/compare/2023.0.6...2023.0.7
2024-06-26 10:57:35 +02:00
Picnic-DevPla-Bot
56f0cc81c9 Upgrade OpenRewrite 2.12.0 -> 2.13.2 (#1225)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.13.0
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.13.1
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.13.2
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.12.0...v2.13.2
2024-06-26 10:34:42 +02:00
Picnic-DevPla-Bot
6c58d4cc01 Upgrade maven-clean-plugin 3.3.2 -> 3.4.0 (#1227)
See:
- https://github.com/apache/maven-clean-plugin/releases/tag/maven-clean-plugin-3.4.0
- https://github.com/apache/maven-clean-plugin/compare/maven-clean-plugin-3.3.2...maven-clean-plugin-3.4.0
2024-06-26 10:21:42 +02:00
Picnic-DevPla-Bot
a1e47542e7 Upgrade Surefire 3.2.5 -> 3.3.0 (#1220)
See:
- https://github.com/apache/maven-surefire/releases/tag/surefire-3.3.0
- https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.3.0
2024-06-26 09:44:47 +02:00
Picnic-DevPla-Bot
eff958d4c1 Upgrade OpenRewrite Templating 1.10.0 -> 1.11.1 (#1226)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.11.1
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.11.0
2024-06-26 08:42:22 +02:00
Picnic-DevPla-Bot
81704c6534 Upgrade maven-dependency-plugin 3.7.0 -> 3.7.1 (#1229)
See:
- https://github.com/apache/maven-dependency-plugin/releases/tag/maven-dependency-plugin-3.7.1
- https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.7.0...maven-dependency-plugin-3.7.1
2024-06-25 16:31:46 +02:00
Picnic-DevPla-Bot
1e229949fc Upgrade Jakarta Servlet 6.0.0 -> 6.1.0 (#1216)
See:
- https://github.com/eclipse-ee4j/servlet-api/compare/6.0.0-RELEASE...6.1.0-RELEASE
2024-06-18 11:04:56 +02:00
Picnic-DevPla-Bot
28a93e949e Upgrade maven-dependency-plugin 3.6.1 -> 3.7.0 (#1217)
See:
- https://github.com/apache/maven-dependency-plugin/releases/tag/maven-dependency-plugin-3.7.0
- https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.6.1...maven-dependency-plugin-3.7.0
2024-06-18 09:11:59 +02:00
Picnic-DevPla-Bot
40ad38bc2a Upgrade maven-release-plugin 3.0.1 -> 3.1.0 (#1221)
See:
- https://github.com/apache/maven-release/releases/tag/maven-release-3.1.0
- https://github.com/apache/maven-release/compare/maven-release-3.0.1...maven-release-3.1.0
2024-06-18 09:02:56 +02:00
Picnic-DevPla-Bot
e125c6b7e2 Upgrade Spring Security 6.3.0 -> 6.3.1 (#1222)
See:
- https://github.com/spring-projects/spring-security/releases/tag/6.3.1
- https://github.com/spring-projects/spring-security/compare/6.3.0...6.3.1
2024-06-18 08:36:10 +02:00
Picnic-DevPla-Bot
5596c4530d Upgrade MongoDB driver 5.1.0 -> 5.1.1 (#1218)
See:
- https://jira.mongodb.org/issues/?jql=project%20%3D%20JAVA%20AND%20fixVersion%20%3E%205.1.0%20AND%20fixVersion%20%3C%3D%205.1.1
- https://github.com/mongodb/mongo-java-driver/releases/tag/r5.1.1
- https://github.com/mongodb/mongo-java-driver/compare/r5.1.0...r5.1.1
2024-06-17 14:03:25 +02:00
Stephan Schroevers
d81fe19836 Extend FluxConcatMap Refaster rule (#1213) 2024-06-10 15:34:16 +02:00
Picnic-DevPla-Bot
d6838ec947 Upgrade errorprone-slf4j 0.1.24 -> 0.1.25 (#1212)
See:
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.25
- https://github.com/KengoTODA/errorprone-slf4j/compare/v0.1.24...v0.1.25
2024-06-10 09:13:54 +02:00
Picnic-DevPla-Bot
b36a69aa5f Upgrade git-commit-id-maven-plugin 8.0.2 -> 9.0.0 (#1211)
See:
- https://github.com/git-commit-id/git-commit-id-maven-plugin/releases/tag/v9.0.0
- https://github.com/git-commit-id/git-commit-id-maven-plugin/compare/v8.0.2...v9.0.0
2024-06-10 08:32:32 +02:00
Picnic-DevPla-Bot
831b757bb1 Upgrade OpenRewrite Templating 1.9.2 -> 1.10.0 (#1210)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.10.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.9.2...v1.10.0
2024-06-08 23:23:26 +02:00
Picnic-DevPla-Bot
527fc5785b Upgrade OpenRewrite 2.11.1 -> 2.12.0 (#1209)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.12.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.11.1...v2.12.0
2024-06-08 12:18:41 +02:00
Picnic-DevPla-Bot
8c8055d381 Upgrade maven-checkstyle-plugin 3.3.1 -> 3.4.0 (#1208)
See https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.1...maven-checkstyle-plugin-3.4.0
2024-06-07 11:08:31 +02:00
Picnic-Bot
b658c19c03 Upgrade Spring Boot 3.2.5 -> 3.3.0 (#1196)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.6
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.0-M1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.0-M2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.0-M3
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.0-RC1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.3.0
- https://github.com/spring-projects/spring-boot/compare/v3.2.5...v3.3.0
2024-06-05 09:42:42 +02:00
Picnic-DevPla-Bot
85976e199f Upgrade Checker Framework Annotations 3.43.0 -> 3.44.0 (#1207)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.44.0
- https://github.com/typetools/checker-framework/compare/checker-framework-3.43.0...checker-framework-3.44.0
2024-06-05 09:20:12 +02:00
Picnic-DevPla-Bot
f6a392e118 Upgrade Guava 33.2.0-jre -> 33.2.1-jre (#1202)
See:
- https://guava.dev/releases/33.2.1-jre/api/diffs/
- https://github.com/google/guava/releases/tag/v33.2.1
- https://github.com/google/guava/compare/v33.2.0...v33.2.1
2024-06-04 16:39:05 +02:00
Picnic-DevPla-Bot
539fcae745 Upgrade maven-javadoc-plugin 3.6.3 -> 3.7.0 (#1205)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MJAVADOC%20AND%20fixVersion%20%3E%203.6.3%20AND%20fixVersion%20%3C%3D%203.7.0
- https://github.com/apache/maven-javadoc-plugin/releases/tag/maven-javadoc-plugin-3.7.0
- https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.3...maven-javadoc-plugin-3.7.0
2024-06-04 14:47:57 +02:00
Picnic-DevPla-Bot
29f1a3d2a6 Upgrade maven-enforcer-plugin 3.4.1 -> 3.5.0 (#1201)
See:
- https://github.com/apache/maven-enforcer/releases/tag/enforcer-3.5.0
- https://github.com/apache/maven-enforcer/compare/enforcer-3.4.1...enforcer-3.5.0
2024-06-04 13:56:07 +02:00
Picnic-DevPla-Bot
01f139b6a4 Upgrade NullAway 0.10.26 -> 0.11.0 (#1204)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.11.0
- https://github.com/uber/NullAway/compare/v0.10.26...v0.11.0
2024-06-04 13:37:52 +02:00
Picnic-DevPla-Bot
c61980721e Upgrade AutoValue 1.10.4 -> 1.11.0 (#1203)
See:
- https://github.com/google/auto/releases/tag/auto-value-1.11.0
- https://github.com/google/auto/compare/auto-value-1.10.4...auto-value-1.11.0
2024-06-04 13:06:01 +02:00
Picnic-DevPla-Bot
471a1ebff1 Upgrade Byte Buddy 1.14.16 -> 1.14.17 (#1199)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.17
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.16...byte-buddy-1.14.17
2024-06-04 07:55:19 +02:00
Picnic-DevPla-Bot
b8d9ff0971 Upgrade sonar-maven-plugin 3.11.0.3922 -> 4.0.0.4121 (#1206)
See:
- https://github.com/SonarSource/sonar-scanner-maven/releases/tag/4.0.0.4121
- https://github.com/SonarSource/sonar-scanner-maven/compare/3.11.0.3922...4.0.0.4121
2024-06-04 07:37:39 +02:00
Picnic-Bot
e02d836c12 Upgrade Modernizer Maven Plugin 2.8.0 -> 2.9.0 (#1195)
See:
- https://github.com/gaul/modernizer-maven-plugin/releases/tag/modernizer-maven-plugin-2.9.0
- https://github.com/gaul/modernizer-maven-plugin/compare/modernizer-maven-plugin-2.8.0...modernizer-maven-plugin-2.9.0
2024-05-27 16:09:23 +02:00
Picnic-Bot
abd47eb269 Upgrade Checkstyle 10.16.0 -> 10.17.0 (#1198)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.17.0
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.16.0...checkstyle-10.17.0
2024-05-27 14:42:20 +02:00
Stephan Schroevers
5219fd8f6c Allow OpenSSF Scorecard analysis to access api.scorecard.dev (#1193) 2024-05-25 19:02:02 +02:00
Picnic-Bot
588fc38f81 Upgrade OpenRewrite 2.11.0 -> 2.11.1 (#1190)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.11.1
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.11.0...v2.11.1
2024-05-24 13:49:50 +02:00
Picnic-Bot
e3aa8a5d12 Upgrade OpenRewrite Templating 1.9.0 -> 1.9.2 (#1191)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.9.1
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.9.2
- https://github.com/openrewrite/rewrite-templating/compare/v1.9.0...v1.9.2
2024-05-24 13:31:25 +02:00
Picnic-Bot
3255c0b6eb Upgrade Spring 6.1.7 -> 6.1.8 (#1192)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.8
- https://github.com/spring-projects/spring-framework/compare/v6.1.7...v6.1.8
2024-05-24 13:21:50 +02:00
Picnic-Bot
d2dbd88f25 Upgrade Byte Buddy 1.14.15 -> 1.14.16 (#1189)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.16
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.15...byte-buddy-1.14.16
2024-05-24 11:41:07 +02:00
Picnic-Bot
ff824cfa20 Upgrade Spring Security 6.2.4 -> 6.3.0 (#1186)
See:
- https://github.com/spring-projects/spring-security/releases/tag/6.3.0-M1
- https://github.com/spring-projects/spring-security/releases/tag/6.3.0-M2
- https://github.com/spring-projects/spring-security/releases/tag/6.3.0-M3
- https://github.com/spring-projects/spring-security/releases/tag/6.3.0-RC1
- https://github.com/spring-projects/spring-security/releases/tag/6.3.0
- https://github.com/spring-projects/spring-security/compare/6.2.4...6.3.0
2024-05-23 16:39:20 +02:00
Picnic-Bot
43303e770a Upgrade actions/checkout v4.1.4 -> v4.1.6 (#1184)
See:
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v416
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v415
2024-05-23 10:36:32 +02:00
Picnic-Bot
cfadbca32a Upgrade ossf/scorecard-action v2.3.1 -> v2.3.3 (#1185)
See:
- https://github.com/ossf/scorecard-action/releases/tag/v2.3.3
- https://github.com/ossf/scorecard-action/compare/v2.3.1...v2.3.2
2024-05-23 09:05:16 +02:00
Picnic-Bot
e7ca4a5325 Upgrade s4u/setup-maven-action v1.12.0 -> v1.13.0 (#1187)
See:
- https://github.com/s4u/setup-maven-action/releases/tag/v1.13.0
2024-05-22 10:23:23 +02:00
Picnic-Bot
7bab1eb7fd Upgrade step-security/harden-runner v2.7.1 -> v2.8.0 (#1188)
See:
- https://github.com/step-security/harden-runner/releases/tag/v2.8.0
2024-05-22 08:36:34 +02:00
Picnic-DevPla-Bot
072e39da32 Upgrade build-helper-maven-plugin 3.5.0 -> 3.6.0 (#1182)
See:
- https://github.com/mojohaus/build-helper-maven-plugin/releases/tag/3.6.0
- https://github.com/mojohaus/build-helper-maven-plugin/compare/3.5.0...3.6.0
2024-05-21 09:49:09 +02:00
Picnic-DevPla-Bot
ec7e84ac45 Upgrade Swagger 2.2.21 -> 2.2.22 (#1178)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.22
- https://github.com/swagger-api/swagger-core/compare/v2.2.21...v2.2.22
2024-05-21 09:39:03 +02:00
Picnic-DevPla-Bot
4228a63ad1 Upgrade Project Reactor 2023.0.5 -> 2023.0.6 (#1176)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.6
- https://github.com/reactor/reactor/compare/2023.0.5...2023.0.6
2024-05-21 09:16:03 +02:00
Picnic-DevPla-Bot
6093e6f322 Upgrade OpenRewrite Templating 1.8.1 -> 1.9.0 (#1181)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.9.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.8.1...v1.9.0
2024-05-21 09:06:51 +02:00
Picnic-DevPla-Bot
ee103a99f6 Upgrade Spring 6.1.6 -> 6.1.7 (#1180)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.7
- https://github.com/spring-projects/spring-framework/compare/v6.1.6...v6.1.7
2024-05-21 08:58:01 +02:00
Pieter Dirk Soels
c34065beab Improve Renovate configuration (#1179) 2024-05-21 07:29:26 +02:00
Picnic-DevPla-Bot
d9e1f3ad5d Upgrade sortpom-maven-plugin 3.4.1 -> 4.0.0 (#1183)
See:
- https://github.com/Ekryd/sortpom/wiki/Versions
- https://github.com/Ekryd/sortpom/compare/sortpom-parent-3.4.1...sortpom-parent-4.0.0
2024-05-20 21:28:31 +02:00
Stephan Schroevers
8a8290587a Update step-security/harden-runner configuration (#1177)
This resolves recent build failures by ensuring that JDKs can be
downloaded.
2024-05-19 14:14:20 +02:00
Picnic-DevPla-Bot
162aa0d458 Upgrade tidy-maven-plugin 1.2.0 -> 1.3.0 (#1175)
See:
- https://github.com/mojohaus/tidy-maven-plugin/releases/tag/1.3.0
- https://github.com/mojohaus/tidy-maven-plugin/compare/tidy-maven-plugin-1.2.0...1.3.0
2024-05-13 08:07:12 +02:00
Picnic-DevPla-Bot
0fb37c45b5 Upgrade Mockito 5.11.0 -> 5.12.0 (#1174)
See:
- https://github.com/mockito/mockito/releases/tag/v5.12.0
- https://github.com/mockito/mockito/compare/v5.11.0...v5.12.0
2024-05-12 10:16:02 +02:00
Picnic-DevPla-Bot
0c2ce44742 Upgrade AspectJ 1.9.22 -> 1.9.22.1 (#1173)
See:
- https://github.com/eclipse-aspectj/aspectj/releases/tag/V1_9_22_1
- https://github.com/eclipse-aspectj/aspectj/compare/V1_9_22...V1_9_22_1
2024-05-12 10:03:43 +02:00
Picnic-DevPla-Bot
f089157443 Upgrade Byte Buddy 1.14.14 -> 1.14.15 (#1169)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.15
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.14...byte-buddy-1.14.15
2024-05-11 14:59:23 +02:00
Picnic-DevPla-Bot
e192dacdfb Upgrade pitest-maven-plugin 1.16.0 -> 1.16.1 (#1172)
See:
- https://github.com/hcoles/pitest/releases/tag/1.16.1
- https://github.com/hcoles/pitest/compare/1.16.0...1.16.1
2024-05-10 19:24:00 +02:00
Picnic-DevPla-Bot
8418652de0 Upgrade OpenRewrite Templating 1.8.0 -> 1.8.1 (#1170)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.8.1
- https://github.com/openrewrite/rewrite-templating/compare/v1.8.0...v1.8.1
2024-05-10 19:13:24 +02:00
Picnic-DevPla-Bot
1d8ac35660 Upgrade OpenRewrite 2.10.0 -> 2.11.0 (#1171)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.11.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.10.0...v2.11.0
2024-05-10 19:00:31 +02:00
Picnic-DevPla-Bot
913cd2ee3a Upgrade Jackson 2.17.0 -> 2.17.1 (#1168)
See:
- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.17.1
- https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.17.0...jackson-bom-2.17.1
2024-05-06 08:56:55 +02:00
Picnic-DevPla-Bot
6adaa6c4f6 Upgrade NullAway 0.10.25 -> 0.10.26 (#1167)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.10.26
- https://github.com/uber/NullAway/compare/v0.10.25...v0.10.26
2024-05-05 12:13:46 +02:00
Stephan Schroevers
08dbb8c298 Upgrade Error Prone 2.26.1 -> 2.27.1 (#1155)
See:
- https://github.com/google/error-prone/releases/tag/v2.27.0
- https://github.com/google/error-prone/releases/tag/v2.27.1
- https://github.com/google/error-prone/compare/v2.26.1...v2.27.1
- https://github.com/PicnicSupermarket/error-prone/compare/v2.26.1-picnic-2...v2.27.1-picnic-1
2024-05-04 16:08:58 +02:00
Picnic-DevPla-Bot
e7bc0e113c Upgrade Guava 33.1.0-jre -> 33.2.0-jre (#1166)
See:
- https://guava.dev/releases/33.2.0-jre/api/diffs/
- https://github.com/google/guava/releases/tag/v33.2.0
- https://github.com/google/guava/compare/v33.1.0...v33.2.0
2024-05-04 13:07:51 +02:00
Picnic-DevPla-Bot
6d2c926b0e Upgrade errorprone-slf4j 0.1.23 -> 0.1.24 (#1164)
See:
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.24
- https://github.com/KengoTODA/errorprone-slf4j/compare/v0.1.23...v0.1.24
2024-05-04 12:58:25 +02:00
Picnic-DevPla-Bot
60e15cb569 Upgrade Checker Framework Annotations 3.42.0 -> 3.43.0 (#1165)
See:
- https://github.com/typetools/checker-framework/releases/tag/checker-framework-3.43.0
- https://github.com/typetools/checker-framework/compare/checker-framework-3.42.0...checker-framework-3.43.0
2024-05-04 12:44:17 +02:00
Picnic-Bot
22f61d3032 Upgrade maven-install-plugin 3.1.1 -> 3.1.2 (#1159)
See:
- https://github.com/apache/maven-install-plugin/releases/tag/maven-install-plugin-3.1.2
- https://github.com/apache/maven-install-plugin/compare/maven-install-plugin-3.1.1...maven-install-plugin-3.1.2
2024-05-02 09:30:44 +02:00
Picnic-DevPla-Bot
5d2a726aec Upgrade MongoDB driver 5.0.1 -> 5.1.0 (#1163)
See:
- https://jira.mongodb.org/issues/?jql=project%20%3D%20JAVA%20AND%20fixVersion%20%3E%205.0.1%20AND%20fixVersion%20%3C%3D%205.1.0
- https://github.com/mongodb/mongo-java-driver/releases/tag/r5.1.0
- https://github.com/mongodb/mongo-java-driver/compare/r5.0.1...r5.1.0
2024-05-02 08:57:49 +02:00
Picnic-Bot
192322a982 Upgrade OpenRewrite Templating 1.6.4 -> 1.8.0 (#1153)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.7.0
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.7.1
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.7.2
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.8.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.6.4...v1.8.0
2024-05-02 08:20:24 +02:00
Picnic-Bot
ddf5d803bd Upgrade Checkstyle 10.15.0 -> 10.16.0 (#1161)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.16.0
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.15.0...checkstyle-10.16.0
2024-04-30 10:53:04 +02:00
Phil Werli
02fb6d468a Introduce OptionalEmpty Refaster rule (#1156) 2024-04-30 10:09:46 +02:00
Picnic-Bot
e7d50c247d Upgrade step-security/harden-runner v2.7.0 -> v2.7.1 (#1160)
See:
- https://github.com/step-security/harden-runner/releases/tag/v2.7.1
2024-04-30 10:02:09 +02:00
Picnic-Bot
85cfb4b4b7 Upgrade maven-deploy-plugin 3.1.1 -> 3.1.2 (#1158)
See:
- https://github.com/apache/maven-deploy-plugin/releases/tag/maven-deploy-plugin-3.1.2
- https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-3.1.1...maven-deploy-plugin-3.1.2
2024-04-30 08:56:36 +02:00
Picnic-Bot
0684c577ac Upgrade TestNG 7.10.1 -> 7.10.2 (#1157)
See:
- https://github.com/testng-team/testng/releases/tag/7.10.2
- https://github.com/testng-team/testng/compare/7.10.1...7.10.2
2024-04-30 08:10:56 +02:00
Picnic-Bot
32778edc74 Upgrade actions/checkout v4.1.3 -> v4.1.4 (#1154)
See:
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v414
2024-04-26 10:10:52 +02:00
Picnic-Bot
1e6780afc1 Upgrade OpenRewrite 2.9.0 -> 2.10.0 (#1152)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.10.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.9.0...v2.10.0
2024-04-25 09:52:16 +02:00
Picnic-Bot
ef4e004141 Upgrade Byte Buddy 1.14.13 -> 1.14.14 (#1151)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.14
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.13...byte-buddy-1.14.14
2024-04-25 09:09:49 +02:00
Picnic-Bot
72c5a42feb Upgrade actions/upload-artifact v4.3.2 -> v4.3.3 (#1150)
See:
- https://github.com/actions/upload-artifact/releases/tag/v4.3.3
2024-04-23 11:24:02 +02:00
Picnic-Bot
271e01a02c Upgrade actions/checkout v4.1.1 -> v4.1.3 (#1149)
See:
- https://github.com/actions/checkout/releases/tag/v4.1.3
- https://github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v412
2024-04-23 10:48:35 +02:00
Picnic-Bot
d47549d68f Upgrade maven-jar-plugin 3.4.0 -> 3.4.1 (#1146)
See:
- https://github.com/apache/maven-jar-plugin/releases/tag/maven-jar-plugin-3.4.1
- https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.0...maven-jar-plugin-3.4.1
2024-04-22 13:05:52 +02:00
Picnic-Bot
01687c7f3e Upgrade maven-gpg-plugin 3.2.3 -> 3.2.4 (#1145)
See:
- https://github.com/apache/maven-gpg-plugin/releases/tag/maven-gpg-plugin-3.2.4
- https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.3...maven-gpg-plugin-3.2.4
2024-04-22 08:50:57 +02:00
Picnic-Bot
85cb7ffdb1 Upgrade CodeQL v3.24.9 -> v3.25.1 (#1147)
See:
- https://github.com/github/codeql-action/blob/main/CHANGELOG.md
- https://github.com/github/codeql-action/compare/v3.25.0...v3.25.1
- https://github.com/github/codeql-action/compare/v3.24.10...v3.25.0
- https://github.com/github/codeql-action/compare/v3.24.9...v3.24.10
2024-04-22 07:44:09 +02:00
Picnic-Bot
0367037f0a Upgrade ruby/setup-ruby v1.173.0 -> v1.174.0 (#1148)
See:
- https://github.com/ruby/setup-ruby/releases/tag/v1.174.0
2024-04-22 07:30:17 +02:00
Picnic-Bot
6669a2e1ec Upgrade Spring Boot 3.2.4 -> 3.2.5 (#1144)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.5
- https://github.com/spring-projects/spring-boot/compare/v3.2.4...v3.2.5
2024-04-20 13:37:38 +02:00
Picnic-Bot
eb36c1e493 Upgrade actions/upload-artifact v4.3.1 -> v4.3.2 (#1143)
See:
- https://github.com/actions/upload-artifact/releases/tag/v4.3.2
2024-04-19 10:14:36 +02:00
Picnic-Bot
8f5faf0f6a Upgrade OpenRewrite Templating 1.6.3 -> 1.6.4 (#1142)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.6.4
- https://github.com/openrewrite/rewrite-templating/compare/v1.6.3...v1.6.4
2024-04-19 09:55:53 +02:00
Picnic-Bot
5fad0ea04f Upgrade Spring Security 6.2.3 -> 6.2.4 (#1140)
See:
- https://github.com/spring-projects/spring-security/releases/tag/6.2.4
- https://github.com/spring-projects/spring-security/compare/6.2.3...6.2.4
2024-04-17 08:01:53 +02:00
Stephan Schroevers
4558f8affb Update FluxTake Refaster rule for Reactor 3.5.0+ (#1128) 2024-04-16 17:04:48 +02:00
Picnic-Bot
7be27614da Upgrade maven-jar-plugin 3.3.0 -> 3.4.0 (#1137)
See:
- https://github.com/apache/maven-jar-plugin/releases/tag/maven-jar-plugin-3.4.0
- https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.0
2024-04-15 08:45:16 +02:00
Picnic-Bot
7118d6bf03 Upgrade Spring 6.1.5 -> 6.1.6 (#1133)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.6
- https://github.com/spring-projects/spring-framework/compare/v6.1.5...v6.1.6
2024-04-15 08:32:41 +02:00
Picnic-Bot
eb84ddf500 Upgrade maven-gpg-plugin 3.2.2 -> 3.2.3 (#1134)
See:
- https://github.com/apache/maven-gpg-plugin/releases/tag/maven-gpg-plugin-3.2.3
- https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.2...maven-gpg-plugin-3.2.3
2024-04-15 07:44:29 +02:00
Picnic-Bot
032109756d Upgrade SLF4J 2.0.12 -> 2.0.13 (#1136)
See:
- https://www.slf4j.org/news.html
- https://github.com/qos-ch/slf4j/compare/v_2.0.12...v_2.0.13
2024-04-15 07:36:02 +02:00
Picnic-Bot
9e230302e9 Upgrade Project Reactor 2023.0.4 -> 2023.0.5 (#1130)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.5
- https://github.com/reactor/reactor/compare/2023.0.4...2023.0.5
2024-04-11 09:46:18 +02:00
Picnic-Bot
4708fec201 Upgrade TestNG 7.10.0 -> 7.10.1 (#1131)
See:
- https://github.com/testng-team/testng/releases/tag/7.10.1
- https://github.com/testng-team/testng/compare/7.10.0...7.10.1
2024-04-10 15:10:21 +02:00
Picnic-Bot
d102d6acbb Upgrade pitest-maven-plugin 1.15.8 -> 1.16.0 (#1127)
See:
- https://github.com/hcoles/pitest/releases/tag/1.16.0
- https://github.com/hcoles/pitest/compare/1.15.8...1.16.0
2024-04-10 08:05:25 +02:00
Picnic-Bot
bc67883579 Upgrade TestNG 7.9.0 -> 7.10.0 (#1126)
See:
- https://github.com/testng-team/testng/releases/tag/7.10.0
- https://github.com/testng-team/testng/compare/7.9.0...7.10.0
2024-04-08 07:18:40 +02:00
Picnic-Bot
069d6ff2f4 Upgrade maven-source-plugin 3.3.0 -> 3.3.1 (#1125)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MSOURCES%20AND%20fixVersion%20%3E%203.3.0%20AND%20fixVersion%20%3C%3D%203.3.1
- https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1
2024-04-06 14:52:39 +02:00
Picnic-Bot
6fbf4d81f0 Upgrade OpenRewrite 2.8.1 -> 2.9.0 (#1123)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.9.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.8.1...v2.9.0
2024-04-06 13:04:51 +02:00
Picnic-Bot
3d51acd613 Upgrade MongoDB driver 5.0.0 -> 5.0.1 (#1121)
See:
- https://jira.mongodb.org/issues/?jql=project%20%3D%20JAVA%20AND%20fixVersion%20%3E%205.0.0%20AND%20fixVersion%20%3C%3D%205.0.1
- https://github.com/mongodb/mongo-java-driver/releases/tag/r5.0.1
- https://github.com/mongodb/mongo-java-driver/compare/r5.0.0...r5.0.1
2024-04-04 14:48:14 +02:00
Picnic-Bot
d2fb576ecc Upgrade jacoco-maven-plugin 0.8.11 -> 0.8.12 (#1122)
See:
- https://github.com/jacoco/jacoco/releases/tag/v0.8.12
- https://github.com/jacoco/jacoco/compare/v0.8.11...v0.8.12
2024-04-04 14:31:03 +02:00
Stephan Schroevers
d658901231 Upgrade Error Prone fork v2.26.1-picnic-1 -> v2.26.1-picnic-2 (#1119)
See:
- https://github.com/PicnicSupermarket/error-prone/releases/tag/v2.26.1-picnic-2
- https://github.com/PicnicSupermarket/error-prone/compare/v2.26.1-picnic-1...v2.26.1-picnic-2
2024-04-03 16:46:24 +02:00
Picnic-Bot
76d1ca7bdf Upgrade Checkstyle 10.14.2 -> 10.15.0 (#1118)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.15.0
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.14.2...checkstyle-10.15.0
2024-04-03 11:22:32 +02:00
Picnic-Bot
341977b227 Upgrade Google Java Format 1.21.0 -> 1.22.0 (#1120)
See:
- https://github.com/google/google-java-format/releases/tag/v1.22.0
- https://github.com/google/google-java-format/compare/v1.21.0...v1.22.0
2024-04-03 08:27:53 +02:00
Rick Ossendrijver
75872dc2f5 Introduce Cody as IntelliJ icon (#1075) 2024-03-30 19:18:42 +01:00
Picnic-Bot
b609537a52 Upgrade pomchecker-maven-plugin 1.10.0 -> 1.11.0 (#1112)
See:
- https://github.com/kordamp/pomchecker/releases/tag/v1.11.0
- https://github.com/kordamp/pomchecker/compare/v1.10.0...v1.11.0
2024-03-30 15:09:54 +01:00
Picnic-Bot
1469d1e157 Upgrade maven-gpg-plugin 3.2.1 -> 3.2.2 (#1113)
See:
- https://github.com/apache/maven-gpg-plugin/releases/tag/maven-gpg-plugin-3.2.2
- https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.1...maven-gpg-plugin-3.2.2
2024-03-30 14:02:27 +01:00
Picnic-Bot
111b7d04f2 Upgrade actions/configure-pages v4.0.0 -> v5.0.0 (#1117)
See:
- https://github.com/actions/configure-pages/releases/tag/v5.0.0
2024-03-30 13:53:38 +01:00
Picnic-Bot
9e297df1c7 Upgrade errorprone-slf4j 0.1.22 -> 0.1.23 (#1111)
See:
- https://github.com/KengoTODA/errorprone-slf4j/releases/tag/v0.1.23
- https://github.com/KengoTODA/errorprone-slf4j/compare/v0.1.22...v0.1.23
2024-03-30 13:27:28 +01:00
Picnic-Bot
7babb48751 Upgrade NullAway 0.10.24 -> 0.10.25 (#1116)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.10.25
- https://github.com/uber/NullAway/compare/v0.10.24...v0.10.25
2024-03-30 12:46:03 +01:00
Picnic-Bot
dfaffacbb5 Upgrade Byte Buddy 1.14.12 -> 1.14.13 (#1115)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.13
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.12...byte-buddy-1.14.13
2024-03-30 12:26:44 +01:00
Stephan Schroevers
769779cf21 Introduce Refaster rules that resolve EnumOrdinal violations (#1104) 2024-03-27 15:44:19 +01:00
Rick Ossendrijver
9d8a5af44a Start release notes with "Update considerations and deprecations" section (#1105) 2024-03-25 14:19:31 +01:00
Picnic-Bot
8a84acca7b Upgrade Forbidden APIs plugin 3.6 -> 3.7 (#1107)
See:
- https://github.com/policeman-tools/forbidden-apis/wiki/Changes
- https://github.com/policeman-tools/forbidden-apis/compare/3.6...3.7
2024-03-25 10:41:39 +01:00
Picnic-Bot
b551f90d38 Upgrade dawidd6/action-download-artifact v3.1.2 -> v3.1.4 (#1109)
See:
- https://github.com/dawidd6/action-download-artifact/releases/tag/v3.1.4
- https://github.com/dawidd6/action-download-artifact/releases/tag/v3.1.3
2024-03-25 10:12:27 +01:00
Picnic-Bot
789a9cc0aa Upgrade AspectJ 1.9.21.2 -> 1.9.22 (#1106)
See:
- https://github.com/eclipse-aspectj/aspectj/releases/tag/V1_9_22
- https://github.com/eclipse-aspectj/aspectj/compare/V1_9_21_2...V1_9_22
2024-03-25 09:53:18 +01:00
Picnic-Bot
13e35338af Upgrade ruby/setup-ruby v1.172.0 -> v1.173.0 (#1110)
See https://github.com/ruby/setup-ruby/releases/tag/v1.173.0
2024-03-25 09:43:35 +01:00
Stephan Schroevers
281a003dd7 Introduce OptionalOrElse check (#1024)
While there, extend the `OptionalIdentity` Refaster rule to
automatically resolve one class of `NestedOptionals` violations.
2024-03-25 09:29:17 +01:00
Picnic-Bot
e40df7e1b8 Upgrade CodeQL v3.24.5 -> v3.24.9 (#1108)
See:
- https://github.com/github/codeql-action/blob/main/CHANGELOG.md
- https://github.com/github/codeql-action/compare/v3.24.8...v3.24.9
- https://github.com/github/codeql-action/compare/v3.24.7...v3.24.8
- https://github.com/github/codeql-action/compare/v3.24.6...v3.24.7
- https://github.com/github/codeql-action/compare/v3.24.5...v3.24.6
2024-03-25 08:42:59 +01:00
Picnic-Bot
bb2b1e6034 Upgrade Spring Boot 3.2.3 -> 3.2.4 (#1103)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.4
- https://github.com/spring-projects/spring-boot/compare/v3.2.3...v3.2.4
2024-03-23 12:49:26 +01:00
Stephan Schroevers
f8cac19330 Compact and replace StreamIs{,Not}Empty Refaster rules (#1028)
The new `StreamFindAnyIs{Empty,Present}` rules are simpler thanks to the
use of `@AlsoNegation`. In some cases an additional application of the
`OptionalIsEmpty` rule will be required.
2024-03-22 08:23:18 +01:00
Picnic-Bot
52fe79c343 Upgrade Swagger 2.2.20 -> 2.2.21 (#1102)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v2.2.21
- https://github.com/swagger-api/swagger-core/compare/v2.2.20...v2.2.21
2024-03-22 08:11:48 +01:00
Picnic-Bot
0b696b95b6 Upgrade maven-compiler-plugin 3.12.1 -> 3.13.0 (#1101)
See:
- https://github.com/apache/maven-compiler-plugin/releases/tag/maven-compiler-plugin-3.13.0
- https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.1...maven-compiler-plugin-3.13.0
2024-03-21 10:39:37 +01:00
Picnic-Bot
63bc903f83 Upgrade Spring Security 6.2.2 -> 6.2.3 (#1093)
See:
- https://github.com/spring-projects/spring-security/releases/tag/6.2.3
- https://github.com/spring-projects/spring-security/compare/6.2.2...6.2.3
2024-03-21 08:17:04 +01:00
Stephan Schroevers
b166d0daea Update Error Prone compatibility matrix (#1092)
While there, improve the generation script.
2024-03-21 07:31:07 +01:00
Picnic-Bot
6914dae822 Upgrade swagger-annotations 1.6.13 -> 1.6.14 (#1100)
See:
- https://github.com/swagger-api/swagger-core/releases/tag/v1.6.13
- https://github.com/swagger-api/swagger-core/compare/v1.6.12...v1.6.13
2024-03-20 17:46:13 +01:00
Picnic-Bot
c5fb53d725 Upgrade Guava 33.0.0-jre -> 33.1.0-jre (#1086)
See:
- https://guava.dev/releases/33.1.0-jre/api/diffs/
- https://github.com/google/guava/releases/tag/v33.1.0
- https://github.com/google/guava/compare/v33.0.0...v33.1.0
2024-03-20 10:59:23 +01:00
Picnic-Bot
d36d20da08 Upgrade OpenRewrite Templating 1.6.2 -> 1.6.3 (#1099)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.6.3
- https://github.com/openrewrite/rewrite-templating/compare/v1.6.2...v1.6.3
2024-03-20 08:35:53 +01:00
Picnic-Bot
502281f4d3 Upgrade maven-gpg-plugin 3.2.0 -> 3.2.1 (#1096)
See:
- https://github.com/apache/maven-gpg-plugin/releases/tag/maven-gpg-plugin-3.2.1
- https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.0...maven-gpg-plugin-3.2.1
2024-03-20 08:06:38 +01:00
Picnic-Bot
daa4f19c57 Upgrade OpenRewrite 2.8.0 -> 2.8.1 (#1098)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.8.1
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.8.0...v2.8.1
2024-03-20 07:42:57 +01:00
Picnic-Bot
02f726f43c Upgrade git-commit-id-maven-plugin 8.0.1 -> 8.0.2 (#1095)
See:
- https://github.com/git-commit-id/git-commit-id-maven-plugin/releases/tag/v8.0.2
- https://github.com/git-commit-id/git-commit-id-maven-plugin/compare/v8.0.1...v8.0.2
2024-03-19 11:57:38 +01:00
Picnic-Bot
b9e8186159 Upgrade actions/deploy-pages v4.0.4 -> v4.0.5 (#1094)
See:
- https://github.com/actions/deploy-pages/releases/tag/v4.0.5
2024-03-19 10:55:56 +01:00
Picnic-Bot
85baadd5df Upgrade Error Prone 2.25.0 -> 2.26.1 (#1078)
See:
- https://github.com/google/error-prone/releases/tag/v2.26.0
- https://github.com/google/error-prone/releases/tag/v2.26.1
- https://github.com/google/error-prone/compare/v2.25.0...v2.26.1
- https://github.com/PicnicSupermarket/error-prone/compare/v2.25.0-picnic-2...v2.26.1-picnic-1
2024-03-19 08:07:43 +01:00
Picnic-Bot
ab871ec9bb Upgrade Checkstyle 10.14.0 -> 10.14.2 (#1079)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.14.1
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.14.2
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.14.0...checkstyle-10.14.2
2024-03-18 15:26:27 +01:00
Picnic-Bot
753928f4da Upgrade Project Reactor 2023.0.3 -> 2023.0.4 (#1085)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.4
- https://github.com/reactor/reactor/compare/2023.0.3...2023.0.4
2024-03-18 14:29:36 +01:00
Picnic-Bot
fe84bada33 Upgrade AspectJ 1.9.21.1 -> 1.9.21.2 (#1089)
See:
- https://github.com/eclipse-aspectj/aspectj/releases/tag/V1_9_21_2
- https://github.com/eclipse/org.aspectj/compare/V1_9_21_1...V1_9_21_2
2024-03-18 12:54:41 +01:00
Picnic-Bot
5b8d6ed9c5 Upgrade Spring 6.1.4 -> 6.1.5 (#1091)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.5
- https://github.com/spring-projects/spring-framework/compare/v6.1.4...v6.1.5
2024-03-18 11:50:49 +01:00
Picnic-Bot
2ad2fdfb0f Upgrade sortpom-maven-plugin 3.4.0 -> 3.4.1 (#1077)
See:
- https://github.com/Ekryd/sortpom/wiki/Versions
- https://github.com/Ekryd/sortpom/releases/tag/sortpom-parent-3.4.1
- https://github.com/Ekryd/sortpom/compare/sortpom-parent-3.4.0...sortpom-parent-3.4.1
2024-03-18 11:01:03 +01:00
Picnic-Bot
a10558a044 Upgrade maven-gpg-plugin 3.1.0 -> 3.2.0 (#1082)
See:
- https://issues.apache.org/jira/issues/?jql=project%20%3D%20MGPG%20AND%20fixVersion%20%3E%203.1.0%20AND%20fixVersion%20%3C%3D%203.2.0
- https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.1.0...maven-gpg-plugin-3.2.0
2024-03-18 10:00:55 +01:00
Picnic-Bot
7316d05c22 Upgrade sonar-maven-plugin 3.10.0.2594 -> 3.11.0.3922 (#1090)
See:
- https://github.com/SonarSource/sonar-scanner-maven/releases/tag/3.11.0.3922
- https://github.com/SonarSource/sonar-scanner-maven/compare/3.10.0.2594...3.11.0.3922
2024-03-18 09:43:40 +01:00
Picnic-Bot
3177db55b8 Upgrade OpenRewrite 2.7.1 -> 2.8.0 (#1081)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.8.0
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.7.1...v2.8.0
2024-03-18 08:45:48 +01:00
Picnic-Bot
a6a63f9553 Upgrade Jackson 2.16.2 -> 2.17.0 (#1087)
See:
- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.17
- https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.16.2...jackson-bom-2.17.0
2024-03-18 07:14:09 +01:00
Rick Ossendrijver
df0eb9ee2f Drop unused field in Slf4jLogStatementTest (#1084) 2024-03-17 10:49:53 +01:00
Stephan Schroevers
e3cda3ea49 [maven-release-plugin] prepare for next development iteration 2024-03-15 13:04:44 +01:00
Stephan Schroevers
8aec87b40e [maven-release-plugin] prepare release v0.16.1 2024-03-15 13:04:44 +01:00
Picnic-Bot
03bd3215c7 Upgrade OpenRewrite Templating 1.6.0 -> 1.6.2 (#1080)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.6.1
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.6.2
- https://github.com/openrewrite/rewrite-templating/compare/v1.6.0...v1.6.2
2024-03-15 12:56:11 +01:00
Stephan Schroevers
c806f4044d Update step-security/harden-runner configuration (#1083) 2024-03-13 14:29:56 +01:00
Stephan Schroevers
23ceb4aa6b [maven-release-plugin] prepare for next development iteration 2024-03-12 08:24:08 +01:00
Stephan Schroevers
5cca9d23da [maven-release-plugin] prepare release v0.16.0 2024-03-12 08:24:08 +01:00
Stephan Schroevers
df701d3d3c Have step-security/harden-runner audit the OpenSSF Scorecard update workflow (#1076)
When executed on `master` this workflow requires additional permissions;
let's find out what they are.
2024-03-12 08:07:16 +01:00
Stephan Schroevers
3b005b0edc Introduce GitHub Actions step-security/harden-runner step (#1063) 2024-03-11 21:43:54 +01:00
Picnic-Bot
4e0eb1e9bf Upgrade extra-enforcer-rules 1.7.0 -> 1.8.0 (#1074)
See:
- https://github.com/mojohaus/extra-enforcer-rules/releases/tag/1.8.0
- https://github.com/mojohaus/extra-enforcer-rules/compare/1.7.0...1.8.0
2024-03-11 09:51:18 +01:00
Picnic-Bot
d6cc4c92c8 Upgrade Jackson 2.16.1 -> 2.16.2 (#1071)
See:
- https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.16.2
- https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.16.1...jackson-bom-2.16.2
2024-03-11 09:19:10 +01:00
Picnic-Bot
d9dd1c5882 Upgrade OpenRewrite Templating 1.5.1 -> 1.6.0 (#1073)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.6.0
- https://github.com/openrewrite/rewrite-templating/compare/v1.5.1...v1.6.0
2024-03-11 08:57:30 +01:00
Picnic-Bot
3950ff5066 Upgrade git-commit-id-maven-plugin 8.0.0 -> 8.0.1 (#1072)
See:
- https://github.com/git-commit-id/git-commit-id-maven-plugin/releases/tag/v8.0.1
- https://github.com/git-commit-id/git-commit-id-maven-plugin/compare/v8.0.0...v8.0.1
2024-03-11 08:24:32 +01:00
Picnic-Bot
8847a15414 Upgrade git-commit-id-maven-plugin 7.0.0 -> 8.0.0 (#1067)
See:
- https://github.com/git-commit-id/git-commit-id-maven-plugin/releases/tag/v8.0.0
- https://github.com/git-commit-id/git-commit-id-maven-plugin/compare/v7.0.0...v8.0.0
2024-03-07 08:59:40 +01:00
Picnic-Bot
03b8925fe5 Upgrade NullAway 0.10.23 -> 0.10.24 (#1066)
USee:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.10.24
- https://github.com/uber/NullAway/compare/v0.10.23...v0.10.24
2024-03-06 12:44:53 +01:00
Picnic-Bot
105cccc245 Upgrade Google Java Format 1.20.0 -> 1.21.0 (#1068)
See:
- https://github.com/google/google-java-format/releases/tag/v1.21.0
- https://github.com/google/google-java-format/compare/v1.20.0...v1.21.0
2024-03-06 08:01:21 +01:00
Rick Ossendrijver
e9263d9d07 Sync Checkstyle integration test (#1064)
Summary of changes:
- Minimize `checkstyle-init.patch`.
- Test against version 10.14.0 rather than 10.13.0.
2024-03-05 21:47:04 +01:00
Picnic-Bot
c214733517 Upgrade Checkstyle 10.13.0 -> 10.14.0 (#1058)
See:
- https://checkstyle.sourceforge.io/releasenotes.html
- https://github.com/checkstyle/checkstyle/releases/tag/checkstyle-10.14.0
- https://github.com/checkstyle/checkstyle/compare/checkstyle-10.13.0...checkstyle-10.14.0
2024-03-05 18:14:16 +01:00
Stephan Schroevers
3d49c80999 Upgrade Error Prone fork v2.25.0-picnic-1 -> v2.25.0-picnic-2 (#1065)
See:
- https://github.com/PicnicSupermarket/error-prone/releases/tag/v2.25.0-picnic-2
- https://github.com/PicnicSupermarket/error-prone/compare/v2.25.0-picnic-1...v2.25.0-picnic-2
2024-03-04 23:08:25 +01:00
Rick Ossendrijver
398d162b8d Exclude error-prone-{experimental,guidelines} checks from integration tests (#1060) 2024-03-04 20:47:46 +01:00
Rick Ossendrijver
110ac01d10 Exempt picocli.CommandLine.Option#names arguments from reordering (#1056) 2024-03-04 11:49:24 +01:00
Dima Legeza
479ded388a Introduce EmptyMonoZip check (#733) 2024-03-04 08:16:02 +01:00
Picnic-Bot
4ceeb2bcd5 Upgrade MongoDB driver 4.11.1 -> 5.0.0 (#1059)
See:
- https://jira.mongodb.org/issues/?jql=project%20%3D%20JAVA%20AND%20fixVersion%20%3E%204.11.1%20AND%20fixVersion%20%3C%3D%205.0.0
- https://github.com/mongodb/mongo-java-driver/releases/tag/r5.0.0
- https://github.com/mongodb/mongo-java-driver/compare/r4.11.1...r5.0.0
2024-03-04 07:42:57 +01:00
Picnic-Bot
fa1adbdb02 Upgrade Mockito 5.10.0 -> 5.11.0 (#1062)
See:
- https://github.com/mockito/mockito/releases/tag/v5.11.0
- https://github.com/mockito/mockito/compare/v5.10.0...v5.11.0
2024-03-04 07:22:01 +01:00
Picnic-Bot
82c23bb332 Upgrade Truth 1.4.1 -> 1.4.2 (#1061)
See:
- https://github.com/google/truth/releases/tag/v1.4.2
- https://github.com/google/truth/compare/v1.4.1...v1.4.2
2024-03-02 18:49:27 +01:00
Picnic-Bot
8f64489fa0 Upgrade Modernizer Maven Plugin 2.7.0 -> 2.8.0 (#1057)
See:
- https://github.com/gaul/modernizer-maven-plugin/releases/tag/modernizer-maven-plugin-2.8.0
- https://github.com/gaul/modernizer-maven-plugin/compare/modernizer-maven-plugin-2.7.0...modernizer-maven-plugin-2.8.0
2024-02-29 15:25:31 +01:00
Picnic-Bot
424f96878f Upgrade CodeQL v3.23.2 -> v3.24.5 (#1054)
See:
- https://github.com/github/codeql-action/blob/main/CHANGELOG.md
- https://github.com/github/codeql-action/compare/v3.23.2...v3.24.5
2024-02-26 07:50:01 +01:00
Picnic-Bot
3c211bdf60 Upgrade dawidd6/action-download-artifact v3.1.1 -> v3.1.2 (#1053)
See:
- https://github.com/dawidd6/action-download-artifact/releases/tag/v3.1.2
2024-02-26 07:32:01 +01:00
Picnic-Bot
219254813e Upgrade ruby/setup-ruby v1.170.0 -> v1.172.0 (#1055)
See:
- https://github.com/ruby/setup-ruby/releases/tag/v1.172.0
- https://github.com/ruby/setup-ruby/releases/tag/v1.171.0
2024-02-26 07:12:13 +01:00
Picnic-Bot
39c40d2f14 Upgrade Error Prone 2.24.1 -> 2.25.0 (#1042)
See:
- https://github.com/google/error-prone/releases/tag/v2.25.0
- https://github.com/google/error-prone/compare/v2.24.1...v2.25.0
- https://github.com/PicnicSupermarket/error-prone/compare/v2.24.1-picnic-1...v2.25.0-picnic-1
2024-02-23 13:55:30 +01:00
Picnic-Bot
01dfa2960d Upgrade Spring Boot 3.2.2 -> 3.2.3 (#1052)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.3
- https://github.com/spring-projects/spring-boot/compare/v3.2.2...v3.2.3
2024-02-23 07:36:07 +01:00
Dirk van Bokkem
ded0a48258 Introduce FluxFromIterable Refaster rule (#1047) 2024-02-22 09:17:14 +01:00
Picnic-Bot
41e42114c6 Upgrade sortpom-maven-plugin 3.3.0 -> 3.4.0 (#1051)
See:
- https://github.com/Ekryd/sortpom/wiki/Versions
- https://github.com/Ekryd/sortpom/releases/tag/sortpom-parent-3.4.0
- https://github.com/Ekryd/sortpom/compare/sortpom-parent-3.3.0...sortpom-parent-3.4.0
2024-02-22 05:22:43 +01:00
Picnic-Bot
d8f0a613b9 Upgrade OpenRewrite 2.6.4 -> 2.7.1 (#1048)
See:
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.7.0
- https://github.com/openrewrite/rewrite-recipe-bom/releases/tag/v2.7.1
- https://github.com/openrewrite/rewrite-recipe-bom/compare/v2.6.4...v2.7.1
2024-02-21 23:25:04 +01:00
Picnic-Bot
efca24141c Upgrade Google Java Format 1.19.2 -> 1.20.0 (#1050)
See:
- https://github.com/google/google-java-format/releases/tag/v1.20.0
- https://github.com/google/google-java-format/compare/v1.19.2...v1.20.0
2024-02-21 23:12:08 +01:00
Picnic-Bot
f8fc14e73a Upgrade OpenRewrite Templating 1.5.0 -> 1.5.1 (#1049)
See:
- https://github.com/openrewrite/rewrite-templating/releases/tag/v1.5.1
- https://github.com/openrewrite/rewrite-templating/compare/v1.5.0...v1.5.1
2024-02-21 21:38:12 +01:00
Rick Ossendrijver
574753022a Have Renovate file action-download-artifact PRs once every four weeks (#1046) 2024-02-21 18:00:06 +01:00
Picnic-Bot
194a828c67 Upgrade Immutables Annotations 2.10.0 -> 2.10.1 (#1045)
See:
- https://github.com/immutables/immutables/releases/tag/2.10.1
- https://github.com/immutables/immutables/compare/2.10.0...2.10.1
2024-02-20 10:25:35 +01:00
Picnic-Bot
1f83eada44 Upgrade dawidd6/action-download-artifact v3.1.0 -> v3.1.1 (#1039)
See:
- https://github.com/dawidd6/action-download-artifact/releases/tag/v3.1.1
2024-02-19 09:27:12 +01:00
Picnic-Bot
34b57b76bc Upgrade Spring Security 6.2.1 -> 6.2.2 (#1038)
See:
- https://github.com/spring-projects/spring-security/releases/tag/6.2.2
- https://github.com/spring-projects/spring-security/compare/6.2.1...6.2.2
2024-02-19 08:25:18 +01:00
Picnic-Bot
cd3c2aab5d Upgrade Truth 1.4.0 -> 1.4.1 (#1041)
See:
- https://github.com/google/truth/releases/tag/v1.4.1
- https://github.com/google/truth/compare/v1.4.0...v1.4.1
2024-02-19 08:14:31 +01:00
Stephan Schroevers
b39e322a67 Upgrade JDKs used by GitHub Actions builds (#1043)
Summary of changes:
- Use JDK 17.0.10 instead of 17.0.8.
- Use JDK 21.0.2 instead of 21.0.0.
- Have GitHub issue template reference more recent version numbers.

See:
- https://adoptium.net/temurin/release-notes/?version=jdk-17.0.9+9
- https://adoptium.net/temurin/release-notes/?version=jdk-17.0.10+7
- https://adoptium.net/temurin/release-notes/?version=jdk-21.0.1+12
- https://adoptium.net/temurin/release-notes/?version=jdk-21.0.2+13
2024-02-18 16:51:54 +01:00
Picnic-Bot
ad9d2dd534 Upgrade Byte Buddy 1.14.11 -> 1.14.12 (#1040)
See:
- https://github.com/raphw/byte-buddy/releases/tag/byte-buddy-1.14.12
- https://github.com/raphw/byte-buddy/compare/byte-buddy-1.14.11...byte-buddy-1.14.12
2024-02-18 16:32:40 +01:00
Picnic-Bot
d3307645cb Upgrade AspectJ 1.9.21 -> 1.9.21.1 (#1033)
See:
- https://github.com/eclipse-aspectj/aspectj/releases/tag/V1_9_21_1
- https://github.com/eclipse/org.aspectj/compare/V1_9_21...V1_9_21_1
2024-02-17 11:14:19 +01:00
Picnic-Bot
2185a0397a Upgrade NullAway 0.10.22 -> 0.10.23 (#1035)
See:
- https://github.com/uber/NullAway/blob/master/CHANGELOG.md
- https://github.com/uber/NullAway/releases/tag/v0.10.23
- https://github.com/uber/NullAway/compare/v0.10.22...v0.10.23
2024-02-16 10:17:56 +01:00
Picnic-Bot
c4a9f6fab7 Upgrade Spring 6.1.3 -> 6.1.4 (#1036)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.4
- https://github.com/spring-projects/spring-framework/compare/v6.1.3...v6.1.4
2024-02-16 09:54:33 +01:00
Picnic-Bot
98b6b7ec0c Upgrade dawidd6/action-download-artifact v3.0.0 -> v3.1.0 (#1037)
See:
- https://github.com/dawidd6/action-download-artifact/releases/tag/v3.1.0
2024-02-16 09:42:32 +01:00
Picnic-Bot
cc6211d560 Upgrade Project Reactor 2023.0.2 -> 2023.0.3 (#1034)
See:
- https://github.com/reactor/reactor/releases/tag/2023.0.3
- https://github.com/reactor/reactor/compare/2023.0.2...2023.0.3
2024-02-16 09:31:15 +01:00
Giovanni Zotta
8855ba33a0 Extend CollectionIsEmpty Refaster rule (#1027) 2024-02-15 08:42:15 +01:00
Picnic-Bot
e87b02cfe3 Upgrade pitest-maven-plugin 1.15.7 -> 1.15.8 (#1032)
See:
- https://github.com/hcoles/pitest/releases/tag/1.15.8
- https://github.com/hcoles/pitest/compare/1.15.7...1.15.8
2024-02-14 09:05:56 +01:00
Picnic-Bot
21a16e8803 Upgrade Spring Boot 2.7.18 -> 3.2.2 (#680)
See:
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.0-M1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.0-M2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.0-M3
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.0-M4
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.0-M5
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.0-RC1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.0-RC2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.0
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.3
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.4
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.5
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.6
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.7
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.8
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.9
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.10
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.11
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.12
- https://github.com/spring-projects/spring-boot/releases/tag/v3.0.13
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.0-M1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.0-M2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.0-RC1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.0-RC2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.0
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.3
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.4
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.5
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.6
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.7
- https://github.com/spring-projects/spring-boot/releases/tag/v3.1.8
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.0-M1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.0-M2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.0-M3
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.0-RC1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.0-RC2
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.0
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.1
- https://github.com/spring-projects/spring-boot/releases/tag/v3.2.2
- https://github.com/spring-projects/spring-boot/compare/v2.7.18...v3.2.2
2024-02-14 08:02:22 +01:00
Picnic-Bot
d3cc77ed93 Upgrade Spring Security 5.8.9 -> 6.2.1 (#1010)
See:
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-M1
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-M2
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-M3
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-M4
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-M5
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-M6
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-M7
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-RC1
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0-RC2
- https://github.com/spring-projects/spring-security/releases/tag/6.0.0
- https://github.com/spring-projects/spring-security/releases/tag/6.0.1
- https://github.com/spring-projects/spring-security/releases/tag/6.0.2
- https://github.com/spring-projects/spring-security/releases/tag/6.0.3
- https://github.com/spring-projects/spring-security/releases/tag/6.0.4
- https://github.com/spring-projects/spring-security/releases/tag/6.0.5
- https://github.com/spring-projects/spring-security/releases/tag/6.0.6
- https://github.com/spring-projects/spring-security/releases/tag/6.0.7
- https://github.com/spring-projects/spring-security/releases/tag/6.0.8
- https://github.com/spring-projects/spring-security/releases/tag/6.1.0-M1
- https://github.com/spring-projects/spring-security/releases/tag/6.1.0-M2
- https://github.com/spring-projects/spring-security/releases/tag/6.1.0-RC1
- https://github.com/spring-projects/spring-security/releases/tag/6.1.0
- https://github.com/spring-projects/spring-security/releases/tag/6.1.1
- https://github.com/spring-projects/spring-security/releases/tag/6.1.2
- https://github.com/spring-projects/spring-security/releases/tag/6.1.3
- https://github.com/spring-projects/spring-security/releases/tag/6.1.4
- https://github.com/spring-projects/spring-security/releases/tag/6.1.5
- https://github.com/spring-projects/spring-security/releases/tag/6.1.6
- https://github.com/spring-projects/spring-security/releases/tag/6.2.0-M1
- https://github.com/spring-projects/spring-security/releases/tag/6.2.0-M2
- https://github.com/spring-projects/spring-security/releases/tag/6.2.0-M3
- https://github.com/spring-projects/spring-security/releases/tag/6.2.0-RC1
- https://github.com/spring-projects/spring-security/releases/tag/6.2.0-RC2
- https://github.com/spring-projects/spring-security/releases/tag/6.2.0
- https://github.com/spring-projects/spring-security/releases/tag/6.2.1
- https://github.com/spring-projects/spring-security/compare/5.8.9...6.2.1
2024-02-13 16:14:36 +01:00
Stephan Schroevers
c2365c01c3 Introduce InputStream{Read,Skip}NBytes Refaster rules (#993) 2024-02-13 09:47:18 +01:00
Picnic-Bot
1d0d1d6cae Upgrade Spring 5.3.31 -> 6.1.3 (#679)
See:
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-M1
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-M2
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-M3
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-M4
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-M5
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-M6
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-RC1
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-RC2
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-RC3
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0-RC4
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.0
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.1
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.2
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.3
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.4
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.5
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.6
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.7
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.8
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.9
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.10
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.11
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.12
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.13
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.14
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.15
- https://github.com/spring-projects/spring-framework/releases/tag/v6.0.16
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.0-M1
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.0-M2
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.0-M3
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.0-M4
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.0-M5
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.0-RC1
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.0-RC2
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.0
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.1
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.2
- https://github.com/spring-projects/spring-framework/releases/tag/v6.1.3
- https://github.com/spring-projects/spring-framework/compare/v5.3.31...v6.1.3
2024-02-13 08:37:56 +01:00
Picnic-Bot
cce897ed4a Upgrade s4u/setup-maven-action v1.11.0 -> v1.12.0 (#1030)
See:
- https://github.com/s4u/setup-maven-action/releases/tag/v1.12.0
2024-02-13 08:08:36 +01:00
Stephan Schroevers
28bb4f6895 Introduce BugPatternLink check (#1026)
This check validates that checks defined by Error Prone Support
reference the public website, unless they explicitly specify that their
diagnostics output must not include a link.
2024-02-12 09:03:25 +01:00
Stephan Schroevers
1fe67677b4 Re-enable SonarCloud analysis on default branch (#1029)
This analysis was accidentally disabled by
ff3be8ae3f.
2024-02-12 08:46:45 +01:00
Stephan Schroevers
433b8b90c0 Require JDK 17 rather than JDK 11 (#603)
By raising this baseline the project can now use Java 17 language features such
as text blocks, switch expressions and `instanceof` pattern matching. The code
has been updated to make use of these constructs.

Note that the project can still be used by builds that target an older version
of Java, as long as those builds are executed using JDK 17+.
2024-02-11 16:57:13 +01:00
Stephan Schroevers
1f50772433 [maven-release-plugin] prepare for next development iteration 2024-02-11 14:31:59 +01:00
Stephan Schroevers
382b79989c [maven-release-plugin] prepare release v0.15.0 2024-02-11 14:31:59 +01:00
Stephan Schroevers
1cc792c615 Introduce ExhaustiveRefasterTypeMigration check (#770)
The new `@TypeMigration` annotation can be placed on Refaster rule
collections to indicate that they migrate most or all public methods of
an indicated type. The new check validates the claim made by the
annotation.
2024-02-11 12:42:39 +01:00
Benura Abeywardena
b5ace6e044 Introduce NewStringFromCharArray{,SubSequence} Refaster rules (#1012)
Resolves #1001.
2024-02-11 12:10:10 +01:00
Giovanni Zotta
1f71ccccf7 Extend StreamIsEmpty Refaster rule (#1025) 2024-02-11 12:01:33 +01:00
Stephan Schroevers
57fa6ae2b8 Introduce package-info.java for tech.picnic.errorprone.guidelines.bugpatterns (#1023) 2024-02-10 18:22:26 +01:00
123 changed files with 5173 additions and 1532 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.8`).
- Error Prone version (e.g. `2.18.0`).
- Error Prone Support version (e.g. `0.9.0`).
- 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`).
### Additional context

8
.github/release.yml vendored
View File

@@ -3,16 +3,16 @@ changelog:
labels:
- "ignore-changelog"
categories:
- title: ":warning: Update considerations and deprecations"
labels:
- "breaking change"
- "deprecation"
- title: ":rocket: New Error Prone checks and Refaster rules"
labels:
- "new feature"
- title: ":sparkles: Improvements"
labels:
- "improvement"
- title: ":warning: Update considerations and deprecations"
labels:
- "breaking change"
- "deprecation"
- title: ":bug: Bug fixes"
labels:
- "bug"

View File

@@ -10,32 +10,43 @@ jobs:
strategy:
matrix:
os: [ ubuntu-22.04 ]
jdk: [ 11.0.20, 17.0.8, 21.0.0 ]
jdk: [ 17.0.10, 21.0.2, 22.0.2 ]
distribution: [ temurin ]
experimental: [ false ]
include:
- os: macos-14
jdk: 17.0.8
jdk: 17.0.10
distribution: temurin
experimental: false
- os: windows-2022
jdk: 17.0.8
jdk: 17.0.10
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
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.adoptium.net:443
github.com:443
jitpack.io:443
objects.githubusercontent.com:443
repo.maven.apache.org:443
# We run the build twice for each supported JDK: once against the
# original Error Prone release, using only Error Prone checks available
# on Maven Central, and once against the Picnic Error Prone fork,
# 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@fa2c7e4517ed008b1f73e7e0195a9eecf5582cd4 # v1.11.0
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.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

View File

@@ -21,20 +21,32 @@ jobs:
security-events: write
runs-on: ubuntu-22.04
steps:
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@fa2c7e4517ed008b1f73e7e0195a9eecf5582cd4 # v1.11.0
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
java-version: 17.0.8
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.adoptium.net:443
api.github.com:443
github.com:443
objects.githubusercontent.com:443
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
with:
java-version: 17.0.10
java-distribution: temurin
maven-version: 3.9.6
maven-version: 3.9.9
- name: Initialize CodeQL
uses: github/codeql-action/init@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2
uses: github/codeql-action/init@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
with:
languages: ${{ matrix.language }}
- name: Perform minimal build
if: matrix.language == 'java'
run: mvn -T1C clean package -DskipTests -Dverification.skip
- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2
uses: github/codeql-action/analyze@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
with:
category: /language:${{ matrix.language }}

View File

@@ -11,16 +11,43 @@ jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.adoptium.net:443
api.github.com:443
bestpractices.coreinfrastructure.org:443
blog.picnic.nl:443
errorprone.info:443
github.com:443
img.shields.io:443
index.rubygems.org:443
jitpack.io:443
maven.apache.org:443
objects.githubusercontent.com:443
pitest.org:443
repo.maven.apache.org:443
rubygems.org:443
search.maven.org:443
securityscorecards.dev:443
sonarcloud.io:443
www.baeldung.com:443
www.bestpractices.dev:443
www.youtube.com:443
youtrack.jetbrains.com:443
- name: Check out code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
persist-credentials: false
- uses: ruby/setup-ruby@bd03e04863f52d169e18a2b190e8fa6b84938215 # v1.170.0
- uses: ruby/setup-ruby@6bd3d993c602f6b675728ebaecb2b569ff86e99b # v1.174.0
with:
working-directory: ./website
bundler-cache: true
- name: Configure Github Pages
uses: actions/configure-pages@1f0c5cde4bc74cd7e1254d0cb4de8d49e9068c7d # v4.0.0
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
- name: Generate documentation
run: ./generate-docs.sh
- name: Build website with Jekyll
@@ -46,6 +73,13 @@ jobs:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@decdde0ac072f6dcbe43649d82d9c635fff5b4e4 # v4.0.4
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5

View File

@@ -20,17 +20,31 @@ jobs:
id-token: write
runs-on: ubuntu-22.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
api.osv.dev:443
api.scorecard.dev:443
api.securityscorecards.dev:443
github.com:443
oss-fuzz-build-logs.storage.googleapis.com:443
*.sigstore.dev:443
www.bestpractices.dev:443
- name: Check out code
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
persist-credentials: false
- name: Run OpenSSF Scorecard analysis
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
publish_results: ${{ github.ref == 'refs/heads/master' }}
- name: Update GitHub's code scanning dashboard
uses: github/codeql-action/upload-sarif@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2
uses: github/codeql-action/upload-sarif@c7f9125735019aa87cfc361530512d50ea439c71 # v3.25.1
with:
sarif_file: results.sarif

View File

@@ -11,13 +11,23 @@ jobs:
analyze-pr:
runs-on: ubuntu-22.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.adoptium.net:443
github.com:443
objects.githubusercontent.com:443
repo.maven.apache.org:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@fa2c7e4517ed008b1f73e7e0195a9eecf5582cd4 # v1.11.0
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
with:
checkout-fetch-depth: 2
java-version: 17.0.8
java-version: 17.0.10
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
@@ -28,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@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: pitest-reports
path: ./target/pit-reports-ci

View File

@@ -19,14 +19,25 @@ jobs:
pull-requests: write
runs-on: ubuntu-22.04
steps:
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@fa2c7e4517ed008b1f73e7e0195a9eecf5582cd4 # v1.11.0
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
java-version: 17.0.8
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.adoptium.net:443
api.github.com:443
github.com:443
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
with:
java-version: 17.0.10
java-distribution: temurin
maven-version: 3.9.6
maven-version: 3.9.9
- name: Download Pitest analysis artifact
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: pitest-reports

View File

@@ -18,20 +18,34 @@ jobs:
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
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.adoptium.net:443
checkstyle.org:443
github.com:443
objects.githubusercontent.com:443
oss.sonatype.org:443
raw.githubusercontent.com:443
repo.maven.apache.org:443
repository.sonatype.org:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@fa2c7e4517ed008b1f73e7e0195a9eecf5582cd4 # v1.11.0
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
with:
checkout-ref: "refs/pull/${{ github.event.issue.number }}/head"
java-version: 17.0.8
java-version: 17.0.10
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"
- name: Upload artifacts on failure
if: ${{ failure() }}
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: integration-test-checkstyle
path: "${{ runner.temp }}/artifacts"

View File

@@ -13,18 +13,34 @@ jobs:
analyze:
# Analysis of code in forked repositories is skipped, as such workflow runs
# do not have access to the requisite secrets.
if: github.event.pull_request.head.repo.full_name == github.repository
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
permissions:
contents: read
runs-on: ubuntu-22.04
steps:
- name: Install Harden-Runner
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
analysis-sensorcache-eu-central-1-prod.s3.amazonaws.com:443
api.adoptium.net: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
*.sonarcloud.io:443
sonarcloud.io:443
- name: Check out code and set up JDK and Maven
uses: s4u/setup-maven-action@fa2c7e4517ed008b1f73e7e0195a9eecf5582cd4 # v1.11.0
uses: s4u/setup-maven-action@489441643219d2b93ee2a127b2402eb640a1b947 # v1.13.0
with:
checkout-fetch-depth: 0
java-version: 17.0.8
java-version: 17.0.10
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

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@
.DS_Store
.factorypath
.idea
!.idea/icon.svg
.project
.settings
target

65
.idea/icon.svg generated Normal file
View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 1259 1199" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-624.154,-988.431)">
<g transform="matrix(1,0,0,1,-70.1122,-35.0561)">
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1227.03,1988.79C1237.78,2070.45 1225.83,2190.1 1192.24,2194.53C1158.65,2198.95 1116.14,2086.46 1105.39,2004.81C1094.64,1923.16 1128.44,1902.11 1153.32,1898.84C1178.18,1895.56 1216.28,1907.14 1227.03,1988.79Z" style="fill:rgb(219,220,211);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1151.08,1881.86C1134.93,1883.99 1114.77,1892.69 1101.6,1913.17C1088.42,1933.64 1082.71,1963.73 1088.42,2007.04C1094.04,2049.75 1107.59,2099.16 1124.51,2138.68C1132.97,2158.45 1142.15,2175.68 1152.59,2188.86C1163.04,2202.05 1176.31,2213.89 1194.48,2211.5C1212.65,2209.11 1222.39,2194.23 1229.07,2178.8C1235.75,2163.36 1240.15,2144.34 1243.21,2123.05C1249.32,2080.5 1249.63,2029.27 1244,1986.56C1238.3,1943.24 1225,1915.66 1206.98,1899.29C1188.95,1882.93 1167.22,1879.74 1151.08,1881.86ZM1155.55,1915.81C1164.27,1914.66 1174.03,1915.62 1183.96,1924.64C1193.89,1933.66 1205.01,1952.69 1210.06,1991.03C1215.18,2029.97 1214.89,2079.4 1209.32,2118.19C1206.53,2137.58 1202.32,2154.4 1197.65,2165.2C1194.14,2173.29 1190.82,2176.3 1189.96,2177.22C1188.89,2176.55 1184.91,2174.51 1179.43,2167.6C1172.12,2158.38 1163.7,2143.22 1155.99,2125.21C1140.57,2089.18 1127.49,2041.51 1122.36,2002.57C1117.32,1964.24 1123.13,1942.97 1130.39,1931.69C1137.65,1920.42 1146.82,1916.96 1155.55,1915.81Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1516.33,1963.1C1466.19,1897.75 1427.4,1906.77 1407.5,1922.05C1387.59,1937.32 1368.84,1972.45 1418.98,2037.8C1431.75,2054.44 1447.26,2071.84 1463.69,2088.19C1495.18,2119.52 1534.33,2139.39 1582.98,2126.14C1606.4,2119.76 1622.19,2110.46 1623.75,2098.64C1625.79,2083.16 1603,2065.78 1569.69,2050.47C1554.75,2019.83 1535.59,1988.2 1516.33,1963.1Z" style="fill:rgb(219,220,211);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1397.07,1908.46C1409.99,1898.55 1430.41,1890.44 1454.2,1895.61C1478,1900.77 1503.31,1918 1529.91,1952.67C1548.92,1977.44 1567.3,2007.65 1582.28,2037.56C1597.47,2044.87 1610.74,2052.64 1621.09,2061.47C1632.68,2071.35 1642.93,2084.12 1640.73,2100.88C1639.05,2113.64 1630.31,2122.66 1620.9,2128.78C1611.49,2134.9 1600.29,2139.17 1587.48,2142.66C1532.39,2157.66 1485.57,2134.11 1451.61,2100.32C1434.7,2083.49 1418.73,2065.6 1405.39,2048.22C1378.79,2013.56 1368.69,1984.64 1369.86,1960.32C1371.04,1936 1384.15,1918.38 1397.07,1908.46ZM1417.92,1935.63C1410.94,1940.99 1404.71,1948.57 1404.07,1961.97C1403.43,1975.37 1409.02,1996.69 1432.56,2027.38C1444.76,2043.27 1459.82,2060.18 1475.77,2076.05C1504.8,2104.93 1536.26,2121.12 1578.48,2109.62C1589.1,2106.73 1597.5,2103.16 1602.23,2100.08C1605.14,2098.18 1606.16,2096.97 1606.54,2096.46C1606.07,2095.66 1604.57,2092.39 1598.86,2087.52C1591.24,2081.02 1578.31,2073.28 1562.54,2066.03L1556.98,2063.47L1554.29,2057.97C1539.86,2028.35 1521.12,1997.46 1502.75,1973.52C1479.2,1942.84 1460.05,1931.91 1446.94,1929.07C1433.84,1926.23 1424.9,1930.27 1417.92,1935.63Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M917.121,1633.14C845.801,1674.32 730.68,1709.07 713.738,1679.73C696.797,1650.39 784.453,1568.07 855.777,1526.89C927.102,1485.71 959.48,1508.89 972.02,1530.62C984.562,1552.34 988.445,1591.97 917.121,1633.14Z" style="fill:rgb(219,220,211);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M986.848,1522.06C978.707,1507.95 962.949,1492.66 938.992,1488.32C915.031,1483.98 885.055,1490.22 847.219,1512.07C809.906,1533.61 769.453,1565.03 739.41,1595.79C724.391,1611.17 711.977,1626.24 703.797,1640.94C695.617,1655.64 689.746,1672.42 698.914,1688.29C708.078,1704.17 725.547,1707.48 742.363,1707.74C759.184,1708.01 778.445,1704.79 799.273,1699.47C840.934,1688.83 888.375,1669.51 925.684,1647.97C963.52,1626.12 983.91,1603.29 992.137,1580.37C1000.36,1557.45 994.988,1536.16 986.848,1522.06ZM957.195,1539.18C961.594,1546.79 964.438,1556.18 959.906,1568.8C955.379,1581.43 942.047,1598.98 908.562,1618.32C874.551,1637.96 828.77,1656.6 790.801,1666.3C771.816,1671.14 754.664,1673.69 742.902,1673.5C734.082,1673.37 730.035,1671.45 728.859,1671C729.062,1669.76 729.426,1665.3 733.715,1657.59C739.434,1647.31 750.215,1633.73 763.906,1619.72C791.285,1591.68 830.324,1561.36 864.336,1541.72C897.824,1522.38 919.695,1519.62 932.895,1522.01C946.09,1524.4 952.797,1531.56 957.195,1539.18Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1791.57,1526.89C1862.89,1568.07 1950.54,1650.39 1933.61,1679.74C1916.66,1709.08 1801.54,1674.33 1730.22,1633.15C1658.9,1591.97 1662.78,1552.34 1675.32,1530.62C1687.86,1508.89 1720.24,1485.72 1791.57,1526.89Z" style="fill:rgb(219,220,211);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1660.5,1522.06C1652.35,1536.16 1646.98,1557.45 1655.21,1580.37C1663.43,1603.29 1683.82,1626.13 1721.66,1647.97C1758.97,1669.52 1806.41,1688.84 1848.07,1699.48C1868.9,1704.79 1888.16,1708.01 1904.98,1707.75C1921.79,1707.48 1939.27,1704.17 1948.43,1688.3C1957.59,1672.42 1951.73,1655.64 1943.55,1640.94C1935.37,1626.25 1922.95,1611.17 1907.93,1595.79C1877.89,1565.04 1837.43,1533.61 1800.12,1512.07C1762.29,1490.22 1732.31,1483.98 1708.35,1488.32C1684.39,1492.66 1668.64,1507.95 1660.5,1522.06ZM1690.15,1539.18C1694.55,1531.56 1701.25,1524.4 1714.45,1522.02C1727.64,1519.62 1749.52,1522.39 1783,1541.72C1817.02,1561.36 1856.06,1591.68 1883.44,1619.72C1897.12,1633.73 1907.91,1647.32 1913.63,1657.59C1917.92,1665.3 1918.28,1669.77 1918.48,1671.01C1917.31,1671.45 1913.26,1673.37 1904.44,1673.51C1892.68,1673.69 1875.52,1671.15 1856.54,1666.3C1818.57,1656.61 1772.79,1637.96 1738.78,1618.32C1705.29,1598.99 1691.97,1581.43 1687.43,1568.81C1682.91,1556.18 1685.75,1546.8 1690.15,1539.18Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1322.81,1013.67C1058.16,1014.17 843.293,1229.45 843.297,1494.11L843.223,1862.19C843.223,1955.32 919.055,2031.16 1012.19,2031.16C1054.55,2031.16 1093.39,2015.51 1123.09,1989.7C1169.54,2049.44 1242.17,2087.79 1323.7,2087.79C1405.22,2087.79 1477.84,2049.45 1524.28,1989.73C1553.98,2015.52 1592.81,2031.16 1635.15,2031.16C1728.29,2031.16 1804.12,1955.32 1804.12,1862.19L1804.12,1494.1C1804.12,1229.09 1588.7,1013.67 1323.69,1013.67L1322.84,1013.67L1322.81,1013.67ZM1322.92,1068.46L1323.69,1068.46C1559.09,1068.46 1749.33,1258.7 1749.33,1494.11L1749.33,1862.19C1749.33,1925.92 1698.88,1976.37 1635.15,1976.37C1596.91,1976.37 1563.67,1958.03 1542.94,1929.68L1517.91,1895.48L1497,1932.34C1462.85,1992.53 1398.48,2033 1323.7,2033C1248.9,2033 1184.52,1992.51 1150.38,1932.3L1129.45,1895.41L1104.43,1929.65C1083.69,1958.02 1050.44,1976.37 1012.19,1976.37C948.461,1976.37 898.016,1925.93 898.012,1862.2L898.086,1494.11C898.086,1259.03 1087.84,1068.92 1322.92,1068.47L1322.92,1068.46Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1322.86,1041.07C1072.99,1041.54 870.684,1244.23 870.688,1494.11L870.648,1862.19C870.648,1940.62 933.789,2003.77 1012.22,2003.77C1073.65,2003.77 1125.69,1965.03 1145.37,1910.56C1201.73,1934.69 1262.41,1947.14 1323.72,1947.14C1385.02,1947.14 1445.69,1934.69 1502.04,1910.57C1521.72,1965.04 1573.76,2003.77 1635.19,2003.77C1713.62,2003.77 1776.76,1940.62 1776.76,1862.19L1776.76,1494.11C1776.76,1243.9 1573.93,1041.07 1323.72,1041.07L1322.86,1041.07Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1323.7,1494.1C1449.2,1494.1 1550.24,1595.14 1550.24,1720.64L1550.24,1833.86C1550.24,1959.36 1449.2,2060.4 1323.7,2060.4C1198.2,2060.4 1097.16,1959.36 1097.16,1833.86L1097.16,1720.64C1097.16,1595.14 1198.2,1494.1 1323.7,1494.1Z" style="fill:white;fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1322.86,1041.07C1262.14,1041.18 1204.25,1053.27 1151.36,1075.05C1316.07,1142.87 1432.03,1304.93 1432.03,1494.11L1432.03,1811.95C1432.03,2003.63 1209.62,2024.85 1126.54,1945.82C1177.52,2034.1 1254.55,2060.4 1323.7,2060.4C1408.4,2060.4 1481.95,2014.37 1520.82,1945.86C1546.53,1981.01 1588.08,2003.77 1635.15,2003.77C1713.58,2003.77 1776.72,1940.62 1776.72,1862.19L1776.72,1494.11C1776.72,1243.9 1573.89,1041.07 1323.68,1041.07L1322.86,1041.07Z" style="fill:rgb(219,220,211);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1322.86,1041.07C1304.33,1041.1 1286.06,1042.28 1268.11,1044.48C1492.04,1071.93 1665.46,1262.75 1665.46,1494.11L1665.46,1862.19C1665.46,1920.85 1630.14,1970.94 1579.54,1992.48C1596.59,1999.74 1615.38,2003.77 1635.15,2003.77C1713.58,2003.77 1776.72,1940.62 1776.72,1862.19L1776.72,1494.11C1776.72,1243.9 1573.89,1041.07 1323.68,1041.07L1322.86,1041.07Z" style="fill:rgb(189,191,175);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1322.85,1034.22C1069.29,1034.69 863.84,1240.54 863.84,1494.11L863.766,1862.19C863.766,1944.3 930.078,2010.61 1012.19,2010.61C1057.88,2010.61 1098.53,1989.94 1125.71,1957.58C1166.88,2023.5 1240.02,2067.25 1323.7,2067.25C1407.36,2067.25 1480.48,2023.52 1521.66,1957.62C1548.84,1989.96 1589.47,2010.61 1635.15,2010.61C1717.25,2010.61 1783.57,1944.3 1783.57,1862.19L1783.57,1494.11C1783.57,1240.2 1577.59,1034.21 1323.68,1034.22L1322.85,1034.22ZM1322.86,1047.92L1323.68,1047.92C1570.19,1047.92 1769.87,1247.6 1769.87,1494.11L1769.87,1862.19C1769.87,1936.95 1709.91,1996.92 1635.15,1996.92C1590.29,1996.92 1550.82,1975.26 1526.36,1941.82L1520.1,1933.27L1514.87,1942.48C1477.18,2008.91 1405.92,2053.55 1323.7,2053.55C1241.46,2053.55 1170.19,2008.89 1132.5,1942.44L1127.27,1933.21L1121.02,1941.77C1096.56,1975.24 1057.07,1996.92 1012.19,1996.92C937.43,1996.92 877.469,1936.95 877.465,1862.19L877.539,1494.11C877.539,1247.94 1076.7,1048.39 1322.86,1047.92Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1576.29,1470.72C1576.29,1481.36 1568.75,1491.56 1555.31,1499.08C1541.88,1506.6 1523.67,1510.83 1504.68,1510.83C1465.12,1510.83 1433.06,1492.87 1433.06,1470.72C1433.06,1448.57 1465.12,1430.62 1504.68,1430.62C1523.67,1430.62 1541.88,1434.84 1555.31,1442.36C1568.75,1449.89 1576.29,1460.09 1576.29,1470.72Z" style="fill:rgb(255,155,173);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1214.28,1470.72C1214.28,1481.36 1206.73,1491.56 1193.31,1499.08C1179.87,1506.6 1161.66,1510.83 1142.66,1510.83C1103.11,1510.83 1071.05,1492.87 1071.05,1470.72C1071.05,1448.57 1103.11,1430.62 1142.66,1430.62C1161.66,1430.62 1179.87,1434.84 1193.31,1442.36C1206.73,1449.89 1214.28,1460.09 1214.28,1470.72Z" style="fill:rgb(255,155,173);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1104.39,1401.46C1104.39,1375.15 1118.45,1350.79 1141.24,1337.63C1164.03,1324.48 1192.16,1324.48 1214.95,1337.63C1237.74,1350.79 1251.81,1375.15 1251.81,1401.46L1224.41,1401.46C1224.41,1384.9 1215.6,1369.64 1201.25,1361.36C1186.9,1353.07 1169.29,1353.07 1154.94,1361.36C1140.59,1369.64 1131.78,1384.9 1131.78,1401.46L1104.39,1401.46Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1395.54,1401.46C1395.54,1375.15 1409.61,1350.79 1432.39,1337.63C1455.18,1324.48 1483.32,1324.48 1506.11,1337.63C1528.89,1350.79 1542.96,1375.15 1542.96,1401.46L1515.56,1401.46C1515.56,1384.9 1506.75,1369.64 1492.41,1361.36C1478.06,1353.07 1460.44,1353.07 1446.09,1361.36C1431.74,1369.64 1422.93,1384.9 1422.93,1401.46L1395.54,1401.46Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
<g transform="matrix(1,0,0,1,0,9.81959)">
<path d="M1256.81,1448.61C1256.81,1472.48 1269.56,1494.57 1290.24,1506.51C1310.92,1518.45 1336.42,1518.45 1357.1,1506.51C1377.78,1494.57 1390.53,1472.48 1390.53,1448.61L1376.83,1448.61C1376.83,1467.61 1366.71,1485.15 1350.25,1494.65C1333.79,1504.15 1313.55,1504.15 1297.09,1494.65C1280.63,1485.15 1270.51,1467.61 1270.51,1448.61L1256.81,1448.61Z" style="fill:rgb(26,26,26);fill-rule:nonzero;"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -12,7 +12,8 @@
"separateMinorPatch": true
},
{
"matchDepNames": [
"matchPackageNames": [
"dawidd6/action-download-artifact",
"github/codeql-action",
"ruby/setup-ruby"
],

View File

@@ -49,7 +49,9 @@ high-quality and consistent Java code_][picnic-blog-ep-post].
### Installation
This library is built on top of [Error Prone][error-prone-orig-repo]. To use
it, read the installation guide for Maven or Gradle below.
it, read the installation guide for Maven or Gradle below. The library requires
that your build is executed using JDK 17 or above, but supports builds that
[target][baeldung-java-source-target-options] older versions of Java.
#### Maven
@@ -263,6 +265,7 @@ guidelines][contributing].
If you want to report a security vulnerability, please do so through a private
channel; please see our [security policy][security] for details.
[baeldung-java-source-target-options]: https://www.baeldung.com/java-source-target-options
[bug-checks]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/
[bug-checks-identity-conversion]: https://github.com/PicnicSupermarket/error-prone-support/blob/master/error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/IdentityConversion.java
[codeql-badge]: https://github.com/PicnicSupermarket/error-prone-support/actions/workflows/codeql.yml/badge.svg?branch=master&event=push

View File

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

View File

@@ -135,8 +135,8 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
}
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
return receiver instanceof MethodInvocationTree
? getClassUnderTest((MethodInvocationTree) receiver, state)
return receiver instanceof MethodInvocationTree methodInvocation
? getClassUnderTest(methodInvocation, state)
: Optional.empty();
}
@@ -154,8 +154,8 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
}
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
if (receiver instanceof MethodInvocationTree) {
extractIdentificationTestCases((MethodInvocationTree) receiver, sink, state);
if (receiver instanceof MethodInvocationTree methodInvocation) {
extractIdentificationTestCases(methodInvocation, sink, state);
}
}
@@ -184,8 +184,8 @@ public final class BugPatternTestExtractor implements Extractor<TestCases> {
}
ExpressionTree receiver = ASTHelpers.getReceiver(tree);
if (receiver instanceof MethodInvocationTree) {
extractReplacementTestCases((MethodInvocationTree) receiver, sink, state);
if (receiver instanceof MethodInvocationTree methodInvocation) {
extractReplacementTestCases(methodInvocation, sink, state);
}
}

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

@@ -93,13 +93,20 @@ final class DocumentationGeneratorTaskListenerTest {
"DocumentationGeneratorTaskListenerTestClass.java",
"class DocumentationGeneratorTaskListenerTestClass {}");
// XXX: Once we support only JDK 15+, use a text block for the `expected` string.
assertThat(
outputDirectory.resolve(
"documentation-generator-task-listener-test-DocumentationGeneratorTaskListenerTestClass.json"))
.content(UTF_8)
.isEqualToIgnoringWhitespace(
"{\"className\":\"DocumentationGeneratorTaskListenerTestClass\",\"path\":[\"CLASS: DocumentationGeneratorTaskListenerTestClass\",\"COMPILATION_UNIT\"]}");
"""
{
"className": "DocumentationGeneratorTaskListenerTestClass",
"path": [
"CLASS: DocumentationGeneratorTaskListenerTestClass",
"COMPILATION_UNIT"
]
}
""");
}
@Immutable
@@ -125,8 +132,8 @@ final class DocumentationGeneratorTaskListenerTest {
}
private static String describeTree(Tree tree) {
return (tree instanceof ClassTree)
? String.join(": ", String.valueOf(tree.getKind()), ((ClassTree) tree).getSimpleName())
return (tree instanceof ClassTree clazz)
? String.join(": ", String.valueOf(tree.getKind()), clazz.getSimpleName())
: tree.getKind().toString();
}
}

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.14.1-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>
<artifactId>error-prone-contrib</artifactId>
@@ -67,6 +67,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>
@@ -122,6 +127,11 @@
<artifactId>jakarta.servlet-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
@@ -279,7 +289,6 @@
</path>
</annotationProcessorPaths>
<compilerArgs combine.children="append">
<arg>-Xplugin:RefasterRuleCompiler</arg>
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
</compilerArgs>
</configuration>

View File

@@ -18,7 +18,7 @@ import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.code.Symbol;
import java.util.Map;
import javax.lang.model.element.AnnotationValue;
@@ -46,7 +46,7 @@ public final class AmbiguousJsonCreator extends BugChecker implements Annotation
}
ClassTree clazz = state.findEnclosing(ClassTree.class);
if (clazz == null || clazz.getKind() != Tree.Kind.ENUM) {
if (clazz == null || clazz.getKind() != Kind.ENUM) {
return Description.NO_MATCH;
}

View File

@@ -19,7 +19,6 @@ import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.Tree.Kind;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -119,7 +118,7 @@ public final class CanonicalAnnotationSyntax extends BugChecker implements Annot
* the expression as a whole.
*/
ExpressionTree value =
(arg.getKind() == Kind.ASSIGNMENT) ? ((AssignmentTree) arg).getExpression() : arg;
(arg instanceof AssignmentTree assignment) ? assignment.getExpression() : arg;
/* Store a fix for each expression that was successfully simplified. */
simplifyAttributeValue(value, state)
@@ -130,13 +129,10 @@ public final class CanonicalAnnotationSyntax extends BugChecker implements Annot
}
private static Optional<String> simplifyAttributeValue(ExpressionTree expr, VisitorState state) {
if (expr.getKind() != Kind.NEW_ARRAY) {
/* There are no curly braces or commas to be dropped here. */
return Optional.empty();
}
NewArrayTree array = (NewArrayTree) expr;
return simplifySingletonArray(array, state).or(() -> dropTrailingComma(array, state));
/* Drop curly braces or commas if possible. */
return expr instanceof NewArrayTree newArray
? simplifySingletonArray(newArray, state).or(() -> dropTrailingComma(newArray, state))
: Optional.empty();
}
/** Returns the expression describing the array's sole element, if any. */

View File

@@ -81,9 +81,8 @@ public final class CanonicalClassNameUsage extends BugChecker
path = path.getParentPath();
}
return path.getLeaf() instanceof MethodInvocationTree
&& isOwnedByCanonicalNameUsingType(
ASTHelpers.getSymbol((MethodInvocationTree) path.getLeaf()));
return path.getLeaf() instanceof MethodInvocationTree methodInvocation
&& isOwnedByCanonicalNameUsingType(ASTHelpers.getSymbol(methodInvocation));
}
private static boolean isOwnedByCanonicalNameUsingType(MethodSymbol symbol) {

View File

@@ -101,19 +101,17 @@ public final class DirectReturn extends BugChecker implements BlockTreeMatcher {
}
private static Optional<ExpressionTree> tryMatchAssignment(Symbol targetSymbol, Tree tree) {
if (tree instanceof ExpressionStatementTree) {
return tryMatchAssignment(targetSymbol, ((ExpressionStatementTree) tree).getExpression());
if (tree instanceof ExpressionStatementTree expressionStatement) {
return tryMatchAssignment(targetSymbol, expressionStatement.getExpression());
}
if (tree instanceof AssignmentTree) {
AssignmentTree assignment = (AssignmentTree) tree;
if (tree instanceof AssignmentTree assignment) {
return targetSymbol.equals(ASTHelpers.getSymbol(assignment.getVariable()))
? Optional.of(assignment.getExpression())
: Optional.empty();
}
if (tree instanceof VariableTree) {
VariableTree declaration = (VariableTree) tree;
if (tree instanceof VariableTree declaration) {
return declaration.getModifiers().getAnnotations().isEmpty()
&& targetSymbol.equals(ASTHelpers.getSymbol(declaration))
? Optional.ofNullable(declaration.getInitializer())
@@ -151,11 +149,11 @@ public final class DirectReturn extends BugChecker implements BlockTreeMatcher {
Streams.stream(state.getPath()).skip(1),
Streams.stream(state.getPath()),
(tree, child) -> {
if (!(tree instanceof TryTree)) {
if (!(tree instanceof TryTree tryTree)) {
return null;
}
BlockTree finallyBlock = ((TryTree) tree).getFinallyBlock();
BlockTree finallyBlock = tryTree.getFinallyBlock();
return !child.equals(finallyBlock) ? finallyBlock : null;
})
.anyMatch(finallyBlock -> referencesIdentifierSymbol(symbol, finallyBlock));

View File

@@ -0,0 +1,89 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
import static com.google.errorprone.matchers.Matchers.staticMethod;
import static com.google.errorprone.matchers.Matchers.typePredicateMatcher;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import static tech.picnic.errorprone.utils.MoreTypePredicates.isSubTypeOf;
import static tech.picnic.errorprone.utils.MoreTypes.generic;
import static tech.picnic.errorprone.utils.MoreTypes.type;
import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.suppliers.Supplier;
import com.google.errorprone.suppliers.Suppliers;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.tools.javac.code.Type;
import reactor.core.publisher.Mono;
/**
* A {@link BugChecker} that flags {@link Mono#zip} and {@link Mono#zipWith} invocations with a
* {@code Mono<Void>} or {@link Mono#empty()} argument or receiver.
*
* <p>When a zipped reactive stream completes empty, then the other zipped streams will be cancelled
* (or not subscribed to), and the operation as a whole will complete empty as well. This is
* generally not what was intended.
*/
// XXX: Generalize this check to also cover `Flux` zip operations.
@AutoService(BugChecker.class)
@BugPattern(
summary = "Don't pass a `Mono<Void>` or `Mono.empty()` argument to `Mono#{zip,With}`",
link = BUG_PATTERNS_BASE_URL + "EmptyMonoZip",
linkType = CUSTOM,
severity = ERROR,
tags = LIKELY_ERROR)
public final class EmptyMonoZip extends BugChecker implements MethodInvocationTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Supplier<Type> MONO =
Suppliers.typeFromString("reactor.core.publisher.Mono");
private static final Matcher<ExpressionTree> MONO_ZIP_OR_ZIP_WITH =
anyOf(
instanceMethod().onDescendantOf(MONO).named("zipWith"),
staticMethod().onClass(MONO).named("zip"));
private static final Matcher<ExpressionTree> EMPTY_MONO =
anyOf(
staticMethod().onDescendantOf(MONO).named("empty"),
typePredicateMatcher(isSubTypeOf(generic(MONO, type(Void.class.getCanonicalName())))));
/** Instantiates a new {@link EmptyMonoZip} instance. */
public EmptyMonoZip() {}
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (!MONO_ZIP_OR_ZIP_WITH.matches(tree, state)) {
return Description.NO_MATCH;
}
if (hasEmptyReceiver(tree, state)) {
return buildDescription(tree)
.setMessage("Invoking `Mono#zipWith` on `Mono#empty()` or a `Mono<Void>` is a no-op")
.build();
}
if (hasEmptyArguments(tree, state)) {
return describeMatch(tree);
}
return Description.NO_MATCH;
}
private static boolean hasEmptyReceiver(MethodInvocationTree tree, VisitorState state) {
return tree.getMethodSelect() instanceof MemberSelectTree memberSelect
&& EMPTY_MONO.matches(memberSelect.getExpression(), state);
}
private static boolean hasEmptyArguments(MethodInvocationTree tree, VisitorState state) {
return tree.getArguments().stream().anyMatch(arg -> EMPTY_MONO.matches(arg, state));
}
}

View File

@@ -50,8 +50,9 @@ import reactor.core.publisher.Flux;
@AutoService(BugChecker.class)
@BugPattern(
summary =
"`Flux#flatMap` and `Flux#flatMapSequential` have subtle semantics; "
+ "please use `Flux#concatMap` or explicitly specify the desired amount of concurrency",
"""
`Flux#flatMap` and `Flux#flatMapSequential` have subtle semantics; please use \
`Flux#concatMap` or explicitly specify the desired amount of concurrency""",
link = BUG_PATTERNS_BASE_URL + "FluxFlatMapUsage",
linkType = CUSTOM,
severity = ERROR,

View File

@@ -245,8 +245,8 @@ public final class FormatStringConcatenation extends BugChecker
}
private void appendExpression(Tree tree) {
if (tree instanceof LiteralTree) {
formatString.append(((LiteralTree) tree).getValue());
if (tree instanceof LiteralTree literal) {
formatString.append(literal.getValue());
} else {
formatString.append(formatSpecifier);
formatArguments.add(tree);

View File

@@ -51,6 +51,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",
@@ -124,8 +125,9 @@ public final class IdentityConversion extends BugChecker implements MethodInvoca
return buildDescription(tree)
.setMessage(
"This method invocation appears redundant; remove it or suppress this warning and "
+ "add a comment explaining its purpose")
"""
This method invocation appears redundant; remove it or suppress this warning and add a \
comment explaining its purpose""")
.addFix(SuggestedFix.replace(tree, SourceCode.treeToString(sourceTree, state)))
.addFix(SuggestedFixes.addSuppressWarnings(state, canonicalName()))
.build();

View File

@@ -43,8 +43,9 @@ import javax.lang.model.element.Modifier;
@AutoService(BugChecker.class)
@BugPattern(
summary =
"`SortedSet` properties of a `@Value.Immutable` or `@Value.Modifiable` type must be "
+ "annotated with `@Value.NaturalOrder` or `@Value.ReverseOrder`",
"""
`SortedSet` properties of a `@Value.Immutable` or `@Value.Modifiable` type must be \
annotated with `@Value.NaturalOrder` or `@Value.ReverseOrder`""",
link = BUG_PATTERNS_BASE_URL + "ImmutablesSortedSetComparator",
linkType = CUSTOM,
severity = ERROR,

View File

@@ -16,7 +16,6 @@ import com.google.errorprone.matchers.Description;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.InstanceOfTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.VariableTree;
import tech.picnic.errorprone.utils.SourceCode;
@@ -41,12 +40,12 @@ public final class IsInstanceLambdaUsage extends BugChecker implements LambdaExp
@Override
public Description matchLambdaExpression(LambdaExpressionTree tree, VisitorState state) {
if (tree.getParameters().size() != 1 || tree.getBody().getKind() != Kind.INSTANCE_OF) {
if (tree.getParameters().size() != 1
|| !(tree.getBody() instanceof InstanceOfTree instanceOf)) {
return Description.NO_MATCH;
}
VariableTree param = Iterables.getOnlyElement(tree.getParameters());
InstanceOfTree instanceOf = (InstanceOfTree) tree.getBody();
if (!ASTHelpers.getSymbol(param).equals(ASTHelpers.getSymbol(instanceOf.getExpression()))) {
return Description.NO_MATCH;
}

View File

@@ -232,7 +232,7 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
@Override
public @Nullable Void visitReturn(ReturnTree node, @Nullable Void unused) {
returnExpressions.add(node.getExpression());
return super.visitReturn(node, unused);
return super.visitReturn(node, null);
}
@Override
@@ -265,8 +265,8 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
arguments.stream()
.map(
arg ->
arg instanceof MethodInvocationTree
? Iterables.getOnlyElement(((MethodInvocationTree) arg).getArguments())
arg instanceof MethodInvocationTree methodInvocation
? Iterables.getOnlyElement(methodInvocation.getArguments())
: arg)
.map(argument -> SourceCode.treeToString(argument, state))
.collect(joining(", ")))
@@ -276,16 +276,12 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
private static String toValueSourceAttributeName(Type type) {
String typeString = type.tsym.name.toString();
switch (typeString) {
case "Class":
return "classes";
case "Character":
return "chars";
case "Integer":
return "ints";
default:
return typeString.toLowerCase(Locale.ROOT) + 's';
}
return switch (typeString) {
case "Class" -> "classes";
case "Character" -> "chars";
case "Integer" -> "ints";
default -> typeString.toLowerCase(Locale.ROOT) + 's';
};
}
private static <T> Optional<T> getElementIfSingleton(Collection<T> collection) {
@@ -297,11 +293,10 @@ public final class JUnitValueSource extends BugChecker implements MethodTreeMatc
private static Matcher<ExpressionTree> isSingleDimensionArrayCreationWithAllElementsMatching(
Matcher<? super ExpressionTree> elementMatcher) {
return (tree, state) -> {
if (!(tree instanceof NewArrayTree)) {
if (!(tree instanceof NewArrayTree newArray)) {
return false;
}
NewArrayTree newArray = (NewArrayTree) tree;
return newArray.getDimensions().isEmpty()
&& !newArray.getInitializers().isEmpty()
&& newArray.getInitializers().stream()

View File

@@ -31,7 +31,6 @@ import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.PrimitiveTypeTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
@@ -52,6 +51,9 @@ import tech.picnic.errorprone.utils.SourceCode;
* <p>The idea behind this checker is that maintaining a sorted sequence simplifies conflict
* resolution, and can even avoid it if two branches add the same entry.
*/
// XXX: In some places we declare a `@SuppressWarnings` annotation with a final value of
// `key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict`. That entry must stay
// last. Consider adding (generic?) support for such cases.
@AutoService(BugChecker.class)
@BugPattern(
summary = "Where possible, sort annotation array attributes lexicographically",
@@ -65,14 +67,15 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
private static final long serialVersionUID = 1L;
private static final ImmutableSet<String> BLACKLISTED_ANNOTATIONS =
ImmutableSet.of(
// XXX: unless JsonPropertyOrder#alphabetic is true...
// XXX: Unless `JsonPropertyOrder#alphabetic` is true...
"com.fasterxml.jackson.annotation.JsonPropertyOrder#value",
"io.swagger.annotations.ApiImplicitParams#value",
"io.swagger.v3.oas.annotations.Parameters#value",
"javax.xml.bind.annotation.XmlType#propOrder",
"org.springframework.context.annotation.PropertySource#value",
"org.springframework.test.context.TestPropertySource#locations",
"org.springframework.test.context.TestPropertySource#value");
"org.springframework.test.context.TestPropertySource#value",
"picocli.CommandLine.Option#names");
private static final String FLAG_PREFIX = "LexicographicalAnnotationAttributeListing:";
private static final String INCLUDED_ANNOTATIONS_FLAG = FLAG_PREFIX + "Includes";
private static final String EXCLUDED_ANNOTATIONS_FLAG = FLAG_PREFIX + "Excludes";
@@ -122,13 +125,9 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
}
private static Optional<NewArrayTree> extractArray(ExpressionTree expr) {
if (expr.getKind() == Kind.ASSIGNMENT) {
return extractArray(((AssignmentTree) expr).getExpression());
}
return Optional.of(expr)
.filter(e -> e.getKind() == Kind.NEW_ARRAY)
.map(NewArrayTree.class::cast);
return expr instanceof AssignmentTree assignment
? extractArray(assignment.getExpression())
: Optional.of(expr).filter(NewArrayTree.class::isInstance).map(NewArrayTree.class::cast);
}
private static Optional<SuggestedFix.Builder> suggestSorting(
@@ -193,24 +192,24 @@ public final class LexicographicalAnnotationAttributeListing extends BugChecker
@Override
public @Nullable Void visitIdentifier(IdentifierTree node, @Nullable Void unused) {
nodes.add(ImmutableList.of(node.getName().toString()));
return super.visitIdentifier(node, unused);
return super.visitIdentifier(node, null);
}
@Override
public @Nullable Void visitLiteral(LiteralTree node, @Nullable Void unused) {
Object value = ASTHelpers.constValue(node);
nodes.add(
value instanceof String
? STRING_ARGUMENT_SPLITTER.splitToStream((String) value).collect(toImmutableList())
value instanceof String str
? STRING_ARGUMENT_SPLITTER.splitToStream(str).collect(toImmutableList())
: ImmutableList.of(String.valueOf(value)));
return super.visitLiteral(node, unused);
return super.visitLiteral(node, null);
}
@Override
public @Nullable Void visitPrimitiveType(PrimitiveTypeTree node, @Nullable Void unused) {
nodes.add(ImmutableList.of(node.getPrimitiveTypeKind().toString()));
return super.visitPrimitiveType(node, unused);
return super.visitPrimitiveType(node, null);
}
}.scan(array, null);

View File

@@ -36,6 +36,10 @@ import tech.picnic.errorprone.utils.SourceCode;
* <p>The idea behind this checker is that maintaining a sorted sequence simplifies conflict
* resolution, and can even avoid it if two branches add the same annotation.
*/
// XXX: Currently this checker only flags method-level annotations. It should likely also flag
// type-, field- and parameter-level annotations.
// XXX: Duplicate entries are often a mistake. Consider introducing a similar `BugChecker` that
// flags duplicates.
@AutoService(BugChecker.class)
@BugPattern(
summary = "Sort annotations lexicographically where possible",

View File

@@ -67,20 +67,19 @@ public final class MockitoMockClassReference extends BugChecker
return describeMatch(tree, SuggestedFixes.removeElement(arguments.get(0), arguments, state));
}
// XXX: Use switch pattern matching once the targeted JDK supports this.
private static boolean isTypeDerivableFromContext(MethodInvocationTree tree, VisitorState state) {
Tree parent = state.getPath().getParentPath().getLeaf();
switch (parent.getKind()) {
case VARIABLE:
return !ASTHelpers.hasImplicitType((VariableTree) parent, state)
&& MoreASTHelpers.areSameType(tree, parent, state);
case ASSIGNMENT:
return MoreASTHelpers.areSameType(tree, parent, state);
case RETURN:
return MoreASTHelpers.findMethodExitedOnReturn(state)
.filter(m -> MoreASTHelpers.areSameType(tree, m.getReturnType(), state))
.isPresent();
default:
return false;
}
return switch (parent.getKind()) {
case VARIABLE ->
!ASTHelpers.hasImplicitType((VariableTree) parent, state)
&& MoreASTHelpers.areSameType(tree, parent, state);
case ASSIGNMENT -> MoreASTHelpers.areSameType(tree, parent, state);
case RETURN ->
MoreASTHelpers.findMethodExitedOnReturn(state)
.filter(m -> MoreASTHelpers.areSameType(tree, m.getReturnType(), state))
.isPresent();
default -> false;
};
}
}

View File

@@ -24,7 +24,9 @@ import com.sun.source.tree.MethodInvocationTree;
@AutoService(BugChecker.class)
@BugPattern(
summary =
"Avoid MongoDB's `$text` filter operator, as it can trigger heavy queries and even cause the server to run out of memory",
"""
Avoid MongoDB's `$text` filter operator, as it can trigger heavy queries and even cause \
the server to run out of memory""",
link = BUG_PATTERNS_BASE_URL + "MongoDBTextFilterUsage",
linkType = CUSTOM,
severity = SUGGESTION,

View File

@@ -34,8 +34,9 @@ import com.sun.tools.javac.code.Type;
@AutoService(BugChecker.class)
@BugPattern(
summary =
"Avoid `Publisher`s that emit other `Publishers`s; "
+ "the resultant code is hard to reason about",
"""
Avoid `Publisher`s that emit other `Publishers`s; the resultant code is hard to reason \
about""",
link = BUG_PATTERNS_BASE_URL + "NestedPublishers",
linkType = CUSTOM,
severity = WARNING,

View File

@@ -169,10 +169,9 @@ public final class NonStaticImport extends BugChecker implements CompilationUnit
ImmutableTable.builder();
for (ImportTree importTree : tree.getImports()) {
Tree qualifiedIdentifier = importTree.getQualifiedIdentifier();
if (importTree.isStatic() && qualifiedIdentifier instanceof MemberSelectTree) {
MemberSelectTree memberSelectTree = (MemberSelectTree) qualifiedIdentifier;
String type = SourceCode.treeToString(memberSelectTree.getExpression(), state);
String member = memberSelectTree.getIdentifier().toString();
if (importTree.isStatic() && qualifiedIdentifier instanceof MemberSelectTree memberSelect) {
String type = SourceCode.treeToString(memberSelect.getExpression(), state);
String member = memberSelect.getIdentifier().toString();
if (shouldNotBeStaticallyImported(type, member)) {
imports.put(
type,
@@ -211,7 +210,7 @@ public final class NonStaticImport extends BugChecker implements CompilationUnit
}
}
return super.visitIdentifier(node, unused);
return super.visitIdentifier(node, null);
}
}.scan(tree, null);
}

View File

@@ -0,0 +1,123 @@
package tech.picnic.errorprone.bugpatterns;
import static com.google.errorprone.BugPattern.LinkType.NONE;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.BugPattern.StandardTags.PERFORMANCE;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
import static com.google.errorprone.matchers.Matchers.staticMethod;
import static java.util.stream.Collectors.joining;
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.MethodInvocationTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.refaster.Refaster;
import com.sun.source.tree.ExpressionTree;
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;
/**
* A {@link BugChecker} that flags arguments to {@link Optional#orElse(Object)} that should be
* deferred using {@link Optional#orElseGet(Supplier)}.
*
* <p>The suggested fix assumes that the argument to {@code orElse} does not have side effects. If
* 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: 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 =
"""
Prefer `Optional#orElseGet` over `Optional#orElse` if the fallback requires additional \
computation""",
linkType = NONE,
severity = WARNING,
tags = PERFORMANCE)
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 OptionalOrElseGet} instance. */
public OptionalOrElseGet() {}
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (!OPTIONAL_OR_ELSE_METHOD.matches(tree, state)) {
return Description.NO_MATCH;
}
ExpressionTree argument = Iterables.getOnlyElement(tree.getArguments());
if (!REQUIRES_COMPUTATION.matches(argument, state)
|| REFASTER_METHOD.matches(argument, state)) {
return Description.NO_MATCH;
}
/*
* We have a match. Construct the method reference or lambda expression to be passed to the
* replacement `#orElseGet` invocation.
*/
String newArgument =
tryMethodReferenceConversion(argument, state)
.orElseGet(() -> "() -> " + SourceCode.treeToString(argument, state));
/* Construct the suggested fix, replacing the method invocation and its argument. */
SuggestedFix fix =
SuggestedFix.builder()
.merge(SuggestedFixes.renameMethodInvocation(tree, "orElseGet", state))
.replace(argument, newArgument)
.build();
return describeMatch(tree, fix);
}
/** Returns the nullary method reference matching the given expression, if any. */
private static Optional<String> tryMethodReferenceConversion(
ExpressionTree tree, VisitorState state) {
if (!(tree instanceof MethodInvocationTree methodInvocation)) {
return Optional.empty();
}
if (!methodInvocation.getArguments().isEmpty()) {
return Optional.empty();
}
if (!(methodInvocation.getMethodSelect() instanceof MemberSelectTree memberSelect)) {
return Optional.empty();
}
if (REQUIRES_COMPUTATION.matches(memberSelect.getExpression(), state)) {
return Optional.empty();
}
return Optional.of(
SourceCode.treeToString(memberSelect.getExpression(), state)
+ "::"
+ (methodInvocation.getTypeArguments().isEmpty()
? ""
: methodInvocation.getTypeArguments().stream()
.map(arg -> SourceCode.treeToString(arg, state))
.collect(joining(",", "<", ">")))
+ memberSelect.getIdentifier());
}
}

View File

@@ -22,6 +22,7 @@ import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
@@ -44,8 +45,9 @@ import tech.picnic.errorprone.utils.SourceCode;
@AutoService(BugChecker.class)
@BugPattern(
summary =
"Ensure invocations of `Comparator#comparing{,Double,Int,Long}` match the return type"
+ " of the provided function",
"""
Ensure invocations of `Comparator#comparing{,Double,Int,Long}` match the return type of \
the provided function""",
link = BUG_PATTERNS_BASE_URL + "PrimitiveComparison",
linkType = CUSTOM,
severity = WARNING,
@@ -147,38 +149,44 @@ public final class PrimitiveComparison extends BugChecker implements MethodInvoc
return isStatic ? "comparing" : "thenComparing";
}
// XXX: Use switch pattern matching once the targeted JDK supports this.
private static Optional<Type> getPotentiallyBoxedReturnType(ExpressionTree tree) {
switch (tree.getKind()) {
case LAMBDA_EXPRESSION:
/* Return the lambda expression's actual return type. */
return Optional.ofNullable(ASTHelpers.getType(((LambdaExpressionTree) tree).getBody()));
case MEMBER_REFERENCE:
/* Return the method's declared return type. */
// XXX: Very fragile. Do better.
Type subType2 = ((JCMemberReference) tree).referentType;
return Optional.of(subType2.getReturnType());
default:
/* This appears to be a genuine `{,ToInt,ToLong,ToDouble}Function`. */
return Optional.empty();
if (tree instanceof LambdaExpressionTree lambdaExpression) {
/* Return the lambda expression's actual return type. */
return Optional.ofNullable(ASTHelpers.getType(lambdaExpression.getBody()));
}
// XXX: The match against a concrete type and reference to one of its fields is fragile. Do
// better.
if (tree instanceof JCMemberReference memberReference) {
/* Return the method's declared return type. */
Type subType = memberReference.referentType;
return Optional.of(subType.getReturnType());
}
/* This appears to be a genuine `{,ToInt,ToLong,ToDouble}Function`. */
return Optional.empty();
}
// XXX: Use switch pattern matching once the targeted JDK supports this.
private static Fix suggestFix(
MethodInvocationTree tree, String preferredMethodName, VisitorState state) {
ExpressionTree expr = tree.getMethodSelect();
switch (expr.getKind()) {
case IDENTIFIER:
SuggestedFix.Builder fix = SuggestedFix.builder();
String replacement =
SuggestedFixes.qualifyStaticImport(
Comparator.class.getCanonicalName() + '.' + preferredMethodName, fix, state);
return fix.replace(expr, replacement).build();
case MEMBER_SELECT:
MemberSelectTree ms = (MemberSelectTree) tree.getMethodSelect();
return SuggestedFix.replace(
ms, SourceCode.treeToString(ms.getExpression(), state) + '.' + preferredMethodName);
default:
throw new VerifyException("Unexpected type of expression: " + expr.getKind());
if (expr instanceof IdentifierTree) {
SuggestedFix.Builder fix = SuggestedFix.builder();
String replacement =
SuggestedFixes.qualifyStaticImport(
Comparator.class.getCanonicalName() + '.' + preferredMethodName, fix, state);
return fix.replace(expr, replacement).build();
}
if (expr instanceof MemberSelectTree memberSelect) {
return SuggestedFix.replace(
memberSelect,
SourceCode.treeToString(memberSelect.getExpression(), state) + '.' + preferredMethodName);
}
throw new VerifyException("Unexpected type of expression: " + expr.getKind());
}
}

View File

@@ -331,36 +331,32 @@ public final class RedundantStringConversion extends BugChecker
}
private Optional<ExpressionTree> trySimplify(ExpressionTree tree, VisitorState state) {
if (tree.getKind() != Kind.METHOD_INVOCATION) {
if (!(tree instanceof MethodInvocationTree methodInvocation)) {
return Optional.empty();
}
MethodInvocationTree methodInvocation = (MethodInvocationTree) tree;
if (!conversionMethodMatcher.matches(methodInvocation, state)) {
return Optional.empty();
}
switch (methodInvocation.getArguments().size()) {
case 0:
return trySimplifyNullaryMethod(methodInvocation, state);
case 1:
return trySimplifyUnaryMethod(methodInvocation, state);
default:
throw new IllegalStateException(
"Cannot simplify method call with two or more arguments: "
+ SourceCode.treeToString(tree, state));
}
return switch (methodInvocation.getArguments().size()) {
case 0 -> trySimplifyNullaryMethod(methodInvocation, state);
case 1 -> trySimplifyUnaryMethod(methodInvocation, state);
default ->
throw new IllegalStateException(
"Cannot simplify method call with two or more arguments: "
+ SourceCode.treeToString(tree, state));
};
}
private static Optional<ExpressionTree> trySimplifyNullaryMethod(
MethodInvocationTree methodInvocation, VisitorState state) {
if (!instanceMethod().matches(methodInvocation, state)) {
if (!instanceMethod().matches(methodInvocation, state)
|| !(methodInvocation.getMethodSelect() instanceof MemberSelectTree memberSelect)) {
return Optional.empty();
}
return Optional.of(methodInvocation.getMethodSelect())
.filter(methodSelect -> methodSelect.getKind() == Kind.MEMBER_SELECT)
.map(methodSelect -> ((MemberSelectTree) methodSelect).getExpression())
return Optional.of(memberSelect.getExpression())
.filter(expr -> !"super".equals(SourceCode.treeToString(expr, state)));
}

View File

@@ -105,9 +105,10 @@ public final class RequestMappingAnnotation extends BugChecker implements Method
&& LACKS_PARAMETER_ANNOTATION.matches(tree, state)
? buildDescription(tree)
.setMessage(
"Not all parameters of this request mapping method are annotated; this may be a "
+ "mistake. If the unannotated parameters represent query string parameters, "
+ "annotate them with `@RequestParam`.")
"""
Not all parameters of this request mapping method are annotated; this may be a \
mistake. If the unannotated parameters represent query string parameters, annotate \
them with `@RequestParam`.""")
.build()
: Description.NO_MATCH;
}

View File

@@ -34,7 +34,9 @@ import tech.picnic.errorprone.utils.Flags;
@AutoService(BugChecker.class)
@BugPattern(
summary =
"By default, `@RequestParam` does not support `ImmutableCollection` and `ImmutableMap` subtypes",
"""
By default, `@RequestParam` does not support `ImmutableCollection` and `ImmutableMap` \
subtypes""",
link = BUG_PATTERNS_BASE_URL + "RequestParamType",
linkType = CUSTOM,
severity = ERROR,

View File

@@ -1,6 +1,5 @@
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.SUGGESTION;
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
@@ -25,7 +24,6 @@ import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.Tree.Kind;
import java.util.Optional;
import tech.picnic.errorprone.utils.AnnotationAttributeMatcher;
import tech.picnic.errorprone.utils.SourceCode;
@@ -80,31 +78,25 @@ public final class SpringMvcAnnotation extends BugChecker implements AnnotationT
}
private static Optional<String> extractUniqueMethod(ExpressionTree arg, VisitorState state) {
verify(
arg.getKind() == Kind.ASSIGNMENT,
"Annotation attribute is not an assignment: %s",
arg.getKind());
ExpressionTree expr = ((AssignmentTree) arg).getExpression();
if (expr.getKind() != Kind.NEW_ARRAY) {
return Optional.of(extractMethod(expr, state));
if (!(arg instanceof AssignmentTree assignment)) {
throw new VerifyException("Annotation attribute is not an assignment:" + arg.getKind());
}
NewArrayTree newArray = (NewArrayTree) expr;
return Optional.of(newArray.getInitializers())
.filter(args -> args.size() == 1)
.map(args -> extractMethod(args.get(0), state));
ExpressionTree expr = assignment.getExpression();
return expr instanceof NewArrayTree newArray
? Optional.of(newArray.getInitializers())
.filter(args -> args.size() == 1)
.map(args -> extractMethod(args.get(0), state))
: Optional.of(extractMethod(expr, state));
}
// XXX: Use switch pattern matching once the targeted JDK supports this.
private static String extractMethod(ExpressionTree expr, VisitorState state) {
switch (expr.getKind()) {
case IDENTIFIER:
return SourceCode.treeToString(expr, state);
case MEMBER_SELECT:
return ((MemberSelectTree) expr).getIdentifier().toString();
default:
throw new VerifyException("Unexpected type of expression: " + expr.getKind());
}
return switch (expr.getKind()) {
case IDENTIFIER -> SourceCode.treeToString(expr, state);
case MEMBER_SELECT -> ((MemberSelectTree) expr).getIdentifier().toString();
default -> throw new VerifyException("Unexpected type of expression: " + expr.getKind());
};
}
private static Fix replaceAnnotation(

View File

@@ -39,11 +39,13 @@ import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matchers;
import com.google.errorprone.predicates.TypePredicates;
import com.google.errorprone.refaster.ImportPolicy;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.code.Type;
import java.nio.charset.StandardCharsets;
import java.time.ZoneOffset;
@@ -100,6 +102,7 @@ public final class StaticImport extends BugChecker implements MemberSelectTreeMa
Preconditions.class.getCanonicalName(),
Predicates.class.getCanonicalName(),
StandardCharsets.class.getCanonicalName(),
TypePredicates.class.getCanonicalName(),
Verify.class.getCanonicalName(),
"com.fasterxml.jackson.annotation.JsonCreator.Mode",
"com.fasterxml.jackson.annotation.JsonFormat.Shape",
@@ -209,15 +212,10 @@ public final class StaticImport extends BugChecker implements MemberSelectTreeMa
Tree parentTree =
requireNonNull(state.getPath().getParentPath(), "MemberSelectTree lacks enclosing node")
.getLeaf();
switch (parentTree.getKind()) {
case IMPORT:
case MEMBER_SELECT:
return false;
case METHOD_INVOCATION:
return ((MethodInvocationTree) parentTree).getTypeArguments().isEmpty();
default:
return true;
}
return parentTree instanceof MethodInvocationTree methodInvocation
? methodInvocation.getTypeArguments().isEmpty()
: (parentTree.getKind() != Kind.IMPORT && parentTree.getKind() != Kind.MEMBER_SELECT);
}
private static boolean isCandidate(MemberSelectTree tree) {

View File

@@ -34,7 +34,9 @@ import java.time.ZonedDateTime;
@AutoService(BugChecker.class)
@BugPattern(
summary =
"Derive the current time from an existing `Clock` Spring bean, and don't rely on a `Clock`'s time zone",
"""
Derive the current time from an existing `Clock` Spring bean, and don't rely on a \
`Clock`'s time zone""",
link = BUG_PATTERNS_BASE_URL + "TimeZoneUsage",
linkType = CUSTOM,
severity = WARNING,

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,39 @@ final class ClassRules {
return clazz::isInstance;
}
}
/**
* Prefer {@link Class#cast(Object)} method references over lambda expressions that require naming
* a variable.
*/
// XXX: Once the `ClassReferenceCast` rule is dropped, rename this rule to just `ClassCast`.
static final class ClassLiteralCast<T, S> {
@BeforeTemplate
@SuppressWarnings("unchecked")
Function<T, S> before() {
return t -> (S) t;
}
@AfterTemplate
Function<T, S> after() {
return Refaster.<S>clazz()::cast;
}
}
/**
* 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
@@ -35,13 +38,21 @@ final class CollectionRules {
*/
static final class CollectionIsEmpty<T> {
@BeforeTemplate
@SuppressWarnings("java:S1155" /* This violation will be rewritten. */)
@SuppressWarnings({
"java:S1155" /* This violation will be rewritten. */,
"LexicographicalAnnotationAttributeListing" /* `key-*` entry must remain last. */,
"OptionalFirstCollectionElement" /* This is a more specific template. */,
"StreamFindAnyIsEmpty" /* This is a more specific template. */,
"key-to-resolve-AnnotationUseStyle-and-TrailingComment-check-conflict"
})
boolean before(Collection<T> collection) {
return Refaster.anyOf(
collection.size() == 0,
collection.size() <= 0,
collection.size() < 1,
Iterables.isEmpty(collection));
Iterables.isEmpty(collection),
collection.stream().findAny().isEmpty(),
collection.stream().findFirst().isEmpty());
}
@BeforeTemplate
@@ -176,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. */)
@@ -268,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
@@ -337,7 +383,9 @@ final class CollectionRules {
/**
* Don't use the ternary operator to extract the first element of a possibly-empty {@link
* Collection} as an {@link Optional}.
* Collection} as an {@link Optional}, and (when applicable) prefer {@link Stream#findFirst()}
* over {@link Stream#findAny()} to communicate that the collection's first element (if any,
* according to iteration order) will be returned.
*/
static final class OptionalFirstCollectionElement<T> {
@BeforeTemplate

View File

@@ -16,13 +16,18 @@ import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
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.Matches;
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
import com.google.errorprone.refaster.annotation.Placeholder;
import com.google.errorprone.refaster.annotation.Repeated;
import com.google.errorprone.refaster.annotation.UseImportPolicy;
import java.util.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;
@@ -92,6 +97,24 @@ final class ComparatorRules {
}
}
/** Don't explicitly compare enums by their ordinal. */
abstract static class ComparingEnum<E extends Enum<E>, T> {
@Placeholder(allowsIdentity = true)
abstract E toEnumFunction(@MayOptionallyUse T value);
@BeforeTemplate
@SuppressWarnings("EnumOrdinal" /* This violation will be rewritten. */)
Comparator<T> before() {
return comparingInt(v -> toEnumFunction(v).ordinal());
}
@AfterTemplate
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
Comparator<T> after() {
return comparing(v -> toEnumFunction(v));
}
}
/** Don't explicitly create {@link Comparator}s unnecessarily. */
static final class ThenComparing<S, T extends Comparable<? super T>> {
@BeforeTemplate
@@ -222,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);
}
}
@@ -269,7 +351,7 @@ final class ComparatorRules {
static final class MinOfPairCustomOrder<T> {
@BeforeTemplate
@SuppressWarnings("java:S1067" /* The conditional operators are independent. */)
T before(T value1, T value2, Comparator<T> cmp) {
T before(T value1, T value2, Comparator<? super T> cmp) {
return Refaster.anyOf(
cmp.compare(value1, value2) <= 0 ? value1 : value2,
cmp.compare(value1, value2) > 0 ? value2 : value1,
@@ -284,23 +366,69 @@ final class ComparatorRules {
}
@AfterTemplate
T after(T value1, T value2, Comparator<T> cmp) {
T after(T value1, T value2, Comparator<? super T> cmp) {
return Comparators.min(value1, value2, cmp);
}
}
/** 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);
}
}
@@ -336,7 +464,7 @@ final class ComparatorRules {
static final class MaxOfPairCustomOrder<T> {
@BeforeTemplate
@SuppressWarnings("java:S1067" /* The conditional operators are independent. */)
T before(T value1, T value2, Comparator<T> cmp) {
T before(T value1, T value2, Comparator<? super T> cmp) {
return Refaster.anyOf(
cmp.compare(value1, value2) >= 0 ? value1 : value2,
cmp.compare(value1, value2) < 0 ? value2 : value1,
@@ -351,7 +479,7 @@ final class ComparatorRules {
}
@AfterTemplate
T after(T value1, T value2, Comparator<T> cmp) {
T after(T value1, T value2, Comparator<? super T> cmp) {
return Comparators.max(value1, value2, cmp);
}
}
@@ -419,4 +547,34 @@ final class ComparatorRules {
return maxBy(naturalOrder());
}
}
/** Don't explicitly compare enums by their ordinal. */
static final class IsLessThan<E extends Enum<E>> {
@BeforeTemplate
@SuppressWarnings("EnumOrdinal" /* This violation will be rewritten. */)
boolean before(E value1, E value2) {
return value1.ordinal() < value2.ordinal();
}
@AfterTemplate
@AlsoNegation
boolean after(E value1, E value2) {
return value1.compareTo(value2) < 0;
}
}
/** Don't explicitly compare enums by their ordinal. */
static final class IsLessThanOrEqualTo<E extends Enum<E>> {
@BeforeTemplate
@SuppressWarnings("EnumOrdinal" /* This violation will be rewritten. */)
boolean before(E value1, E value2) {
return value1.ordinal() <= value2.ordinal();
}
@AfterTemplate
@AlsoNegation
boolean after(E value1, E value2) {
return value1.compareTo(value2) <= 0;
}
}
}

View File

@@ -1,5 +1,6 @@
package tech.picnic.errorprone.refasterrules;
import static java.util.function.Predicate.isEqual;
import static java.util.function.Predicate.not;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
@@ -19,9 +20,9 @@ import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
final class EqualityRules {
private EqualityRules() {}
/** Prefer reference-based quality for enums. */
// Primitive value comparisons are not listed, because Error Prone flags those out of the box.
static final class PrimitiveOrReferenceEquality<T extends Enum<T>> {
/** Prefer reference-based equality for enums. */
// Primitive value comparisons are not matched, because Error Prone flags those out of the box.
static final class EnumReferenceEquality<T extends Enum<T>> {
/**
* Enums can be compared by reference. It is safe to do so even in the face of refactorings,
* because if the type is ever converted to a non-enum, then Error-Prone will complain about any
@@ -30,8 +31,9 @@ final class EqualityRules {
// XXX: This Refaster rule is the topic of https://github.com/google/error-prone/issues/559. We
// work around the issue by selecting the "largest replacements". See the `Refaster` check.
@BeforeTemplate
@SuppressWarnings("EnumOrdinal" /* This violation will be rewritten. */)
boolean before(T a, T b) {
return Refaster.anyOf(a.equals(b), Objects.equals(a, b));
return Refaster.anyOf(a.equals(b), Objects.equals(a, b), a.ordinal() == b.ordinal());
}
@AfterTemplate
@@ -42,6 +44,20 @@ final class EqualityRules {
}
}
/** Prefer reference-based equality for enums. */
static final class EnumReferenceEqualityLambda<T extends Enum<T>> {
@BeforeTemplate
Predicate<T> before(T e) {
return Refaster.anyOf(isEqual(e), e::equals);
}
@AfterTemplate
@SuppressWarnings("java:S1698" /* Reference comparison is valid for enums. */)
Predicate<T> after(T e) {
return v -> v == e;
}
}
/** Prefer {@link Object#equals(Object)} over the equivalent lambda function. */
// XXX: As it stands, this rule is a special case of what `MethodReferenceUsage` tries to achieve.
// If/when `MethodReferenceUsage` becomes production ready, we should simply drop this check.

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

@@ -9,8 +9,6 @@ import java.io.OutputStream;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
/** Refaster rules related to expressions dealing with {@link InputStream}s. */
// XXX: Add a rule for `ByteStreams.skipFully(in, n)` -> `in.skipNBytes(n)` once we have a way to
// target JDK 12+ APIs.
@OnlineDocumentation
final class InputStreamRules {
private InputStreamRules() {}
@@ -38,4 +36,28 @@ final class InputStreamRules {
return in.readAllBytes();
}
}
static final class InputStreamReadNBytes {
@BeforeTemplate
byte[] before(InputStream in, int n) throws IOException {
return ByteStreams.limit(in, n).readAllBytes();
}
@AfterTemplate
byte[] after(InputStream in, int n) throws IOException {
return in.readNBytes(n);
}
}
static final class InputStreamSkipNBytes {
@BeforeTemplate
void before(InputStream in, long n) throws IOException {
ByteStreams.skipFully(in, n);
}
@AfterTemplate
void after(InputStream in, long n) throws IOException {
in.skipNBytes(n);
}
}
}

View File

@@ -26,6 +26,7 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.function.Executable;
import org.junit.jupiter.api.function.ThrowingSupplier;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
import tech.picnic.errorprone.refaster.annotation.TypeMigration;
/**
* Refaster rules to replace JUnit assertions with AssertJ equivalents.
@@ -40,19 +41,283 @@ import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
// `() -> toString()` match both `ThrowingSupplier` and `ThrowingCallable`, but `() -> "constant"`
// is only compatible with the former.
@OnlineDocumentation
@TypeMigration(
of = Assertions.class,
unmigratedMethods = {
"assertAll(Collection<Executable>)",
"assertAll(Executable[])",
"assertAll(Stream<Executable>)",
"assertAll(String, Collection<Executable>)",
"assertAll(String, Executable[])",
"assertAll(String, Stream<Executable>)",
"assertArrayEquals(boolean[], boolean[])",
"assertArrayEquals(boolean[], boolean[], String)",
"assertArrayEquals(boolean[], boolean[], Supplier<String>)",
"assertArrayEquals(byte[], byte[])",
"assertArrayEquals(byte[], byte[], String)",
"assertArrayEquals(byte[], byte[], Supplier<String>)",
"assertArrayEquals(char[], char[])",
"assertArrayEquals(char[], char[], String)",
"assertArrayEquals(char[], char[], Supplier<String>)",
"assertArrayEquals(double[], double[])",
"assertArrayEquals(double[], double[], double)",
"assertArrayEquals(double[], double[], double, String)",
"assertArrayEquals(double[], double[], double, Supplier<String>)",
"assertArrayEquals(double[], double[], String)",
"assertArrayEquals(double[], double[], Supplier<String>)",
"assertArrayEquals(float[], float[])",
"assertArrayEquals(float[], float[], float)",
"assertArrayEquals(float[], float[], float, String)",
"assertArrayEquals(float[], float[], float, Supplier<String>)",
"assertArrayEquals(float[], float[], String)",
"assertArrayEquals(float[], float[], Supplier<String>)",
"assertArrayEquals(int[], int[])",
"assertArrayEquals(int[], int[], String)",
"assertArrayEquals(int[], int[], Supplier<String>)",
"assertArrayEquals(long[], long[])",
"assertArrayEquals(long[], long[], String)",
"assertArrayEquals(long[], long[], Supplier<String>)",
"assertArrayEquals(Object[], Object[])",
"assertArrayEquals(Object[], Object[], String)",
"assertArrayEquals(Object[], Object[], Supplier<String>)",
"assertArrayEquals(short[], short[])",
"assertArrayEquals(short[], short[], String)",
"assertArrayEquals(short[], short[], Supplier<String>)",
"assertEquals(Byte, Byte)",
"assertEquals(Byte, byte)",
"assertEquals(byte, Byte)",
"assertEquals(byte, byte)",
"assertEquals(Byte, Byte, String)",
"assertEquals(Byte, byte, String)",
"assertEquals(byte, Byte, String)",
"assertEquals(byte, byte, String)",
"assertEquals(Byte, Byte, Supplier<String>)",
"assertEquals(Byte, byte, Supplier<String>)",
"assertEquals(byte, Byte, Supplier<String>)",
"assertEquals(byte, byte, Supplier<String>)",
"assertEquals(char, char)",
"assertEquals(char, char, String)",
"assertEquals(char, char, Supplier<String>)",
"assertEquals(char, Character)",
"assertEquals(char, Character, String)",
"assertEquals(char, Character, Supplier<String>)",
"assertEquals(Character, char)",
"assertEquals(Character, char, String)",
"assertEquals(Character, char, Supplier<String>)",
"assertEquals(Character, Character)",
"assertEquals(Character, Character, String)",
"assertEquals(Character, Character, Supplier<String>)",
"assertEquals(Double, Double)",
"assertEquals(Double, double)",
"assertEquals(double, Double)",
"assertEquals(double, double)",
"assertEquals(double, double, double)",
"assertEquals(double, double, double, String)",
"assertEquals(double, double, double, Supplier<String>)",
"assertEquals(Double, Double, String)",
"assertEquals(Double, double, String)",
"assertEquals(double, Double, String)",
"assertEquals(double, double, String)",
"assertEquals(Double, Double, Supplier<String>)",
"assertEquals(Double, double, Supplier<String>)",
"assertEquals(double, Double, Supplier<String>)",
"assertEquals(double, double, Supplier<String>)",
"assertEquals(Float, Float)",
"assertEquals(Float, float)",
"assertEquals(float, Float)",
"assertEquals(float, float)",
"assertEquals(float, float, float)",
"assertEquals(float, float, float, String)",
"assertEquals(float, float, float, Supplier<String>)",
"assertEquals(Float, Float, String)",
"assertEquals(Float, float, String)",
"assertEquals(float, Float, String)",
"assertEquals(float, float, String)",
"assertEquals(Float, Float, Supplier<String>)",
"assertEquals(Float, float, Supplier<String>)",
"assertEquals(float, Float, Supplier<String>)",
"assertEquals(float, float, Supplier<String>)",
"assertEquals(int, int)",
"assertEquals(int, int, String)",
"assertEquals(int, int, Supplier<String>)",
"assertEquals(int, Integer)",
"assertEquals(int, Integer, String)",
"assertEquals(int, Integer, Supplier<String>)",
"assertEquals(Integer, int)",
"assertEquals(Integer, int, String)",
"assertEquals(Integer, int, Supplier<String>)",
"assertEquals(Integer, Integer)",
"assertEquals(Integer, Integer, String)",
"assertEquals(Integer, Integer, Supplier<String>)",
"assertEquals(Long, Long)",
"assertEquals(Long, long)",
"assertEquals(long, Long)",
"assertEquals(long, long)",
"assertEquals(Long, Long, String)",
"assertEquals(Long, long, String)",
"assertEquals(long, Long, String)",
"assertEquals(long, long, String)",
"assertEquals(Long, Long, Supplier<String>)",
"assertEquals(Long, long, Supplier<String>)",
"assertEquals(long, Long, Supplier<String>)",
"assertEquals(long, long, Supplier<String>)",
"assertEquals(Object, Object)",
"assertEquals(Object, Object, String)",
"assertEquals(Object, Object, Supplier<String>)",
"assertEquals(Short, Short)",
"assertEquals(Short, short)",
"assertEquals(short, Short)",
"assertEquals(short, short)",
"assertEquals(Short, Short, String)",
"assertEquals(Short, short, String)",
"assertEquals(short, Short, String)",
"assertEquals(short, short, String)",
"assertEquals(Short, Short, Supplier<String>)",
"assertEquals(Short, short, Supplier<String>)",
"assertEquals(short, Short, Supplier<String>)",
"assertEquals(short, short, Supplier<String>)",
"assertFalse(BooleanSupplier)",
"assertFalse(BooleanSupplier, String)",
"assertFalse(BooleanSupplier, Supplier<String>)",
"assertIterableEquals(Iterable<?>, Iterable<?>)",
"assertIterableEquals(Iterable<?>, Iterable<?>, String)",
"assertIterableEquals(Iterable<?>, Iterable<?>, Supplier<String>)",
"assertLinesMatch(List<String>, List<String>)",
"assertLinesMatch(List<String>, List<String>, String)",
"assertLinesMatch(List<String>, List<String>, Supplier<String>)",
"assertLinesMatch(Stream<String>, Stream<String>)",
"assertLinesMatch(Stream<String>, Stream<String>, String)",
"assertLinesMatch(Stream<String>, Stream<String>, Supplier<String>)",
"assertNotEquals(Byte, Byte)",
"assertNotEquals(Byte, byte)",
"assertNotEquals(byte, Byte)",
"assertNotEquals(byte, byte)",
"assertNotEquals(Byte, Byte, String)",
"assertNotEquals(Byte, byte, String)",
"assertNotEquals(byte, Byte, String)",
"assertNotEquals(byte, byte, String)",
"assertNotEquals(Byte, Byte, Supplier<String>)",
"assertNotEquals(Byte, byte, Supplier<String>)",
"assertNotEquals(byte, Byte, Supplier<String>)",
"assertNotEquals(byte, byte, Supplier<String>)",
"assertNotEquals(char, char)",
"assertNotEquals(char, char, String)",
"assertNotEquals(char, char, Supplier<String>)",
"assertNotEquals(char, Character)",
"assertNotEquals(char, Character, String)",
"assertNotEquals(char, Character, Supplier<String>)",
"assertNotEquals(Character, char)",
"assertNotEquals(Character, char, String)",
"assertNotEquals(Character, char, Supplier<String>)",
"assertNotEquals(Character, Character)",
"assertNotEquals(Character, Character, String)",
"assertNotEquals(Character, Character, Supplier<String>)",
"assertNotEquals(Double, Double)",
"assertNotEquals(Double, double)",
"assertNotEquals(double, Double)",
"assertNotEquals(double, double)",
"assertNotEquals(double, double, double)",
"assertNotEquals(double, double, double, String)",
"assertNotEquals(double, double, double, Supplier<String>)",
"assertNotEquals(Double, Double, String)",
"assertNotEquals(Double, double, String)",
"assertNotEquals(double, Double, String)",
"assertNotEquals(double, double, String)",
"assertNotEquals(Double, Double, Supplier<String>)",
"assertNotEquals(Double, double, Supplier<String>)",
"assertNotEquals(double, Double, Supplier<String>)",
"assertNotEquals(double, double, Supplier<String>)",
"assertNotEquals(Float, Float)",
"assertNotEquals(Float, float)",
"assertNotEquals(float, Float)",
"assertNotEquals(float, float)",
"assertNotEquals(float, float, float)",
"assertNotEquals(float, float, float, String)",
"assertNotEquals(float, float, float, Supplier<String>)",
"assertNotEquals(Float, Float, String)",
"assertNotEquals(Float, float, String)",
"assertNotEquals(float, Float, String)",
"assertNotEquals(float, float, String)",
"assertNotEquals(Float, Float, Supplier<String>)",
"assertNotEquals(Float, float, Supplier<String>)",
"assertNotEquals(float, Float, Supplier<String>)",
"assertNotEquals(float, float, Supplier<String>)",
"assertNotEquals(int, int)",
"assertNotEquals(int, int, String)",
"assertNotEquals(int, int, Supplier<String>)",
"assertNotEquals(int, Integer)",
"assertNotEquals(int, Integer, String)",
"assertNotEquals(int, Integer, Supplier<String>)",
"assertNotEquals(Integer, int)",
"assertNotEquals(Integer, int, String)",
"assertNotEquals(Integer, int, Supplier<String>)",
"assertNotEquals(Integer, Integer)",
"assertNotEquals(Integer, Integer, String)",
"assertNotEquals(Integer, Integer, Supplier<String>)",
"assertNotEquals(Long, Long)",
"assertNotEquals(Long, long)",
"assertNotEquals(long, Long)",
"assertNotEquals(long, long)",
"assertNotEquals(Long, Long, String)",
"assertNotEquals(Long, long, String)",
"assertNotEquals(long, Long, String)",
"assertNotEquals(long, long, String)",
"assertNotEquals(Long, Long, Supplier<String>)",
"assertNotEquals(Long, long, Supplier<String>)",
"assertNotEquals(long, Long, Supplier<String>)",
"assertNotEquals(long, long, Supplier<String>)",
"assertNotEquals(Object, Object)",
"assertNotEquals(Object, Object, String)",
"assertNotEquals(Object, Object, Supplier<String>)",
"assertNotEquals(Short, Short)",
"assertNotEquals(Short, short)",
"assertNotEquals(short, Short)",
"assertNotEquals(short, short)",
"assertNotEquals(Short, Short, String)",
"assertNotEquals(Short, short, String)",
"assertNotEquals(short, Short, String)",
"assertNotEquals(short, short, String)",
"assertNotEquals(Short, Short, Supplier<String>)",
"assertNotEquals(Short, short, Supplier<String>)",
"assertNotEquals(short, Short, Supplier<String>)",
"assertNotEquals(short, short, Supplier<String>)",
"assertTimeout(Duration, Executable)",
"assertTimeout(Duration, Executable, String)",
"assertTimeout(Duration, Executable, Supplier<String>)",
"assertTimeout(Duration, ThrowingSupplier<T>)",
"assertTimeout(Duration, ThrowingSupplier<T>, String)",
"assertTimeout(Duration, ThrowingSupplier<T>, Supplier<String>)",
"assertTimeoutPreemptively(Duration, Executable)",
"assertTimeoutPreemptively(Duration, Executable, String)",
"assertTimeoutPreemptively(Duration, Executable, Supplier<String>)",
"assertTimeoutPreemptively(Duration, ThrowingSupplier<T>)",
"assertTimeoutPreemptively(Duration, ThrowingSupplier<T>, String)",
"assertTimeoutPreemptively(Duration, ThrowingSupplier<T>, Supplier<String>)",
"assertTimeoutPreemptively(Duration, ThrowingSupplier<T>, Supplier<String>, TimeoutFailureFactory<E>)",
"assertTrue(BooleanSupplier)",
"assertTrue(BooleanSupplier, String)",
"assertTrue(BooleanSupplier, Supplier<String>)",
"fail(Supplier<String>)"
})
final class JUnitToAssertJRules {
private JUnitToAssertJRules() {}
static final class ThrowNewAssertionError {
static final class Fail<T> {
@BeforeTemplate
void before() {
Assertions.fail();
T before() {
return Assertions.fail();
}
// XXX: Add `@UseImportPolicy(STATIC_IMPORT_ALWAYS)` once
// https://github.com/google/error-prone/pull/3584 is resolved. Until that time, statically
// importing AssertJ's `fail` is likely to clash with an existing static import of JUnit's
// `fail`. Note that combining Error Prone's `RemoveUnusedImports` and
// `UnnecessarilyFullyQualified` checks and our `StaticImport` check will anyway cause the
// method to be imported statically if possible; just in a less efficient manner.
@AfterTemplate
@DoNotCall
void after() {
throw new AssertionError();
T after() {
return fail();
}
}
@@ -62,12 +327,7 @@ final class JUnitToAssertJRules {
return Assertions.fail(message);
}
// XXX: Add `@UseImportPolicy(STATIC_IMPORT_ALWAYS)` once
// https://github.com/google/error-prone/pull/3584 is resolved. Until that time, statically
// importing AssertJ's `fail` is likely to clash with an existing static import of JUnit's
// `fail`. Note that combining Error Prone's `RemoveUnusedImports` and
// `UnnecessarilyFullyQualified` checks and our `StaticImport` check will anyway cause the
// method to be imported statically if possible; just in a less efficient manner.
// XXX: Add `@UseImportPolicy(STATIC_IMPORT_ALWAYS)`. See `Fail` comment.
@AfterTemplate
T after(String message) {
return fail(message);
@@ -80,28 +340,24 @@ final class JUnitToAssertJRules {
return Assertions.fail(message, throwable);
}
// XXX: Add `@UseImportPolicy(STATIC_IMPORT_ALWAYS)` once
// https://github.com/google/error-prone/pull/3584 is resolved. Until that time, statically
// importing AssertJ's `fail` is likely to clash with an existing static import of JUnit's
// `fail`. Note that combining Error Prone's `RemoveUnusedImports` and
// `UnnecessarilyFullyQualified` checks and our `StaticImport` check will anyway cause the
// method to be imported statically if possible; just in a less efficient manner.
// XXX: Add `@UseImportPolicy(STATIC_IMPORT_ALWAYS)`. See `Fail` comment.
@AfterTemplate
T after(String message, Throwable throwable) {
return fail(message, throwable);
}
}
static final class FailWithThrowable {
static final class FailWithThrowable<T> {
@BeforeTemplate
void before(Throwable throwable) {
Assertions.fail(throwable);
T before(Throwable throwable) {
return Assertions.fail(throwable);
}
// XXX: Add `@UseImportPolicy(STATIC_IMPORT_ALWAYS)`. See `Fail` comment.
@AfterTemplate
@DoNotCall
void after(Throwable throwable) {
throw new AssertionError(throwable);
T after(Throwable throwable) {
return fail(throwable);
}
}

View File

@@ -20,13 +20,26 @@ 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
final class OptionalRules {
private OptionalRules() {}
/** Prefer {@link Optional#empty()} over the more contrived alternative. */
static final class OptionalEmpty<T> {
@BeforeTemplate
Optional<T> before() {
return Optional.ofNullable(null);
}
@AfterTemplate
Optional<T> after() {
return Optional.empty();
}
}
static final class OptionalOfNullable<T> {
// XXX: Refaster should be smart enough to also rewrite occurrences in which there are
// parentheses around the null check, but that's currently not the case. Try to fix that.
@@ -242,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);
}
}
@@ -360,7 +370,12 @@ final class OptionalRules {
/** Prefer {@link Optional#or(Supplier)} over more verbose alternatives. */
static final class OptionalOrOtherOptional<T> {
@BeforeTemplate
@SuppressWarnings("NestedOptionals" /* Auto-fix for the `NestedOptionals` check. */)
@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.
@@ -386,9 +401,13 @@ final class OptionalRules {
*/
static final class OptionalIdentity<T> {
@BeforeTemplate
@SuppressWarnings("NestedOptionals")
Optional<T> before(Optional<T> optional, Comparator<? super T> comparator) {
return Refaster.anyOf(
optional.or(Refaster.anyOf(() -> Optional.empty(), Optional::empty)),
optional
.map(Optional::of)
.orElseGet(Refaster.anyOf(() -> Optional.empty(), Optional::empty)),
optional.stream().findFirst(),
optional.stream().findAny(),
optional.stream().min(comparator),
@@ -442,9 +461,7 @@ final class OptionalRules {
static final class OptionalStream<T> {
@BeforeTemplate
Stream<T> before(Optional<T> optional) {
return Refaster.anyOf(
optional.map(Stream::of).orElse(Stream.empty()),
optional.map(Stream::of).orElseGet(Stream::empty));
return optional.map(Stream::of).orElseGet(Stream::empty);
}
@AfterTemplate

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,72 +196,8 @@ 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. */
// XXX: Drop this rule once https://github.com/google/guava/pull/7371 is released.
static final class FloatCompare {
@BeforeTemplate
int before(float a, float b) {
@@ -271,6 +211,7 @@ final class PrimitiveRules {
}
/** Prefer {@link Double#compare(double, double)} over the Guava alternative. */
// XXX: Drop this rule once https://github.com/google/guava/pull/7371 is released.
static final class DoubleCompare {
@BeforeTemplate
int before(double a, double b) {
@@ -442,4 +383,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

@@ -3,7 +3,6 @@ package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.MoreCollectors.toOptional;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.reverseOrder;
@@ -14,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;
@@ -34,6 +34,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@@ -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;
@@ -52,7 +54,6 @@ import reactor.util.context.Context;
import reactor.util.function.Tuple2;
import tech.picnic.errorprone.refaster.annotation.Description;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
import tech.picnic.errorprone.refaster.annotation.Severity;
import tech.picnic.errorprone.refaster.matchers.IsEmpty;
import tech.picnic.errorprone.refaster.matchers.IsIdentityOperation;
import tech.picnic.errorprone.refaster.matchers.ThrowsCheckedException;
@@ -380,30 +381,23 @@ final class ReactorRules {
}
/**
* Prefer {@link Flux#take(long, boolean)} over {@link Flux#take(long)}.
* Prefer {@link Flux#take(long)} over {@link Flux#take(long, boolean)} where relevant.
*
* <p>In Reactor versions prior to 3.5.0, {@code Flux#take(long)} makes an unbounded request
* upstream, and is equivalent to {@code Flux#take(long, false)}. In 3.5.0, the behavior of {@code
* Flux#take(long)} will change to that of {@code Flux#take(long, true)}.
*
* <p>The intent with this Refaster rule is to get the new behavior before upgrading to Reactor
* 3.5.0.
* upstream, and is equivalent to {@code Flux#take(long, false)}. From version 3.5.0 onwards, the
* behavior of {@code Flux#take(long)} instead matches {@code Flux#take(long, true)}.
*/
// XXX: Drop this rule some time after upgrading to Reactor 3.6.0, or introduce a way to apply
// this rule only when an older version of Reactor is on the classpath.
// XXX: Once Reactor 3.6.0 is out, introduce a rule that rewrites code in the opposite direction.
@Description(
"Prior to Reactor 3.5.0, `take(n)` requests and unbounded number of elements upstream.")
@Severity(WARNING)
"From Reactor 3.5.0 onwards, `take(n)` no longer requests an unbounded number of elements upstream.")
static final class FluxTake<T> {
@BeforeTemplate
Flux<T> before(Flux<T> flux, long n) {
return flux.take(n);
return flux.take(n, /* limitRequest= */ true);
}
@AfterTemplate
Flux<T> after(Flux<T> flux, long n) {
return flux.take(n, /* limitRequest= */ true);
return flux.take(n);
}
}
@@ -489,15 +483,20 @@ final class ReactorRules {
}
/** Prefer {@link Flux#just(Object)} over more contrived alternatives. */
static final class FluxJust {
static final class FluxJust<T> {
@BeforeTemplate
Flux<Integer> before(int start) {
return Flux.range(start, 1);
Flux<Integer> before(int value) {
return Flux.range(value, 1);
}
@BeforeTemplate
Flux<T> before(T value) {
return Mono.just(value).repeat().take(1);
}
@AfterTemplate
Flux<Integer> after(int start) {
return Flux.just(start);
Flux<T> after(T value) {
return Flux.just(value);
}
}
@@ -566,6 +565,7 @@ final class ReactorRules {
@Matches(IsIdentityOperation.class)
Function<? super P, ? extends Publisher<? extends S>> identityOperation) {
return Refaster.anyOf(
flux.concatMap(function, 0),
flux.flatMap(function, 1),
flux.flatMapSequential(function, 1),
flux.map(function).concatMap(identityOperation));
@@ -1205,6 +1205,26 @@ 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(
Refaster.<Supplier<Stream<? extends T>>>anyOf(
collection::stream, () -> collection.stream()));
}
@AfterTemplate
Flux<T> after(Collection<T> collection) {
return Flux.fromIterable(collection);
}
}
/**
* Prefer {@link Flux#count()} followed by a conversion from {@code long} to {@code int} over
* collecting into a list and counting its elements.
@@ -1899,4 +1919,76 @@ final class ReactorRules {
return step.verifyTimeout(duration);
}
}
/**
* Prefer {@link Mono#fromFuture(Supplier)} over {@link Mono#fromFuture(CompletableFuture)}, as
* 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
// `IsIdentityOperation` no longer matches nullary method invocations.
@BeforeTemplate
Mono<T> before(CompletableFuture<T> future) {
return Mono.fromFuture(future);
}
@AfterTemplate
Mono<T> after(CompletableFuture<T> future) {
return Mono.fromFuture(() -> future);
}
}
/**
* Prefer {@link Mono#fromFuture(Supplier, boolean)} over {@link
* Mono#fromFuture(CompletableFuture, boolean)}, as the former may defer initiation of the
* asynchronous computation until subscription.
*/
static final class MonoFromFutureSupplierBoolean<T> {
// XXX: Constrain the `future` parameter using `@NotMatches(IsIdentityOperation.class)` once
// `IsIdentityOperation` no longer matches nullary method invocations.
@BeforeTemplate
Mono<T> before(CompletableFuture<T> future, boolean suppressCancel) {
return Mono.fromFuture(future, suppressCancel);
}
@AfterTemplate
Mono<T> after(CompletableFuture<T> future, boolean suppressCancel) {
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

@@ -4,6 +4,7 @@ import static com.google.errorprone.refaster.ImportPolicy.STATIC_IMPORT_ALWAYS;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.reverseOrder;
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.filtering;
import static java.util.stream.Collectors.flatMapping;
@@ -24,6 +25,7 @@ import com.google.common.collect.Streams;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
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.Matches;
import com.google.errorprone.refaster.annotation.MayOptionallyUse;
@@ -37,6 +39,7 @@ import java.util.Comparator;
import java.util.DoubleSummaryStatistics;
import java.util.IntSummaryStatistics;
import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BinaryOperator;
@@ -254,32 +257,38 @@ final class StreamRules {
// XXX: This rule assumes that any matched `Collector` does not perform any filtering.
// (Perhaps we could add a `@Matches` guard that validates that the collector expression does not
// contain a `Collectors#filtering` call. That'd still not be 100% accurate, though.)
static final class StreamIsEmpty<T> {
static final class StreamFindAnyIsEmpty<T, K, V, C extends Collection<K>, M extends Map<K, V>> {
@BeforeTemplate
boolean before(Stream<T> stream, Collector<? super T, ?, ? extends Collection<?>> collector) {
boolean before(Stream<T> stream, Collector<? super T, ?, ? extends C> collector) {
return Refaster.anyOf(
stream.count() == 0,
stream.count() <= 0,
stream.count() < 1,
stream.findFirst().isEmpty(),
stream.collect(collector).isEmpty());
stream.collect(collector).isEmpty(),
stream.collect(collectingAndThen(collector, C::isEmpty)));
}
@BeforeTemplate
boolean before2(Stream<T> stream, Collector<? super T, ?, ? extends M> collector) {
return stream.collect(collectingAndThen(collector, M::isEmpty));
}
@AfterTemplate
@AlsoNegation
boolean after(Stream<T> stream) {
return stream.findAny().isEmpty();
}
}
/** In order to test whether a stream has any element, simply try to find one. */
static final class StreamIsNotEmpty<T> {
/**
* Prefer {@link Stream#findAny()} over {@link Stream#findFirst()} if one only cares whether the
* stream is nonempty.
*/
static final class StreamFindAnyIsPresent<T> {
@BeforeTemplate
boolean before(Stream<T> stream) {
return Refaster.anyOf(
stream.count() != 0,
stream.count() > 0,
stream.count() >= 1,
stream.findFirst().isPresent());
return stream.findFirst().isPresent();
}
@AfterTemplate

View File

@@ -29,7 +29,9 @@ final class StringRules {
private StringRules() {}
/** Prefer {@link String#isEmpty()} over alternatives that consult the string's length. */
// XXX: Once we target JDK 15+, generalize this rule to cover all `CharSequence` subtypes.
// XXX: Now that we build with JDK 15+, this rule can be generalized to cover all `CharSequence`
// subtypes. This does require a mechanism (perhaps an annotation, or a separate Maven module) to
// make sure that non-String expressions are rewritten only if client code also targets JDK 15+.
static final class StringIsEmpty {
@BeforeTemplate
boolean before(String str) {
@@ -44,7 +46,9 @@ final class StringRules {
}
/** Prefer a method reference to {@link String#isEmpty()} over the equivalent lambda function. */
// XXX: Once we target JDK 15+, generalize this rule to cover all `CharSequence` subtypes.
// XXX: Now that we build with JDK 15+, this rule can be generalized to cover all `CharSequence`
// subtypes. However, `CharSequence::isEmpty` isn't as nice as `String::isEmpty`, so we might want
// to introduce a rule that suggests `String::isEmpty` where possible.
// XXX: As it stands, this rule is a special case of what `MethodReferenceUsage` tries to achieve.
// If/when `MethodReferenceUsage` becomes production ready, we should simply drop this check.
static final class StringIsEmptyPredicate {
@@ -60,7 +64,9 @@ final class StringRules {
}
/** Prefer a method reference to {@link String#isEmpty()} over the equivalent lambda function. */
// XXX: Once we target JDK 15+, generalize this rule to cover all `CharSequence` subtypes.
// XXX: Now that we build with JDK 15+, this rule can be generalized to cover all `CharSequence`
// subtypes. However, `CharSequence::isEmpty` isn't as nice as `String::isEmpty`, so we might want
// to introduce a rule that suggests `String::isEmpty` where possible.
static final class StringIsNotEmptyPredicate {
@BeforeTemplate
Predicate<String> before() {
@@ -162,6 +168,39 @@ final class StringRules {
}
}
/**
* Prefer direct invocation of {@link String#String(char[], int, int)} over the indirection
* introduced by alternatives.
*/
static final class NewStringFromCharArraySubSequence {
@BeforeTemplate
String before(char[] data, int offset, int count) {
return Refaster.anyOf(
String.valueOf(data, offset, count), String.copyValueOf(data, offset, count));
}
@AfterTemplate
String after(char[] data, int offset, int count) {
return new String(data, offset, count);
}
}
/**
* Prefer direct invocation of {@link String#String(char[])} over the indirection introduced by
* alternatives.
*/
static final class NewStringFromCharArray {
@BeforeTemplate
String before(char[] data) {
return Refaster.anyOf(String.valueOf(data), new String(data, 0, data.length));
}
@AfterTemplate
String after(char[] data) {
return new String(data);
}
}
/**
* Prefer direct delegation to {@link String#valueOf(Object)} over the indirection introduced by
* {@link Objects#toString(Object)}.
@@ -205,4 +244,11 @@ final class StringRules {
return Utf8.encodedLength(str);
}
}
// Rewrite `String#copyValueOf(char[])` to `new String(char[])`.
// Example:
// String.copyValueOf(new char[]);
// -->
// new String(new char[]);
}

View File

@@ -29,6 +29,7 @@ import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.testng.Assert;
import org.testng.Assert.ThrowingRunnable;
import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
import tech.picnic.errorprone.refaster.annotation.TypeMigration;
/**
* Refaster rules that replace TestNG assertions with equivalent AssertJ assertions.
@@ -48,32 +49,107 @@ import tech.picnic.errorprone.refaster.annotation.OnlineDocumentation;
* List<Map<String, Object>> myMaps = new ArrayList<>();
* assertEquals(myMaps, ImmutableList.of(ImmutableMap.of()));
* }</pre>
*
* <p>A few {@link Assert} methods are not rewritten:
*
* <ul>
* <li>These methods cannot (easily) be expressed using AssertJ because they mix regular equality
* and array equality:
* <ul>
* <li>{@link Assert#assertEqualsDeep(Map, Map)}
* <li>{@link Assert#assertEqualsDeep(Map, Map, String)}
* <li>{@link Assert#assertEqualsDeep(Set, Set, String)}
* <li>{@link Assert#assertNotEqualsDeep(Map, Map)}
* <li>{@link Assert#assertNotEqualsDeep(Map, Map, String)}
* <li>{@link Assert#assertNotEqualsDeep(Set, Set)}
* <li>{@link Assert#assertNotEqualsDeep(Set, Set, String)}
* </ul>
* <li>This method returns the caught exception; there is no direct counterpart for this in
* AssertJ:
* <ul>
* <li>{@link Assert#expectThrows(Class, ThrowingRunnable)}
* </ul>
* </ul>
*/
// XXX: As-is these rules do not result in a complete migration:
// - Expressions containing comments are skipped due to a limitation of Refaster.
// - Assertions inside lambda expressions are also skipped. Unclear why.
// XXX: The `assertEquals` tests for this class generally use the same expression for `expected` and
// `actual`, which makes the validation weaker than necessary; fix this. (And investigate whether we
// can introduce validation for this.)
@OnlineDocumentation
@TypeMigration(
of = Assert.class,
unmigratedMethods = {
// XXX: Add migrations for the methods below.
"assertEquals(Boolean, Boolean)",
"assertEquals(Boolean, boolean)",
"assertEquals(boolean, Boolean)",
"assertEquals(Boolean, Boolean, String)",
"assertEquals(Boolean, boolean, String)",
"assertEquals(boolean, Boolean, String)",
"assertEquals(Byte, Byte)",
"assertEquals(Byte, byte)",
"assertEquals(byte, Byte)",
"assertEquals(Byte, Byte, String)",
"assertEquals(Byte, byte, String)",
"assertEquals(byte, Byte, String)",
"assertEquals(char, Character)",
"assertEquals(char, Character, String)",
"assertEquals(Character, char)",
"assertEquals(Character, char, String)",
"assertEquals(Character, Character)",
"assertEquals(Character, Character, String)",
"assertEquals(Double, Double)",
"assertEquals(Double, double)",
"assertEquals(double, Double)",
"assertEquals(Double, Double, String)",
"assertEquals(Double, double, String)",
"assertEquals(double, Double, String)",
"assertEquals(double[], double[], double)",
"assertEquals(double[], double[], double, String)",
"assertEquals(Float, Float)",
"assertEquals(Float, float)",
"assertEquals(float, Float)",
"assertEquals(Float, Float, String)",
"assertEquals(Float, float, String)",
"assertEquals(float, Float, String)",
"assertEquals(float[], float[], float)",
"assertEquals(float[], float[], float, String)",
"assertEquals(int, Integer)",
"assertEquals(int, Integer, String)",
"assertEquals(Integer, int)",
"assertEquals(Integer, int, String)",
"assertEquals(Integer, Integer)",
"assertEquals(Integer, Integer, String)",
"assertEquals(Long, Long)",
"assertEquals(Long, long)",
"assertEquals(long, Long)",
"assertEquals(Long, Long, String)",
"assertEquals(Long, long, String)",
"assertEquals(Short, Short)",
"assertEquals(Short, short)",
"assertEquals(short, Short)",
"assertEquals(Short, Short, String)",
"assertEquals(Short, short, String)",
"assertEquals(short, Short, String)",
/*
* These `assertEqualsDeep` methods cannot (easily) be expressed using AssertJ because they
* mix regular equality and array equality:
*/
"assertEqualsDeep(Map<?, ?>, Map<?, ?>)",
"assertEqualsDeep(Map<?, ?>, Map<?, ?>, String)",
"assertEqualsDeep(Set<?>, Set<?>, String)",
// XXX: Add migrations for the methods below.
"assertEqualsNoOrder(Collection<?>, Collection<?>)",
"assertEqualsNoOrder(Collection<?>, Collection<?>, String)",
"assertEqualsNoOrder(Iterator<?>, Iterator<?>)",
"assertEqualsNoOrder(Iterator<?>, Iterator<?>, String)",
"assertListContains(List<T>, Predicate<T>, String)",
"assertListContainsObject(List<T>, T, String)",
"assertListNotContains(List<T>, Predicate<T>, String)",
"assertListNotContainsObject(List<T>, T, String)",
"assertNotEquals(Collection<?>, Collection<?>)",
"assertNotEquals(Collection<?>, Collection<?>, String)",
"assertNotEquals(Iterator<?>, Iterator<?>)",
"assertNotEquals(Iterator<?>, Iterator<?>, String)",
"assertNotEquals(Object[], Object[], String)",
/*
* These `assertNotEqualsDeep` methods cannot (easily) be expressed using AssertJ because they
* mix regular equality and array equality:
*/
"assertNotEqualsDeep(Map<?, ?>, Map<?, ?>)",
"assertNotEqualsDeep(Map<?, ?>, Map<?, ?>, String)",
"assertNotEqualsDeep(Set<?>, Set<?>)",
"assertNotEqualsDeep(Set<?>, Set<?>, String)",
// XXX: Add a migration for this `assertThrows` method.
"assertThrows(String, Class<T>, ThrowingRunnable)",
/*
* These `expectThrows` methods return the caught exception; there is no direct counterpart
* for this in AssertJ.
*/
"expectThrows(Class<T>, ThrowingRunnable)",
"expectThrows(String, Class<T>, ThrowingRunnable)"
})
final class TestNGToAssertJRules {
private TestNGToAssertJRules() {}
@@ -85,8 +161,9 @@ final class TestNGToAssertJRules {
@AfterTemplate
@DoNotCall
@UseImportPolicy(STATIC_IMPORT_ALWAYS)
void after() {
throw new AssertionError();
fail();
}
}

View File

@@ -0,0 +1,80 @@
package tech.picnic.errorprone.bugpatterns;
import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;
final class EmptyMonoZipTest {
@Test
void identification() {
CompilationTestHelper.newInstance(EmptyMonoZip.class, getClass())
.expectErrorMessage(
"ARGUMENT",
m ->
m.contains(
"Don't pass a `Mono<Void>` or `Mono.empty()` argument to `Mono#{zip,With}`"))
.expectErrorMessage(
"RECEIVER",
m ->
m.contains(
"Invoking `Mono#zipWith` on `Mono#empty()` or a `Mono<Void>` is a no-op"))
.addSourceLines(
"A.java",
"import static reactor.core.publisher.Mono.zip;",
"",
"import reactor.core.publisher.Flux;",
"import reactor.core.publisher.Mono;",
"",
"class A {",
" void m() {",
" Flux.just(1).zip(Mono.empty(), Flux.just(2));",
"",
" Mono<Void> voidMono = Mono.empty();",
" Mono<Integer> integerMono = Mono.empty();",
"",
" zip(Mono.just(1), Mono.just(2));",
" Mono.zip(Mono.just(1), Mono.just(2));",
" Mono.zip(Mono.just(1), Mono.just(2), Mono.just(3));",
" Mono.zip(integerMono, integerMono);",
"",
" // BUG: Diagnostic matches: ARGUMENT",
" zip(Mono.empty(), Mono.empty());",
" // BUG: Diagnostic matches: ARGUMENT",
" Mono.zip(Mono.empty(), Mono.empty());",
" // BUG: Diagnostic matches: ARGUMENT",
" Mono.zip(voidMono, Mono.just(1));",
" // BUG: Diagnostic matches: ARGUMENT",
" Mono.zip(voidMono, voidMono);",
" // BUG: Diagnostic matches: ARGUMENT",
" Mono.zip(Mono.just(1).then(), Mono.just(2));",
" // BUG: Diagnostic matches: ARGUMENT",
" Mono.zip(Mono.just(1), Mono.just(2), voidMono);",
"",
" Mono.just(1).zipWith(Mono.just(2));",
" Mono.just(1).zipWith(integerMono);",
" Mono.just(1).zipWith(integerMono, (a, b) -> a + b);",
"",
" // BUG: Diagnostic matches: ARGUMENT",
" Mono.just(1).zipWith(Mono.empty());",
" // BUG: Diagnostic matches: ARGUMENT",
" Mono.just(1).zipWith(voidMono);",
" // BUG: Diagnostic matches: RECEIVER",
" Mono.empty().zipWith(Mono.just(1));",
" // BUG: Diagnostic matches: RECEIVER",
" voidMono.zipWith(Mono.just(1));",
" }",
"",
" abstract class MyMono extends Mono<Object> {",
" void m() {",
" zip(Mono.just(1), Mono.just(2));",
" // BUG: Diagnostic matches: ARGUMENT",
" zip(Mono.empty(), Mono.empty());",
"",
" zipWith(Mono.just(1));",
" // BUG: Diagnostic matches: ARGUMENT",
" zipWith(Mono.empty());",
" }",
" }",
"}")
.doTest();
}
}

View File

@@ -0,0 +1,137 @@
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 OptionalOrElseGetTest {
@Test
void identification() {
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();",
" private final String string = optional.toString();",
"",
" void m() {",
" Optional.empty().orElse(null);",
" optional.orElse(null);",
" optional.orElse(\"constant\");",
" optional.orElse(\"constant\" + 0);",
" optional.orElse(Boolean.TRUE);",
" 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\");",
" // BUG: Diagnostic contains:",
" optional.orElse(string + \"constant\");",
" // BUG: Diagnostic contains:",
" optional.orElse(\"constant\".toString());",
" // BUG: Diagnostic contains:",
" optional.orElse(string.toString());",
" // BUG: Diagnostic contains:",
" optional.orElse(this.string.toString());",
" // BUG: Diagnostic contains:",
" optional.orElse(String.valueOf(42));",
" // BUG: Diagnostic contains:",
" optional.orElse(string.toString().length());",
" // BUG: Diagnostic contains:",
" optional.orElse(\"constant\".equals(string));",
" // BUG: Diagnostic contains:",
" optional.orElse(string.equals(string));",
" // BUG: Diagnostic contains:",
" optional.orElse(this.string.equals(string));",
" // BUG: Diagnostic contains:",
" optional.orElse(foo());",
" // BUG: Diagnostic contains:",
" optional.orElse(this.foo());",
" // BUG: Diagnostic contains:",
" optional.orElse(new Object() {});",
" // BUG: Diagnostic contains:",
" optional.orElse(new int[0].length);",
" }",
"",
" private <T> T foo() {",
" return null;",
" }",
"}")
.doTest();
}
@Test
void replacement() {
BugCheckerRefactoringTestHelper.newInstance(OptionalOrElseGet.class, getClass())
.addInputLines(
"A.java",
"import java.util.Optional;",
"",
"class A {",
" private final Optional<Object> optional = Optional.empty();",
" private final String string = optional.toString();",
"",
" void m() {",
" optional.orElse(string + \"constant\");",
" optional.orElse(\"constant\".toString());",
" optional.orElse(string.toString());",
" optional.orElse(this.string.toString());",
" optional.orElse(String.valueOf(42));",
" optional.orElse(string.toString().length());",
" optional.orElse(string.equals(string));",
" optional.orElse(foo());",
" optional.orElse(this.<Number>foo());",
" optional.orElse(this.<String, Integer>bar());",
" optional.orElse(new Object() {});",
" optional.orElse(new int[0].length);",
" }",
"",
" private <T> T foo() {",
" return null;",
" }",
"",
" private <S, T> T bar() {",
" return null;",
" }",
"}")
.addOutputLines(
"A.java",
"import java.util.Optional;",
"",
"class A {",
" private final Optional<Object> optional = Optional.empty();",
" private final String string = optional.toString();",
"",
" void m() {",
" optional.orElseGet(() -> string + \"constant\");",
" optional.orElseGet(\"constant\"::toString);",
" optional.orElseGet(string::toString);",
" optional.orElseGet(this.string::toString);",
" optional.orElseGet(() -> String.valueOf(42));",
" optional.orElseGet(() -> string.toString().length());",
" optional.orElseGet(() -> string.equals(string));",
" optional.orElseGet(() -> foo());",
" optional.orElseGet(this::<Number>foo);",
" optional.orElseGet(this::<String, Integer>bar);",
" optional.orElseGet(() -> new Object() {});",
" optional.orElseGet(() -> new int[0].length);",
" }",
"",
" private <T> T foo() {",
" return null;",
" }",
"",
" private <S, T> T bar() {",
" return null;",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -19,7 +19,6 @@ final class Slf4jLogStatementTest {
"class A {",
" private static final String FMT0 = \"format-string-without-placeholders\";",
" private static final String FMT1 = \"format-string-with-{}-placeholder\";",
" private static final String FMT2 = \"format-string-with-{}-{}-placeholders\";",
" private static final String FMT_ERR = \"format-string-with-%s-placeholder\";",
" private static final Logger LOG = LoggerFactory.getLogger(A.class);",
"",

View File

@@ -1,26 +1,34 @@
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> testClassLiteralCast() {
return i -> (Integer) i;
}
Function<Number, Integer> testClassReferenceCast() {
return i -> Integer.class.cast(i);
}
}

View File

@@ -1,26 +1,34 @@
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> testClassLiteralCast() {
return Integer.class::cast;
}
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;
@@ -29,7 +31,9 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
ImmutableSet.of(5).size() > 0,
ImmutableSet.of(6).size() >= 1,
Iterables.isEmpty(ImmutableSet.of(7)),
ImmutableSet.of(8).asList().isEmpty());
ImmutableSet.of(8).stream().findAny().isEmpty(),
ImmutableSet.of(9).stream().findFirst().isEmpty(),
ImmutableSet.of(10).asList().isEmpty());
}
ImmutableSet<Integer> testCollectionSize() {
@@ -68,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"));
}
@@ -92,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]),

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;
@@ -29,7 +31,9 @@ final class CollectionRulesTest implements RefasterRuleCollectionTestCase {
!ImmutableSet.of(5).isEmpty(),
!ImmutableSet.of(6).isEmpty(),
ImmutableSet.of(7).isEmpty(),
ImmutableSet.of(8).isEmpty());
ImmutableSet.of(8).isEmpty(),
ImmutableSet.of(9).isEmpty(),
ImmutableSet.of(10).isEmpty());
}
ImmutableSet<Integer> testCollectionSize() {
@@ -60,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"));
}
@@ -84,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());

View File

@@ -9,6 +9,7 @@ import static java.util.stream.Collectors.minBy;
import com.google.common.collect.Comparators;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
@@ -54,6 +55,10 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
Comparator.comparing(s -> "foo", Comparator.comparingInt(String::length)));
}
Comparator<String> testComparingEnum() {
return Comparator.comparingInt(s -> RoundingMode.valueOf(s).ordinal());
}
Comparator<String> testThenComparing() {
return Comparator.<String>naturalOrder().thenComparing(Comparator.comparing(String::isEmpty));
}
@@ -102,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();
}
@@ -130,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();
}
@@ -173,4 +210,16 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
Collector<Integer, ?, Optional<Integer>> testMaxByNaturalOrder() {
return minBy(reverseOrder());
}
ImmutableSet<Boolean> testIsLessThan() {
return ImmutableSet.of(
RoundingMode.UP.ordinal() < RoundingMode.DOWN.ordinal(),
RoundingMode.UP.ordinal() >= RoundingMode.DOWN.ordinal());
}
ImmutableSet<Boolean> testIsLessThanOrEqualTo() {
return ImmutableSet.of(
RoundingMode.UP.ordinal() <= RoundingMode.DOWN.ordinal(),
RoundingMode.UP.ordinal() > RoundingMode.DOWN.ordinal());
}
}

View File

@@ -1,5 +1,6 @@
package tech.picnic.errorprone.refasterrules;
import static java.util.Comparator.comparing;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.reverseOrder;
import static java.util.function.Function.identity;
@@ -9,6 +10,7 @@ import static java.util.stream.Collectors.minBy;
import com.google.common.collect.Comparators;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
@@ -52,6 +54,10 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
Comparator.comparing(s -> "foo", Comparator.comparingInt(String::length)));
}
Comparator<String> testComparingEnum() {
return comparing(s -> RoundingMode.valueOf(s));
}
Comparator<String> testThenComparing() {
return Comparator.<String>naturalOrder().thenComparing(String::isEmpty);
}
@@ -92,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());
}
@@ -120,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());
}
@@ -163,4 +199,16 @@ final class ComparatorRulesTest implements RefasterRuleCollectionTestCase {
Collector<Integer, ?, Optional<Integer>> testMaxByNaturalOrder() {
return maxBy(naturalOrder());
}
ImmutableSet<Boolean> testIsLessThan() {
return ImmutableSet.of(
RoundingMode.UP.compareTo(RoundingMode.DOWN) < 0,
RoundingMode.UP.compareTo(RoundingMode.DOWN) >= 0);
}
ImmutableSet<Boolean> testIsLessThanOrEqualTo() {
return ImmutableSet.of(
RoundingMode.UP.compareTo(RoundingMode.DOWN) <= 0,
RoundingMode.UP.compareTo(RoundingMode.DOWN) > 0);
}
}

View File

@@ -1,5 +1,6 @@
package tech.picnic.errorprone.refasterrules;
import static java.util.function.Predicate.isEqual;
import static java.util.function.Predicate.not;
import com.google.common.collect.BoundType;
@@ -14,15 +15,21 @@ import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class EqualityRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(Objects.class, Optional.class, not(null));
return ImmutableSet.of(Objects.class, Optional.class, isEqual(null), not(null));
}
ImmutableSet<Boolean> testPrimitiveOrReferenceEquality() {
ImmutableSet<Boolean> testEnumReferenceEquality() {
return ImmutableSet.of(
RoundingMode.UP.equals(RoundingMode.DOWN),
Objects.equals(RoundingMode.UP, RoundingMode.DOWN),
RoundingMode.UP.ordinal() == RoundingMode.DOWN.ordinal(),
!RoundingMode.UP.equals(RoundingMode.DOWN),
!Objects.equals(RoundingMode.UP, RoundingMode.DOWN));
!Objects.equals(RoundingMode.UP, RoundingMode.DOWN),
RoundingMode.UP.ordinal() != RoundingMode.DOWN.ordinal());
}
ImmutableSet<Predicate<RoundingMode>> testEnumReferenceEqualityLambda() {
return ImmutableSet.of(isEqual(RoundingMode.DOWN), RoundingMode.UP::equals);
}
boolean testEqualsPredicate() {

View File

@@ -1,5 +1,6 @@
package tech.picnic.errorprone.refasterrules;
import static java.util.function.Predicate.isEqual;
import static java.util.function.Predicate.not;
import com.google.common.collect.BoundType;
@@ -14,17 +15,23 @@ import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
final class EqualityRulesTest implements RefasterRuleCollectionTestCase {
@Override
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(Objects.class, Optional.class, not(null));
return ImmutableSet.of(Objects.class, Optional.class, isEqual(null), not(null));
}
ImmutableSet<Boolean> testPrimitiveOrReferenceEquality() {
ImmutableSet<Boolean> testEnumReferenceEquality() {
return ImmutableSet.of(
RoundingMode.UP == RoundingMode.DOWN,
RoundingMode.UP == RoundingMode.DOWN,
RoundingMode.UP == RoundingMode.DOWN,
RoundingMode.UP != RoundingMode.DOWN,
RoundingMode.UP != RoundingMode.DOWN,
RoundingMode.UP != RoundingMode.DOWN);
}
ImmutableSet<Predicate<RoundingMode>> testEnumReferenceEqualityLambda() {
return ImmutableSet.of(v -> v == RoundingMode.DOWN, v -> v == RoundingMode.UP);
}
boolean testEqualsPredicate() {
// XXX: When boxing is involved this rule seems to break. Example:
// Stream.of(1).anyMatch(e -> Integer.MIN_VALUE.equals(e));

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

@@ -20,4 +20,12 @@ final class InputStreamRulesTest implements RefasterRuleCollectionTestCase {
byte[] testInputStreamReadAllBytes() throws IOException {
return ByteStreams.toByteArray(new ByteArrayInputStream(new byte[0]));
}
byte[] testInputStreamReadNBytes() throws IOException {
return ByteStreams.limit(new ByteArrayInputStream(new byte[0]), 0).readAllBytes();
}
void testInputStreamSkipNBytes() throws IOException {
ByteStreams.skipFully(new ByteArrayInputStream(new byte[0]), 0);
}
}

View File

@@ -20,4 +20,12 @@ final class InputStreamRulesTest implements RefasterRuleCollectionTestCase {
byte[] testInputStreamReadAllBytes() throws IOException {
return new ByteArrayInputStream(new byte[0]).readAllBytes();
}
byte[] testInputStreamReadNBytes() throws IOException {
return new ByteArrayInputStream(new byte[0]).readNBytes(0);
}
void testInputStreamSkipNBytes() throws IOException {
new ByteArrayInputStream(new byte[0]).skipNBytes(0);
}
}

View File

@@ -32,8 +32,8 @@ final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
(Runnable) () -> assertTrue(true));
}
void testThrowNewAssertionError() {
Assertions.fail();
Object testFail() {
return Assertions.fail();
}
Object testFailWithMessage() {
@@ -44,8 +44,8 @@ final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
return Assertions.fail("foo", new IllegalStateException());
}
void testFailWithThrowable() {
Assertions.fail(new IllegalStateException());
Object testFailWithThrowable() {
return Assertions.fail(new IllegalStateException());
}
void testAssertThatIsTrue() {

View File

@@ -35,8 +35,8 @@ final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
(Runnable) () -> assertTrue(true));
}
void testThrowNewAssertionError() {
throw new AssertionError();
Object testFail() {
return org.assertj.core.api.Assertions.fail();
}
Object testFailWithMessage() {
@@ -47,8 +47,8 @@ final class JUnitToAssertJRulesTest implements RefasterRuleCollectionTestCase {
return org.assertj.core.api.Assertions.fail("foo", new IllegalStateException());
}
void testFailWithThrowable() {
throw new AssertionError(new IllegalStateException());
Object testFailWithThrowable() {
return org.assertj.core.api.Assertions.fail(new IllegalStateException());
}
void testAssertThatIsTrue() {

View File

@@ -13,6 +13,10 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(Streams.class);
}
Optional<String> testOptionalEmpty() {
return Optional.ofNullable(null);
}
ImmutableSet<Optional<String>> testOptionalOfNullable() {
return ImmutableSet.of(
toString() == null ? Optional.empty() : Optional.of(toString()),
@@ -79,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() {
@@ -120,10 +122,12 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(
Optional.of("foo").or(() -> Optional.empty()),
Optional.of("bar").or(Optional::empty),
Optional.of("baz").stream().findFirst(),
Optional.of("qux").stream().findAny(),
Optional.of("quux").stream().min(String::compareTo),
Optional.of("quuz").stream().max(String::compareTo));
Optional.of("baz").map(Optional::of).orElseGet(() -> Optional.empty()),
Optional.of("qux").map(Optional::of).orElseGet(Optional::empty),
Optional.of("quux").stream().findFirst(),
Optional.of("quuz").stream().findAny(),
Optional.of("corge").stream().min(String::compareTo),
Optional.of("grault").stream().max(String::compareTo));
}
ImmutableSet<Optional<String>> testOptionalFilter() {
@@ -136,9 +140,7 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
return Optional.of(1).stream().map(String::valueOf).findAny();
}
ImmutableSet<Stream<String>> testOptionalStream() {
return ImmutableSet.of(
Optional.of("foo").map(Stream::of).orElse(Stream.empty()),
Optional.of("bar").map(Stream::of).orElseGet(Stream::empty));
Stream<String> testOptionalStream() {
return Optional.of("foo").map(Stream::of).orElseGet(Stream::empty);
}
}

View File

@@ -15,6 +15,10 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
return ImmutableSet.of(Streams.class);
}
Optional<String> testOptionalEmpty() {
return Optional.empty();
}
ImmutableSet<Optional<String>> testOptionalOfNullable() {
return ImmutableSet.of(Optional.ofNullable(toString()), Optional.ofNullable(toString()));
}
@@ -76,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() {
@@ -120,7 +122,9 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
Optional.of("baz"),
Optional.of("qux"),
Optional.of("quux"),
Optional.of("quuz"));
Optional.of("quuz"),
Optional.of("corge"),
Optional.of("grault"));
}
ImmutableSet<Optional<String>> testOptionalFilter() {
@@ -132,7 +136,7 @@ final class OptionalRulesTest implements RefasterRuleCollectionTestCase {
return Optional.of(1).map(String::valueOf);
}
ImmutableSet<Stream<String>> testOptionalStream() {
return ImmutableSet.of(Optional.of("foo").stream(), Optional.of("bar").stream());
Stream<String> testOptionalStream() {
return Optional.of("foo").stream();
}
}

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,26 +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);
}
@@ -190,4 +174,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,26 +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);
}
@@ -190,4 +174,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;
@@ -21,7 +22,9 @@ import java.util.HashMap;
import java.util.List;
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;
@@ -142,7 +145,7 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
}
Flux<Integer> testFluxTake() {
return Flux.just(1, 2, 3).take(1);
return Flux.just(1, 2, 3).take(1, true);
}
Mono<String> testMonoDefaultIfEmpty() {
@@ -182,8 +185,8 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Flux.range(0, 0));
}
Flux<Integer> testFluxJust() {
return Flux.range(0, 1);
ImmutableSet<Flux<Integer>> testFluxJust() {
return ImmutableSet.of(Flux.range(0, 1), Mono.just(2).repeat().take(1));
}
ImmutableSet<Mono<?>> testMonoIdentity() {
@@ -207,11 +210,12 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
ImmutableSet<Flux<Integer>> testFluxConcatMap() {
return ImmutableSet.of(
Flux.just(1).flatMap(Mono::just, 1),
Flux.just(2).flatMapSequential(Mono::just, 1),
Flux.just(3).map(Mono::just).concatMap(identity()),
Flux.just(4).map(Mono::just).concatMap(v -> v),
Flux.just(5).map(Mono::just).concatMap(v -> Mono.empty()));
Flux.just(1).concatMap(Mono::just, 0),
Flux.just(2).flatMap(Mono::just, 1),
Flux.just(3).flatMapSequential(Mono::just, 1),
Flux.just(4).map(Mono::just).concatMap(identity()),
Flux.just(5).map(Mono::just).concatMap(v -> v),
Flux.just(6).map(Mono::just).concatMap(v -> Mono.empty()));
}
ImmutableSet<Flux<Integer>> testFluxConcatMapWithPrefetch() {
@@ -432,6 +436,12 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Flux.just(ImmutableList.of("bar")).concatMap(Flux::fromIterable, 2));
}
ImmutableSet<Flux<String>> testFluxFromIterable() {
return ImmutableSet.of(
Flux.fromStream(ImmutableList.of("foo")::stream),
Flux.fromStream(() -> ImmutableList.of("bar").stream()));
}
ImmutableSet<Mono<Integer>> testFluxCountMapMathToIntExact() {
return ImmutableSet.of(
Flux.just(1).collect(toImmutableList()).map(Collection::size),
@@ -646,4 +656,20 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Duration testStepVerifierLastStepVerifyTimeout() {
return Mono.empty().as(StepVerifier::create).expectTimeout(Duration.ZERO).verify();
}
Mono<Void> testMonoFromFutureSupplier() {
return Mono.fromFuture(CompletableFuture.completedFuture(null));
}
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;
@@ -23,7 +24,9 @@ import java.util.HashMap;
import java.util.List;
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;
@@ -147,7 +150,7 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
}
Flux<Integer> testFluxTake() {
return Flux.just(1, 2, 3).take(1, true);
return Flux.just(1, 2, 3).take(1);
}
Mono<String> testMonoDefaultIfEmpty() {
@@ -186,8 +189,8 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Flux.empty());
}
Flux<Integer> testFluxJust() {
return Flux.just(0);
ImmutableSet<Flux<Integer>> testFluxJust() {
return ImmutableSet.of(Flux.just(0), Flux.just(2));
}
ImmutableSet<Mono<?>> testMonoIdentity() {
@@ -214,7 +217,8 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Flux.just(2).concatMap(Mono::just),
Flux.just(3).concatMap(Mono::just),
Flux.just(4).concatMap(Mono::just),
Flux.just(5).map(Mono::just).concatMap(v -> Mono.empty()));
Flux.just(5).concatMap(Mono::just),
Flux.just(6).map(Mono::just).concatMap(v -> Mono.empty()));
}
ImmutableSet<Flux<Integer>> testFluxConcatMapWithPrefetch() {
@@ -427,6 +431,11 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Flux.just(ImmutableList.of("bar")).concatMapIterable(identity(), 2));
}
ImmutableSet<Flux<String>> testFluxFromIterable() {
return ImmutableSet.of(
Flux.fromIterable(ImmutableList.of("foo")), Flux.fromIterable(ImmutableList.of("bar")));
}
ImmutableSet<Mono<Integer>> testFluxCountMapMathToIntExact() {
return ImmutableSet.of(
Flux.just(1).count().map(Math::toIntExact),
@@ -627,4 +636,20 @@ final class ReactorRulesTest implements RefasterRuleCollectionTestCase {
Duration testStepVerifierLastStepVerifyTimeout() {
return Mono.empty().as(StepVerifier::create).verifyTimeout(Duration.ZERO);
}
Mono<Void> testMonoFromFutureSupplier() {
return Mono.fromFuture(() -> CompletableFuture.completedFuture(null));
}
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

@@ -1,10 +1,13 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.Comparator.comparingInt;
import static java.util.Comparator.reverseOrder;
import static java.util.function.Function.identity;
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.filtering;
import static java.util.stream.Collectors.flatMapping;
@@ -21,11 +24,14 @@ import static java.util.stream.Collectors.summingInt;
import static java.util.stream.Collectors.summingLong;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import java.util.DoubleSummaryStatistics;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
@@ -38,8 +44,12 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase {
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(
ImmutableList.class,
ImmutableMap.class,
List.class,
Map.class,
Objects.class,
Streams.class,
collectingAndThen(null, null),
counting(),
filtering(null, null),
flatMapping(null, null),
@@ -54,7 +64,9 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase {
summarizingLong(null),
summingDouble(null),
summingInt(null),
summingLong(null));
summingLong(null),
toImmutableList(),
toImmutableMap(null, null));
}
String testJoining() {
@@ -108,21 +120,25 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase {
Stream.of("bar").map(String::length).findFirst());
}
ImmutableSet<Boolean> testStreamIsEmpty() {
ImmutableSet<Boolean> testStreamFindAnyIsEmpty() {
return ImmutableSet.of(
Stream.of(1).count() == 0,
Stream.of(2).count() <= 0,
Stream.of(3).count() < 1,
Stream.of(4).findFirst().isEmpty(),
Stream.of(5).collect(toImmutableSet()).isEmpty());
Stream.of(5).collect(toImmutableSet()).isEmpty(),
Stream.of(6).collect(collectingAndThen(toImmutableList(), List::isEmpty)),
Stream.of(7).collect(collectingAndThen(toImmutableList(), ImmutableList::isEmpty)),
Stream.of(8).collect(collectingAndThen(toImmutableMap(k -> k, v -> v), Map::isEmpty)),
Stream.of(9)
.collect(collectingAndThen(toImmutableMap(k -> k, v -> v), ImmutableMap::isEmpty)),
Stream.of(10).count() != 0,
Stream.of(11).count() > 0,
Stream.of(12).count() >= 1);
}
ImmutableSet<Boolean> testStreamIsNotEmpty() {
return ImmutableSet.of(
Stream.of(1).count() != 0,
Stream.of(2).count() > 0,
Stream.of(3).count() >= 1,
Stream.of(4).findFirst().isPresent());
boolean testStreamFindAnyIsPresent() {
return Stream.of(1).findFirst().isPresent();
}
ImmutableSet<Optional<String>> testStreamMin() {

View File

@@ -1,11 +1,14 @@
package tech.picnic.errorprone.refasterrules;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.Comparator.comparingInt;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.reverseOrder;
import static java.util.function.Function.identity;
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.filtering;
import static java.util.stream.Collectors.flatMapping;
@@ -22,12 +25,15 @@ import static java.util.stream.Collectors.summingInt;
import static java.util.stream.Collectors.summingLong;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
@@ -40,8 +46,12 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase {
public ImmutableSet<Object> elidedTypesAndStaticImports() {
return ImmutableSet.of(
ImmutableList.class,
ImmutableMap.class,
List.class,
Map.class,
Objects.class,
Streams.class,
collectingAndThen(null, null),
counting(),
filtering(null, null),
flatMapping(null, null),
@@ -56,7 +66,9 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase {
summarizingLong(null),
summingDouble(null),
summingInt(null),
summingLong(null));
summingLong(null),
toImmutableList(),
toImmutableMap(null, null));
}
String testJoining() {
@@ -109,21 +121,24 @@ final class StreamRulesTest implements RefasterRuleCollectionTestCase {
Stream.of("bar").findFirst().map(String::length));
}
ImmutableSet<Boolean> testStreamIsEmpty() {
ImmutableSet<Boolean> testStreamFindAnyIsEmpty() {
return ImmutableSet.of(
Stream.of(1).findAny().isEmpty(),
Stream.of(2).findAny().isEmpty(),
Stream.of(3).findAny().isEmpty(),
Stream.of(4).findAny().isEmpty(),
Stream.of(5).findAny().isEmpty());
Stream.of(5).findAny().isEmpty(),
Stream.of(6).findAny().isEmpty(),
Stream.of(7).findAny().isEmpty(),
Stream.of(8).findAny().isEmpty(),
Stream.of(9).findAny().isEmpty(),
!Stream.of(10).findAny().isEmpty(),
!Stream.of(11).findAny().isEmpty(),
!Stream.of(12).findAny().isEmpty());
}
ImmutableSet<Boolean> testStreamIsNotEmpty() {
return ImmutableSet.of(
Stream.of(1).findAny().isPresent(),
Stream.of(2).findAny().isPresent(),
Stream.of(3).findAny().isPresent(),
Stream.of(4).findAny().isPresent());
boolean testStreamFindAnyIsPresent() {
return Stream.of(1).findAny().isPresent();
}
ImmutableSet<Optional<String>> testStreamMin() {

View File

@@ -73,6 +73,18 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
return Objects.toString("foo");
}
ImmutableSet<String> testNewStringFromCharArraySubSequence() {
return ImmutableSet.of(
String.valueOf(new char[] {'f', 'o', 'o'}, 0, 1),
String.copyValueOf(new char[] {'b', 'a', 'r'}, 2, 3));
}
ImmutableSet<String> testNewStringFromCharArray() {
return ImmutableSet.of(
String.valueOf(new char[] {'f', 'o', 'o'}),
new String(new char[] {'b', 'a', 'r'}, 0, new char[] {'b', 'a', 'r'}.length));
}
Function<Object, String> testStringValueOfMethodReference() {
return Objects::toString;
}
@@ -84,4 +96,8 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
int testUtf8EncodedLength() {
return "foo".getBytes(UTF_8).length;
}
String testNewStringChar() {
return String.copyValueOf(new char[] {'f', 'o', 'o'});
}
}

View File

@@ -75,6 +75,16 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
return String.valueOf("foo");
}
ImmutableSet<String> testNewStringFromCharArraySubSequence() {
return ImmutableSet.of(
new String(new char[] {'f', 'o', 'o'}, 0, 1), new String(new char[] {'b', 'a', 'r'}, 2, 3));
}
ImmutableSet<String> testNewStringFromCharArray() {
return ImmutableSet.of(
new String(new char[] {'f', 'o', 'o'}), new String(new char[] {'b', 'a', 'r'}));
}
Function<Object, String> testStringValueOfMethodReference() {
return String::valueOf;
}
@@ -86,4 +96,8 @@ final class StringRulesTest implements RefasterRuleCollectionTestCase {
int testUtf8EncodedLength() {
return Utf8.encodedLength("foo");
}
String testNewStringChar() {
return new String(new char[] {'f', 'o', 'o'});
}
}

View File

@@ -41,7 +41,7 @@ final class TestNGToAssertJRulesTest implements RefasterRuleCollectionTestCase {
}
void testFail() {
throw new AssertionError();
fail();
}
void testFailWithMessage() {

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.14.1-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>
<artifactId>error-prone-experimental</artifactId>
@@ -20,6 +20,11 @@
<artifactId>error_prone_annotation</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${groupId.error-prone}</groupId>
<artifactId>error_prone_annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${groupId.error-prone}</groupId>
<artifactId>error_prone_check_api</artifactId>
@@ -45,6 +50,11 @@
<artifactId>guava</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>

View File

@@ -27,7 +27,6 @@ import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.ParenthesizedTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
@@ -84,22 +83,19 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
.orElse(Description.NO_MATCH);
}
// XXX: Use switch pattern matching once the targeted JDK supports this.
private static Optional<SuggestedFix.Builder> constructMethodRef(
LambdaExpressionTree lambdaExpr, Tree subTree) {
switch (subTree.getKind()) {
case BLOCK:
return constructMethodRef(lambdaExpr, (BlockTree) subTree);
case EXPRESSION_STATEMENT:
return constructMethodRef(lambdaExpr, ((ExpressionStatementTree) subTree).getExpression());
case METHOD_INVOCATION:
return constructMethodRef(lambdaExpr, (MethodInvocationTree) subTree);
case PARENTHESIZED:
return constructMethodRef(lambdaExpr, ((ParenthesizedTree) subTree).getExpression());
case RETURN:
return constructMethodRef(lambdaExpr, ((ReturnTree) subTree).getExpression());
default:
return Optional.empty();
}
return switch (subTree.getKind()) {
case BLOCK -> constructMethodRef(lambdaExpr, (BlockTree) subTree);
case EXPRESSION_STATEMENT ->
constructMethodRef(lambdaExpr, ((ExpressionStatementTree) subTree).getExpression());
case METHOD_INVOCATION -> constructMethodRef(lambdaExpr, (MethodInvocationTree) subTree);
case PARENTHESIZED ->
constructMethodRef(lambdaExpr, ((ParenthesizedTree) subTree).getExpression());
case RETURN -> constructMethodRef(lambdaExpr, ((ReturnTree) subTree).getExpression());
default -> Optional.empty();
};
}
private static Optional<SuggestedFix.Builder> constructMethodRef(
@@ -117,33 +113,35 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
.flatMap(expectedInstance -> constructMethodRef(lambdaExpr, subTree, expectedInstance));
}
@SuppressWarnings(
"java:S1151" /* Extracting `IDENTIFIER` case block to separate method does not improve readability. */)
// XXX: Review whether to use switch pattern matching once the targeted JDK supports this.
private static Optional<SuggestedFix.Builder> constructMethodRef(
LambdaExpressionTree lambdaExpr,
MethodInvocationTree subTree,
Optional<Name> expectedInstance) {
ExpressionTree methodSelect = subTree.getMethodSelect();
switch (methodSelect.getKind()) {
case IDENTIFIER:
if (expectedInstance.isPresent()) {
/* Direct method call; there is no matching "implicit parameter". */
return Optional.empty();
}
Symbol sym = ASTHelpers.getSymbol(methodSelect);
return ASTHelpers.isStatic(sym)
? constructFix(lambdaExpr, sym.owner, methodSelect)
: constructFix(lambdaExpr, "this", methodSelect);
case MEMBER_SELECT:
return constructMethodRef(lambdaExpr, (MemberSelectTree) methodSelect, expectedInstance);
default:
throw new VerifyException("Unexpected type of expression: " + methodSelect.getKind());
if (methodSelect instanceof IdentifierTree) {
if (expectedInstance.isPresent()) {
/* Direct method call; there is no matching "implicit parameter". */
return Optional.empty();
}
Symbol sym = ASTHelpers.getSymbol(methodSelect);
return ASTHelpers.isStatic(sym)
? constructFix(lambdaExpr, sym.owner, methodSelect)
: constructFix(lambdaExpr, "this", methodSelect);
}
if (methodSelect instanceof MemberSelectTree memberSelect) {
return constructMethodRef(lambdaExpr, memberSelect, expectedInstance);
}
throw new VerifyException("Unexpected type of expression: " + methodSelect.getKind());
}
private static Optional<SuggestedFix.Builder> constructMethodRef(
LambdaExpressionTree lambdaExpr, MemberSelectTree subTree, Optional<Name> expectedInstance) {
if (subTree.getExpression().getKind() != Kind.IDENTIFIER) {
if (!(subTree.getExpression() instanceof IdentifierTree identifier)) {
// XXX: Could be parenthesized. Handle. Also in other classes.
/*
* Only suggest a replacement if the method select's expression provably doesn't have
@@ -152,12 +150,12 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
return Optional.empty();
}
Name lhs = ((IdentifierTree) subTree.getExpression()).getName();
Name lhs = identifier.getName();
if (expectedInstance.isEmpty()) {
return constructFix(lambdaExpr, lhs, subTree.getIdentifier());
}
Type lhsType = ASTHelpers.getType(subTree.getExpression());
Type lhsType = ASTHelpers.getType(identifier);
if (lhsType == null || !expectedInstance.orElseThrow().equals(lhs)) {
return Optional.empty();
}
@@ -182,8 +180,8 @@ public final class MethodReferenceUsage extends BugChecker implements LambdaExpr
for (int i = 0; i < args.size(); i++) {
ExpressionTree arg = args.get(i);
if (arg.getKind() != Kind.IDENTIFIER
|| !((IdentifierTree) arg).getName().equals(expectedArguments.get(i + diff))) {
if (!(arg instanceof IdentifierTree identifier)
|| !identifier.getName().equals(expectedArguments.get(i + diff))) {
return Optional.empty();
}
}

View File

@@ -0,0 +1,4 @@
/** Experimental Error Prone checks. */
@com.google.errorprone.annotations.CheckReturnValue
@org.jspecify.annotations.NullMarked
package tech.picnic.errorprone.experimental.bugpatterns;

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.14.1-SNAPSHOT</version>
<version>0.18.1-SNAPSHOT</version>
</parent>
<artifactId>error-prone-guidelines</artifactId>
@@ -53,6 +53,16 @@
<artifactId>error-prone-utils</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-support</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.auto</groupId>
<artifactId>auto-common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service-annotations</artifactId>

View File

@@ -0,0 +1,140 @@
package tech.picnic.errorprone.guidelines.bugpatterns;
import static com.google.common.base.Verify.verify;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
import static com.google.errorprone.matchers.FieldMatchers.staticField;
import static com.google.errorprone.matchers.Matchers.annotations;
import static com.google.errorprone.matchers.Matchers.isType;
import static com.google.errorprone.matchers.Matchers.packageStartsWith;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.AnnotationMatcherUtils;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.matchers.MultiMatcher;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.util.Constants;
import javax.lang.model.element.Name;
/**
* A {@link BugChecker} that flags {@link BugChecker} declarations inside {@code
* tech.picnic.errorprone.*} packages that do not reference the Error Prone Support website.
*/
// XXX: Introduce a similar check to enforce the Refaster `@OnlineDocumentation` annotation. (Or
// update the website generation to document Refaster collections by default, and provide an
// exclusion annotation instead. This may make more sense.)
@AutoService(BugChecker.class)
@BugPattern(
summary = "Error Prone Support checks must reference their online documentation",
link = BUG_PATTERNS_BASE_URL + "BugPatternLink",
linkType = CUSTOM,
severity = SUGGESTION,
tags = LIKELY_ERROR)
public final class BugPatternLink extends BugChecker implements ClassTreeMatcher {
private static final long serialVersionUID = 1L;
private static final Matcher<ClassTree> IS_ERROR_PRONE_SUPPORT_CLASS =
packageStartsWith("tech.picnic.errorprone");
private static final Matcher<ExpressionTree> IS_LINK_TYPE_NONE =
staticField(BugPattern.LinkType.class.getCanonicalName(), "NONE");
private static final Matcher<ExpressionTree> IS_BUG_PATTERNS_BASE_URL =
staticField("tech.picnic.errorprone.utils.Documentation", "BUG_PATTERNS_BASE_URL");
private static final MultiMatcher<ClassTree, AnnotationTree> HAS_BUG_PATTERN_ANNOTATION =
annotations(AT_LEAST_ONE, isType(BugPattern.class.getCanonicalName()));
/** Instantiates a new {@link BugPatternLink} instance. */
public BugPatternLink() {}
@Override
public Description matchClass(ClassTree tree, VisitorState state) {
if (ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class) != null) {
/*
* This is a nested class; even if it's bug checker, then it's likely declared within a test
* class.
*/
return Description.NO_MATCH;
}
if (!IS_ERROR_PRONE_SUPPORT_CLASS.matches(tree, state)) {
/*
* Bug checkers defined elsewhere are unlikely to be documented on the Error Prone Support
* website.
*/
return Description.NO_MATCH;
}
ImmutableList<AnnotationTree> bugPatternAnnotations =
HAS_BUG_PATTERN_ANNOTATION.multiMatchResult(tree, state).matchingNodes();
if (bugPatternAnnotations.isEmpty()) {
/* This isn't a bug checker. */
return Description.NO_MATCH;
}
AnnotationTree annotation = Iterables.getOnlyElement(bugPatternAnnotations);
if (isCompliant(annotation, tree.getSimpleName(), state)) {
/* The bug checker is correctly configured. */
return Description.NO_MATCH;
}
return describeMatch(annotation, suggestFix(tree, state, annotation));
}
private static boolean isCompliant(
AnnotationTree annotation, Name className, VisitorState state) {
ExpressionTree linkType = AnnotationMatcherUtils.getArgument(annotation, "linkType");
if (IS_LINK_TYPE_NONE.matches(linkType, state)) {
/* This bug checker explicitly declares that there is no link. */
return true;
}
ExpressionTree link = AnnotationMatcherUtils.getArgument(annotation, "link");
if (!(link instanceof BinaryTree binary)) {
return false;
}
verify(binary.getKind() == Kind.PLUS, "Unexpected binary operator");
return IS_BUG_PATTERNS_BASE_URL.matches(binary.getLeftOperand(), state)
&& className.contentEquals(ASTHelpers.constValue(binary.getRightOperand(), String.class));
}
private static SuggestedFix suggestFix(
ClassTree tree, VisitorState state, AnnotationTree annotation) {
SuggestedFix.Builder fix = SuggestedFix.builder();
String linkPrefix =
SuggestedFixes.qualifyStaticImport(
"tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL", fix, state);
fix.merge(
SuggestedFixes.updateAnnotationArgumentValues(
annotation,
state,
"link",
ImmutableList.of(
linkPrefix + " + " + Constants.format(tree.getSimpleName().toString()))));
String linkType =
SuggestedFixes.qualifyStaticImport(
BugPattern.LinkType.class.getCanonicalName() + ".CUSTOM", fix, state);
fix.merge(
SuggestedFixes.updateAnnotationArgumentValues(
annotation, state, "linkType", ImmutableList.of(linkType)));
return fix.build();
}
}

View File

@@ -50,8 +50,9 @@ import tech.picnic.errorprone.utils.ThirdPartyLibrary;
@AutoService(BugChecker.class)
@BugPattern(
summary =
"Prefer `Class#getCanonicalName()` over an equivalent string literal if and only if the "
+ "type will be on the runtime classpath",
"""
Prefer `Class#getCanonicalName()` over an equivalent string literal if and only if the \
type will be on the runtime classpath""",
link = BUG_PATTERNS_BASE_URL + "ErrorProneRuntimeClasspath",
linkType = CUSTOM,
severity = SUGGESTION,

View File

@@ -0,0 +1,232 @@
package tech.picnic.errorprone.guidelines.bugpatterns;
import static com.google.common.base.Verify.verify;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.errorprone.BugPattern.LinkType.CUSTOM;
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
import static com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR;
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
import static com.google.errorprone.matchers.Matchers.annotations;
import static com.google.errorprone.matchers.Matchers.isType;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toCollection;
import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;
import com.google.auto.common.AnnotationMirrors;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
import com.google.errorprone.fixes.SuggestedFixes;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.matchers.MultiMatcher;
import com.google.errorprone.matchers.MultiMatcher.MultiMatchResult;
import com.google.errorprone.refaster.annotation.BeforeTemplate;
import com.google.errorprone.util.ASTHelpers;
import com.google.errorprone.util.Signatures;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.util.Constants;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Modifier;
import org.jspecify.annotations.Nullable;
/**
* A {@link BugChecker} that validates the claim made by {@link
* tech.picnic.errorprone.refaster.annotation.TypeMigration} annotations.
*/
// XXX: As-is this checker assumes that a method is fully migrated if it is invoked inside at least
// one `@BeforeTemplate` method. A stronger check would be to additionally verify that:
// 1. Such invocations are not conditionally matched. That is, there should be no constraint on
// their context (i.e. any surrounding code), and their parameters must be `@BeforeTemplate`
// method parameters with types that are not more restrictive than those of the method itself.
// Additionally, the result of non-void methods should be "returned" by the `@BeforeTemplate`
// method, so that Refaster will match any expression, rather than just statements. (One caveat
// with this "context-independent migrations only" approach is that APIs often expose methods
// that are only useful in combination with other methods of the API; insisting that such methods
// are migrated in isolation is unreasonable.)
// 2. Where relevant, method references should also be migrated. (TBD what "relevant" means in this
// case, and whether in fact method reference matchers can be _derived_ from the associated
// method invocation matchers.)
// XXX: This checker currently does no concern itself with public fields. Consider adding support
// for those.
@AutoService(BugChecker.class)
@BugPattern(
summary =
"""
The set of unmigrated methods listed by the `@TypeMigration` annotation must be minimal \
yet exhaustive""",
link = BUG_PATTERNS_BASE_URL + "ExhaustiveRefasterTypeMigration",
linkType = CUSTOM,
severity = WARNING,
tags = LIKELY_ERROR)
public final class ExhaustiveRefasterTypeMigration extends BugChecker implements ClassTreeMatcher {
private static final long serialVersionUID = 1L;
private static final MultiMatcher<Tree, AnnotationTree> IS_TYPE_MIGRATION =
annotations(AT_LEAST_ONE, isType("tech.picnic.errorprone.refaster.annotation.TypeMigration"));
private static final MultiMatcher<Tree, AnnotationTree> HAS_BEFORE_TEMPLATE =
annotations(AT_LEAST_ONE, isType(BeforeTemplate.class.getCanonicalName()));
private static final String TYPE_MIGRATION_TYPE_ELEMENT = "of";
private static final String TYPE_MIGRATION_UNMIGRATED_METHODS_ELEMENT = "unmigratedMethods";
/** Instantiates a new {@link ExhaustiveRefasterTypeMigration} instance. */
public ExhaustiveRefasterTypeMigration() {}
@Override
public Description matchClass(ClassTree tree, VisitorState state) {
MultiMatchResult<AnnotationTree> migrationAnnotations =
IS_TYPE_MIGRATION.multiMatchResult(tree, state);
if (!migrationAnnotations.matches()) {
return Description.NO_MATCH;
}
AnnotationTree migrationAnnotation = migrationAnnotations.onlyMatchingNode();
AnnotationMirror annotationMirror = ASTHelpers.getAnnotationMirror(migrationAnnotation);
TypeSymbol migratedType = getMigratedType(annotationMirror);
if (migratedType.asType().isPrimitive() || !(migratedType instanceof ClassSymbol)) {
return buildDescription(migrationAnnotation)
.setMessage(String.format("Migration of type '%s' is unsupported", migratedType))
.build();
}
ImmutableList<String> methodsClaimedUnmigrated = getMethodsClaimedUnmigrated(annotationMirror);
ImmutableList<String> unmigratedMethods =
getMethodsDefinitelyUnmigrated(
tree, (ClassSymbol) migratedType, signatureOrder(methodsClaimedUnmigrated), state);
if (unmigratedMethods.equals(methodsClaimedUnmigrated)) {
return Description.NO_MATCH;
}
/*
* The `@TypeMigration` annotation lists a different set of unmigrated methods than the one
* produced by our analysis; suggest a replacement.
*/
// XXX: `updateAnnotationArgumentValues` will prepend the new attribute argument if it is not
// already present. It would be nicer if it _appended_ the new attribute.
return describeMatch(
migrationAnnotation,
SuggestedFixes.updateAnnotationArgumentValues(
migrationAnnotation,
state,
TYPE_MIGRATION_UNMIGRATED_METHODS_ELEMENT,
unmigratedMethods.stream().map(Constants::format).collect(toImmutableList()))
.build());
}
private static TypeSymbol getMigratedType(AnnotationMirror migrationAnnotation) {
AnnotationValue value =
AnnotationMirrors.getAnnotationValue(migrationAnnotation, TYPE_MIGRATION_TYPE_ELEMENT);
verify(
value instanceof Attribute.Class,
"Value of annotation element `%s` is '%s' rather than a class",
TYPE_MIGRATION_TYPE_ELEMENT,
value);
return ((Attribute.Class) value).classType.tsym;
}
private static ImmutableList<String> getMethodsClaimedUnmigrated(
AnnotationMirror migrationAnnotation) {
AnnotationValue value =
AnnotationMirrors.getAnnotationValue(
migrationAnnotation, TYPE_MIGRATION_UNMIGRATED_METHODS_ELEMENT);
verify(
value instanceof Attribute.Array,
"Value of annotation element `%s` is '%s' rather than an array",
TYPE_MIGRATION_UNMIGRATED_METHODS_ELEMENT,
value);
return ((Attribute.Array) value)
.getValue().stream().map(a -> a.getValue().toString()).collect(toImmutableList());
}
// XXX: Once only JDK 14 and above are supported, change the
// `m.getModifiers().contains(Modifier.PUBLIC)` check to just `m.isPublic()`.
private static ImmutableList<String> getMethodsDefinitelyUnmigrated(
ClassTree tree, ClassSymbol migratedType, Comparator<String> comparator, VisitorState state) {
Set<MethodSymbol> publicMethods =
Streams.stream(
ASTHelpers.scope(migratedType.members())
.getSymbols(
m ->
m.getModifiers().contains(Modifier.PUBLIC)
&& m instanceof MethodSymbol))
.map(MethodSymbol.class::cast)
.collect(toCollection(HashSet::new));
/* Remove methods that *appear* to be migrated. Note that this is an imperfect heuristic. */
removeMethodsInvokedInBeforeTemplateMethods(tree, publicMethods, state);
return publicMethods.stream()
.map(m -> Signatures.prettyMethodSignature(migratedType, m))
.sorted(comparator)
.collect(toImmutableList());
}
/**
* Creates a {@link Comparator} that orders method signatures to match the given list of
* signatures, with any signatures not listed ordered first, lexicographically.
*
* @implNote This method does not use {@code comparing(list::indexOf)}, as that would make each
* comparison a linear, rather than constant-time operation.
*/
private static Comparator<String> signatureOrder(ImmutableList<String> existingOrder) {
Map<String, Integer> knownEntries = new HashMap<>();
for (int i = 0; i < existingOrder.size(); i++) {
knownEntries.putIfAbsent(existingOrder.get(i), i);
}
// XXX: The lexicographical order applied to unknown entries aims to match the order applied by
// the `LexicographicalAnnotationAttributeListing` check; consider deduplicating this logic.
return comparing((String v) -> knownEntries.getOrDefault(v, -1))
.thenComparing(String.CASE_INSENSITIVE_ORDER);
}
/**
* Removes from the given set of {@link MethodSymbol}s the ones that refer to a method that is
* invoked inside a {@link com.google.errorprone.refaster.annotation.BeforeTemplate} method inside
* the specified {@link ClassTree}.
*/
private static void removeMethodsInvokedInBeforeTemplateMethods(
ClassTree tree, Set<MethodSymbol> candidates, VisitorState state) {
new TreeScanner<@Nullable Void, Consumer<MethodSymbol>>() {
@Override
public @Nullable Void visitMethod(MethodTree tree, Consumer<MethodSymbol> sink) {
return HAS_BEFORE_TEMPLATE.matches(tree, state)
? super.visitMethod(tree, candidates::remove)
: null;
}
@Override
public @Nullable Void visitNewClass(NewClassTree tree, Consumer<MethodSymbol> sink) {
sink.accept(ASTHelpers.getSymbol(tree));
return super.visitNewClass(tree, sink);
}
@Override
public @Nullable Void visitMethodInvocation(
MethodInvocationTree tree, Consumer<MethodSymbol> sink) {
sink.accept(ASTHelpers.getSymbol(tree));
return super.visitMethodInvocation(tree, sink);
}
}.scan(tree, s -> {});
}
}

View File

@@ -42,21 +42,18 @@ public final class RefasterAnyOfUsage extends BugChecker implements MethodInvoca
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (REFASTER_ANY_OF.matches(tree, state)) {
switch (tree.getArguments().size()) {
case 0:
// We can't safely fix this case; dropping the expression may produce non-compilable code.
return describeMatch(tree);
case 1:
return describeMatch(
tree,
SuggestedFix.replace(
tree, SourceCode.treeToString(tree.getArguments().get(0), state)));
default:
/* Handled below. */
}
int argumentCount = tree.getArguments().size();
if (argumentCount > 1 || !REFASTER_ANY_OF.matches(tree, state)) {
return Description.NO_MATCH;
}
return Description.NO_MATCH;
if (argumentCount == 0) {
/* We can't safely fix this case; dropping the expression may produce non-compilable code. */
return describeMatch(tree);
}
return describeMatch(
tree,
SuggestedFix.replace(tree, SourceCode.treeToString(tree.getArguments().get(0), state)));
}
}

View File

@@ -45,16 +45,14 @@ public final class UnqualifiedSuggestedFixImport extends BugChecker
return Description.NO_MATCH;
}
switch (ASTHelpers.getSymbol(tree).getSimpleName().toString()) {
case "addImport":
return createDescription(
tree, "SuggestedFix.Builder#addImport", "SuggestedFixes#qualifyType");
case "addStaticImport":
return createDescription(
tree, "SuggestedFix.Builder#addStaticImport", "SuggestedFixes#qualifyStaticImport");
default:
return Description.NO_MATCH;
}
return switch (ASTHelpers.getSymbol(tree).getSimpleName().toString()) {
case "addImport" ->
createDescription(tree, "SuggestedFix.Builder#addImport", "SuggestedFixes#qualifyType");
case "addStaticImport" ->
createDescription(
tree, "SuggestedFix.Builder#addStaticImport", "SuggestedFixes#qualifyStaticImport");
default -> Description.NO_MATCH;
};
}
private Description createDescription(

View File

@@ -0,0 +1,193 @@
package tech.picnic.errorprone.guidelines.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 BugPatternLinkTest {
@Test
void identification() {
CompilationTestHelper.newInstance(BugPatternLink.class, getClass())
.addSourceLines(
"A.java",
"import com.google.errorprone.BugPattern;",
"",
"@BugPattern(summary = \"Class in default package\", severity = BugPattern.SeverityLevel.ERROR)",
"class A {}")
.addSourceLines(
"com/example/B.java",
"package com.example;",
"",
"import com.google.errorprone.BugPattern;",
"",
"@BugPattern(summary = \"Class in custom package\", severity = BugPattern.SeverityLevel.ERROR)",
"class B {}")
.addSourceLines(
"tech/picnic/errorprone/C.java",
"package tech.picnic.errorprone;",
"",
"import com.google.errorprone.BugPattern;",
"",
"@BugPattern(",
" summary = \"Class explicitly without link\",",
" linkType = BugPattern.LinkType.NONE,",
" severity = BugPattern.SeverityLevel.ERROR)",
"class C {}")
.addSourceLines(
"tech/picnic/errorprone/subpackage/D.java",
"package tech.picnic.errorprone.subpackage;",
"",
"import com.google.errorprone.BugPattern;",
"import tech.picnic.errorprone.utils.Documentation;",
"",
"@BugPattern(",
" summary = \"Error Prone Support class in subpackage with proper link\",",
" link = Documentation.BUG_PATTERNS_BASE_URL + \"D\",",
" linkType = BugPattern.LinkType.CUSTOM,",
" severity = BugPattern.SeverityLevel.ERROR)",
"class D {}")
.addSourceLines(
"tech/picnic/errorprone/E.java",
"package tech.picnic.errorprone;",
"",
"import static com.google.errorprone.BugPattern.LinkType.CUSTOM;",
"import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;",
"import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;",
"",
"import com.google.errorprone.BugPattern;",
"",
"@BugPattern(",
" summary = \"Error Prone Support class with proper link and static imports\",",
" link = BUG_PATTERNS_BASE_URL + \"E\",",
" linkType = CUSTOM,",
" severity = ERROR)",
"class E {}")
.addSourceLines(
"tech/picnic/errorprone/F.java",
"package tech.picnic.errorprone;",
"",
"import com.google.errorprone.BugPattern;",
"",
"class F {",
" @BugPattern(",
" summary = \"Nested Error Prone Support class\",",
" severity = BugPattern.SeverityLevel.ERROR)",
" class Inner {}",
"}")
.addSourceLines(
"tech/picnic/errorprone/G.java",
"package tech.picnic.errorprone;",
"",
"import com.google.errorprone.BugPattern;",
"",
"// BUG: Diagnostic contains:",
"@BugPattern(",
" summary = \"Error Prone Support class lacking link\",",
" severity = BugPattern.SeverityLevel.ERROR)",
"class G {}")
.addSourceLines(
"tech/picnic/errorprone/H.java",
"package tech.picnic.errorprone;",
"",
"import com.google.errorprone.BugPattern;",
"import tech.picnic.errorprone.utils.Documentation;",
"",
"// BUG: Diagnostic contains:",
"@BugPattern(",
" summary = \"Error Prone Support class with incorrect link\",",
" link = Documentation.BUG_PATTERNS_BASE_URL + \"NotH\",",
" linkType = BugPattern.LinkType.CUSTOM,",
" severity = BugPattern.SeverityLevel.ERROR)",
"class H {}")
.addSourceLines(
"tech/picnic/errorprone/I.java",
"package tech.picnic.errorprone;",
"",
"import com.google.errorprone.BugPattern;",
"",
"// BUG: Diagnostic contains:",
"@BugPattern(",
" summary = \"Error Prone Support class with non-canonical link\",",
" link = \"https://error-prone.picnic.tech/bugpatterns/I\",",
" linkType = BugPattern.LinkType.CUSTOM,",
" severity = BugPattern.SeverityLevel.ERROR)",
"class I {}")
.addSourceLines(
"tech/picnic/errorprone/J.java",
"package tech.picnic.errorprone;",
"",
"import com.google.errorprone.BugPattern;",
"",
"// BUG: Diagnostic contains:",
"@BugPattern(",
" summary = \"Error Prone Support class in with non-canonical link\",",
" link = \"https://error-prone.picnic.tech/bugpatterns/\" + \"J\",",
" linkType = BugPattern.LinkType.CUSTOM,",
" severity = BugPattern.SeverityLevel.ERROR)",
"class J {}")
.doTest();
}
@Test
void replacement() {
BugCheckerRefactoringTestHelper.newInstance(BugPatternLink.class, getClass())
.addInputLines(
"tech/picnic/errorprone/A.java",
"package tech.picnic.errorprone;",
"",
"import com.google.errorprone.BugPattern;",
"",
"@BugPattern(",
" summary = \"Error Prone Support class lacking link\",",
" severity = BugPattern.SeverityLevel.ERROR)",
"class A {}")
.addOutputLines(
"tech/picnic/errorprone/A.java",
"package tech.picnic.errorprone;",
"",
"import static com.google.errorprone.BugPattern.LinkType.CUSTOM;",
"import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;",
"",
"import com.google.errorprone.BugPattern;",
"",
"@BugPattern(",
" link = BUG_PATTERNS_BASE_URL + \"A\",",
" linkType = CUSTOM,",
" summary = \"Error Prone Support class lacking link\",",
" severity = BugPattern.SeverityLevel.ERROR)",
"class A {}")
.addInputLines(
"tech/picnic/errorprone/B.java",
"package tech.picnic.errorprone;",
"",
"import static com.google.errorprone.BugPattern.LinkType.CUSTOM;",
"import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;",
"",
"import com.google.errorprone.BugPattern;",
"",
"@BugPattern(",
" summary = \"Error Prone Support class with incorrect link\",",
" link = \"Not the right link\",",
" linkType = CUSTOM,",
" severity = ERROR)",
"class B {}")
.addOutputLines(
"tech/picnic/errorprone/B.java",
"package tech.picnic.errorprone;",
"",
"import static com.google.errorprone.BugPattern.LinkType.CUSTOM;",
"import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;",
"import static tech.picnic.errorprone.utils.Documentation.BUG_PATTERNS_BASE_URL;",
"",
"import com.google.errorprone.BugPattern;",
"",
"@BugPattern(",
" summary = \"Error Prone Support class with incorrect link\",",
" link = BUG_PATTERNS_BASE_URL + \"B\",",
" linkType = CUSTOM,",
" severity = ERROR)",
"class B {}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

@@ -0,0 +1,263 @@
package tech.picnic.errorprone.guidelines.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 ExhaustiveRefasterTypeMigrationTest {
@Test
void identification() {
CompilationTestHelper.newInstance(ExhaustiveRefasterTypeMigration.class, getClass())
.addSourceLines(
"Util.java",
"class Util {",
" public static int CONSTANT = 42;",
"",
" public static void publicStaticVoidMethod() {}",
"",
" static void packagePrivateStaticVoidMethod() {}",
"",
" protected static void protectedStaticVoidMethod() {}",
"",
" private static void privateStaticVoidMethod() {}",
"",
" public static int publicStaticIntMethod2() {",
" return 0;",
" }",
"",
" public String publicStringMethodWithArg(int arg) {",
" return String.valueOf(arg);",
" }",
"}")
.addSourceLines(
"A.java",
"import com.google.errorprone.refaster.annotation.AfterTemplate;",
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
"import tech.picnic.errorprone.refaster.annotation.TypeMigration;",
"",
"class A {",
" class UnannotatedEmptyClass {}",
"",
" // BUG: Diagnostic contains: Migration of type 'int' is unsupported",
" @TypeMigration(of = int.class)",
" class AnnotatedWithPrimitive {}",
"",
" @TypeMigration(",
" of = Util.class,",
" unmigratedMethods = {",
" \"publicStaticIntMethod2()\",",
" \"publicStringMethodWithArg(int)\",",
" \"publicStaticVoidMethod()\"",
" })",
" class AnnotatedEmptyClass {}",
"",
" @TypeMigration(",
" of = Util.class,",
" unmigratedMethods = {",
" \"publicStaticVoidMethod()\",",
" \"publicStringMethodWithArg(int)\",",
" \"publicStaticIntMethod2()\"",
" })",
" class AnnotatedEmptyClassWithUnsortedMethodListing {}",
"",
" class UnannotatedTemplate {",
" @BeforeTemplate",
" void before(int value) {",
" Util.publicStaticVoidMethod();",
" Util.publicStaticIntMethod2();",
" new Util().publicStringMethodWithArg(value);",
" }",
" }",
"",
" @TypeMigration(",
" of = Util.class,",
" unmigratedMethods = {",
" \"publicStaticIntMethod2()\",",
" \"publicStringMethodWithArg(int)\",",
" \"publicStaticVoidMethod()\"",
" })",
" class AnnotatedWithoutBeforeTemplate {",
" {",
" Util.publicStaticIntMethod2();",
" }",
"",
" @AfterTemplate",
" void after(int value) {",
" Util.publicStaticVoidMethod();",
" new Util().publicStringMethodWithArg(value);",
" }",
" }",
"",
" @TypeMigration(of = Util.class)",
" class AnnotatedFullyMigrated {",
" @BeforeTemplate",
" void before() {",
" new Util().publicStringMethodWithArg(Util.publicStaticIntMethod2());",
" }",
"",
" @BeforeTemplate",
" void before2() {",
" Util.publicStaticVoidMethod();",
" }",
" }",
"",
" @TypeMigration(of = Util.class, unmigratedMethods = \"publicStringMethodWithArg(int)\")",
" class AnnotatedPartiallyMigrated {",
" @BeforeTemplate",
" void before() {",
" Util.publicStaticVoidMethod();",
" Util.publicStaticIntMethod2();",
" }",
" }",
"",
" // BUG: Diagnostic contains: The set of unmigrated methods listed by the `@TypeMigration`",
" // annotation must be minimal yet exhaustive",
" @TypeMigration(of = Util.class, unmigratedMethods = \"publicStringMethodWithArg(int)\")",
" class AnnotatedWithIncompleteMethodListing {",
" @BeforeTemplate",
" void before() {",
" Util.publicStaticIntMethod2();",
" }",
" }",
"",
" // BUG: Diagnostic contains: The set of unmigrated methods listed by the `@TypeMigration`",
" // annotation must be minimal yet exhaustive",
" @TypeMigration(",
" of = Util.class,",
" unmigratedMethods = {\"publicStaticIntMethod2()\", \"publicStringMethodWithArg(int)\"})",
" class AnnotatedWithMigratedMethodReference {",
" @BeforeTemplate",
" void before() {",
" Util.publicStaticVoidMethod();",
" Util.publicStaticIntMethod2();",
" }",
" }",
"",
" // BUG: Diagnostic contains: The set of unmigrated methods listed by the `@TypeMigration`",
" // annotation must be minimal yet exhaustive",
" @TypeMigration(",
" of = Util.class,",
" unmigratedMethods = {\"extra\", \"publicStringMethodWithArg(int)\"})",
" class AnnotatedWithUnknownMethodReference {",
" @BeforeTemplate",
" void before() {",
" Util.publicStaticVoidMethod();",
" Util.publicStaticIntMethod2();",
" }",
" }",
"}")
.doTest();
}
@Test
void replacement() {
BugCheckerRefactoringTestHelper.newInstance(ExhaustiveRefasterTypeMigration.class, getClass())
.addInputLines(
"Util.java",
"public final class Util {",
" public static void publicStaticVoidMethod() {}",
"",
" public static int publicStaticIntMethod2() {",
" return 0;",
" }",
"",
" public String publicStringMethodWithArg(int arg) {",
" return String.valueOf(arg);",
" }",
"",
" public String publicStringMethodWithArg(String arg) {",
" return arg;",
" }",
"}")
.expectUnchanged()
.addInputLines(
"A.java",
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
"import tech.picnic.errorprone.refaster.annotation.TypeMigration;",
"",
"class A {",
" @TypeMigration(of = Util.class)",
" class AnnotatedWithoutMethodListing {",
" {",
" new Util().publicStringMethodWithArg(1);",
" }",
"",
" @BeforeTemplate",
" void before() {",
" Util.publicStaticIntMethod2();",
" }",
" }",
"",
" @TypeMigration(",
" of = Util.class,",
" unmigratedMethods = {\"publicStaticIntMethod2()\", \"extra\", \"publicStringMethodWithArg(int)\"})",
" class AnnotatedWithIncorrectMethodReference {",
" @BeforeTemplate",
" void before() {",
" new Util().publicStringMethodWithArg(\"1\");",
" Util.publicStaticVoidMethod();",
" Util.publicStaticIntMethod2();",
" }",
" }",
"",
" @TypeMigration(",
" of = Util.class,",
" unmigratedMethods = {\"publicStaticVoidMethod()\", \"publicStaticVoidMethod()\"})",
" class AnnotatedWithDuplicateMethodReference {",
" @BeforeTemplate",
" void before() {",
" new Util().publicStringMethodWithArg(1);",
" new Util().publicStringMethodWithArg(\"1\");",
" Util.publicStaticIntMethod2();",
" }",
" }",
"}")
.addOutputLines(
"A.java",
"import com.google.errorprone.refaster.annotation.BeforeTemplate;",
"import tech.picnic.errorprone.refaster.annotation.TypeMigration;",
"",
"class A {",
" @TypeMigration(",
" unmigratedMethods = {",
" \"publicStaticVoidMethod()\",",
" \"publicStringMethodWithArg(int)\",",
" \"publicStringMethodWithArg(String)\",",
" \"Util()\"",
" },",
" of = Util.class)",
" class AnnotatedWithoutMethodListing {",
" {",
" new Util().publicStringMethodWithArg(1);",
" }",
"",
" @BeforeTemplate",
" void before() {",
" Util.publicStaticIntMethod2();",
" }",
" }",
"",
" @TypeMigration(of = Util.class, unmigratedMethods = \"publicStringMethodWithArg(int)\")",
" class AnnotatedWithIncorrectMethodReference {",
" @BeforeTemplate",
" void before() {",
" new Util().publicStringMethodWithArg(\"1\");",
" Util.publicStaticVoidMethod();",
" Util.publicStaticIntMethod2();",
" }",
" }",
"",
" @TypeMigration(of = Util.class, unmigratedMethods = \"publicStaticVoidMethod()\")",
" class AnnotatedWithDuplicateMethodReference {",
" @BeforeTemplate",
" void before() {",
" new Util().publicStringMethodWithArg(1);",
" new Util().publicStringMethodWithArg(\"1\");",
" Util.publicStaticIntMethod2();",
" }",
" }",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

View File

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

View File

@@ -9,7 +9,6 @@ import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.Tree.Kind;
import com.sun.tools.javac.code.Type;
import java.io.Serializable;
import java.util.HashSet;
@@ -116,8 +115,8 @@ public final class AnnotationAttributeMatcher implements Serializable {
}
private static String extractAttributeName(ExpressionTree expr) {
return (expr.getKind() == Kind.ASSIGNMENT)
? ASTHelpers.getSymbol(((AssignmentTree) expr).getVariable()).getSimpleName().toString()
return (expr instanceof AssignmentTree assignment)
? ASTHelpers.getSymbol(assignment.getVariable()).getSimpleName().toString()
: "value";
}

View File

@@ -99,14 +99,13 @@ public final class MoreJUnitMatchers {
String methodName = method.getName().toString();
ExpressionTree value = AnnotationMatcherUtils.getArgument(methodSourceAnnotation, "value");
if (!(value instanceof NewArrayTree)) {
if (!(value instanceof NewArrayTree newArray)) {
return ImmutableList.of(toMethodSourceFactoryDescriptor(value, methodName));
}
return ((NewArrayTree) value)
.getInitializers().stream()
.map(name -> toMethodSourceFactoryDescriptor(name, methodName))
.collect(toImmutableList());
return newArray.getInitializers().stream()
.map(name -> toMethodSourceFactoryDescriptor(name, methodName))
.collect(toImmutableList());
}
private static String toMethodSourceFactoryDescriptor(

File diff suppressed because it is too large Load Diff

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