diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt index 81d7f8f6fb1..ca49a3fc950 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/parseCommandLineArguments.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.cli.common.CompilerSystemProperties import org.jetbrains.kotlin.utils.SmartList import kotlin.reflect.KClass import kotlin.reflect.KMutableProperty1 +import kotlin.reflect.cast import kotlin.reflect.full.memberProperties @Target(AnnotationTarget.PROPERTY) @@ -63,6 +64,19 @@ data class ArgumentParseErrors( val internalArgumentsParsingProblems: MutableList = SmartList() ) +inline fun parseCommandLineArguments(args: List): T { + return parseCommandLineArguments(T::class, args) +} + +fun parseCommandLineArguments(clazz: KClass, args: List): T { + val constructor = clazz.java.constructors.find { it.parameters.isEmpty() } + ?: error("Missing empty constructor on '${clazz.java.name}") + val arguments = clazz.cast(constructor.newInstance()) + parseCommandLineArguments(args, arguments) + return arguments +} + + // Parses arguments into the passed [result] object. Errors related to the parsing will be collected into [CommonToolArguments.errors]. fun parseCommandLineArguments(args: List, result: A, overrideArguments: Boolean = false) { val errors = lazy { result.errors ?: ArgumentParseErrors().also { result.errors = it } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts index c302d98ae5f..58a5e5a042b 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/build.gradle.kts @@ -73,6 +73,7 @@ dependencies { testImplementation(project(":kotlin-compiler-embeddable")) testImplementation(commonDependency("org.jetbrains.intellij.deps:jdom")) + testImplementation(project(":compiler:cli-common")) // testCompileOnly dependency on non-shaded artifacts is needed for IDE support // testRuntimeOnly on shaded artifact is needed for running tests with shaded compiler testCompileOnly(project(":kotlin-gradle-plugin-test-utils-embeddable")) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt index bcd29e10c7d..9ccb6dff91c 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt @@ -7,9 +7,13 @@ package org.jetbrains.kotlin.gradle import org.gradle.api.logging.LogLevel import org.gradle.util.GradleVersion +import org.jetbrains.kotlin.cli.common.arguments.K2NativeCompilerArguments +import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments import org.jetbrains.kotlin.gradle.testbase.* import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.fail import kotlin.io.path.appendText +import kotlin.test.fail internal class CompilerOptionsIT : KGPBaseTest() { @@ -25,11 +29,11 @@ internal class CompilerOptionsIT : KGPBaseTest() { project("buildSrcWithKotlinDslAndKgp", gradleVersion) { gradleProperties .appendText( - """ + """ | |systemProp.org.gradle.kotlin.dsl.precompiled.accessors.strict=true """.trimMargin() - ) + ) build("tasks") { assertOutputContains("kotlinOptions.freeCompilerArgs were changed on task :compileKotlin execution phase:") @@ -285,16 +289,17 @@ internal class CompilerOptionsIT : KGPBaseTest() { ) build("compileKotlinHost", forceOutput = true) { - val expectedOptIn = listOf("-opt-in=kotlin.RequiresOptIn", "-opt-in=my.CustomOptIn") - val optInArgs = output + val expectedOptIn = listOf("kotlin.RequiresOptIn", "my.CustomOptIn") + val argumentsString = output .substringAfter("Arguments = [") .substringBefore("]") - .lines() - .filter { it.trim() in expectedOptIn } - assert(optInArgs.size == 2) { - printBuildOutput() - "compiler arguments does not contain '${expectedOptIn.joinToString()}': ${optInArgs.joinToString()}" + val rawArguments = argumentsString.lines().map { it.trim() } + val arguments = parseCommandLineArguments(rawArguments) + if (arguments.optIn?.toList() != listOf("kotlin.RequiresOptIn", "my.CustomOptIn")) { + fail( + "compiler arguments does not contain expected optIns'${expectedOptIn.joinToString()}': ${arguments.optIn}" + ) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinNativeCompileArgumentsTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinNativeCompileArgumentsTest.kt index ca4825a29aa..c1999a50837 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinNativeCompileArgumentsTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinNativeCompileArgumentsTest.kt @@ -74,4 +74,24 @@ class KotlinNativeCompileArgumentsTest { assertNull(commonMainCompileTask.createCompilerArguments(lenient).libraries) assertFails { commonMainCompileTask.createCompilerArguments(default) } } + + @Test + fun `test - opt in`() { + val project = buildProjectWithMPP() + val kotlin = project.multiplatformExtension + val linuxX64Target = kotlin.linuxX64() + linuxX64Target.compilations.all { + it.compilerOptions.options.apply { + optIn.add("my.OptIn") + optIn.add("my.other.OptIn") + } + } + + project.evaluate() + + val arguments = linuxX64Target.compilations.main.compileTaskProvider.get().createCompilerArguments(lenient) + assertEquals( + listOf("my.OptIn", "my.other.OptIn"), arguments.optIn?.toList() + ) + } } \ No newline at end of file