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 index a2f6d675171..97920c0e41c 100644 --- 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 @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.gradle.internal +import com.android.build.gradle.TestedExtension import com.android.build.gradle.api.TestVariant import com.android.build.gradle.api.UnitTestVariant import org.gradle.api.Project @@ -16,15 +17,15 @@ 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.KotlinAndroidProjectExtension import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension 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.* 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 @@ -53,14 +54,18 @@ private fun configureDefaultVersionsResolutionStrategy(project: Project) { } //region stdlib -internal fun configureStdlibDefaultDependency(project: Project) { +internal fun configureStdlibDefaultDependency(project: Project) = project.whenEvaluated { if (!PropertiesProvider(project).stdlibDefaultDependency) - return + return@whenEvaluated project.kotlinExtension.sourceSets.all { kotlinSourceSet -> - val apiConfiguration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, KotlinDependencyScope.API_SCOPE) + val scope = if (isRelatedToAndroidTestSourceSet(project, kotlinSourceSet)) // AGP deprecates API configurations in test source sets + KotlinDependencyScope.IMPLEMENTATION_SCOPE + else KotlinDependencyScope.API_SCOPE - apiConfiguration.withDependencies { dependencies -> + val scopeConfiguration = project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope) + + scopeConfiguration.withDependencies { dependencies -> val sourceSetDependencyConfigurations = KotlinDependencyScope.values().map { project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, it) } @@ -77,8 +82,8 @@ internal fun configureStdlibDefaultDependency(project: Project) { val sourceSetStdlibPlatformType = when { platformTypes.isEmpty() -> KotlinPlatformType.common - setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> KotlinPlatformType.jvm platformTypes.size == 1 -> platformTypes.single() + setOf(KotlinPlatformType.jvm, KotlinPlatformType.androidJvm).containsAll(platformTypes) -> KotlinPlatformType.jvm else -> KotlinPlatformType.common } @@ -88,7 +93,9 @@ internal fun configureStdlibDefaultDependency(project: Project) { if (!isStdlibAddedByUser) { val stdlibModuleName = when (sourceSetStdlibPlatformType) { - KotlinPlatformType.jvm, KotlinPlatformType.androidJvm -> jvmStdlibModuleForJvmCompilations(compilations) + KotlinPlatformType.jvm -> stdlibModuleForJvmCompilations(compilations) + KotlinPlatformType.androidJvm -> + if (kotlinSourceSet.name == androidMainSourceSetName(project)) stdlibModuleForJvmCompilations(compilations) else null KotlinPlatformType.js -> "kotlin-stdlib-js" KotlinPlatformType.native -> null KotlinPlatformType.common -> // there's no platform compilation that the source set is default for @@ -107,9 +114,42 @@ internal fun configureStdlibDefaultDependency(project: Project) { } } +private fun Project.findAndroidTarget(): KotlinAndroidTarget? { + val kotlinExtension = project.kotlinExtension + return when (kotlinExtension) { + is KotlinMultiplatformExtension -> kotlinExtension.targets.withType(KotlinAndroidTarget::class.java).single() + is KotlinAndroidProjectExtension -> kotlinExtension.target + else -> null + } +} + +private fun androidMainSourceSetName(project: Project): String { + val target = project.findAndroidTarget() ?: error("No Android target found") + return AbstractAndroidProjectHandler.kotlinSourceSetNameForAndroidSourceSet(target, "main") +} + +private fun isRelatedToAndroidTestSourceSet(project: Project, kotlinSourceSet: KotlinSourceSet): Boolean { + val androidExtension = project.extensions.findByName("android") as? TestedExtension ?: return false + val androidTarget = project.findAndroidTarget() ?: return false + + if (androidTarget.compilations.any { + (it.androidVariant is UnitTestVariant || it.androidVariant is TestVariant) && it.defaultSourceSet === kotlinSourceSet + } + ) return true + + (androidExtension.testVariants + androidExtension.unitTestVariants).forEach { variant -> + if (variant.sourceSets.any { + kotlinSourceSet.name == AbstractAndroidProjectHandler.kotlinSourceSetNameForAndroidSourceSet(androidTarget, it.name) + } + ) return true + } + + return false +} + private val stdlibModules = setOf("kotlin-stdlib-common", "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8", "kotlin-stdlib-js") -private fun jvmStdlibModuleForJvmCompilations(compilations: Iterable>): String { +private fun stdlibModuleForJvmCompilations(compilations: Iterable>): String { val jvmTargets = compilations.map { (it.kotlinOptions as KotlinJvmOptions).jvmTarget } return if ("1.6" in jvmTargets) "kotlin-stdlib" else "kotlin-stdlib-jdk8" } 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 b05e6ba791b..39b187d9b2a 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 @@ -735,6 +735,11 @@ class KotlinConfigurationTools internal constructor( ) abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTools: KotlinConfigurationTools) { + companion object { + fun kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget: KotlinAndroidTarget, androidSourceSetName: String) = + lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, androidSourceSetName) + } + protected val logger = Logging.getLogger(this.javaClass) abstract fun getFlavorNames(variant: BaseVariant): List @@ -762,7 +767,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool ext.sourceSets.all { sourceSet -> logger.kotlinDebug("Creating KotlinBaseSourceSet for source set $sourceSet") val kotlinSourceSet = project.kotlinExtension.sourceSets.maybeCreate( - lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, sourceSet.name) + kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget, sourceSet.name) ).apply { kotlin.srcDir(project.file(project.file("src/${sourceSet.name}/kotlin"))) kotlin.srcDirs(sourceSet.java.srcDirs) @@ -862,7 +867,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTool * see [org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler.configureTarget] */ (project.extensions.getByName("android") as BaseExtension).sourceSets.forEach { androidSourceSet -> - val kotlinSourceSetName = lowerCamelCaseName(kotlinAndroidTarget.disambiguationClassifier, androidSourceSet.name) + val kotlinSourceSetName = kotlinSourceSetNameForAndroidSourceSet(kotlinAndroidTarget, androidSourceSet.name) project.kotlinExtension.sourceSets.findByName(kotlinSourceSetName)?.let { kotlinSourceSet -> addDependenciesToAndroidSourceSet( androidSourceSet,