diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt index 55153f6e11d..3fd42f6a94e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeBinaryDependencyResolver.kt @@ -7,10 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers import org.gradle.api.artifacts.ArtifactView import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.component.LibraryBinaryIdentifier -import org.gradle.api.artifacts.component.ModuleComponentIdentifier -import org.gradle.api.artifacts.component.ModuleComponentSelector -import org.gradle.api.artifacts.component.ProjectComponentIdentifier +import org.gradle.api.artifacts.component.* import org.gradle.api.attributes.AttributeContainer import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging @@ -18,7 +15,6 @@ import org.gradle.internal.component.local.model.OpaqueComponentArtifactIdentifi import org.gradle.internal.resolve.ModuleVersionResolveException import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi import org.jetbrains.kotlin.gradle.idea.tcs.* -import org.jetbrains.kotlin.gradle.kpm.external.ExternalVariantApi import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet @@ -76,6 +72,7 @@ class IdeBinaryDependencyResolver( data class PlatformLikeSourceSet( internal val setupPlatformResolutionAttributes: AttributeContainer.(sourceSet: KotlinSourceSet) -> Unit, internal val setupArtifactViewAttributes: AttributeContainer.(sourceSet: KotlinSourceSet) -> Unit = {}, + internal val componentFilter: ((ComponentIdentifier) -> Boolean)? = null ) : ArtifactResolutionStrategy() } @@ -192,6 +189,9 @@ class IdeBinaryDependencyResolver( return platformLikeCompileDependenciesConfiguration.incoming.artifactView { view -> view.isLenient = true view.attributes.setupArtifactViewAttributes(sourceSet) + if (componentFilter != null) { + view.componentFilter(componentFilter) + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidPlatformDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidPlatformDependencyResolver.kt index 1ec3e8c05a4..f0c42556bee 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidPlatformDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidPlatformDependencyResolver.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers import org.gradle.api.Project +import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.attributes.Category import org.gradle.api.attributes.Usage import org.gradle.api.attributes.java.TargetJvmEnvironment @@ -33,5 +34,11 @@ internal fun IdeJvmAndAndroidPlatformBinaryDependencyResolver(project: Project): project.objects.named(TargetJvmEnvironment.STANDARD_JVM) ) }, + /* + Prevent this resolver from running against project dependencies: + Otherwise we would match the -jvm.jar from the dependency project which will result in + matching the jvmMain source set as well (which is undesired) + */ + componentFilter = { identifier -> identifier !is ProjectComponentIdentifier } ) ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidSourceDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidSourceDependencyResolver.kt index 96d17a67640..db6d97824d2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidSourceDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/ide/dependencyResolvers/IdeJvmAndAndroidSourceDependencyResolver.kt @@ -9,29 +9,47 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceDependency import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinSourceDependency.Type.Regular +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.ide.IdeDependencyResolver +import org.jetbrains.kotlin.gradle.plugin.ide.IdeMultiplatformImport.SourceSetConstraint.Companion.isJvmAndAndroid import org.jetbrains.kotlin.gradle.plugin.ide.IdeaKotlinSourceCoordinates +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution +import org.jetbrains.kotlin.gradle.plugin.mpp.isMain import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.sources.android.AndroidVariantType +import org.jetbrains.kotlin.gradle.plugin.sources.android.type import org.jetbrains.kotlin.gradle.plugin.sources.internal internal object IdeJvmAndAndroidSourceDependencyResolver : IdeDependencyResolver { override fun resolve(sourceSet: KotlinSourceSet): Set { - if (!sourceSet.isJvmAndAndroid) return emptySet() + if (!isJvmAndAndroid(sourceSet)) return emptySet() if (sourceSet !is DefaultKotlinSourceSet) return emptySet() return sourceSet.resolveMetadata() .flatMap { chooseVisibleSourceSets -> val projectDependency = chooseVisibleSourceSets.projectDependency ?: return@flatMap emptyList() val kotlin = projectDependency.multiplatformExtensionOrNull ?: return@flatMap emptyList() kotlin.sourceSets - .filter { sourceSet -> sourceSet.isJvmAndAndroid } + .filter { sourceSet -> isJvmAndAndroidMain(sourceSet) } .map { sourceSet -> IdeaKotlinSourceDependency(type = Regular, coordinates = IdeaKotlinSourceCoordinates(sourceSet)) } } .toSet() } - private val KotlinSourceSet.isJvmAndAndroid: Boolean - get() = internal.compilations.map { it.platformType }.toSet() == setOf(KotlinPlatformType.androidJvm, KotlinPlatformType.jvm) + private fun isJvmAndAndroidMain(sourceSet: KotlinSourceSet): Boolean { + if (!isJvmAndAndroid(sourceSet)) return false + return sourceSet.internal.compilations.filter { it.platformType != KotlinPlatformType.common }.all { compilation -> + isJvmMain(compilation) || isAndroidMain(compilation) + } + } + + private fun isJvmMain(compilation: KotlinCompilation<*>): Boolean { + return compilation.platformType == KotlinPlatformType.jvm && compilation.isMain() + } + + private fun isAndroidMain(compilation: KotlinCompilation<*>): Boolean { + return compilation is KotlinJvmAndroidCompilation && compilation.androidVariant.type == AndroidVariantType.Main + } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeJvmAndAndroidPlatformDependencyResolverTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeJvmAndAndroidDependencyResolutionTest.kt similarity index 59% rename from libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeJvmAndAndroidPlatformDependencyResolverTest.kt rename to libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeJvmAndAndroidDependencyResolutionTest.kt index 64d82162538..32bc962dca8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeJvmAndAndroidPlatformDependencyResolverTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/ide/IdeJvmAndAndroidDependencyResolutionTest.kt @@ -7,36 +7,36 @@ package org.jetbrains.kotlin.gradle.ide +import org.gradle.api.Project import org.jetbrains.kotlin.gradle.* import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.assertMatches import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.binaryCoordinates +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.dependsOnDependency +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.regularSourceDependency import org.jetbrains.kotlin.gradle.kpm.idea.mavenCentralCacheRedirector import org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers.IdeJvmAndAndroidPlatformBinaryDependencyResolver +import org.jetbrains.kotlin.gradle.plugin.ide.kotlinIdeMultiplatformImport import org.jetbrains.kotlin.gradle.utils.androidExtension import kotlin.test.BeforeTest import kotlin.test.Test -class IdeJvmAndAndroidPlatformDependencyResolverTest { +class IdeJvmAndAndroidDependencyResolutionTest { @BeforeTest fun checkEnvironment() { assumeAndroidSdkAvailable() } - @Test - fun `test - MVIKotlin - on jvmAndAndroidMain`() { - val project = buildProject { - enableDefaultStdlibDependency(false) - enableDependencyVerification(false) - applyMultiplatformPlugin() - plugins.apply("com.android.library") - androidExtension.compileSdkVersion(33) - repositories.mavenCentralCacheRedirector() - } + private fun Project.configureAndroidAndMultiplatform() { + enableDefaultStdlibDependency(false) + enableDependencyVerification(false) + applyMultiplatformPlugin() + plugins.apply("com.android.library") + androidExtension.compileSdkVersion(33) + repositories.mavenCentralCacheRedirector() - val kotlin = project.multiplatformExtension - kotlin.targetHierarchy.custom { + project.multiplatformExtension.targetHierarchy.custom { common { group("jvmAndAndroid") { anyJvm() @@ -45,9 +45,15 @@ class IdeJvmAndAndroidPlatformDependencyResolverTest { } } - kotlin.jvm() - kotlin.android() + project.multiplatformExtension.jvm() + project.multiplatformExtension.android() + } + + @Test + fun `test - MVIKotlin - on jvmAndAndroidMain`() { + val project = buildProject { configureAndroidAndMultiplatform() } + val kotlin = project.multiplatformExtension kotlin.sourceSets.getByName("commonMain").dependencies { implementation("com.arkivanov.mvikotlin:mvikotlin:3.0.2") } @@ -72,4 +78,25 @@ class IdeJvmAndAndroidPlatformDependencyResolverTest { IdeJvmAndAndroidPlatformBinaryDependencyResolver(project).resolve(kotlin.sourceSets.getByName("jvmAndAndroidTest")) .assertMatches(jvmAndAndroidDependencies) } + + @Test + fun `test - project to project dependency`() { + val root = buildProject() + val producer = buildProject({ withParent(root).withName("producer") }) { configureAndroidAndMultiplatform() } + val consumer = buildProject({ withParent(root).withName("consumer") }) { configureAndroidAndMultiplatform() } + + root.evaluate() + producer.evaluate() + consumer.evaluate() + + consumer.multiplatformExtension.sourceSets.getByName("commonMain").dependencies { + implementation(project(":producer")) + } + + consumer.kotlinIdeMultiplatformImport.resolveDependencies("jvmAndAndroidMain").assertMatches( + dependsOnDependency(":consumer/commonMain"), + regularSourceDependency(":producer/commonMain"), + regularSourceDependency(":producer/jvmAndAndroidMain"), + ) + } }