OptionalNotPresentToIsEmpty rewrites `!isPresent()` on a non-`java.util.Optional` type, producing uncompilable `isEmpty()`
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
- #1147 của @timtebeek — đã đóng, không merge
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 70/100
Hướng nghiên cứu
Bắt đầu trong OptionalNotPresentToIsEmpty.java, đặc biệt là MethodMatcher và mẫu rewrite được tham chiếu ở dòng 46 và 56. Tái hiện phép biến đổi bằng com.bazaarvoice.jolt.common.Optional, sau đó thêm một regression test cho thấy các receiver chưa được resolve hoặc không thuộc JDK vẫn giữ nguyên và java.util.Optional vẫn được rewrite chính xác.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
What version of OpenRewrite are you using?
- Gradle plugin
org.openrewrite:pluginv7.35.0 - rewrite-migrate-java v3.38.0
- Active recipe:
org.openrewrite.java.migrate.UpgradeToJava21(which pulls inorg.openrewrite.java.migrate.util.OptionalNotPresentToIsEmpty)
How are you running OpenRewrite?
Gradle plugin, applied via an init script over a large multi-module project:
rootProject {
plugins.apply(org.openrewrite.gradle.RewritePlugin)
dependencies {
rewrite("org.openrewrite.recipe:rewrite-migrate-java:3.38.0")
}
rewrite {
activeRecipe("org.openrewrite.java.migrate.UpgradeToJava21")
setExportDatatables(true)
}
}
The affected module depends on Jolt (com.bazaarvoice.jolt:jolt-core:0.1.8), which ships its own
com.bazaarvoice.jolt.common.Optional<T>. That class exposes isPresent() and get() but has no
isEmpty() method (its full public API is empty(), of(T), get(), isPresent(), equals, toString).
The project is private, but the third-party type is public and small; the relevant snippet is below.
What is the smallest, simplest way to reproduce the problem?
The receiver is a Jolt Optional, not a JDK Optional:
import com.bazaarvoice.jolt.common.Optional; // NOT java.util.Optional
class ConvertMarkdownToHtmlRTL {
Optional<Object> applySingle(Object input) {
Optional<Object> baseHtmlOpt = convert(input);
if (!baseHtmlOpt.isPresent()) { // original, compiles fine
return Optional.empty();
}
// ...
}
}
What did you expect to see?
The code left unchanged. baseHtmlOpt is a com.bazaarvoice.jolt.common.Optional, not a
java.util.Optional, so the recipe should not apply. The recipe's MethodMatcher is in fact scoped to the
JDK type — new MethodMatcher("java.util.Optional isPresent()") with template
#{any(java.util.Optional)}.isEmpty()
(OptionalNotPresentToIsEmpty.java, lines 46 and 56 on v3.38.0) — so the intent is clearly JDK-only.
What did you see instead?
The recipe rewrote it to call isEmpty() on the Jolt type, which does not have that method, so the module
no longer compiles:
import com.bazaarvoice.jolt.common.Optional;
class ConvertMarkdownToHtmlRTL {
Optional<Object> applySingle(Object input) {
Optional<Object> baseHtmlOpt = convert(input);
if (baseHtmlOpt.isEmpty()) { // does not compile: no isEmpty() on com.bazaarvoice.jolt.common.Optional
return Optional.empty();
}
// ...
}
}
Because the JDK-scoped MethodMatcher nevertheless matched a com.bazaarvoice.jolt.common.Optional
receiver, this looks like the matcher firing when the receiver's type is unresolved/incompletely attributed
(the third-party Optional not being on the recipe's typed classpath), falling through to a name-only match
on isPresent(). A type-scoped migration recipe should not rewrite when it cannot positively confirm the
receiver is java.util.Optional — otherwise it silently emits uncompilable code with no warning or error from
the run itself.
- Note this is a distinct failure mode from #417/#418 (a
ClassCastExceptionthrown by the sibling
OptionalNotEmptyToIsPresent); here there is no crash — the recipe completes "successfully" and the breakage
only surfaces at the nextcompileJava.
What is the full stack trace of any errors you encountered?
No stack trace — the recipe run completes without error. The failure is a downstream Java compile error:
error: cannot find symbol
if (baseHtmlOpt.isEmpty()) {
^
symbol: method isEmpty()
location: variable baseHtmlOpt of type com.bazaarvoice.jolt.common.Optional<Object>
Are you interested in contributing a fix to OpenRewrite?
Open to it if you can point me at the preferred guard (e.g. requiring resolved receiver type before applying). Happy to add a recipe test that reproduces the mis-fire on a non-JDK Optional.
- Ngôn ngữ chính
- Java
- Star
- 159
- Fork
- 130
- Merge trung bình
- 6 giờ 49 phút
- Pull request đã merge (30 ngày)
- 47
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của openrewrite/rewrite-migrate-java
-
bug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 68/100
openrewrite/rewrite-migrate-java#1246 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 32/100
openrewrite/rewrite-migrate-java#1227 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 50/100
openrewrite/rewrite-migrate-java#1119 · 5 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
openrewrite/rewrite-migrate-java#1069 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
FacesManagedBeansRemoved for Faces 4.0 recipe updatesCó thể làm lại được @salaheddinemchich đã nhận 190 ngày trước và không có pull request nào đang mở. Đang mởbug
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
openrewrite/rewrite-migrate-java#1023 · 4 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của openrewrite/rewrite-migrate-java
Issue tương tự
-
enhancement Improvement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
zowe/zowe-client-java-sdk#647 ·
-
NullPointerException when a `DeserializationProblemHandler` returns `null` for `byte[]` (single value unwrapped) and `char[]` elementsCó thể đã có người làm @Marti2203 đã nhận hôm nay. Đang mở
Độ khó 2/5 Nửa ngày Mức phù hợp với người mới 88/100
FasterXML/jackson-databind#6300 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
content good first issue
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 95/100
cpinitiative/usaco-guide#6699 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
BC remittance upload: a claim MSP refused (S03) is saved with a blank status instead of refused (F)Có thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởtype: bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
carlos-emr/carlos#4933 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
apache/rocketmq-dashboard#6925 ·
Maintainer thường phản hồi trong vòng 3 ngày