diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index bff8ab610c2..c5669979e02 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -28,7 +28,7 @@ abstract class BaseGradleIT { protected var workingDir = File(".") - protected open fun defaultBuildOptions(): BuildOptions = BuildOptions(withDaemon = true) + internal open fun defaultBuildOptions(): BuildOptions = BuildOptions(withDaemon = true) open val defaultGradleVersion: GradleVersionRequired get() = GradleVersionRequired.None diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt new file mode 100644 index 00000000000..7c916a87290 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinSpecificDependenciesIT.kt @@ -0,0 +1,307 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle + +import org.jetbrains.kotlin.gradle.internals.KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME +import org.jetbrains.kotlin.gradle.util.AGPVersion +import org.jetbrains.kotlin.gradle.util.modify +import org.jetbrains.kotlin.test.KotlinTestUtils +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class KotlinSpecificDependenciesIT : BaseGradleIT() { + + override val defaultGradleVersion: GradleVersionRequired + get() = GradleVersionRequired.FOR_MPP_SUPPORT + + override fun defaultBuildOptions(): BuildOptions = + super.defaultBuildOptions().copy(androidGradlePluginVersion = AGPVersion.v3_6_0, androidHome = KotlinTestUtils.findAndroidSdk()) + + private var testBuildRunId = 0 + + private fun Project.prepare() { // call this when reusing a project after a test, too, in order to remove any added dependencies + setupWorkingDir() + gradleSettingsScript().takeIf { it.exists() }?.modify(::transformBuildScriptWithPluginsDsl) + gradleBuildScript().modify { + transformBuildScriptWithPluginsDsl(it).lines().filter { line -> + "stdlib" !in line && "kotlin(\"test" !in line && "kotlin-test" !in line + }.joinToString("\n") + } + } + + private fun jsProject() = Project("kotlin-js-plugin-project").apply { + setupWorkingDir() + gradleBuildScript().modify { it.lines().filter { "html" !in it }.joinToString("\n") } + projectFile("Main.kt").modify { "fun f() = listOf(1, 2, 3).joinToString()" } + prepare() + } + + private fun androidProject() = Project("AndroidLibraryKotlinProject").apply { prepare() } + + private fun mppProject() = Project("jvm-and-js-hmpp").apply { + setupWorkingDir() + prepare() + } + + private fun jvmProject() = Project("simpleProject").apply { + prepare() + gradleBuildScript().modify { it.lines().filter { "testng" !in it }.joinToString("\n") } + } + + @Test + fun testStdlibByDefault() { + listOf( // projects and tasks: + androidProject() to listOf("compileDebugKotlin"), + jvmProject() to listOf("compileKotlin"), + jsProject() to listOf("compileKotlinJs"), + mppProject() to listOf( + "compileKotlinJvm", + "compileKotlinJs", + "compileCommonMainKotlinMetadata", + "compileJvmAndJsMainKotlinMetadata" + ) + ).forEach { (project, tasks) -> + with(project) { + prepare() + tasks.forEach { task -> + project.checkTaskCompileClasspath(task, listOf("kotlin-stdlib" /*any of them*/)) + } + projectDir.resolve("gradle.properties").appendText( + "\nkotlin.stdlib.default.dependency=false" + ) + tasks.forEach { task -> + project.checkTaskCompileClasspath(task, listOf(), checkModulesNotInClasspath = listOf("kotlin-stdlib" /*any of them*/)) + } + } + } + } + + @Test + fun testStdlibBasedOnJdk() = with(jvmProject()) { + prepare() + gradleBuildScript().modify { "$it\nkotlin.target.compilations[\"main\"].kotlinOptions { jvmTarget = \"1.6\" }" } + val version = defaultBuildOptions().kotlinVersion + checkTaskCompileClasspath( + "compileKotlin", + listOf("kotlin-stdlib-$version"), + listOf("kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8") + ) + gradleBuildScript().modify { "$it\nkotlin.target.compilations[\"main\"].kotlinOptions { jvmTarget = \"11\" }" } + checkTaskCompileClasspath( + "compileKotlin", + listOf("kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8"), + ) + } + + @Test + fun testOverrideStdlib() = with(jvmProject().apply { prepare() }) { + gradleBuildScript().appendText( + "\n" + """ + kotlin.target.compilations["main"].kotlinOptions.jvmTarget = "1.8" + dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib") } + """.trimIndent() + ) + // Check that the explicit stdlib overrides the plugin's choice of stdlib-jdk8 + checkTaskCompileClasspath( + "compileKotlin", + listOf("kotlin-stdlib-${defaultBuildOptions().kotlinVersion}"), + listOf("kotlin-stdlib-jdk8") + ) + } + + private val kotlinTestMultiplatformDependency = "org.jetbrains.kotlin:$KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME" + + @Test + fun testKotlinTestSingleDependency() { + data class TestCase( + val project: Project, + val configurationsToAddDependency: List, + val classpathElementsExpectedByTask: Map>, + val filesExpectedByConfiguration: Map> = emptyMap() + ) + + listOf( + TestCase( + androidProject(), + listOf("testImplementation"), + mapOf( + "compileDebugUnitTestKotlin" to listOf("kotlin-test-junit"), + "compileReleaseUnitTestKotlin" to listOf("kotlin-test-junit") + ) + ), + TestCase( + androidProject(), + listOf("androidTestImplementation"), + mapOf("compileDebugAndroidTestKotlin" to listOf("kotlin-test-junit")) + ), + TestCase(jvmProject(), listOf("testImplementation"), mapOf("compileTestKotlin" to listOf("kotlin-test-testng"))), + TestCase(jsProject(), listOf("testImplementation"), mapOf("compileTestKotlinJs" to listOf("kotlin-test-js"))), + TestCase( + mppProject(), + listOf("commonTestImplementation"), + mapOf( + "compileTestKotlinJvm" to listOf("kotlin-test-junit"), + "compileTestKotlinJs" to listOf("kotlin-test-js") + ), + mapOf( + "commonTestImplementationDependenciesMetadata" to listOf("kotlin-test-common", "kotlin-test-annotations-common"), + "commonTestApiDependenciesMetadata" to listOf("!kotlin-test-common", "!kotlin-test-annotations-common"), + ) + ), + TestCase( + mppProject(), + listOf("jvmAndJsTestApi", "jvmAndJsTestCompileOnly"), // add to the intermediate source set, and to two scopes + mapOf( + "compileTestKotlinJvm" to listOf("kotlin-test-junit"), + "compileTestKotlinJs" to listOf("kotlin-test-js") + ), + mapOf( + "commonTestApiDependenciesMetadata" to listOf("!kotlin-test-common"), + "commonTestCompileOnlyDependenciesMetadata" to listOf("!kotlin-test-common"), + "jvmAndJsTestApiDependenciesMetadata" to listOf("kotlin-test-common"), + "jvmAndJsTestCompileOnlyDependenciesMetadata" to listOf("kotlin-test-common"), + "jvmAndJsTestImplementationDependenciesMetadata" to listOf("!kotlin-test-common"), + ) + ) + ).forEach { testCase -> + with(testCase) { + project.prepare() + project.gradleBuildScript().appendText( + configurationsToAddDependency.joinToString("\n", "\n") { configuration -> + "\ndependencies { \"$configuration\"(\"$kotlinTestMultiplatformDependency\") }" + } + ) + classpathElementsExpectedByTask.forEach { (task, expected) -> + val (notInClasspath, inClasspath) = expected.partition { it.startsWith("!") } + project.checkTaskCompileClasspath(task, inClasspath, notInClasspath.map { it.removePrefix("!") }) + } + filesExpectedByConfiguration.forEach { (configuration, expected) -> + val (notInItems, inItems) = expected.partition { it.startsWith("!") } + project.checkConfigurationContent(configuration, subproject = null, inItems, notInItems.map { it.removePrefix("!") }) + } + } + } + } + + @Test + fun testFrameworkSelection() { + data class TestCase( + val project: Project, + val testTaskName: String, + val compileTaskName: String, + val configurationToAddDependency: String + ) + + val frameworks = listOf("useJUnit()" to "junit", "useTestNG()" to "testng", "useJUnitPlatform()" to "junit5") + listOf( + TestCase(jvmProject(), "test", "compileTestKotlin", "testImplementation"), + TestCase(mppProject(), "jvmTest", "compileTestKotlinJvm", "commonTestImplementation"), + TestCase(mppProject(), "jvmTest", "compileTestKotlinJvm", "jvmAndJsTestImplementation") + ).forEach { (project, testTaskName, compileTaskName, configuration) -> + project.prepare() + project.gradleBuildScript().appendText("""${'\n'}dependencies { "$configuration"("$kotlinTestMultiplatformDependency") }""") + + frameworks.forEach { (setup, frameworkName) -> + with(project) { + gradleBuildScript().appendText("\n(tasks.getByName(\"$testTaskName\") as Test).$setup") + val expectedModule = "kotlin-test-$frameworkName-" + checkTaskCompileClasspath( + compileTaskName, + listOf(expectedModule), + frameworks.map { "kotlin-test-" + it.second + "-" } - expectedModule + ) + } + } + } + } + + @Test + fun testRemoveKotlinTestDependency() = with(jvmProject().apply { prepare() }) { + gradleBuildScript().appendText( + "\n" + """ + dependencies { testImplementation("$kotlinTestMultiplatformDependency") } + configurations.getByName("testImplementation").dependencies.removeAll { it.name == "$KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME" } + """.trimIndent() + ) + checkTaskCompileClasspath("compileTestKotlin", checkModulesNotInClasspath = listOf("kotlin-test")) + + // Add it back after removal: + gradleBuildScript().appendText( + "\n" + """ + dependencies { testImplementation("$kotlinTestMultiplatformDependency") } + """ + ) + checkTaskCompileClasspath("compileTestKotlin", checkModulesInClasspath = listOf("kotlin-test")) + } + + @Test + fun testCoreLibraryVersionsDsl() = with(jvmProject().apply { prepare() }) { + val customVersion = "1.3.70" + gradleBuildScript().appendText( + "\n" + """ + kotlin.coreLibrariesVersion = "$customVersion" + dependencies { + testImplementation("org.jetbrains.kotlin:kotlin-reflect") + testImplementation("org.jetbrains.kotlin:kotlin-test-multiplatform") + } + test.useJUnit() + """.trimIndent() + ) + checkTaskCompileClasspath( + "compileTestKotlin", + listOf("kotlin-stdlib-", "kotlin-reflect-", "kotlin-test-junit-").map { it + customVersion } + ) + } + + private fun Project.checkConfigurationContent( + configurationName: String, + subproject: String? = null, + checkModulesInResolutionResult: List = emptyList(), + checkModulesNotInResolutionResult: List = emptyList() + ) { + val expression = """configurations["$configurationName"].toList()""" + checkPrintedItems(subproject, expression, checkModulesInResolutionResult, checkModulesNotInResolutionResult) + } + + private fun Project.checkTaskCompileClasspath( + taskPath: String, + checkModulesInClasspath: List = emptyList(), + checkModulesNotInClasspath: List = emptyList() + ) { + val subproject = taskPath.substringBeforeLast(":").takeIf { it.isNotEmpty() && it != taskPath } + val taskName = taskPath.removePrefix(subproject.orEmpty()) + val expression = """(tasks.getByName("$taskName") as AbstractCompile).classpath.toList()""" + checkPrintedItems(subproject, expression, checkModulesInClasspath, checkModulesNotInClasspath) + } + + private fun Project.checkPrintedItems( + subproject: String?, + itemsExpression: String, + checkAnyItemsContains: List, + checkNoItemContains: List + ) { + setupWorkingDir() + val printingTaskName = "printItems${testBuildRunId++}" + gradleBuildScript(subproject).appendText( + """ + ${'\n'} + tasks.create("$printingTaskName") { + doLast { + println("###$printingTaskName" + $itemsExpression) + } + } + """.trimIndent() + ) + build("${subproject?.prependIndent(":").orEmpty()}:$printingTaskName") { + assertSuccessful() + val itemsLine = output.lines().single { "###$printingTaskName" in it }.substringAfter(printingTaskName) + val items = itemsLine.removeSurrounding("[", "]").split(", ").toSet() + checkAnyItemsContains.forEach { pattern -> assertTrue { items.any { pattern in it } } } + checkNoItemContains.forEach { pattern -> assertFalse { items.any { pattern in it } } } + } + } +} \ 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 14010fca230..57a5ddcb4ea 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 @@ -2107,13 +2107,13 @@ class NewMultiplatformIT : BaseGradleIT() { fun testDependencies() = testResolveAllConfigurations("app") { assertContains(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata --> junit-4.12.jar") assertEquals( - 1, + 2, // the dependency above and stdlib (Regex.escape(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata") + " .*").toRegex().findAll(output).count() ) assertContains(">> :app:testNonTransitiveDependencyNotationApiDependenciesMetadata --> kotlin-reflect-${defaultBuildOptions().kotlinVersion}.jar") assertEquals( - 1, + 2, // the dependency above and stdlib (Regex.escape(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata") + " .*").toRegex().findAll(output).count() ) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/build.gradle.kts new file mode 100644 index 00000000000..6cb16f2b5e6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/build.gradle.kts @@ -0,0 +1,67 @@ +plugins { + kotlin("multiplatform").version("") + `maven-publish` +} + +repositories { + mavenLocal() + jcenter() +} + +group = "com.example.thirdparty" +version = "1.0" + +kotlin { + jvm() + js() + + sourceSets { + val commonMain by getting { + dependencies { + implementation(kotlin("stdlib-common")) + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + implementation(kotlin("test-annotations-common")) + } + } + val jvmAndJsMain by creating { + dependsOn(commonMain) + } + val jvmAndJsTest by creating { + dependsOn(commonTest) + } + jvm().compilations["main"].defaultSourceSet { + dependsOn(jvmAndJsMain) + dependencies { + implementation(kotlin("stdlib")) + } + } + jvm().compilations["test"].defaultSourceSet { + dependsOn(jvmAndJsTest) + dependencies { + implementation(kotlin("test-junit")) + } + } + js().compilations["main"].defaultSourceSet { + dependsOn(jvmAndJsMain) + dependencies { + implementation(kotlin("stdlib-js")) + } + } + js().compilations["test"].defaultSourceSet { + dependsOn(jvmAndJsTest) + dependencies { + implementation(kotlin("test-js")) + } + } + } +} + +publishing { + repositories { + maven("../repo") + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/gradle.properties new file mode 100755 index 00000000000..2a391fe78b0 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/gradle.properties @@ -0,0 +1 @@ +kotlin.mpp.enableGranularSourceSetsMetadata=true \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/settings.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/settings.gradle.kts new file mode 100644 index 00000000000..055148414fb --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/settings.gradle.kts @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + } +} + +rootProject.name = "third-party-lib" + +enableFeaturePreview("GRADLE_METADATA") \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/commonMain/kotlin/ThirdParty.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/commonMain/kotlin/ThirdParty.kt new file mode 100644 index 00000000000..52ee4ee68a6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/commonMain/kotlin/ThirdParty.kt @@ -0,0 +1,5 @@ +package com.example.thirdparty + +expect fun thirdPartyFun(): String + +private fun useStdlibInCommonMain() = listOf(1, 2, 3).joinToString() \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jsMain/kotlin/ThirdPartyJs.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jsMain/kotlin/ThirdPartyJs.kt new file mode 100644 index 00000000000..dba00046373 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jsMain/kotlin/ThirdPartyJs.kt @@ -0,0 +1,5 @@ +package com.example.thirdparty + +actual fun thirdPartyFun(): String = "thirdPartyFun @ js" + +fun thirdPartyJsFun() { } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmAndJsMain/kotlin/ThirdPartyJvmAndJs.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmAndJsMain/kotlin/ThirdPartyJvmAndJs.kt new file mode 100644 index 00000000000..21856b2ffb3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmAndJsMain/kotlin/ThirdPartyJvmAndJs.kt @@ -0,0 +1,3 @@ +package com.example.thirdparty + +private fun useStdlibInJvmAndJsMain() = listOf(1, 2, 3).joinToString() \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmMain/kotlin/ThirdPartyJvm.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmMain/kotlin/ThirdPartyJvm.kt new file mode 100644 index 00000000000..ad7e11903d8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/jvm-and-js-hmpp/src/jvmMain/kotlin/ThirdPartyJvm.kt @@ -0,0 +1,5 @@ +package com.example.thirdparty + +actual fun thirdPartyFun(): String = "thirdPartyFun @ jvm" + +fun thirdPartyJvmFun() { } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt index 8a6ee31ef53..0ed2ff1b822 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt @@ -47,6 +47,8 @@ open class KotlinProjectExtension : KotlinSourceSetContainer { val experimental: ExperimentalExtension get() = DslObject(this).extensions.getByType(ExperimentalExtension::class.java) + lateinit var coreLibrariesVersion: String + var explicitApi: ExplicitApiMode? = null fun explicitApi() { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt new file mode 100644 index 00000000000..a2f6d675171 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt @@ -0,0 +1,246 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.internal + +import com.android.build.gradle.api.TestVariant +import com.android.build.gradle.api.UnitTestVariant +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ExternalDependency +import org.gradle.api.tasks.testing.AbstractTestTask +import org.gradle.api.tasks.testing.Test +import org.gradle.api.tasks.testing.junit.JUnitOptions +import org.gradle.api.tasks.testing.junitplatform.JUnitPlatformOptions +import org.gradle.api.tasks.testing.testng.TestNGOptions +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions +import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.execution.KotlinAggregateExecutionSource +import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider +import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget +import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope +import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy +import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope +import org.jetbrains.kotlin.gradle.targets.jvm.JvmCompilationsTestRunSource +import org.jetbrains.kotlin.gradle.tasks.KOTLIN_MODULE_GROUP +import org.jetbrains.kotlin.gradle.tasks.locateTask +import org.jetbrains.kotlin.gradle.testing.KotlinTaskTestRun +import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName + +internal fun customizeKotlinDependencies(project: Project) { + configureStdlibDefaultDependency(project) + configureKotlinTestDependencies(project) + configureDefaultVersionsResolutionStrategy(project) +} + +private fun configureDefaultVersionsResolutionStrategy(project: Project) { + project.configurations.all { configuration -> + // Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved: + configuration.withDependencies { dependencySet -> + val coreLibrariesVersion = project.kotlinExtension.coreLibrariesVersion + dependencySet.filterIsInstance() + .filter { it.group == KOTLIN_MODULE_GROUP && it.version.isNullOrEmpty() } + .forEach { it.version { constraint -> constraint.require(coreLibrariesVersion) } } + } + } +} + +//region stdlib +internal fun configureStdlibDefaultDependency(project: Project) { + if (!PropertiesProvider(project).stdlibDefaultDependency) + return + + project.kotlinExtension.sourceSets.all { kotlinSourceSet -> + val apiConfiguration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, KotlinDependencyScope.API_SCOPE) + + apiConfiguration.withDependencies { dependencies -> + val sourceSetDependencyConfigurations = + KotlinDependencyScope.values().map { project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, it) } + + val hierarchySourceSetsDependencyConfigurations = kotlinSourceSet.getSourceSetHierarchy().flatMap { hierarchySourceSet -> + if (hierarchySourceSet === kotlinSourceSet) emptyList() else + KotlinDependencyScope.values().map { scope -> + project.sourceSetDependencyConfigurationByScope(hierarchySourceSet, scope) + } + } + + val compilations = CompilationSourceSetUtil.compilationsBySourceSets(project).getValue(kotlinSourceSet) + .filter { it.target !is KotlinMetadataTarget } + val platformTypes = compilations.mapTo(mutableSetOf()) { it.platformType } + + val sourceSetStdlibPlatformType = when { + platformTypes.isEmpty() -> KotlinPlatformType.common + setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> KotlinPlatformType.jvm + platformTypes.size == 1 -> platformTypes.single() + else -> KotlinPlatformType.common + } + + val isStdlibAddedByUser = sourceSetDependencyConfigurations + .flatMap { it.allDependencies } + .any { dependency -> dependency.group == KOTLIN_MODULE_GROUP && dependency.name in stdlibModules } + + if (!isStdlibAddedByUser) { + val stdlibModuleName = when (sourceSetStdlibPlatformType) { + KotlinPlatformType.jvm, KotlinPlatformType.androidJvm -> jvmStdlibModuleForJvmCompilations(compilations) + KotlinPlatformType.js -> "kotlin-stdlib-js" + KotlinPlatformType.native -> null + KotlinPlatformType.common -> // there's no platform compilation that the source set is default for + "kotlin-stdlib-common" + } + + // If the exact same module is added in the source sets hierarchy, possibly even with a different scope, we don't add it + val moduleAddedInHierarchy = hierarchySourceSetsDependencyConfigurations.any { + it.allDependencies.any { dependency -> dependency.group == KOTLIN_MODULE_GROUP && dependency.name == stdlibModuleName } + } + + if (stdlibModuleName != null && !moduleAddedInHierarchy) + dependencies.add(project.kotlinDependency(stdlibModuleName, project.kotlinExtension.coreLibrariesVersion)) + } + } + } +} + +private val stdlibModules = setOf("kotlin-stdlib-common", "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-stdlib-js") + +private fun jvmStdlibModuleForJvmCompilations(compilations: Iterable>): String { + val jvmTargets = compilations.map { (it.kotlinOptions as KotlinJvmOptions).jvmTarget } + return if ("1.6" in jvmTargets) "kotlin-stdlib" else "kotlin-stdlib-jdk8" +} +//endregion + +//region kotlin-test +internal fun configureKotlinTestDependencies(project: Project) { + fun isKotlinTestMultiplatformDependency(dependency: Dependency) = + dependency.group == KOTLIN_MODULE_GROUP && dependency.name == KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME + + KotlinDependencyScope.values().forEach { scope -> + val versionOrNullBySourceSet = mutableMapOf() + + project.kotlinExtension.sourceSets.all { kotlinSourceSet -> + val configuration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope) + var finalizingDependencies = false + + configuration.dependencies.matching(::isKotlinTestMultiplatformDependency).apply { + firstOrNull()?.let { versionOrNullBySourceSet[kotlinSourceSet] = it.version } + whenObjectRemoved { + if (!finalizingDependencies && !any()) + versionOrNullBySourceSet.remove(kotlinSourceSet) + } + whenObjectAdded { item -> + versionOrNullBySourceSet[kotlinSourceSet] = item.version + } + } + + configuration.withDependencies { dependencies -> + val parentOrOwnVersions: List = + kotlinSourceSet.getSourceSetHierarchy().filter(versionOrNullBySourceSet::contains).map(versionOrNullBySourceSet::get) + + finalizingDependencies = true + + parentOrOwnVersions.distinct().forEach { version -> // add dependencies with each version and let Gradle disambiguate them + val dependenciesToAdd = kotlinTestDependenciesForSourceSet(project, kotlinSourceSet, version) + dependenciesToAdd.filterIsInstance().forEach { + if (it.version == null) { + it.version { constraint -> constraint.require(project.kotlinExtension.coreLibrariesVersion) } + } + } + dependencies.addAll(dependenciesToAdd) + dependencies.removeIf(::isKotlinTestMultiplatformDependency) + } + } + } + } +} + +private fun kotlinTestDependenciesForSourceSet(project: Project, kotlinSourceSet: KotlinSourceSet, version: String?): List { + val compilations = CompilationSourceSetUtil.compilationsBySourceSets(project).getValue(kotlinSourceSet) + .filter { it.target !is KotlinMetadataTarget } + + val platformTypes = compilations.mapTo(mutableSetOf()) { it.platformType } + + return when { + platformTypes.isEmpty() -> emptyList() + setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> listOf( + kotlinTestDependenciesForJvm(project, compilations, version) + ) + platformTypes.singleOrNull() == KotlinPlatformType.js -> listOf( + project.kotlinDependency("kotlin-test-js", version) + ) + platformTypes.singleOrNull() == KotlinPlatformType.native -> emptyList() + else -> listOf( + project.kotlinDependency("kotlin-test-common", version), + project.kotlinDependency("kotlin-test-annotations-common", version) + ) + } +} + +internal const val KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME = "kotlin-test-multiplatform" + +private fun Project.kotlinDependency(moduleName: String, versionOrNull: String?) = + project.dependencies.create("$KOTLIN_MODULE_GROUP:$moduleName${versionOrNull?.prependIndent(":").orEmpty()}") + +private fun kotlinTestDependenciesForJvm(project: Project, compilations: Iterable>, version: String?): Dependency { + val testTaskLists: List?> = compilations.map { compilation -> + val target = compilation.target + when { + target is KotlinTargetWithTests<*, *> -> + target.findTestRunsByCompilation(compilation)?.filterIsInstance>()?.map { it.executionTask.get() } + target is KotlinWithJavaTarget<*> -> + if (compilation.name == KotlinCompilation.TEST_COMPILATION_NAME) + project.locateTask(target.testTaskName)?.get()?.let(::listOf) + else null + compilation is KotlinJvmAndroidCompilation -> when (compilation.androidVariant) { + is UnitTestVariant -> + project.locateTask(lowerCamelCaseName("test", compilation.androidVariant.name))?.get()?.let(::listOf) + is TestVariant -> (compilation.androidVariant as TestVariant).connectedInstrumentTest?.let(::listOf) + else -> null + } + else -> null + } + } + if (null in testTaskLists) { + return project.kotlinDependency("kotlin-test", version) + } + val testTasks = testTaskLists.flatMap { checkNotNull(it) } + val frameworks = testTasks.mapTo(mutableSetOf()) { testTask -> + when (testTask) { + is Test -> testFrameworkOf(testTask) + else -> // Android connected test tasks don't inherit from Test, but we use JUnit for them + KotlinTestJvmFramework.junit + } + } + return when { + frameworks.size > 1 -> project.kotlinDependency("kotlin-test", version) + else -> project.kotlinDependency("kotlin-test-${frameworks.single().name}", version) + } +} + +private enum class KotlinTestJvmFramework { + junit, testng, junit5 +} + +private fun testFrameworkOf(testTask: Test): KotlinTestJvmFramework = when (testTask.options) { + is JUnitOptions -> KotlinTestJvmFramework.junit + is JUnitPlatformOptions -> KotlinTestJvmFramework.junit5 + is TestNGOptions -> KotlinTestJvmFramework.testng + else -> // failed to detect, fallback to junit + KotlinTestJvmFramework.junit +} + +private fun KotlinTargetWithTests<*, *>.findTestRunsByCompilation(byCompilation: KotlinCompilation<*>): List>? { + fun KotlinExecution.ExecutionSource.isProducedFromTheCompilation(): Boolean = when (this) { + is CompilationExecutionSource<*> -> compilation == byCompilation + is JvmCompilationsTestRunSource -> byCompilation in testCompilations + is KotlinAggregateExecutionSource<*> -> this.executionSources.any { it.isProducedFromTheCompilation() } + else -> false + } + return testRuns.filter { it.executionSource.isProducedFromTheCompilation() }.takeIf { it.isNotEmpty() } +} +//endregion \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index dd9322b85d8..b05e6ba791b 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -6,11 +6,8 @@ package org.jetbrains.kotlin.gradle.plugin import com.android.build.gradle.* -import com.android.build.gradle.api.AndroidSourceSet -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.SourceKind +import com.android.build.gradle.api.* import org.gradle.api.* -import org.gradle.api.artifacts.ExternalDependency import org.gradle.api.artifacts.maven.Conf2ScopeMappingContainer import org.gradle.api.artifacts.maven.MavenResolver import org.gradle.api.attributes.Usage @@ -32,8 +29,9 @@ import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.jvm.tasks.Jar import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.jetbrains.kotlin.gradle.dsl.* -import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin +import org.jetbrains.kotlin.gradle.internal.* import org.jetbrains.kotlin.gradle.internal.checkAndroidAnnotationProcessorDependencyUsage +import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.model.builder.KotlinModelBuilder import org.jetbrains.kotlin.gradle.plugin.mpp.* @@ -412,7 +410,7 @@ internal abstract class AbstractKotlinPlugin( rewriteMppDependenciesInPom(target) - configureProjectGlobalSettings(project, kotlinPluginVersion) + configureProjectGlobalSettings(project) registry.register(KotlinModelBuilder(kotlinPluginVersion, null)) project.components.addAll(target.components) @@ -452,8 +450,8 @@ internal abstract class AbstractKotlinPlugin( } companion object { - fun configureProjectGlobalSettings(project: Project, kotlinPluginVersion: String) { - configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) + fun configureProjectGlobalSettings(project: Project) { + customizeKotlinDependencies(project) configureClassInspectionForIC(project) project.setupGeneralKotlinExtensionParameters() } @@ -590,17 +588,6 @@ internal abstract class AbstractKotlinPlugin( } } -internal fun configureDefaultVersionsResolutionStrategy(project: Project, kotlinPluginVersion: String) { - project.configurations.all { configuration -> - // Use the API introduced in Gradle 4.4 to modify the dependencies directly before they are resolved: - configuration.withDependencies { dependencySet -> - dependencySet.filterIsInstance() - .filter { it.group == "org.jetbrains.kotlin" && it.version.isNullOrEmpty() } - .forEach { it.version { constraint -> constraint.require(kotlinPluginVersion) } } - } - } -} - internal open class KotlinPlugin( kotlinPluginVersion: String, registry: ToolingModelBuilderRegistry @@ -703,7 +690,7 @@ internal open class KotlinAndroidPlugin( applyUserDefinedAttributes(androidTarget) - configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) + customizeKotlinDependencies(project) registry.register(KotlinModelBuilder(kotlinPluginVersion, androidTarget)) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index 0a6f897043f..0ee7e85c486 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -78,6 +78,8 @@ abstract class KotlinBasePluginWrapper( kotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion) project.createKotlinExtension(projectExtensionClass).apply { + coreLibrariesVersion = kotlinPluginVersion + fun kotlinSourceSetContainer(factory: NamedDomainObjectFactory) = project.container(KotlinSourceSet::class.java, factory) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt index 918057a0512..60916deb739 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt @@ -202,6 +202,9 @@ internal class PropertiesProvider private constructor(private val project: Proje val jsCompiler: KotlinJsCompilerType get() = property(jsCompilerProperty)?.let { KotlinJsCompilerType.byArgumentOrNull(it) } ?: KotlinJsCompilerType.LEGACY + val stdlibDefaultDependency: Boolean + get() = booleanProperty("kotlin.stdlib.default.dependency") ?: true + private fun propertyWithDeprecatedVariant(propName: String, deprecatedPropName: String): String? { val deprecatedProperty = property(deprecatedPropName) if (deprecatedProperty != null) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 6891f0603bc..37e3ba6d4ab 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.configureOrCreate import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin.Companion.sourceSetFreeCompilerArgsPropertyName import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder @@ -84,7 +85,7 @@ class KotlinMultiplatformPlugin( } setupDefaultPresets(project) - configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) + customizeKotlinDependencies(project) configureSourceSets(project) // set up metadata publishing diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt index 1eeea339e4c..da9769e154f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt @@ -21,6 +21,7 @@ import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.internal.component.SoftwareComponentInternal import org.gradle.api.internal.component.UsageContext import org.gradle.api.internal.project.ProjectInternal +import org.gradle.api.provider.Provider import org.gradle.api.publish.maven.MavenPublication import org.gradle.util.ConfigureUtil import org.gradle.util.WrapUtil @@ -98,7 +99,10 @@ abstract class AbstractKotlinTarget( ?: project.configurations.create(kotlinUsageContext.name).also { configuration -> configuration.isCanBeConsumed = false configuration.isCanBeResolved = false - configuration.dependencies.addAll(kotlinUsageContext.dependencies) + /** Add dependencies lazily to avoid freezing the content of the configuration held by [kotlinUsageContext] */ + configuration.withDependencies { dependencies -> + dependencies.addAll(kotlinUsageContext.dependencies) + } configuration.dependencyConstraints.addAll(kotlinUsageContext.dependencyConstraints) configuration.artifacts.addAll(kotlinUsageContext.artifacts) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsPlugin.kt index ea3344ca0a8..d6f2c72ee03 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsPlugin.kt @@ -10,10 +10,10 @@ import org.gradle.api.Project import org.gradle.api.plugins.JavaBasePlugin import org.jetbrains.kotlin.gradle.dsl.KotlinJsProjectExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider -import org.jetbrains.kotlin.gradle.plugin.configureDefaultVersionsResolutionStrategy import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsSingleTargetPreset import org.jetbrains.kotlin.gradle.plugin.whenEvaluated import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrSingleTargetPreset @@ -36,7 +36,7 @@ open class KotlinJsPlugin( checkGradleCompatibility() val kotlinExtension = project.kotlinExtension as KotlinJsProjectExtension - configureDefaultVersionsResolutionStrategy(project, kotlinPluginVersion) + customizeKotlinDependencies(project) kotlinExtension.apply { irPreset = KotlinJsIrSingleTargetPreset(project, kotlinPluginVersion) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTestRun.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTestRun.kt index a6fc642114c..fc8d4e9d5e4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTestRun.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/jvm/KotlinJvmTestRun.kt @@ -64,6 +64,7 @@ open class KotlinJvmTestRun(testRunName: String, override val target: KotlinJvmT get() = _executionSource private set(value) { setTestTaskClasspathAndClassesDirs(value.classpath, value.testClassesDirs) + _executionSource = value } private fun setTestTaskClasspathAndClassesDirs(classpath: FileCollection, testClassesDirs: FileCollection) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internals/ExposedForIntegrationTests.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internals/ExposedForIntegrationTests.kt index 1cd9ad5d151..a7c224b5349 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internals/ExposedForIntegrationTests.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internals/ExposedForIntegrationTests.kt @@ -26,3 +26,5 @@ const val NO_NATIVE_STDLIB_WARNING = NO_NATIVE_STDLIB_WARNING const val NO_NATIVE_STDLIB_PROPERTY_WARNING = NO_NATIVE_STDLIB_PROPERTY_WARNING val KOTLIN_12X_MPP_DEPRECATION_WARNING = KOTLIN_12X_MPP_DEPRECATION_WARNING + +const val KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME = org.jetbrains.kotlin.gradle.internal.KOTLIN_TEST_MULTIPLATFORM_MODULE_NAME \ No newline at end of file