[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) { fun registerProjectStructureMetadata(project: Project, metadataProvider: () -> KotlinProjectStructureMetadata) {
val compositeBuildRoot = generateSequence(project.gradle) { it.parent }.last().rootProject project.compositeBuildRoot.extensions.extraProperties.set(
compositeBuildRoot.extensions.extraProperties.set(
propertyName(project.rootProject.name, project.path), propertyName(project.rootProject.name, project.path),
{ metadataProvider().toJson() } { metadataProvider().toJson() }
) )
} }
fun getProjectStructureMetadata(project: Project, otherBuildName: String, otherProjectPath: String): KotlinProjectStructureMetadata? { fun getAllProjectStructureMetadata(project: Project): Map<ProjectPathWithBuildName, Lazy<KotlinProjectStructureMetadata?>> {
val compositeBuildRoot = generateSequence(project.gradle) { it.parent }.last().rootProject return project.compositeBuildRoot.extensions.extraProperties.properties
val property = propertyName(otherBuildName, otherProjectPath) .filterKeys { it.startsWith(propertyPrefix) }
return with(compositeBuildRoot.extensions.extraProperties) { .entries
if (has(property)) { .associate { (propertyName, propertyValue) ->
val jsonStringProvider = get(property) as? Function0<*> ?: return null Pair(
val jsonString = jsonStringProvider.invoke() as? String ?: return null propertyName.toProjectPathWithBuildName(),
parseKotlinSourceSetMetadataFromJson(jsonString) lazy { propertyValue?.getProjectStructureMetadataOrNull() }
} else null )
} }
}
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.Project
import org.gradle.api.artifacts.component.ProjectComponentIdentifier 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.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.pm20Extension import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.dsl.pm20ExtensionOrNull import org.jetbrains.kotlin.gradle.dsl.pm20ExtensionOrNull
@@ -73,20 +72,14 @@ internal open class JarMppDependencyProjectStructureMetadataExtractor(
} }
internal class IncludedBuildMppDependencyProjectStructureMetadataExtractor( internal class IncludedBuildMppDependencyProjectStructureMetadataExtractor(
private val project: Project, componentId: ProjectComponentIdentifier,
dependency: ResolvedComponentResult, primaryArtifact: File,
primaryArtifact: File private val projectStructureMetadataProvider: () -> KotlinProjectStructureMetadata?,
) : JarMppDependencyProjectStructureMetadataExtractor(primaryArtifact) { ) : JarMppDependencyProjectStructureMetadataExtractor(primaryArtifact) {
private val id: ProjectComponentIdentifier
init { init {
val id = dependency.id require(!componentId.build.isCurrentBuild) { "should be a project from an included build" }
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
} }
override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? = override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? = projectStructureMetadataProvider()
GlobalProjectStructureMetadataStorage.getProjectStructureMetadata(project, id.build.name, id.projectPath)
} }
@@ -17,42 +17,53 @@ import org.jetbrains.kotlin.gradle.utils.getOrPut
internal val Project.kotlinMppDependencyProjectStructureMetadataExtractorFactory: MppDependencyProjectStructureMetadataExtractorFactory internal val Project.kotlinMppDependencyProjectStructureMetadataExtractorFactory: MppDependencyProjectStructureMetadataExtractorFactory
get() = MppDependencyProjectStructureMetadataExtractorFactory.getOrCreate(this) get() = MppDependencyProjectStructureMetadataExtractorFactory.getOrCreate(this)
internal class MppDependencyProjectStructureMetadataExtractorFactory( internal data class ProjectPathWithBuildName(
private val projectStructureMetadataByProjectPath: Map<String, Provider<KotlinProjectStructureMetadata?>> val projectPath: String,
val buildName: String
)
internal class MppDependencyProjectStructureMetadataExtractorFactory
private constructor(
private val allProjectStructureMetadataProviders: Lazy<Map<ProjectPathWithBuildName, Lazy<KotlinProjectStructureMetadata?>>>
) { ) {
fun create( fun create(
metadataArtifact: ResolvedArtifactResult metadataArtifact: ResolvedArtifactResult
): MppDependencyProjectStructureMetadataExtractor { ): MppDependencyProjectStructureMetadataExtractor {
val moduleId = metadataArtifact.variant.owner val moduleId = metadataArtifact.variant.owner
if (moduleId is ProjectComponentIdentifier && moduleId.build.isCurrentBuild) { return if (moduleId is ProjectComponentIdentifier) {
val psm = projectStructureMetadataByProjectPath[moduleId.projectPath] val key = ProjectPathWithBuildName(moduleId.projectPath, moduleId.build.name)
?: error("Project structure metadata not found for project ${moduleId.projectPath}") val projectStructureMetadataProvider = allProjectStructureMetadataProviders.value[key]
return ProjectMppDependencyProjectStructureMetadataExtractor( ?: error("Project structure metadata not found for project $key")
moduleIdentifier = metadataArtifact.variant.toSingleKpmModuleIdentifier(),
projectPath = moduleId.projectPath,
projectStructureMetadataProvider = psm::get
)
}
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 { companion object {
private val extensionName = MppDependencyProjectStructureMetadataExtractorFactory::class.java.simpleName private val extensionName = MppDependencyProjectStructureMetadataExtractorFactory::class.java.simpleName
fun getOrCreate(project: Project): MppDependencyProjectStructureMetadataExtractorFactory = fun getOrCreate(project: Project): MppDependencyProjectStructureMetadataExtractorFactory =
project.extraProperties.getOrPut(extensionName) { project.extraProperties.getOrPut(extensionName) {
val projectStructureMetadataByProjectPath = collectProjectStructureMetadataFromAllProjects(project) val allProjectStructureMetadataProviders = lazy {
MppDependencyProjectStructureMetadataExtractorFactory(projectStructureMetadataByProjectPath) GlobalProjectStructureMetadataStorage
} .getAllProjectStructureMetadata(project)
}
/** MppDependencyProjectStructureMetadataExtractorFactory(allProjectStructureMetadataProviders)
* 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 }
} }
}
} }
} }
@@ -348,9 +348,6 @@ class KotlinMetadataTargetConfigurator :
project.locateOrRegisterTask<Task>(TRANSFORM_ALL_SOURCESETS_DEPENDENCIES_METADATA).dependsOn(transformationTask) project.locateOrRegisterTask<Task>(TRANSFORM_ALL_SOURCESETS_DEPENDENCIES_METADATA).dependsOn(transformationTask)
@OptIn(Idea222Api::class)
project.ideaImportDependsOn(transformationTask)
val artifacts = sourceSet.internal.resolvableMetadataConfiguration.incoming.artifacts val artifacts = sourceSet.internal.resolvableMetadataConfiguration.incoming.artifacts
// Metadata from visible source sets within dependsOn closure // Metadata from visible source sets within dependsOn closure