fix: support Kotlin 2.4.0 by building against the 2.4.0 compiler API#32
Merged
Conversation
Kotlin 2.4.0 replaced ProjectExtensionDescriptor with ExtensionPointDescriptor in the CompilerPluginRegistrar extension-storage API, so the plugin binary built against older Kotlin crashes registration with a ClassCastException (FirExtensionRegistrarAdapter$Companion cannot be cast to ProjectExtensionDescriptor). Rebuilding against 2.4.0 emits the new registerExtension(ExtensionPointDescriptor, ...) call. Other changes needed to get the build green on 2.4.0: - Patch declaration parents after the IR transform: the lambdas synthesized for List mappings were created without a parent, which 2.4.0 IR lowering now rejects (IllegalStateException: parent not initialized). - Depend on the Kotlin compiler test framework directly and vendor kctf's ClasspathBasedStandardLibrariesPathProvider (MIT): kctf-runtime is not published for Kotlin 2.4 and its provider was compiled when KotlinStandardLibrariesPathProvider was still a class, which 2.4.0 turned into an interface (IncompatibleClassChangeError). - Drop -Xcontext-parameters, which is redundant with language version 2.4. - Run the TestKit integration tests and document the README against 2.4.0. Fixes #31
The compiler plugin is built against the Kotlin 2.4 compiler API and cannot be loaded by older compilers. Instead of letting 2.3.x users hit an obscure crash (the mirror image of #31), the Gradle plugin now fails fast at apply time with a clear message when the project's Kotlin Gradle Plugin is older than 2.4.0. Also scope kotlin-gradle-plugin-api as compileOnly. With implementation scope the published POM carried a runtime dependency on the API plus a 2.4.0 dependencyManagement pin, and KGP's BOM alignment then silently upgraded the consumer's entire Kotlin Gradle Plugin to 2.4.0 even when the project requested an older version — masking the incompatibility instead of surfacing it. With compileOnly the consumer's own KGP stays in control and the version check sees the version the project actually asked for. Covered by a new integration test that applies the plugin to a Kotlin 2.3.21 TestKit project and asserts the clear failure message.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #31
Problem
kmapper 0.0.15 crashes the Kotlin 2.4.0 compiler during plugin registration:
Kotlin 2.4.0 replaced
ProjectExtensionDescriptorwith a newExtensionPointDescriptortype in theCompilerPluginRegistrar.ExtensionStorageAPI (FirExtensionRegistrarAdapter.CompanionandIrGenerationExtension.Companionnow extend the new type). The kmapper source is already correct — the published binary was just compiled against the old hierarchy, so itscheckcast ProjectExtensionDescriptorfails at runtime on 2.4.0. The fix is to build and publish against Kotlin 2.4.0.Changes
registerExtension(ExtensionPointDescriptor, ...)(verified viajavap).Listmappings were created without an initializedparent, which 2.4.0's IR lowering rejects (IllegalStateException: Parent of element ... is not initialized).KMapperExtensionnow callspatchDeclarationParents()after the transform. This was caught byListMappingTest.shouldCompile_complexListandshouldCompile_valueClassUnwrapInListonce the integration tests ran on 2.4.0.KotlinVersionGuardTestthat applies the plugin to a Kotlin 2.3.21 TestKit project.kotlin-gradle-plugin-apiis nowcompileOnly. It used to beimplementation, which put a 2.x-pinned runtime dependency in the published POM — KGP's BOM alignment then silently upgraded the consumer's entire Kotlin Gradle Plugin to kmapper's Kotlin version, masking incompatibilities instead of surfacing them. WithcompileOnlythe consumer's own KGP stays in control and the version guard sees the version the project actually asked for.com.gradleup.kctf:kctf-runtimeis not published for Kotlin 2.4, and its single class was compiled whenKotlinStandardLibrariesPathProviderwas still an abstract class — 2.4.0 turned it into an interface, causingIncompatibleClassChangeError. The compiler test framework is now depended on directly at the project's Kotlin version, and kctf's classpath-based path provider (MIT) is vendored into the test sources (samekctfpackage, so the kctf-generated test source keeps working).-Xcontext-parameters, which is enabled by default (and reported as redundant) with language version 2.4.Verification
./gradlew build— green (compiler-plugin box tests + all 73 TestKit integration tests, including the new minimum-version guard test)../gradlew -Pkmapper.benchmarks=true :benchmarks:verifyBenchmarkThresholds— green (kmapper vs manual ratio 0.98x / 0.99x).javapon the rebuiltKMapperCompilerPluginRegistrarconfirms the newExtensionPointDescriptor-based registration that 2.4.0 expects.kmapper requires Kotlin 2.4.0 or newer, but this project uses Kotlin 2.3.21 ....https://claude.ai/code/session_01SgLsvFcF9CfGLkLbYG267U