From 49d0f69227d6f8e1a037b3114316e220ea15c408 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Mon, 30 Jan 2017 21:19:30 +0300 Subject: [PATCH] Fix exception when Groovy lazy string (GString) is in freeCompilerArgs #KT-15500 fixed GString is an object that represents string literal like `"${project.name}"` in Groovy. It is not an instance of string. Groovy automatically converts GString to String when it is passed where String is expected. However freeCompilerArgs is a List, so type parameter info is lost at runtime. When iterating freeCompilerArgs in Kotlin as a list of string, an exception is thrown because GString cannot be casted to String (toString should be called instead). --- .../kotlin/gradle/KotlinGradlePluginIT.kt | 19 +++++++++++++++++++ .../kotlin/gradle/dsl/KotlinJsOptionsImpl.kt | 6 ++++-- .../kotlin/gradle/dsl/KotlinJvmOptionsImpl.kt | 4 +++- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt index fc01f9e5bae..1ef9e87a8dd 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt @@ -346,4 +346,23 @@ class KotlinGradleIT: BaseGradleIT() { assertFileExists("libJs/build/classes/test/libJs_test.js") } } + + @Test + fun testFreeCompilerArgs() { + val project = Project("kotlinProject", GRADLE_VERSION) + project.setupWorkingDir() + + File(project.projectDir, "build.gradle").modify { + // lazy eval is important + val customModuleName = "\${project.name}" + it + """ + compileKotlin { + kotlinOptions.freeCompilerArgs = [ "-module-name", "$customModuleName" ] + }""" + } + + project.build("build") { + assertSuccessful() + } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsImpl.kt index 88d8ddaf1a5..ac7b19c650b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsImpl.kt @@ -19,11 +19,13 @@ package org.jetbrains.kotlin.gradle.dsl import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.js.K2JSCompiler -internal class KotlinJsOptionsImpl() : KotlinJsOptionsBase() { +internal class KotlinJsOptionsImpl : KotlinJsOptionsBase() { override var freeCompilerArgs: List = listOf() override fun updateArguments(args: K2JSCompilerArguments) { super.updateArguments(args) - K2JSCompiler().parseArguments(freeCompilerArgs.toTypedArray(), args) + // cast to List is important because in Groovy a GString can be inside of a list + val freeArgsArray = (freeCompilerArgs as List).map(Any::toString).toTypedArray() + K2JSCompiler().parseArguments(freeArgsArray, args) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsImpl.kt index ba5c336ee4b..72ed22d34b8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsImpl.kt @@ -24,6 +24,8 @@ internal class KotlinJvmOptionsImpl : KotlinJvmOptionsBase() { override fun updateArguments(args: K2JVMCompilerArguments) { super.updateArguments(args) - K2JVMCompiler().parseArguments(freeCompilerArgs.toTypedArray(), args) + // cast to List is important because in Groovy a GString can be inside of a list + val freeArgsArray = (freeCompilerArgs as List).map(Any::toString).toTypedArray() + K2JVMCompiler().parseArguments(freeArgsArray, args) } }