From 33a680c12384a65e2cb58848d07d2b6068fcb674 Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Thu, 19 Jan 2023 14:07:01 +0100 Subject: [PATCH] [Gradle] Re-use GlobalProjectStructureMetadataStorage to obrain all... ...Kotlin Project Structure Metadata to feed it for Metadata Dependency Transformation process ^KT-49933 --- .../mpp/KotlinProjectStructureMetadata.kt | 44 ++++++++++----- ...ndencyProjectStructureMetadataExtractor.kt | 17 ++---- ...rojectStructureMetadataExtractorFactory.kt | 55 +++++++++++-------- .../KotlinMetadataTargetConfigurator.kt | 3 - 4 files changed, 68 insertions(+), 51 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt index f798d589861..d4f9bd9d046 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt @@ -408,28 +408,44 @@ internal fun 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> { + 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 + ) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractor.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractor.kt index bc6f5a1974a..ecf162a2087 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/MppDependencyProjectStructureMetadataExtractor.kt @@ -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() } 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 886fe75bb92..25bbc660ce1 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 @@ -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> +internal data class ProjectPathWithBuildName( + val projectPath: String, + val buildName: String +) + +internal class MppDependencyProjectStructureMetadataExtractorFactory +private constructor( + private val allProjectStructureMetadataProviders: Lazy>> ) { 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> { - return project.rootProject.allprojects.associateBy { it.path }.mapValues { (_, subProject) -> - project.provider { subProject.multiplatformExtensionOrNull?.kotlinProjectStructureMetadata } + MppDependencyProjectStructureMetadataExtractorFactory(allProjectStructureMetadataProviders) } - } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt index 6ad69d0ec8a..17709d477c2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt @@ -348,9 +348,6 @@ class KotlinMetadataTargetConfigurator : project.locateOrRegisterTask(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