[Gradle] Re-use GlobalProjectStructureMetadataStorage to obrain all...

...Kotlin Project Structure Metadata to feed it for Metadata Dependency
Transformation process

^KT-49933
This commit is contained in:
Anton Lakotka
2023-01-19 14:07:01 +01:00
committed by Space Team
parent 321647b831
commit 33a680c123
4 changed files with 68 additions and 51 deletions
@@ -408,28 +408,44 @@ internal fun <ParsingContext> parseKotlinSourceSetMetadata(
)
}
object GlobalProjectStructureMetadataStorage {
internal object GlobalProjectStructureMetadataStorage {
private const val propertyPrefix = "kotlin.projectStructureMetadata.build"
fun propertyName(buildName: String, projectPath: String) = "kotlin.projectStructureMetadata.build.$buildName.path.$projectPath"
fun propertyName(buildName: String, projectPath: String) = "$propertyPrefix.$buildName.path.$projectPath"
fun registerProjectStructureMetadata(project: Project, metadataProvider: () -> KotlinProjectStructureMetadata) {
val compositeBuildRoot = generateSequence(project.gradle) { it.parent }.last().rootProject
compositeBuildRoot.extensions.extraProperties.set(
project.compositeBuildRoot.extensions.extraProperties.set(
propertyName(project.rootProject.name, project.path),
{ metadataProvider().toJson() }
)
}
fun getProjectStructureMetadata(project: Project, otherBuildName: String, otherProjectPath: String): KotlinProjectStructureMetadata? {
val compositeBuildRoot = generateSequence(project.gradle) { it.parent }.last().rootProject
val property = propertyName(otherBuildName, otherProjectPath)
return with(compositeBuildRoot.extensions.extraProperties) {
if (has(property)) {
val jsonStringProvider = get(property) as? Function0<*> ?: return null
val jsonString = jsonStringProvider.invoke() as? String ?: return null
parseKotlinSourceSetMetadataFromJson(jsonString)
} else null
}
fun getAllProjectStructureMetadata(project: Project): Map<ProjectPathWithBuildName, Lazy<KotlinProjectStructureMetadata?>> {
return project.compositeBuildRoot.extensions.extraProperties.properties
.filterKeys { it.startsWith(propertyPrefix) }
.entries
.associate { (propertyName, propertyValue) ->
Pair(
propertyName.toProjectPathWithBuildName(),
lazy { propertyValue?.getProjectStructureMetadataOrNull() }
)
}
}
private val Project.compositeBuildRoot: Project get() = generateSequence(project.gradle) { it.parent }.last().rootProject
private fun Any.getProjectStructureMetadataOrNull(): KotlinProjectStructureMetadata? {
val jsonStringProvider = this as? Function0<*> ?: return null
val jsonString = jsonStringProvider.invoke() as? String ?: return null
return parseKotlinSourceSetMetadataFromJson(jsonString)
}
private fun String.toProjectPathWithBuildName(): ProjectPathWithBuildName {
val (buildName, projectPath) = removePrefix("$propertyPrefix.").split(".path.")
return ProjectPathWithBuildName(
projectPath = projectPath,
buildName = buildName
)
}
}
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.dsl.pm20ExtensionOrNull
@@ -73,20 +72,14 @@ internal open class JarMppDependencyProjectStructureMetadataExtractor(
}
internal class IncludedBuildMppDependencyProjectStructureMetadataExtractor(
private val project: Project,
dependency: ResolvedComponentResult,
primaryArtifact: File
componentId: ProjectComponentIdentifier,
primaryArtifact: File,
private val projectStructureMetadataProvider: () -> KotlinProjectStructureMetadata?,
) : JarMppDependencyProjectStructureMetadataExtractor(primaryArtifact) {
private val id: ProjectComponentIdentifier
init {
val id = dependency.id
require(id is ProjectComponentIdentifier) { "dependency should resolve to a project" }
require(!id.build.isCurrentBuild) { "should be a project from an included build" }
this.id = id
require(!componentId.build.isCurrentBuild) { "should be a project from an included build" }
}
override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? =
GlobalProjectStructureMetadataStorage.getProjectStructureMetadata(project, id.build.name, id.projectPath)
override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? = projectStructureMetadataProvider()
}
@@ -17,42 +17,53 @@ import org.jetbrains.kotlin.gradle.utils.getOrPut
internal val Project.kotlinMppDependencyProjectStructureMetadataExtractorFactory: MppDependencyProjectStructureMetadataExtractorFactory
get() = MppDependencyProjectStructureMetadataExtractorFactory.getOrCreate(this)
internal class MppDependencyProjectStructureMetadataExtractorFactory(
private val projectStructureMetadataByProjectPath: Map<String, Provider<KotlinProjectStructureMetadata?>>
internal data class ProjectPathWithBuildName(
val projectPath: String,
val buildName: String
)
internal class MppDependencyProjectStructureMetadataExtractorFactory
private constructor(
private val allProjectStructureMetadataProviders: Lazy<Map<ProjectPathWithBuildName, Lazy<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 if (moduleId is ProjectComponentIdentifier) {
val key = ProjectPathWithBuildName(moduleId.projectPath, moduleId.build.name)
val projectStructureMetadataProvider = allProjectStructureMetadataProviders.value[key]
?: error("Project structure metadata not found for project $key")
return JarMppDependencyProjectStructureMetadataExtractor(metadataArtifact.file)
if (moduleId.build.isCurrentBuild) {
ProjectMppDependencyProjectStructureMetadataExtractor(
moduleIdentifier = metadataArtifact.variant.toSingleKpmModuleIdentifier(),
projectPath = moduleId.projectPath,
projectStructureMetadataProvider = projectStructureMetadataProvider::value
)
} else {
IncludedBuildMppDependencyProjectStructureMetadataExtractor(
componentId = moduleId,
primaryArtifact = metadataArtifact.file,
projectStructureMetadataProvider = projectStructureMetadataProvider::value
)
}
} else {
JarMppDependencyProjectStructureMetadataExtractor(metadataArtifact.file)
}
}
companion object {
private val extensionName = MppDependencyProjectStructureMetadataExtractorFactory::class.java.simpleName
fun getOrCreate(project: Project): MppDependencyProjectStructureMetadataExtractorFactory =
project.extraProperties.getOrPut(extensionName) {
val projectStructureMetadataByProjectPath = collectProjectStructureMetadataFromAllProjects(project)
MppDependencyProjectStructureMetadataExtractorFactory(projectStructureMetadataByProjectPath)
}
val allProjectStructureMetadataProviders = lazy {
GlobalProjectStructureMetadataStorage
.getAllProjectStructureMetadata(project)
}
/**
* Collect Kotlin Project StructureMetadata.
*/
private fun collectProjectStructureMetadataFromAllProjects(project: Project): Map<String, Provider<KotlinProjectStructureMetadata?>> {
return project.rootProject.allprojects.associateBy { it.path }.mapValues { (_, subProject) ->
project.provider { subProject.multiplatformExtensionOrNull?.kotlinProjectStructureMetadata }
MppDependencyProjectStructureMetadataExtractorFactory(allProjectStructureMetadataProviders)
}
}
}
}
@@ -348,9 +348,6 @@ class KotlinMetadataTargetConfigurator :
project.locateOrRegisterTask<Task>(TRANSFORM_ALL_SOURCESETS_DEPENDENCIES_METADATA).dependsOn(transformationTask)
@OptIn(Idea222Api::class)
project.ideaImportDependsOn(transformationTask)
val artifacts = sourceSet.internal.resolvableMetadataConfiguration.incoming.artifacts
// Metadata from visible source sets within dependsOn closure