[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
This commit is contained in:
Anton Lakotka
2023-01-12 10:13:13 +01:00
committed by Space Team
parent ceefc4f1ee
commit 84d7139a12
2 changed files with 66 additions and 0 deletions
@@ -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<String, Provider<KotlinProjectStructureMetadata?>>
) {
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<MppDependencyProjectStructureMetadataExtractorFactory>(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<String, Provider<KotlinProjectStructureMetadata?>> {
return project.rootProject.allprojects.associateBy { it.path }.mapValues { (_, subProject) ->
project.provider { subProject.multiplatformExtensionOrNull?.kotlinProjectStructureMetadata }
}
}
}
}
internal fun MppDependencyProjectStructureMetadataExtractor.Factory.create(
project: Project,
resolvedComponentResult: ResolvedComponentResult,
@@ -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<KpmModuleIde
return classifiers.map { moduleClassifier -> toKpmModuleIdentifier(moduleClassifier) }
}
internal fun ResolvedVariantResult.toKpmModuleIdentifiers(): List<KpmModuleIdentifier> {
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<Capability>): Iterable<String?> {
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*/ }