diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LanguageSettingsBuilder.kt b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LanguageSettingsBuilder.kt index 9eef9c25cf0..dbbfdc086b7 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LanguageSettingsBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LanguageSettingsBuilder.kt @@ -15,4 +15,8 @@ interface LanguageSettingsBuilder { fun enableLanguageFeature(name: String) val enabledLanguageFeatures: Set + + fun useExperimentalAnnotation(name: String) + + val experimentalAnnotationsInUse: Set } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt index c37f45266e0..aab5390a896 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt @@ -311,18 +311,29 @@ class NewMultiplatformIT : BaseGradleIT() { gradleBuildScript().appendText( "\n" + """ - kotlin.sourceSets.jvm6Main.languageSettings { - languageVersion = '1.3' - apiVersion = '1.3' - enableLanguageFeature('InlineClasses') - progressiveMode = true + kotlin.sourceSets.all { + it.languageSettings { + languageVersion = '1.3' + apiVersion = '1.3' + enableLanguageFeature('InlineClasses') + useExperimentalAnnotation('kotlin.ExperimentalUnsignedTypes') + useExperimentalAnnotation('kotlin.contracts.ExperimentalContracts') + progressiveMode = true + } } """.trimIndent() ) - build("compileKotlinJvm6") { - assertSuccessful() - assertContains("-language-version 1.3", "-api-version 1.3", "-XXLanguage:+InlineClasses", " -progressive") + listOf("compileKotlinJvm6", "compileKotlinNodeJs", "compileKotlin${nativeHostTargetName.capitalize()}").forEach { + build(it) { + assertSuccessful() + assertTasksExecuted(":$it") + assertContains( + "-language-version 1.3", "-api-version 1.3", "-XXLanguage:+InlineClasses", + " -progressive", "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes", + "-Xuse-experimental=kotlin.contracts.ExperimentalContracts" + ) + } } } @@ -351,8 +362,20 @@ class NewMultiplatformIT : BaseGradleIT() { } } - testMonotonousCheck("languageSettings.languageVersion = '1.4'", SourceSetConsistencyChecks.languageVersionCheckHint) - testMonotonousCheck("languageSettings.enableLanguageFeature('InlineClasses')", SourceSetConsistencyChecks.unstableFeaturesHint) + testMonotonousCheck( + "languageSettings.languageVersion = '1.4'", + SourceSetConsistencyChecks.languageVersionCheckHint + ) + + testMonotonousCheck( + "languageSettings.enableLanguageFeature('InlineClasses')", + SourceSetConsistencyChecks.unstableFeaturesHint + ) + + testMonotonousCheck( + "languageSettings.useExperimentalAnnotation('kotlin.ExperimentalUnsignedTypes')", + SourceSetConsistencyChecks.experimentalAnnotationsInUseHint + ) // check that enabling a bugfix feature and progressive mode or advancing API level // don't require doing the same for dependent source sets: @@ -951,4 +974,4 @@ class NewMultiplatformIT : BaseGradleIT() { assertFileExists("foo/2.txt") } } -} +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-lib-and-app/sample-lib/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-lib-and-app/sample-lib/build.gradle index 1ea2c61505a..d8923e3c33d 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-lib-and-app/sample-lib/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-lib-and-app/sample-lib/build.gradle @@ -38,13 +38,20 @@ kotlin { } sourceSets { + commonMain { + dependencies { + api 'org.jetbrains.kotlin:kotlin-stdlib-common' + } + } jvm6Main { dependencies { + api 'org.jetbrains.kotlin:kotlin-stdlib' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.23.4' } } nodeJsMain { dependencies { + api 'org.jetbrains.kotlin:kotlin-stdlib-js' implementation 'org.jetbrains.kotlinx:kotlinx-html-js:0.6.11' } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt index a896e95805f..203b2b9278f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/DefaultLanguageSettingsBuilder.kt @@ -50,6 +50,14 @@ internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder { enabledLanguageFeaturesImpl += languageFeature } + private val experimentalAnnotationsInUseImpl = mutableSetOf() + + override val experimentalAnnotationsInUse: Set = experimentalAnnotationsInUseImpl + + override fun useExperimentalAnnotation(name: String) { + experimentalAnnotationsInUseImpl += name + } + companion object { } } @@ -68,6 +76,10 @@ internal fun applyLanguageSettingsToKotlinTask( languageSettingsBuilder.enabledLanguageFeatures.forEach { featureName -> freeCompilerArgs += "-XXLanguage:+$featureName" } + + languageSettingsBuilder.experimentalAnnotationsInUse.forEach { annotationName -> + freeCompilerArgs += "-Xuse-experimental=$annotationName" + } } private val apiVersionValues = ApiVersion.run { listOf(KOTLIN_1_0, KOTLIN_1_1, KOTLIN_1_2, KOTLIN_1_3) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/SourceSetConsistencyChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/SourceSetConsistencyChecker.kt index b34092112d6..362e27f428f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/SourceSetConsistencyChecker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/SourceSetConsistencyChecker.kt @@ -44,6 +44,15 @@ object SourceSetConsistencyChecks { leftExtendsRightConsistently = { left, right -> left.containsAll(right) }, consistencyConditionHint = unstableFeaturesHint ) + + const val experimentalAnnotationsInUseHint = "The dependent source set must use all experimental annotations that its dependency uses." + + internal val experimentalAnnotationsCheck = ConsistencyCheck>( + name = "set of experimental annotations in use", + getValue = { sourceSet -> sourceSet.languageSettings.experimentalAnnotationsInUse }, + leftExtendsRightConsistently = { left, right -> left.containsAll(right) }, + consistencyConditionHint = experimentalAnnotationsInUseHint + ) } internal class SourceSetConsistencyChecker( @@ -76,5 +85,5 @@ internal class SourceSetConsistencyChecker( internal val defaultSourceSetLanguageSettingsChecker = with(SourceSetConsistencyChecks) { // We don't check the progressive mode, since the features it enables are bugfixes - SourceSetConsistencyChecker(listOf(languageVersionCheck, unstableFeaturesCheck)) + SourceSetConsistencyChecker(listOf(languageVersionCheck, experimentalAnnotationsCheck, unstableFeaturesCheck)) } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinNativeTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinNativeTasks.kt index ba992997470..2bfc3371b85 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinNativeTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinNativeTasks.kt @@ -5,7 +5,6 @@ import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.file.FileCollection import org.gradle.api.file.FileTree -import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.api.tasks.compile.AbstractCompile @@ -21,10 +20,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName import org.jetbrains.kotlin.gradle.plugin.mpp.isMainCompilation import org.jetbrains.kotlin.konan.target.CompilerOutputKind -import org.jetbrains.kotlin.konan.target.CompilerOutputKind.DYNAMIC -import org.jetbrains.kotlin.konan.target.CompilerOutputKind.FRAMEWORK -import org.jetbrains.kotlin.konan.target.CompilerOutputKind.PROGRAM -import org.jetbrains.kotlin.konan.target.CompilerOutputKind.STATIC +import org.jetbrains.kotlin.konan.target.CompilerOutputKind.* import org.jetbrains.kotlin.konan.target.KonanTarget import java.io.File @@ -154,6 +150,9 @@ open class KotlinNativeCompile : AbstractCompile() { val enabledLanguageFeatures: Set @Input get() = languageSettings?.enabledLanguageFeatures ?: emptySet() + + val experimentalAnnotationsInUse: Set + @Input get() = languageSettings?.experimentalAnnotationsInUse.orEmpty() // endregion. // region DSL for compiler options @@ -227,6 +226,9 @@ open class KotlinNativeCompile : AbstractCompile() { enabledLanguageFeatures.forEach { featureName -> add("-XXLanguage:+$featureName") } + experimentalAnnotationsInUse.forEach { annotationName -> + add("-Xuse-experimental=$annotationName") + } // Compiler plugins. compilerPluginClasspath?.let { pluginClasspath ->