From 943c11d23956dd1349a523406642492cc3a9baab Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Thu, 19 Oct 2023 05:08:44 +0200 Subject: [PATCH] [Gradle] Support multiple variants of a module resolved when determining visible common source sets With capabilities in variants it is possible to depend on multiple variants of an artifact in the same target compilation. These variants can implement different common source sets which all should be visible from that target. Instead of intersecting single variant source sets visible from different targets, first union source sets from all target variant dependencies and only then intersect these union results from different targets. --- .../plugin/mpp/SourceSetVisibilityProvider.kt | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt index c2665e7e54d..ef611c7ec0d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt @@ -87,44 +87,55 @@ internal class SourceSetVisibilityProvider( val platformCompilationsByResolvedVariantName = mutableMapOf() - val visiblePlatformVariantNames: Set = platformCompilations + val visiblePlatformVariantNames: List> = platformCompilations .filter { visibleFromSourceSet in it.allSourceSets } - .map { platformCompilationData -> - val resolvedPlatformDependency = platformCompilationData + .mapNotNull { platformCompilationData -> + val resolvedPlatformDependencies = platformCompilationData .resolvedDependenciesConfiguration .allResolvedDependencies - .find { it.selected.id == resolvedRootMppDependencyId } - /* - Returning null if we can't find the given dependency in a certain platform compilations dependencies. - This is not expected, since this means the dependency does not support the given targets which will - lead to a dependency resolution error. + .filter { it.selected.id == resolvedRootMppDependencyId } + /* + Returning null if we can't find the given dependency in a certain platform compilations dependencies. + This is not expected, since this means the dependency does not support the given targets which will + lead to a dependency resolution error. - Esoteric cases can still get into this branch: e.g. broken publications (or broken .m2 and mavenLocal()). - In this case we just return null, effectively ignoring this situation for this algorithm. + Esoteric cases can still get into this branch: e.g. broken publications (or broken .m2 and mavenLocal()). + In this case we just return null, effectively ignoring this situation for this algorithm. - Ignoring this will still lead to a more graceful behaviour in the IDE. - A broken publication will potentially lead to 'too many' source sets being visible, which is - more desirable than having none. - */ ?: return@map null + Ignoring this will still lead to a more graceful behaviour in the IDE. + A broken publication will potentially lead to 'too many' source sets being visible, which is + more desirable than having none. + */ + .ifEmpty { return@mapNotNull null } - val resolvedVariant = kotlinVariantNameFromPublishedVariantName( - resolvedPlatformDependency.resolvedVariant.displayName - ) + resolvedPlatformDependencies.map { resolvedPlatformDependency -> + val resolvedVariant = kotlinVariantNameFromPublishedVariantName( + resolvedPlatformDependency.resolvedVariant.displayName + ) - if (resolvedVariant !in platformCompilationsByResolvedVariantName) { - platformCompilationsByResolvedVariantName[resolvedVariant] = platformCompilationData - } + if (resolvedVariant !in platformCompilationsByResolvedVariantName) { + platformCompilationsByResolvedVariantName[resolvedVariant] = platformCompilationData + } - resolvedVariant - }.toSet() + resolvedVariant + }.toSet() + } if (visiblePlatformVariantNames.isEmpty()) { return SourceSetVisibilityResult(emptySet(), emptyMap()) } - val visibleSourceSetNames = dependencyProjectStructureMetadata.sourceSetNamesByVariantName - .filterKeys { it in visiblePlatformVariantNames } - .values.let { if (it.isEmpty()) emptySet() else it.reduce { acc, item -> acc intersect item } } + val visibleSourceSetNames = visiblePlatformVariantNames + .mapNotNull { platformVariants -> + platformVariants + .map { dependencyProjectStructureMetadata.sourceSetNamesByVariantName[it].orEmpty() } + // join together visible source sets from multiple variants of the same platform + .fold(emptySet()) { acc, item -> acc union item } + .ifEmpty { null } + } + // intersect visible variants from different platforms + .ifEmpty { listOf(emptySet()) } // to avoid calling reduce on an empty list + .reduce { acc, item -> acc intersect item } val hostSpecificArtifactBySourceSet: Map = if (resolvedToOtherProject) {