From 84d7139a124f5cd1f1e7262b49e09bc72d70c6d2 Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Thu, 12 Jan 2023 10:13:13 +0100 Subject: [PATCH] [Gradle] Add MppDependency[PSM]Factory Since ProjectMppDependency[PMS]Extractor is decoupled from Project it is possible to create MppDependency[PSM]Extractor just from `ResolvedArtifactResult` using its ComponentIdentifier and file. ^KT-49933 --- ...rojectStructureMetadataExtractorFactory.kt | 50 +++++++++++++++++++ .../pm20/GradleKpmModuleDependencyResolver.kt | 16 ++++++ 2 files changed, 66 insertions(+) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractorFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractorFactory.kt index e3c123b3f58..9d1ef95f996 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractorFactory.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractorFactory.kt @@ -8,11 +8,61 @@ package org.jetbrains.kotlin.gradle.plugin.mpp import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.component.ProjectComponentIdentifier +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.provider.Provider +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull +import org.jetbrains.kotlin.gradle.plugin.addExtension +import org.jetbrains.kotlin.gradle.plugin.findExtension import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toSingleKpmModuleIdentifier import org.jetbrains.kotlin.project.model.KpmModuleIdentifier +class MppDependencyProjectStructureMetadataExtractorFactory( + private val projectStructureMetadataByProjectPath: Map> +) { + fun create( + metadataArtifact: ResolvedArtifactResult + ): MppDependencyProjectStructureMetadataExtractor { + val moduleId = metadataArtifact.variant.owner + + if (moduleId is ProjectComponentIdentifier && moduleId.build.isCurrentBuild) { + val psm = projectStructureMetadataByProjectPath[moduleId.projectPath] + ?: error("Project structure metadata not found for project ${moduleId.projectPath}") + return ProjectMppDependencyProjectStructureMetadataExtractor( + moduleIdentifier = metadataArtifact.variant.toSingleKpmModuleIdentifier(), + projectPath = moduleId.projectPath, + projectStructureMetadataProvider = psm::get + ) + } + + return JarMppDependencyProjectStructureMetadataExtractor(metadataArtifact.file) + } + + companion object { + private val extensionName = MppDependencyProjectStructureMetadataExtractorFactory::class.java.simpleName + fun getOrCreate(project: Project): MppDependencyProjectStructureMetadataExtractorFactory { + val existing = project.findExtension(extensionName) + if (existing != null) return existing + + val projectStructureMetadataByProjectPath = collectProjectStructureMetadataFromAllProjects(project) + val newFactory = MppDependencyProjectStructureMetadataExtractorFactory(projectStructureMetadataByProjectPath) + project.addExtension(extensionName, newFactory) + return newFactory + } + + /** + * Collect Kotlin Project StructureMetadata only for TCS model. + * TODO: Add support for KPM and auxiliary modules + */ + private fun collectProjectStructureMetadataFromAllProjects(project: Project): Map> { + return project.rootProject.allprojects.associateBy { it.path }.mapValues { (_, subProject) -> + project.provider { subProject.multiplatformExtensionOrNull?.kotlinProjectStructureMetadata } + } + } + } +} + internal fun MppDependencyProjectStructureMetadataExtractor.Factory.create( project: Project, resolvedComponentResult: ResolvedComponentResult, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmModuleDependencyResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmModuleDependencyResolver.kt index 940d8a6c1ee..5be69ef6d65 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmModuleDependencyResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmModuleDependencyResolver.kt @@ -10,6 +10,7 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.component.* import org.gradle.api.artifacts.result.ResolvedComponentResult import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.gradle.api.artifacts.result.ResolvedVariantResult import org.gradle.api.capabilities.Capability import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion import org.jetbrains.kotlin.gradle.plugin.mpp.* @@ -115,6 +116,11 @@ internal fun ResolvedComponentResult.toKpmModuleIdentifiers(): List toKpmModuleIdentifier(moduleClassifier) } } +internal fun ResolvedVariantResult.toKpmModuleIdentifiers(): List { + val classifiers = moduleClassifiersFromCapabilities(capabilities) + return classifiers.map { moduleClassifier -> toKpmModuleIdentifier(moduleClassifier) } +} + // FIXME this mapping doesn't have enough information to choose auxiliary modules internal fun ResolvedComponentResult.toSingleKpmModuleIdentifier(): KpmModuleIdentifier { val classifiers = moduleClassifiersFromCapabilities(variants.flatMap { it.capabilities }) @@ -122,6 +128,8 @@ internal fun ResolvedComponentResult.toSingleKpmModuleIdentifier(): KpmModuleIde return toKpmModuleIdentifier(moduleClassifier) } +internal fun ResolvedVariantResult.toSingleKpmModuleIdentifier(): KpmModuleIdentifier = toKpmModuleIdentifiers().single() + private fun ResolvedComponentResult.toKpmModuleIdentifier(moduleClassifier: String?): KpmModuleIdentifier { return when (val id = id) { is ProjectComponentIdentifier -> KpmLocalModuleIdentifier(id.build.name, id.projectPath, moduleClassifier) @@ -130,6 +138,14 @@ private fun ResolvedComponentResult.toKpmModuleIdentifier(moduleClassifier: Stri } } +private fun ResolvedVariantResult.toKpmModuleIdentifier(moduleClassifier: String?): KpmModuleIdentifier { + return when (val id = owner) { + is ProjectComponentIdentifier -> KpmLocalModuleIdentifier(id.build.name, id.projectPath, moduleClassifier) + is ModuleComponentIdentifier -> id.toSingleKpmModuleIdentifier() + else -> error("Unexpected component identifier '$id' of type ${id.javaClass}") + } +} + internal fun moduleClassifiersFromCapabilities(capabilities: Iterable): Iterable { val classifierCapabilities = capabilities.filter { it.name.contains("..") } return if (classifierCapabilities.none()) listOf(null) else classifierCapabilities.map { it.name.substringAfterLast("..") /*FIXME invent a more stable scheme*/ }