diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/LazyResolvedConfiguration.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/LazyResolvedConfiguration.kt index 2c7b7f0f84c..5028c7eb1a5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/LazyResolvedConfiguration.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/LazyResolvedConfiguration.kt @@ -7,10 +7,8 @@ package org.jetbrains.kotlin.gradle.utils import org.gradle.api.artifacts.ArtifactCollection import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.result.DependencyResult -import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.artifacts.result.ResolvedComponentResult -import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.gradle.api.artifacts.ResolveException +import org.gradle.api.artifacts.result.* import org.gradle.api.file.FileCollection /** @@ -24,14 +22,16 @@ import org.gradle.api.file.FileCollection internal class LazyResolvedConfiguration private constructor( private val resolvedComponentsRootProvider: Lazy, - private val artifactCollection: ArtifactCollection + private val artifactCollection: ArtifactCollection, + private val configurationName: String, ) { constructor(configuration: Configuration) : this( // Calling resolutionResult doesn't actually trigger resolution. But accessing its root ResolvedComponentResult // via ResolutionResult::root does. ResolutionResult can't be serialised for Configuration Cache // but ResolvedComponentResult can. Wrapping it in `lazy` makes it resolve upon serialisation. resolvedComponentsRootProvider = configuration.incoming.resolutionResult.let { rr -> lazy { rr.root } }, - artifactCollection = configuration.incoming.artifacts // lazy ArtifactCollection + artifactCollection = configuration.incoming.artifacts, // lazy ArtifactCollection + configurationName = configuration.name ) val root get() = resolvedComponentsRootProvider.value @@ -51,8 +51,54 @@ private constructor( return root.dependencies.flatMap { it.allDependenciesRecursive() } } + /** + * Returns artifacts of a given dependency walking through external variants (the ones that referenced in `available-at`) + * For example given a MPP library: + * lib + * / \ + * lib-jvm lib-iosX64 + * + * And some requested dependency on `lib` in `jvmMain` source set. In this case it should be resolved to `lib-jvm` + * so requesting [dependencyArtifacts] for `lib` should actually return a jvm artifact from `lib-jvm` + * + * If you need to avoid such behavior see [moduleArtifacts] + */ fun dependencyArtifacts(dependency: ResolvedDependencyResult): List { - val componentId = dependency.selected.id + fun ResolvedVariantResult.findNonExternalVariant(): ResolvedVariantResult = + if (externalVariant.isPresent) { + externalVariant.get().findNonExternalVariant() + } else { + this + } + + val componentId = dependency.resolvedVariant.findNonExternalVariant().owner return artifactsByComponentId[componentId] ?: emptyList() } + + /** + * Returns own artifacts of a given dependency. + * Acts in the same way as [org.gradle.api.artifacts.ResolvedDependency.getModuleArtifacts]. + * + * To get artifacts from External Variants (aka `available-at`) use [dependencyArtifacts] + */ + fun moduleArtifacts(dependency: ResolvedDependencyResult): List { + val componentId = dependency.resolvedVariant.owner + return artifactsByComponentId[componentId] ?: emptyList() + } + + override fun toString(): String = "ResolvedDependencyGraph(configuration='$configurationName')" +} + +internal val LazyResolvedConfiguration.allResolvedDependencies: Set get() = allDependencies + .filterIsInstance() + .toSet() + +/** + * Same as [LazyResolvedConfiguration.dependencyArtifacts] except it returns null for cases when dependency is resolved + * but artifact is not available. For example when host-specific part of the library is not yet published + */ +internal fun LazyResolvedConfiguration.dependencyArtifactsOrNull(dependency: ResolvedDependencyResult): List? = try { + dependencyArtifacts(dependency) +} catch (_: ResolveException) { + null } \ No newline at end of file