diff --git a/generators/tests/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt b/generators/tests/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt index 656aaba33be..efb79c67c7c 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt @@ -720,9 +720,24 @@ private fun Printer.generateCompilerOptionsHelper( } println(") {") withIndent { + val multiValuesReturnTypes = setOf( + "org.gradle.api.provider.ListProperty", + "org.gradle.api.provider.SetProperty", + ) if (parentHelperName != null) println("$parentHelperName.syncOptionsAsConvention(from, into)") for (property in properties) { - println("into.${property.name}.convention(from.${property.name})") + + // Behaviour of ListProperty, SetProperty, MapProperty append operators in regard to convention value + // is confusing for users: https://github.com/gradle/gradle/issues/18352 + // To make it less confusing for such types instead of wiring them via ".convention()" we updating + // current value + val gradleLazyReturnType = property.gradleLazyReturnType + val mapper = when { + multiValuesReturnTypes.any { gradleLazyReturnType.startsWith(it) } -> "addAll" + gradleLazyReturnType.startsWith("org.gradle.api.provider.MapProperty") -> "putAll" + else -> "convention" + } + println("into.${property.name}.$mapper(from.${property.name})") } } println("}") diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsProjectIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsProjectIT.kt index d3432b7e1a3..f5f34c7f3a8 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsProjectIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsProjectIT.kt @@ -151,32 +151,16 @@ class CompilerOptionsProjectIT : KGPBaseTest() { build("compileKotlin") { assertTasksExecuted(":compileKotlin") - val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") } + assertCompilerArguments( + ":compileKotlin", + "-language-version 1.9", + "-api-version 1.9", + "-Xdebug", + "-opt-in my.custom.OptInAnnotation,another.CustomOptInAnnotation", + "-XXLanguage:+UnitConversionsOnArbitraryExpressions" + ) - assert(compilationArgs.contains("-language-version 1.9")) { - printBuildOutput() - "Compiler arguments does not contain '-language-version 1.9': $compilationArgs" - } - - assert(compilationArgs.contains("-api-version 1.9")) { - printBuildOutput() - "Compiler arguments does not contain '-api-version 2.0': $compilationArgs" - } - - assert(!compilationArgs.contains("-progressive")) { - printBuildOutput() - "Compiler arguments contains '-progressive': $compilationArgs" - } - - assert(compilationArgs.contains("-opt-in another.CustomOptInAnnotation")) { - printBuildOutput() - "Compiler arguments does not contain '-opt-in another.CustomOptInAnnotation': $compilationArgs" - } - - assert(compilationArgs.contains("-XXLanguage:+UnitConversionsOnArbitraryExpressions")) { - printBuildOutput() - "Compiler arguments does not contain '-XXLanguage:+UnitConversionsOnArbitraryExpressions': $compilationArgs" - } + assertNoCompilerArgument(":compileKotlin", "-progressive") } } } @@ -268,6 +252,58 @@ class CompilerOptionsProjectIT : KGPBaseTest() { } } + @DisplayName("KT-59056: freeCompilerArgs are combined with android.kotlinOptions.freeCompilerArgs") + @AndroidGradlePluginTests + @GradleAndroidTest + fun kotlinOptionsFreeCompilerArgs( + gradleVersion: GradleVersion, + agpVersion: String, + jdk: JdkVersions.ProvidedJdk + ) { + project( + "AndroidIncrementalMultiModule", + gradleVersion, + buildOptions = defaultBuildOptions.copy( + androidVersion = agpVersion, + logLevel = LogLevel.DEBUG + ), + buildJdk = jdk.location + ) { + buildGradle.appendText( + //language=groovy + """ + | + |subprojects { + | tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile.class).configureEach { + | compilerOptions { + | freeCompilerArgs.addAll("-progressive") + | } + | } + |} + """.trimMargin() + ) + + subProject("libAndroid").buildGradle.appendText( + //language=groovy + """ + | + |android { + | kotlinOptions { + | freeCompilerArgs += ["-opt-in=com.example.roo.requiresOpt.FunTests"] + | } + |} + """.trimMargin() + ) + + build(":libAndroid:compileDebugKotlin") { + assertTasksExecuted(":libAndroid:compileDebugKotlin") + + assertCompilerArgument(":libAndroid:compileDebugKotlin", "-progressive") + assertCompilerArgument(":libAndroid:compileDebugKotlin", "-opt-in=com.example.roo.requiresOpt.FunTests") + } + } + } + @DisplayName("KT-57688: task moduleName input overrides project level moduleName") @JvmGradlePluginTests @GradleTest diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputAssertions.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputAssertions.kt index ae1cd11cd08..30cb14a1518 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputAssertions.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/testbase/outputAssertions.kt @@ -253,6 +253,27 @@ fun BuildResult.assertCompilerArgument( } } +fun BuildResult.assertCompilerArguments( + taskPath: String, + vararg expectedArguments: String, +) { + val taskOutput = getOutputForTask(taskPath) + val compilerArguments = taskOutput.lines().first { + it.contains("Kotlin compiler args:") + }.substringAfter("Kotlin compiler args:") + + val nonExistingArguments = expectedArguments + .filter { + !compilerArguments.contains(it) + } + + assert(nonExistingArguments.isEmpty()) { + printBuildOutput() + + "$taskPath task compiler arguments don't contain ${nonExistingArguments.joinToString()}. Actual content: $compilerArguments" + } +} + fun BuildResult.assertNoCompilerArgument( taskPath: String, notExpectedArgument: String, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerOptionsHelper.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerOptionsHelper.kt index 1ddcd741204..a1d4e8dafed 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerOptionsHelper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerOptionsHelper.kt @@ -26,7 +26,7 @@ internal object KotlinCommonCompilerOptionsHelper { org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerToolOptionsHelper.syncOptionsAsConvention(from, into) into.apiVersion.convention(from.apiVersion) into.languageVersion.convention(from.languageVersion) - into.optIn.convention(from.optIn) + into.optIn.addAll(from.optIn) into.progressiveMode.convention(from.progressiveMode) into.useK2.convention(from.useK2) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerToolOptionsHelper.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerToolOptionsHelper.kt index e21697cb965..09d972aa262 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerToolOptionsHelper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonCompilerToolOptionsHelper.kt @@ -24,6 +24,6 @@ internal object KotlinCommonCompilerToolOptionsHelper { into.allWarningsAsErrors.convention(from.allWarningsAsErrors) into.suppressWarnings.convention(from.suppressWarnings) into.verbose.convention(from.verbose) - into.freeCompilerArgs.convention(from.freeCompilerArgs) + into.freeCompilerArgs.addAll(from.freeCompilerArgs) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt index b6607b9d46f..a4e84496bdd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt @@ -118,7 +118,6 @@ internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder { internal fun applyLanguageSettingsToCompilerOptions( languageSettingsBuilder: LanguageSettings, compilerOptions: KotlinCommonCompilerOptions, - addFreeCompilerArgsAsConvention: Boolean = true, ) = with(compilerOptions) { val languageSettingsBuilderDefault = languageSettingsBuilder as DefaultLanguageSettingsBuilder languageSettingsBuilderDefault.languageVersion?.let { @@ -139,11 +138,7 @@ internal fun applyLanguageSettingsToCompilerOptions( freeArgs.addAll(languageSettingsBuilderDefault.freeCompilerArgsForNonImport) if (freeArgs.isNotEmpty()) { - if (addFreeCompilerArgsAsConvention) { - freeCompilerArgs.convention(freeArgs) - } else { - freeCompilerArgs.addAll(freeArgs) - } + freeCompilerArgs.addAll(freeArgs) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/AbstractKotlinCompileConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/AbstractKotlinCompileConfig.kt index fc93b13bf9d..71cff59ee6c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/AbstractKotlinCompileConfig.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/AbstractKotlinCompileConfig.kt @@ -56,9 +56,6 @@ internal abstract class AbstractKotlinCompileConfig).compilerOptions, - // KotlinJsIrTarget and KotlinJsIrTargetConfigurator add additional freeCompilerArgs essentially - // always overwriting convention value - addFreeCompilerArgsAsConvention = it !is Kotlin2JsCompile ) } }