Skip to content

Make ChangeStaticFieldToMethod work on Kotlin sources - #8352

Merged
timtebeek merged 1 commit into
mainfrom
tim/belo-horizonte-v4
Jul 30, 2026
Merged

Make ChangeStaticFieldToMethod work on Kotlin sources#8352
timtebeek merged 1 commit into
mainfrom
tim/belo-horizonte-v4

Conversation

@timtebeek

@timtebeek timtebeek commented Jul 30, 2026

Copy link
Copy Markdown
Member

What was actually broken

The marker the customer saw was attributed to org.openrewrite.java.ReplaceConstantWithAnotherConstant, but that recipe builds no JavaTemplate at all, so it cannot produce a "Failed to parse expression template" error. The template in the message — StandardCharsets.UTF_8.name() — comes from org.openrewrite.java.ChangeStaticFieldToMethod, as used by org.openrewrite.apache.commons.lang3.UseStandardCharsets to migrate CharEncoding.UTF_8. So F is another instance of the misattribution tracked as defect G.

The fix

ChangeStaticFieldToMethod built its replacement template contextSensitive(). The template is a fully qualified static method invocation that references nothing from the surrounding scope, so context sensitivity buys nothing — but it makes BlockStatementTemplateGenerator emit the enclosing type printed as Java. For a Kotlin source that stub is not valid Java, it compiles to zero trees, and JavaTemplateParser#parseExpression throws.

Dropping .contextSensitive() fixes it. As a bonus, the resulting J.MethodInvocation now carries type attribution on Kotlin, which it did not before (Kotlin's assertValidTypes flagged it even in the cases that did not throw).

Tests

  • rewrite-kotlin ChangeStaticFieldToMethodTest — a qualified field access, a statically imported one, and the reported shape (argument to a call inside a val in a generic function of a subclass with backtick-named members). All three fail on main: the first two with LST contains missing or invalid type information, the third with the exact Failed to parse expression template from the issue.
  • rewrite-kotlin ReplaceConstantWithAnotherConstantTest — added to pin down that this recipe is in fact Kotlin-clean, so the next report of this shape is not chased into the wrong file.

rewrite-java-test's existing ChangeStaticFieldToMethodTest still passes unchanged.

The replacement template is a fully qualified static method invocation
(`StandardCharsets.UTF_8.name()`) that references nothing from the
surrounding scope, but it was built `contextSensitive()`. That made the
generated stub include the enclosing type printed as Java, which for
Kotlin sources is not valid Java, so the stub compiled to nothing and
the recipe threw "Failed to parse expression template" instead of making
a change. Even where the stub did compile, the resulting
`J.MethodInvocation` came back without type attribution.

Reported as defect F on moderneinc/customer-requests#2924, where the
error marker was attributed to `ReplaceConstantWithAnotherConstant`;
that recipe uses no template and is fine on Kotlin, so tests are added
for it as well.
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Jul 30, 2026
@timtebeek
timtebeek merged commit c7301d7 into main Jul 30, 2026
1 check passed
@timtebeek
timtebeek deleted the tim/belo-horizonte-v4 branch July 30, 2026 12:08
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant