From be12ac645fb7e0cb742896e6ea2be97479d39659 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 12:14:22 +0000 Subject: [PATCH 1/2] fix: support Kotlin 2.4.0 by building against the 2.4.0 compiler API 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 --- .idea/kotlinc.xml | 2 +- README.md | 12 +-- benchmarks/build.gradle.kts | 4 +- build.gradle.kts | 2 +- compiler-plugin/build.gradle.kts | 13 +++- .../kmapper/compiler/KMapperExtension.kt | 5 ++ ...spathBasedStandardLibrariesPathProvider.kt | 75 +++++++++++++++++++ compiler-runtime/build.gradle.kts | 2 +- test-integration/build.gradle.kts | 4 +- .../flock/kmapper/BasicMappingTest.kt | 6 +- .../flock/kmapper/EnumMappingTest.kt | 2 +- .../flock/kmapper/ListMappingTest.kt | 2 +- .../flock/kmapper/NullableAndDefaultsTest.kt | 2 +- .../flock/kmapper/NumericWideningTest.kt | 2 +- .../flock/kmapper/SerializableTest.kt | 4 +- .../community/flock/kmapper/ValueClassTest.kt | 2 +- 16 files changed, 113 insertions(+), 26 deletions(-) create mode 100644 compiler-plugin/src/test/kotlin/kctf/ClasspathBasedStandardLibrariesPathProvider.kt diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index f203762..7ca2a83 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -2,6 +2,6 @@ \ No newline at end of file diff --git a/README.md b/README.md index 9d92d41..d4d04d8 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ KMapper is a Kotlin compiler plugin that provides code generation capabilities f ## Features -- **Kotlin 2.0+ Support**: Built with K2 compiler support (Kotlin 2.3.10) +- **Kotlin 2.0+ Support**: Built with K2 compiler support (Kotlin 2.4.0) - **Fluent DSL**: Intuitive assignment-based mapping syntax with `property = value` - **Compile-time Validation**: Ensures all required constructor parameters are mapped - **IR-Based Generation**: Uses Kotlin's IR (Intermediate Representation) for robust code generation @@ -16,7 +16,7 @@ KMapper is a Kotlin compiler plugin that provides code generation capabilities f ## Requirements -- Kotlin 2.3.10 or later +- Kotlin 2.4.0 or later - JVM 17+ - Gradle build system @@ -29,7 +29,7 @@ Add the plugin to your project's `build.gradle.kts`: build.gradle.kts ```kotlin plugins { - kotlin("jvm") version "2.3.10" + kotlin("jvm") version "2.4.0" id("community.flock.kmapper") version "0.0.0-SNAPSHOT" } ``` @@ -52,7 +52,7 @@ Load the KMapper Maven integration by adding it as a dependency of kotlin-maven- - Auto-register the KMapper Kotlin compiler plugin (transitively on the plugin classpath) - Ensure the runtime library (compiler-runtime) is on your project compile classpath -Kotlin version used/tested: 2.3.10. +Kotlin version used/tested: 2.4.0. Minimal setup: @@ -74,7 +74,7 @@ Minimal setup: org.jetbrains.kotlin kotlin-maven-plugin - 2.3.10 + 2.4.0 ...(other plugin configuration) @@ -90,7 +90,7 @@ Minimal setup: Troubleshooting: -- Ensure kotlin-maven-plugin version is 2.3.10 (matching our tested Kotlin version). +- Ensure kotlin-maven-plugin version is 2.4.0 (matching our tested Kotlin version). - Make sure the KMapper maven-plugin dependency is placed under kotlin-maven-plugin’s (not in the project section). - In multi-module builds, add the kotlin-maven-plugin configuration in each module that compiles Kotlin (you can use in the parent for reuse). - You can set a property 0.0.0-SNAPSHOT and the extension will use it to resolve the runtime version if needed. diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 1fc8187..420b7b2 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - kotlin("jvm") version "2.3.20" - kotlin("plugin.allopen") version "2.3.20" + kotlin("jvm") version "2.4.0" + kotlin("plugin.allopen") version "2.4.0" id("org.jetbrains.kotlinx.benchmark") version "0.4.13" id("community.flock.kmapper") version "0.0.0-SNAPSHOT" application diff --git a/build.gradle.kts b/build.gradle.kts index e21f873..202443b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm") version "2.3.20" + kotlin("jvm") version "2.4.0" id("io.github.gradle-nexus.publish-plugin") version "2.0.0" id("org.jetbrains.dokka") version "2.0.0" apply false } diff --git a/compiler-plugin/build.gradle.kts b/compiler-plugin/build.gradle.kts index b81fdf1..a1e167a 100644 --- a/compiler-plugin/build.gradle.kts +++ b/compiler-plugin/build.gradle.kts @@ -1,8 +1,9 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "2.3.20" + kotlin("jvm") version "2.4.0" id("maven-publish") id("org.jetbrains.dokka") id("com.gradleup.kctf").version("2.3.10-0.0.2-SNAPSHOT-a524b7d38d0ad625c3b891df859cc0be4b9c339b") @@ -22,7 +23,14 @@ val kMapperRuntimeClasspath: Configuration by configurations.creating { dependencies { compileOnly(kotlin("compiler-embeddable")) - testImplementation("com.gradleup.kctf:kctf-runtime:2.3.10-0.0.2-SNAPSHOT-a524b7d38d0ad625c3b891df859cc0be4b9c339b") + // kctf-runtime is not published for Kotlin 2.4 yet, so the compiler test + // framework is depended on directly and kctf's classpath-based stdlib path + // provider is vendored in src/test/kotlin/kctf. + testImplementation(kotlin("compiler", getKotlinPluginVersion())) + testImplementation(kotlin("compiler-internal-test-framework", getKotlinPluginVersion())) + testRuntimeOnly(kotlin("reflect", getKotlinPluginVersion())) + testRuntimeOnly(kotlin("script-runtime", getKotlinPluginVersion())) + testRuntimeOnly(kotlin("annotations-jvm", getKotlinPluginVersion())) testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") testImplementation(project(":compiler-runtime")) add(kMapperRuntimeClasspath.name, project(":compiler-runtime")) @@ -34,7 +42,6 @@ kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_17) } - compilerOptions.freeCompilerArgs.add("-Xcontext-parameters") } val javadocJar by tasks.registering(Jar::class) { diff --git a/compiler-plugin/src/main/kotlin/community/flock/kmapper/compiler/KMapperExtension.kt b/compiler-plugin/src/main/kotlin/community/flock/kmapper/compiler/KMapperExtension.kt index 76a9b1e..4a8ffa8 100644 --- a/compiler-plugin/src/main/kotlin/community/flock/kmapper/compiler/KMapperExtension.kt +++ b/compiler-plugin/src/main/kotlin/community/flock/kmapper/compiler/KMapperExtension.kt @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid /** @@ -15,5 +16,9 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid class KMapperExtension(val collector: MessageCollector) : IrGenerationExtension { override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { moduleFragment.transformChildrenVoid(KMapperIrBuildMapperVisitor(pluginContext, collector)) + // Declarations synthesized by the visitor (e.g. the lambdas built for + // List mappings) are created detached; Kotlin >= 2.4 fails IR lowering + // when it encounters a declaration without an initialized parent. + moduleFragment.patchDeclarationParents() } } diff --git a/compiler-plugin/src/test/kotlin/kctf/ClasspathBasedStandardLibrariesPathProvider.kt b/compiler-plugin/src/test/kotlin/kctf/ClasspathBasedStandardLibrariesPathProvider.kt new file mode 100644 index 0000000..031d09f --- /dev/null +++ b/compiler-plugin/src/test/kotlin/kctf/ClasspathBasedStandardLibrariesPathProvider.kt @@ -0,0 +1,75 @@ +// Vendored from GradleUp/kctf (MIT), adapted to the Kotlin 2.4 test framework: +// KotlinStandardLibrariesPathProvider is an interface since 2.4 and kctf-runtime +// is not published for Kotlin 2.4 yet. The `kctf` package is kept so the +// kctf-generated test sources keep referring to this provider. +package kctf + +import org.jetbrains.kotlin.platform.wasm.WasmTarget +import org.jetbrains.kotlin.test.services.KotlinStandardLibrariesPathProvider +import java.io.File + +object ClasspathBasedStandardLibrariesPathProvider : KotlinStandardLibrariesPathProvider { + private val SEP = "\\${File.separator}" + + private val GRADLE_DEPENDENCY = + (".*?" + + SEP + + "(?[^$SEP]*)" + + SEP + + "(?[^$SEP]*)" + + SEP + + "[^$SEP]*" + + SEP + + "\\1-\\2\\.jar") + .toRegex() + + private val jars = + System.getProperty("java.class.path") + .split("\\${File.pathSeparator}".toRegex()) + .dropLastWhile(String::isEmpty) + .map(::File) + .associateBy { + GRADLE_DEPENDENCY.matchEntire(it.path)?.let { it.groups["name"]!!.value } ?: it.name + } + + private fun getFile(name: String): File { + return jars[name] + ?: error("Jar $name not found in classpath:\n${jars.entries.joinToString("\n")}") + } + + override fun runtimeJarForTests(): File = getFile("kotlin-stdlib") + + override fun runtimeJarForTestsWithJdk8(): File = getFile("kotlin-stdlib-jdk8") + + override fun minimalRuntimeJarForTests(): File = getFile("kotlin-stdlib") + + override fun reflectJarForTests(): File = getFile("kotlin-reflect") + + override fun kotlinTestJarForTests(): File = getFile("kotlin-test") + + override fun scriptRuntimeJarForTests(): File = getFile("kotlin-script-runtime") + + override fun jvmAnnotationsForTests(): File = getFile("kotlin-annotations-jvm") + + override fun getAnnotationsJar(): File = getFile("kotlin-annotations-jvm") + + override fun fullJsStdlib(): File = getFile("kotlin-stdlib-js") + + override fun defaultJsStdlib(): File = getFile("kotlin-stdlib-js") + + override fun kotlinTestJsKLib(): File = getFile("kotlin-test-js") + + override fun fullWasmStdlib(target: WasmTarget): File = TODO("Wasm is not supported by these tests") + + override fun kotlinTestWasmKLib(target: WasmTarget): File = TODO("Wasm is not supported by these tests") + + override fun webStdlibForTests(): File = TODO("Web is not supported by these tests") + + override fun commonStdlibForTests(): File { + TODO("Not yet implemented") + } + + override fun scriptingPluginFilesForTests(): Collection { + TODO("KT-67573") + } +} diff --git a/compiler-runtime/build.gradle.kts b/compiler-runtime/build.gradle.kts index 5d83779..b5b0d95 100644 --- a/compiler-runtime/build.gradle.kts +++ b/compiler-runtime/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { - kotlin("jvm") version "2.3.20" + kotlin("jvm") version "2.4.0" id("maven-publish") id("org.jetbrains.dokka") signing diff --git a/test-integration/build.gradle.kts b/test-integration/build.gradle.kts index bcefcd9..c14a698 100644 --- a/test-integration/build.gradle.kts +++ b/test-integration/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm") version "2.3.20" + kotlin("jvm") version "2.4.0" } group = rootProject.group @@ -10,7 +10,7 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.2") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.2") implementation(gradleTestKit()) - implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:2.3.20") + implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:2.4.0") } kotlin { diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/BasicMappingTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/BasicMappingTest.kt index d71665f..04bd79e 100644 --- a/test-integration/src/test/kotlin/community/flock/kmapper/BasicMappingTest.kt +++ b/test-integration/src/test/kotlin/community/flock/kmapper/BasicMappingTest.kt @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test class BasicMappingTest { val options = IntegrationTest.Options( - kotlinVersion = "2.3.10", + kotlinVersion = "2.4.0", ) @Test @@ -579,8 +579,8 @@ class BasicMappingTest { """ |plugins { | id("community.flock.kmapper") version "0.0.0-SNAPSHOT" - | kotlin("jvm") version "2.3.10" - | kotlin("plugin.serialization") version "2.3.10" + | kotlin("jvm") version "2.4.0" + | kotlin("plugin.serialization") version "2.4.0" | application |} |repositories { diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/EnumMappingTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/EnumMappingTest.kt index ba387c3..df3a1a3 100644 --- a/test-integration/src/test/kotlin/community/flock/kmapper/EnumMappingTest.kt +++ b/test-integration/src/test/kotlin/community/flock/kmapper/EnumMappingTest.kt @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test class EnumMappingTest { val options = IntegrationTest.Options( - kotlinVersion = "2.3.10", + kotlinVersion = "2.4.0", ) @Test diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/ListMappingTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/ListMappingTest.kt index 3340be6..726bd99 100644 --- a/test-integration/src/test/kotlin/community/flock/kmapper/ListMappingTest.kt +++ b/test-integration/src/test/kotlin/community/flock/kmapper/ListMappingTest.kt @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test class ListMappingTest { val options = IntegrationTest.Options( - kotlinVersion = "2.3.10", + kotlinVersion = "2.4.0", ) @Test diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/NullableAndDefaultsTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/NullableAndDefaultsTest.kt index f7c3a6a..5dc1949 100644 --- a/test-integration/src/test/kotlin/community/flock/kmapper/NullableAndDefaultsTest.kt +++ b/test-integration/src/test/kotlin/community/flock/kmapper/NullableAndDefaultsTest.kt @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test class NullableAndDefaultsTest { val options = IntegrationTest.Options( - kotlinVersion = "2.3.10", + kotlinVersion = "2.4.0", ) @Test diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/NumericWideningTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/NumericWideningTest.kt index f6efe49..ca8a950 100644 --- a/test-integration/src/test/kotlin/community/flock/kmapper/NumericWideningTest.kt +++ b/test-integration/src/test/kotlin/community/flock/kmapper/NumericWideningTest.kt @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test class NumericWideningTest { val options = IntegrationTest.Options( - kotlinVersion = "2.3.10", + kotlinVersion = "2.4.0", ) @Test diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/SerializableTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/SerializableTest.kt index 52c38f7..e47f29d 100644 --- a/test-integration/src/test/kotlin/community/flock/kmapper/SerializableTest.kt +++ b/test-integration/src/test/kotlin/community/flock/kmapper/SerializableTest.kt @@ -6,8 +6,8 @@ import org.junit.jupiter.api.Test class SerializableTest { val options = IntegrationTest.Options( - kotlinVersion = "2.3.10", - additionalPlugins = listOf("""kotlin("plugin.serialization") version "2.3.10""""), + kotlinVersion = "2.4.0", + additionalPlugins = listOf("""kotlin("plugin.serialization") version "2.4.0""""), additionalDependencies = listOf("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1"), ) diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/ValueClassTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/ValueClassTest.kt index b64d5e4..9bc29f8 100644 --- a/test-integration/src/test/kotlin/community/flock/kmapper/ValueClassTest.kt +++ b/test-integration/src/test/kotlin/community/flock/kmapper/ValueClassTest.kt @@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test class ValueClassTest { val options = IntegrationTest.Options( - kotlinVersion = "2.3.10", + kotlinVersion = "2.4.0", ) @Test From 6d8dda690c09f097cc0d80978b800f9e81e2536c Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 12:36:47 +0000 Subject: [PATCH 2/2] feat: enforce Kotlin 2.4.0 as the minimum supported version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- gradle-plugin/build.gradle.kts | 6 +++- .../gradle/plugin/KMapperGradlePlugin.kt | 26 +++++++++++++++ .../flock/kmapper/KotlinVersionGuardTest.kt | 32 +++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 test-integration/src/test/kotlin/community/flock/kmapper/KotlinVersionGuardTest.kt diff --git a/gradle-plugin/build.gradle.kts b/gradle-plugin/build.gradle.kts index 1de71e2..0afda4b 100644 --- a/gradle-plugin/build.gradle.kts +++ b/gradle-plugin/build.gradle.kts @@ -26,7 +26,11 @@ sourceSets { } dependencies { - implementation(kotlin("gradle-plugin-api")) + // compileOnly so the consumer project's own Kotlin Gradle Plugin provides + // this API at runtime. With implementation scope the published POM would + // drag this version of KGP onto the consumer's plugin classpath, silently + // overriding the Kotlin version the project asked for. + compileOnly(kotlin("gradle-plugin-api")) testImplementation(kotlin("test-junit5")) } diff --git a/gradle-plugin/src/community/flock/kmapper/gradle/plugin/KMapperGradlePlugin.kt b/gradle-plugin/src/community/flock/kmapper/gradle/plugin/KMapperGradlePlugin.kt index 8fbbc70..7628c2f 100644 --- a/gradle-plugin/src/community/flock/kmapper/gradle/plugin/KMapperGradlePlugin.kt +++ b/gradle-plugin/src/community/flock/kmapper/gradle/plugin/KMapperGradlePlugin.kt @@ -2,8 +2,10 @@ package community.flock.kmapper.gradle.plugin import community.flock.kmapper.BuildConfig import community.flock.kmapper.BuildConfig.ANNOTATIONS_LIBRARY_COORDINATES +import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerPluginSupportPlugin import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact @@ -11,8 +13,32 @@ import org.jetbrains.kotlin.gradle.plugin.SubpluginOption @Suppress("unused") // Used via reflection. class KMapperGradlePlugin : KotlinCompilerPluginSupportPlugin { + + companion object { + // The compiler plugin is built against the Kotlin 2.4 compiler API and + // cannot be loaded by older compilers; fail fast with a clear message + // instead of crashing compilation (see issue #31 for the 2.3-on-2.4 + // counterpart of that crash). + private val MINIMUM_KOTLIN_VERSION = KotlinVersion(2, 4, 0) + } + override fun apply(target: Project) { target.extensions.create("flockPlugin", KMapperGradleExtension::class.java) + target.plugins.withType(KotlinBasePlugin::class.java).configureEach { kotlinPlugin -> + checkKotlinVersion(kotlinPlugin.pluginVersion) + } + } + + private fun checkKotlinVersion(version: String) { + val parts = version.substringBefore('-').split('.').map { it.toIntOrNull() ?: return } + if (parts.size < 3) return + if (KotlinVersion(parts[0], parts[1], parts[2]) < MINIMUM_KOTLIN_VERSION) { + throw GradleException( + "kmapper requires Kotlin $MINIMUM_KOTLIN_VERSION or newer, but this project uses " + + "Kotlin $version. Older compilers cannot load the kmapper compiler plugin; " + + "either upgrade Kotlin or use a kmapper release built for Kotlin $version." + ) + } } override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = true diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/KotlinVersionGuardTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/KotlinVersionGuardTest.kt new file mode 100644 index 0000000..2ede1fc --- /dev/null +++ b/test-integration/src/test/kotlin/community/flock/kmapper/KotlinVersionGuardTest.kt @@ -0,0 +1,32 @@ +package community.flock.kmapper + +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +class KotlinVersionGuardTest { + + val options = IntegrationTest.Options( + kotlinVersion = "2.3.21", + ) + + @Test + fun shouldFailFast_onKotlinOlderThanMinimum() { + IntegrationTest(options) + .file("App.kt") { + """ + |package sample + | + |fun main() { + | println("should never compile") + |} + | + """.trimMargin() + } + .compileFail { output -> + assertTrue( + output.contains("kmapper requires Kotlin 2.4.0 or newer"), + "Expected a clear minimum-Kotlin-version error, got:\n$output" + ) + } + } +}