From 750ae2c85047b25b2e388f936abfeaa1168c7fcc Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Tue, 3 Oct 2023 09:00:36 +0200 Subject: [PATCH] [Gradle][KMP] IdeJvmAndAndroidPlatformDependencyResolver: Do not filter ProjectDependencies as this will result in losing transitive dependencies from said project dependency. KT-59020 is now fixed by detecting this case before creating the 'IdeaKotlinUnresolvedBinaryDependency' Caused by: KT-59020 ^KT-62029 Verification Pending --- .../IdeBinaryDependencyResolver.kt | 31 ++++++++++++++----- ...JvmAndAndroidPlatformDependencyResolver.kt | 3 +- ...deJvmAndAndroidSourceDependencyResolver.kt | 6 ++++ ...deJvmAndAndroidDependencyResolutionTest.kt | 28 +++++++++++++++++ 4 files changed, 58 insertions(+), 10 deletions(-) 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 c1e1529fa95..8ed2dce0c26 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 @@ -121,18 +121,33 @@ class IdeBinaryDependencyResolver @JvmOverloads constructor( val unresolvedDependencies = artifacts.failures .onEach { reason -> sourceSet.project.logger.info("Failed to resolve platform dependency on ${sourceSet.name}", reason) } - .map { reason -> + .mapNotNull { reason -> + val selector = (reason as? ModuleVersionResolveException)?.selector - val selector = (reason as? ModuleVersionResolveException)?.selector as? ModuleComponentSelector - /* Can't figure out the dependency here :( */ - ?: return@map IdeaKotlinUnresolvedBinaryDependency( - coordinates = null, cause = reason.message?.takeIf { it.isNotBlank() }, extras = mutableExtrasOf() + /* We failed to resolve a library module (e.g., from a remote repository) */ + if (selector is ModuleComponentSelector) + return@mapNotNull IdeaKotlinUnresolvedBinaryDependency( + coordinates = IdeaKotlinBinaryCoordinates(selector.group, selector.module, selector.version, null), + cause = reason.message?.takeIf { it.isNotBlank() }, + extras = mutableExtrasOf() ) + /* + We failed to resolve the same project as the SourceSet was declared to in a + 'PlatformLikeSourceSet' mode: We ignore this error: + https://youtrack.jetbrains.com/issue/KT-59020/ + It seems like 'detachedConfiguration' causes an issue resolving to its project. + */ + if (selector is ProjectComponentSelector && + selector.projectPath == sourceSet.project.path && + artifactResolutionStrategy is ArtifactResolutionStrategy.PlatformLikeSourceSet + ) { + return@mapNotNull null + } + + /* Can't figure out the dependency here :( */ IdeaKotlinUnresolvedBinaryDependency( - coordinates = IdeaKotlinBinaryCoordinates(selector.group, selector.module, selector.version, null), - cause = reason.message?.takeIf { it.isNotBlank() }, - extras = mutableExtrasOf() + coordinates = null, cause = reason.message?.takeIf { it.isNotBlank() }, extras = mutableExtrasOf() ) }.toSet() 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 d3b5f60790c..46b09e27bde 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 @@ -45,8 +45,7 @@ internal fun IdeJvmAndAndroidPlatformBinaryDependencyResolver(project: Project): 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 }, // paranoia: Only dependencyFilter should be OK - dependencyFilter = { dependency -> dependency !is ProjectDependency }, + componentFilter = { identifier -> identifier !is ProjectComponentIdentifier }, dependencySubstitution = ::substituteStdlibCommonWithAndroidJvm, ) ) 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 791830c022d..0bb7efd3c1e 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 @@ -56,10 +56,16 @@ internal object IdeJvmAndAndroidSourceDependencyResolver : IdeDependencyResolver if (sourceSet !is DefaultKotlinSourceSet) return emptySet() return sourceSet.resolveMetadata() + /** + * Only care about project dependencies as this resolver tries to provide source dependencies + */ + .filter { metadataDependencyResolution -> metadataDependencyResolution.projectDependency(sourceSet.project) != null } /** * See [IdeVisibleMultiplatformSourceDependencyResolver] on why this could happen */ .filter { metadataDependencyResolution -> metadataDependencyResolution.projectDependency(sourceSet.project) != sourceSet.project } + + .flatMap { metadataDependencyResolution -> when (metadataDependencyResolution) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeJvmAndAndroidDependencyResolutionTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeJvmAndAndroidDependencyResolutionTest.kt index 3fffeed7219..7aaac4a2240 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeJvmAndAndroidDependencyResolutionTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/dependencyResolutionTests/tcs/IdeJvmAndAndroidDependencyResolutionTest.kt @@ -198,6 +198,34 @@ class IdeJvmAndAndroidDependencyResolutionTest { ) } + @Test + fun `test - KT-62029 - transitive dependencies form project dependency`() { + val root = buildProject { enableDefaultStdlibDependency(false) } + val producer = buildProject({ withName("producer").withParent(root) }) { configureAndroidAndMultiplatform() } + val consumer = buildProject({ withName("consumer").withParent(root) }) { configureAndroidAndMultiplatform() } + + producer.multiplatformExtension.sourceSets.commonMain.dependencies { + api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2") + } + + consumer.multiplatformExtension.sourceSets.commonMain.dependencies { + implementation(producer) + } + + root.evaluate() + producer.evaluate() + consumer.evaluate() + + consumer.kotlinIdeMultiplatformImport.resolveDependencies("commonMain").assertMatches( + regularSourceDependency(":producer/commonMain"), + regularSourceDependency(":producer/jvmAndAndroidMain"), + binaryCoordinates(Regex(".*stdlib.*")), + binaryCoordinates(Regex("org.jetbrains:annotations.*")), + binaryCoordinates("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.2") + ) + + } + @Test fun `test - default stdlib with no other dependencies`() { val project = buildProject { configureAndroidAndMultiplatform(enableDefaultStdlib = true) }