[Gradle] GranularMetadataTransformation: ProjectData: Use Future instead of lambda

^KT-34662 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-03-13 22:36:08 +01:00
committed by Space Team
parent 7c65d00f29
commit ea48b52d43
6 changed files with 31 additions and 35 deletions
@@ -387,6 +387,8 @@ private class KotlinPluginLifecycleImpl(override val project: Project) : KotlinP
"${KotlinPluginLifecycle::class.java.name} cannot be started in ProjectState '${project.state}'"
}
loopIfNecessary()
project.whenEvaluated {
assert(enqueuedActions.getValue(stage).isEmpty()) { "Expected empty queue from '$stage'" }
stage = stage.nextOrThrow
@@ -445,14 +447,13 @@ private class KotlinPluginLifecycleImpl(override val project: Project) : KotlinP
enqueuedActions.getValue(stage).addLast(action)
if (stage == Stage.Configure) {
if (stage == Stage.Configure && isStarted.get()) {
loopIfNecessary()
}
}
override fun launch(block: suspend KotlinPluginLifecycle.() -> Unit) {
val lifecycle = this
check(isStarted.get()) { "Cannot launch when ${KotlinPluginLifecycle::class.simpleName} is not started" }
val coroutine = block.createCoroutine(this, object : Continuation<Unit> {
override val context: CoroutineContext = EmptyCoroutineContext +
@@ -77,8 +77,6 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin {
checkGradleCompatibility()
project.startKotlinPluginLifecycle()
project.gradle.projectsEvaluated {
whenBuildEvaluated(project)
}
@@ -233,6 +231,8 @@ abstract class KotlinBasePluginWrapper : DefaultKotlinBasePlugin() {
project.addNpmDependencyExtension()
project.registerBuildKotlinToolingMetadataTask()
project.startKotlinPluginLifecycle()
}
internal open fun createTestRegistry(project: Project) = KotlinTestsRegistry(project)
@@ -14,12 +14,10 @@ import org.gradle.api.file.FileCollection
import org.gradle.api.logging.Logging
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.extraProperties
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ArtifactMetadataProvider
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.utils.Future
import org.jetbrains.kotlin.gradle.utils.LazyResolvedConfiguration
import org.jetbrains.kotlin.gradle.utils.future
import org.jetbrains.kotlin.gradle.utils.getOrPut
@@ -118,12 +116,9 @@ internal class GranularMetadataTransformation(
class ProjectData(
val path: String,
sourceSetMetadataOutputsProvider: () -> Map<String, SourceSetMetadataOutputs>,
moduleIdProvider: () -> ModuleDependencyIdentifier
val sourceSetMetadataOutputs: Future<Map<String, SourceSetMetadataOutputs>>,
val moduleId: Future<ModuleDependencyIdentifier>
) {
val sourceSetMetadataOutputs by lazy(sourceSetMetadataOutputsProvider)
val moduleId by lazy(moduleIdProvider)
override fun toString(): String = "ProjectData[path='$path']"
}
@@ -275,7 +270,7 @@ internal class GranularMetadataTransformation(
val metadataProvider = when (mppDependencyMetadataExtractor) {
is ProjectMppDependencyProjectStructureMetadataExtractor -> ProjectMetadataProvider(
sourceSetMetadataOutputs = params.projectData[mppDependencyMetadataExtractor.projectPath]?.sourceSetMetadataOutputs
?: error("Unexpected project path '${mppDependencyMetadataExtractor.projectPath}'")
?.getOrThrow() ?: error("Unexpected project path '${mppDependencyMetadataExtractor.projectPath}'")
)
is JarMppDependencyProjectStructureMetadataExtractor -> ArtifactMetadataProvider(
@@ -308,7 +303,7 @@ internal class GranularMetadataTransformation(
is ModuleComponentIdentifier -> ModuleDependencyIdentifier(componentId.group, componentId.module)
is ProjectComponentIdentifier -> {
if (componentId.build.isCurrentBuild) {
params.projectData[componentId.projectPath]?.moduleId
params.projectData[componentId.projectPath]?.moduleId?.getOrThrow()
?: error("Cant find project Module ID by ${componentId.projectPath}")
} else {
ModuleDependencyIdentifier(
@@ -337,15 +332,18 @@ private val Project.allProjectsData: Map<String, GranularMetadataTransformation.
get() = rootProject
.extraProperties
.getOrPut("all${GranularMetadataTransformation.ProjectData::class.java.simpleName}") {
future { collectAllProjectsData() }.getOrThrow()
collectAllProjectsData()
}
private fun Project.collectAllProjectsData(): Map<String, GranularMetadataTransformation.ProjectData> {
return rootProject.allprojects.associateBy { it.path }.mapValues { (path, subProject) ->
return rootProject.allprojects.associateBy { it.path }.mapValues { (path, currentProject) ->
GranularMetadataTransformation.ProjectData(
path = path,
sourceSetMetadataOutputsProvider = future { subProject.collectSourceSetMetadataOutputs() }::getOrThrow,
moduleIdProvider = { ModuleIds.idOfRootModule(subProject) }
sourceSetMetadataOutputs = currentProject.future { currentProject.collectSourceSetMetadataOutputs() },
moduleId = currentProject.future {
await(KotlinPluginLifecycle.Stage.AfterFinaliseDsl)
ModuleIds.idOfRootModule(currentProject)
}
)
}
}
@@ -9,8 +9,11 @@ import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.await
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ProjectMetadataProvider
import org.jetbrains.kotlin.gradle.targets.metadata.findMetadataCompilation
import org.jetbrains.kotlin.gradle.targets.native.internal.*
private typealias SourceSetName = String
@@ -33,7 +36,7 @@ internal class SourceSetMetadataOutputs(
private class ProjectMetadataProviderImpl(
private val sourceSetMetadataOutputs: Map<SourceSetName, SourceSetMetadataOutputs>
): ProjectMetadataProvider() {
) : ProjectMetadataProvider() {
override fun getSourceSetCompiledMetadata(sourceSetName: String): FileCollection =
sourceSetMetadataOutputs[sourceSetName]?.metadata ?: error("Unexpected source set '$sourceSetName'")
@@ -63,16 +66,11 @@ internal suspend fun Project.collectSourceSetMetadataOutputs(): Map<SourceSetNam
}.mapKeys { it.key.name }
}
private fun KotlinMultiplatformExtension.sourceSetsMetadataOutputs(): Map<KotlinSourceSet, FileCollection> {
val commonTarget = metadata()
val compilations = commonTarget.compilations
private suspend fun KotlinMultiplatformExtension.sourceSetsMetadataOutputs(): Map<KotlinSourceSet, FileCollection> {
await(KotlinPluginLifecycle.Stage.AfterFinaliseDsl)
return sourceSets.mapNotNull { sourceSet ->
val compilation = compilations.findByName(sourceSet.name)
?: return@mapNotNull null // given source set is not shared
val destination = when (compilation) {
val destination = when (val compilation = project.findMetadataCompilation(sourceSet) ?: return@mapNotNull null) {
is KotlinCommonCompilation -> compilation.output.classesDirs
is KotlinSharedNativeCompilation -> compilation.output.classesDirs
else -> error("Unexpected compilation type: $compilation")
@@ -9,10 +9,6 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.GranularMetadataTransformation
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
import org.jetbrains.kotlin.gradle.plugin.mpp.ModuleIds
import org.jetbrains.kotlin.gradle.plugin.mpp.projectDependency
import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCompilationDependencies
import org.jetbrains.kotlin.tooling.core.extrasNullableLazyProperty
@@ -80,7 +80,7 @@ internal fun <T> Project.future(block: suspend Project.() -> T): Future<T> = kot
internal fun <T> Project.lazyFuture(block: suspend Project.() -> T): Lazy<Future<T>> = lazy { future(block) }
internal fun <T> KotlinPluginLifecycle.future(block: suspend () -> T): Future<T> {
return FutureImpl<T>(CompletableDeferred()).also { future ->
return FutureImpl<T>(lifecycle = this).also { future ->
launch { future.completeWith(runCatching { block() }) }
}
}
@@ -90,7 +90,10 @@ internal fun <T> CompletableFuture(): CompletableFuture<T> {
}
@OptIn(ExperimentalCoroutinesApi::class)
private class FutureImpl<T>(private val deferred: CompletableDeferred<T> = CompletableDeferred()) : CompletableFuture<T>, Serializable {
private class FutureImpl<T>(
private val deferred: CompletableDeferred<T> = CompletableDeferred(),
private val lifecycle: KotlinPluginLifecycle? = null
) : CompletableFuture<T>, Serializable {
fun completeWith(result: Result<T>) = deferred.completeWith(result)
override fun complete(value: T) {
@@ -103,7 +106,7 @@ private class FutureImpl<T>(private val deferred: CompletableDeferred<T> = Compl
override fun getOrThrow(): T {
return if (deferred.isCompleted) deferred.getCompleted() else throw IllegalLifecycleException(
"Future was not completed yet"
"Future was not completed yet" + if (lifecycle != null) " (stage '${lifecycle.stage}')" else ""
)
}
}