Skip to content

Align Kotlin jvmTarget with the Java version during UpgradeJavaVersion#1120

Open
MBoegers wants to merge 2 commits into
mainfrom
upgrade-kotlin-jvmtarget
Open

Align Kotlin jvmTarget with the Java version during UpgradeJavaVersion#1120
MBoegers wants to merge 2 commits into
mainfrom
upgrade-kotlin-jvmtarget

Conversation

@MBoegers
Copy link
Copy Markdown
Contributor

@MBoegers MBoegers commented May 29, 2026

Summary

  • Add UpgradeKotlinJvmTargetVersion and run it from UpgradeJavaVersion
  • Raise the Kotlin jvmTarget to match the requested Java version (Maven + Gradle)
  • Never downgrade; no-op for non-Kotlin projects

Problem

When UpgradeJavaVersion raises a project's Java version, the Kotlin compiler keeps emitting bytecode at the old jvmTarget, leaving Kotlin classes at a mismatched bytecode level.

Solution

A new UpgradeKotlinJvmTargetVersion(version) recipe, added to UpgradeJavaVersion's recipe list, raises the Kotlin jvmTarget to match across:

  • kotlin-maven-plugin <jvmTarget> configuration
  • Gradle Groovy and Kotlin DSL kotlinOptions/compilerOptions blocks (string and JvmTarget.JVM_X forms, including the jvmTarget.set(...) provider)

This flows automatically through the existing UpgradeBuildToJava*ForKotlin recipes. Adds rewrite-kotlin as an implementation dependency (needed to parse build.gradle.kts).

Test plan

  • New tests: Maven, Gradle Groovy, Gradle Kotlin DSL, do-not-downgrade, non-Kotlin no-ops, outside-block negatives

  • UpgradeJavaVersionTest regression passes

  • Full CI build (local full-suite run blocked by an unrelated Java-parser environment issue)

  • See moderneinc/customer-requests#2439

When UpgradeJavaVersion bumps a project's Java version, the Kotlin compiler
keeps emitting bytecode at the older jvmTarget, leaving Kotlin classes at a
mismatched bytecode level. UpgradeJavaVersion now also runs a new
UpgradeKotlinJvmTargetVersion recipe that raises the Kotlin jvmTarget to match
the requested Java version across:

- kotlin-maven-plugin <jvmTarget> configuration
- Gradle Groovy and Kotlin DSL kotlinOptions/compilerOptions blocks
  (string and JvmTarget.JVM_X forms, including the jvmTarget.set(...) provider)

It never downgrades, and is a no-op for non-Kotlin projects. This flows through
the existing UpgradeBuildToJava*ForKotlin recipes, which delegate to
UpgradeJavaVersion.

Discovered while testing the Spring Boot 4 migration for Kotlin.

See moderneinc/customer-requests#2439
A string jvmTarget value is only valid in the legacy kotlinOptions DSL; in
compilerOptions jvmTarget is a Property<JvmTarget>, so a String assignment does
not compile. UpgradeKotlinJvmTargetVersion now distinguishes the enclosing
block: it bumps a string literal only inside kotlinOptions, and inside
compilerOptions acts only on the JvmTarget.JVM_X enum and jvmTarget.set(...)
provider forms. A stray string inside compilerOptions (already non-compiling
input) is left untouched for UseJvmTargetProviderSyntax to convert.
@MBoegers
Copy link
Copy Markdown
Contributor Author

MBoegers commented Jun 1, 2026

Looks like it overlaps UseJvmTargetProviderSyntax (rewrite-migrate-kotlin), but they're orthogonal: this bumps the version (jvmTarget = "11""21", plus the enum/.set(...) forms; also Maven + Groovy), runs from UpgradeJavaVersion. That one rewrites syntax (= "11".set(JvmTarget.JVM_11)), keeping the version. Neither subsumes the other; compilerOptions { jvmTarget.set(JvmTarget.JVM_21) } needs both.

@MBoegers MBoegers marked this pull request as ready for review June 1, 2026 07:56
@MBoegers MBoegers requested a review from timtebeek June 1, 2026 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

1 participant