[Gradle] Implement CurrentBuildIdentifier to replace 'BuildIdentifier.isCurrentBuild()' usages

^KT-58157 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-07-28 10:24:33 +02:00
committed by Space Team
parent e9e0a4741c
commit 749f13ca09
14 changed files with 111 additions and 73 deletions
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ArtifactMetadataProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.currentBuildId
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.utils.*
import java.util.*
@@ -95,6 +96,7 @@ internal class GranularMetadataTransformation(
private val logger = Logging.getLogger("GranularMetadataTransformation[${params.sourceSetName}]")
class Params(
val build: CurrentBuildIdentifier,
val sourceSetName: String,
val resolvedMetadataConfiguration: LazyResolvedConfiguration,
val sourceSetVisibilityProvider: SourceSetVisibilityProvider,
@@ -103,6 +105,7 @@ internal class GranularMetadataTransformation(
val platformCompilationSourceSets: Set<String>,
) {
constructor(project: Project, kotlinSourceSet: KotlinSourceSet) : this(
build = project.currentBuild,
sourceSetName = kotlinSourceSet.name,
resolvedMetadataConfiguration = LazyResolvedConfiguration(kotlinSourceSet.internal.resolvableMetadataConfiguration),
sourceSetVisibilityProvider = SourceSetVisibilityProvider(project),
@@ -232,7 +235,7 @@ internal class GranularMetadataTransformation(
error("Artifacts of dependency ${module.id.displayName} is built by old Kotlin Gradle Plugin and can't be consumed in this way")
}
val isResolvedToProject = moduleId is ProjectComponentIdentifier && moduleId.build.isCurrentBuildCompat
val isResolvedToProject = moduleId in params.build
val sourceSetVisibility =
params.sourceSetVisibilityProvider.getVisibleSourceSets(
@@ -300,7 +303,7 @@ internal class GranularMetadataTransformation(
return when (val componentId = component.id) {
is ModuleComponentIdentifier -> ModuleDependencyIdentifier(componentId.group, componentId.module)
is ProjectComponentIdentifier -> {
if (componentId.build.isCurrentBuildCompat) {
if (componentId in params.build) {
params.projectData[componentId.projectPath]?.moduleId?.getOrThrow()
?: error("Cant find project Module ID by ${componentId.projectPath}")
} else {
@@ -361,7 +364,8 @@ internal fun MetadataDependencyResolution.projectDependency(currentProject: Proj
dependency.toProjectOrNull(currentProject)
internal fun ResolvedComponentResult.toProjectOrNull(currentProject: Project): Project? {
val projectId = currentBuildProjectIdOrNull ?: return null
if (this !in currentProject.currentBuild) return null
val projectId = id as? ProjectComponentIdentifier ?: return null
return currentProject.project(projectId.projectPath)
}
@@ -6,11 +6,10 @@ import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.*
import org.gradle.work.NormalizeLineEndings
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.utils.currentBuild
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.isProjectComponentIdentifierInCurrentBuild
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
internal class MetadataDependencyTransformationTaskInputs(
@@ -18,6 +17,9 @@ internal class MetadataDependencyTransformationTaskInputs(
kotlinSourceSet: KotlinSourceSet,
private val keepProjectDependencies: Boolean = true,
) {
private val currentBuild = project.currentBuild
@Suppress("unused") // Gradle input
@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
@@ -66,10 +68,11 @@ internal class MetadataDependencyTransformationTaskInputs(
.map { listOf(it.group, it.name, it.version) }.toSet()
}
}
}
private fun Configuration.withoutProjectDependencies(): FileCollection {
return incoming.artifactView { view ->
view.componentFilter { componentIdentifier -> !componentIdentifier.isProjectComponentIdentifierInCurrentBuild }
}.files
private fun Configuration.withoutProjectDependencies(): FileCollection {
return incoming.artifactView { view ->
view.componentFilter { componentIdentifier -> componentIdentifier !in currentBuild }
}.files
}
}
@@ -15,8 +15,8 @@ import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.PublishedModuleCoordinatesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.currentBuildId
import org.jetbrains.kotlin.gradle.utils.currentBuild
import org.jetbrains.kotlin.gradle.utils.getValue
import org.jetbrains.kotlin.gradle.utils.isProjectComponentIdentifierInCurrentBuild
import org.jetbrains.kotlin.project.model.KpmLocalModuleIdentifier
import org.jetbrains.kotlin.project.model.KpmMavenModuleIdentifier
import org.jetbrains.kotlin.project.model.KpmModuleIdentifier
@@ -48,7 +48,7 @@ internal object ModuleIds {
fun fromComponent(thisProject: Project, component: ResolvedComponentResult) =
// If the project component comes from another build, we can't extract anything from it, so just use the module coordinates:
if (!component.id.isProjectComponentIdentifierInCurrentBuild)
if (component is ProjectComponentIdentifier && component !in thisProject.currentBuild)
ModuleDependencyIdentifier(component.moduleVersion?.group ?: "unspecified", component.moduleVersion?.name ?: "unspecified")
else
fromComponentId(thisProject, component.id)
@@ -5,8 +5,6 @@
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.jetbrains.kotlin.gradle.utils.isCurrentBuildCompat
import org.jetbrains.kotlin.project.model.KpmModuleIdentifier
import java.io.File
import java.io.InputStream
@@ -22,14 +20,14 @@ sealed class MppDependencyProjectStructureMetadataExtractor {
internal class ProjectMppDependencyProjectStructureMetadataExtractor(
val moduleIdentifier: KpmModuleIdentifier,
val projectPath: String,
private val projectStructureMetadataProvider: () -> KotlinProjectStructureMetadata?
private val projectStructureMetadataProvider: () -> KotlinProjectStructureMetadata?,
) : MppDependencyProjectStructureMetadataExtractor() {
override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? = projectStructureMetadataProvider()
}
internal open class JarMppDependencyProjectStructureMetadataExtractor(
val primaryArtifactFile: File
val primaryArtifactFile: File,
) : MppDependencyProjectStructureMetadataExtractor() {
private fun parseJsonProjectStructureMetadata(input: InputStream) =
@@ -51,14 +49,8 @@ internal open class JarMppDependencyProjectStructureMetadataExtractor(
}
internal class IncludedBuildMppDependencyProjectStructureMetadataExtractor(
componentId: ProjectComponentIdentifier,
primaryArtifact: File,
private val projectStructureMetadataProvider: () -> KotlinProjectStructureMetadata?,
) : JarMppDependencyProjectStructureMetadataExtractor(primaryArtifact) {
init {
require(!componentId.build.isCurrentBuildCompat) { "should be a project from an included build" }
}
override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? = projectStructureMetadataProvider()
}
@@ -11,10 +11,11 @@ import org.gradle.api.artifacts.result.ResolvedArtifactResult
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.extraProperties
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toSingleKpmModuleIdentifier
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.CurrentBuildIdentifier
import org.jetbrains.kotlin.gradle.utils.buildNameCompat
import org.jetbrains.kotlin.gradle.utils.buildPathCompat
import org.jetbrains.kotlin.gradle.utils.getOrPut
import org.jetbrains.kotlin.gradle.utils.isCurrentBuildCompat
internal val Project.kotlinMppDependencyProjectStructureMetadataExtractorFactory: MppDependencyProjectStructureMetadataExtractorFactory
get() = MppDependencyProjectStructureMetadataExtractorFactory.getOrCreate(this)
@@ -26,6 +27,7 @@ internal data class ProjectPathWithBuildPath(
internal class MppDependencyProjectStructureMetadataExtractorFactory
private constructor(
private val currentBuild: CurrentBuildIdentifier,
private val includedBuildsProjectStructureMetadataProviders: Lazy<Map<ProjectPathWithBuildPath, Lazy<KotlinProjectStructureMetadata?>>>,
private val currentBuildProjectStructureMetadataProviders: Map<String, Lazy<KotlinProjectStructureMetadata?>>,
) {
@@ -35,7 +37,7 @@ private constructor(
val moduleId = metadataArtifact.variant.owner
return if (moduleId is ProjectComponentIdentifier) {
if (moduleId.build.isCurrentBuildCompat) {
if (moduleId in currentBuild) {
val projectStructureMetadataProvider = currentBuildProjectStructureMetadataProviders[moduleId.projectPath]
?: error("Project structure metadata not found for project '${moduleId.projectPath}'")
@@ -54,8 +56,8 @@ private constructor(
*/
val pre1920Key = ProjectPathWithBuildPath(moduleId.projectPath, moduleId.build.buildNameCompat)
val key = ProjectPathWithBuildPath(moduleId.projectPath, moduleId.build.buildPathCompat)
IncludedBuildMppDependencyProjectStructureMetadataExtractor(
componentId = moduleId,
primaryArtifact = metadataArtifact.file,
projectStructureMetadataProvider = {
includedBuildsProjectStructureMetadataProviders.value[key]?.value
@@ -73,6 +75,7 @@ private constructor(
fun getOrCreate(project: Project): MppDependencyProjectStructureMetadataExtractorFactory =
project.rootProject.extraProperties.getOrPut(extensionName) {
MppDependencyProjectStructureMetadataExtractorFactory(
currentBuild = project.currentBuild,
lazy { GlobalProjectStructureMetadataStorage.getProjectStructureMetadataProvidersFromAllGradleBuilds(project) },
collectAllProjectStructureMetadataInCurrentBuild(project)
)
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.utils.getOrPutRootProjectProperty
import org.jetbrains.kotlin.gradle.utils.isCurrentBuildCompat
import org.jetbrains.kotlin.project.model.*
class GradleKpmModuleDependencyResolver(
@@ -35,8 +34,9 @@ class GradleKpmModuleDependencyResolver(
//FIXME multiple?
val classifier = moduleClassifiersFromCapabilities(component?.variants?.flatMap { it.capabilities }.orEmpty()).single()
@Suppress("DEPRECATION")
return when {
id is ProjectComponentIdentifier && id.build.isCurrentBuildCompat ->
id is ProjectComponentIdentifier && id.build.isCurrentBuild ->
projectModuleBuilder.buildModulesFromProject(project.project(id.projectPath))
.find { it.moduleIdentifier.moduleClassifier == classifier }
id is ModuleComponentIdentifier -> {
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KpmGradleModuleVariantResolver
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.allDependencyModules
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.isCurrentBuildCompat
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.project.model.KpmVariantResolution
@@ -39,7 +38,8 @@ interface GradleKpmVariantCompilationDataInternal<T : KotlinCommonOptions> : Gra
view.componentFilter { id ->
// FIXME rewrite using the proper module resolution after those changes are merged
val asProject = id as? ProjectComponentIdentifier
asProject?.build?.isCurrentBuildCompat == true &&
@Suppress("DEPRECATION")
asProject?.build?.isCurrentBuild == true &&
asProject.projectPath == owner.project.path
}
}.artifacts.filter {
@@ -9,6 +9,7 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.component.BuildIdentifier
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.internal.build.BuildState
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.internal.BasePluginConfiguration
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
import org.jetbrains.kotlin.project.model.KpmModule
@@ -17,7 +18,7 @@ import org.jetbrains.kotlin.project.model.KpmLocalModuleIdentifier
fun KpmModule.representsProject(project: Project): Boolean =
moduleIdentifier.let { it is KpmLocalModuleIdentifier && it.buildId == project.currentBuildId().name && it.projectId == project.path }
// FIXME internal API?
@InternalKotlinGradlePluginApi
fun Project.currentBuildId(): BuildIdentifier =
(project as ProjectInternal).services.get(BuildState::class.java).buildIdentifier
@@ -21,14 +21,13 @@ import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.closure
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
import java.io.File
import java.util.*
import javax.inject.Inject
const val METADATA_CONFIGURATION_NAME_SUFFIX = "DependenciesMetadata"
abstract class DefaultKotlinSourceSet @Inject constructor(
final override val project: Project,
val displayName: String
val displayName: String,
) : AbstractKotlinSourceSet() {
override val extras: MutableExtras = mutableExtrasOf()
@@ -131,7 +130,7 @@ abstract class DefaultKotlinSourceSet @Inject constructor(
val allVisibleSourceSets: Set<String>,
/** If empty, then this source set does not see any 'new' source sets of the dependency, compared to its dependsOn parents, but it
* still does see all what the dependsOn parents see. */
val useFilesForSourceSets: Map<String, Iterable<File>>
val useFilesForSourceSets: Map<String, Iterable<File>>,
)
@Suppress("unused", "UNUSED_PARAMETER") // Used in IDE import, [configurationName] is kept for backward compatibility
@@ -148,7 +147,9 @@ abstract class DefaultKotlinSourceSet @Inject constructor(
return metadataDependencyResolutionByModule.mapNotNull { (groupAndName, resolution) ->
val (group, name) = groupAndName
val projectPath = resolution.dependency.currentBuildProjectIdOrNull?.projectPath
val dependencyIdentifier = resolution.dependency.id
val projectPath = dependencyIdentifier.projectPathOrNull?.takeIf { dependencyIdentifier in project.currentBuild }
when (resolution) {
// No metadata transformation leads to original dependency being used during import
is MetadataDependencyResolution.KeepOriginalDependency -> null
@@ -10,7 +10,8 @@ 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.targets.metadata.dependsOnClosureWithInterCompilationDependencies
import org.jetbrains.kotlin.gradle.utils.isProjectComponentIdentifierInCurrentBuild
import org.jetbrains.kotlin.gradle.utils.contains
import org.jetbrains.kotlin.gradle.utils.currentBuild
import org.jetbrains.kotlin.tooling.core.extrasNullableLazyProperty
/**
@@ -84,7 +85,7 @@ private fun Project.applyTransformationToLegacyDependenciesMetadataConfiguration
configuration.exclude(mapOf("group" to group, "module" to name))
}
requested.filter { !it.dependency.id.isProjectComponentIdentifierInCurrentBuild }.forEach {
requested.filter { it.dependency !in currentBuild }.forEach {
val (group, name) = ModuleIds.fromComponent(project, it.dependency)
val notation = listOfNotNull(group.orEmpty(), name, it.dependency.moduleVersion?.version).joinToString(":")
configuration.resolutionStrategy.force(notation)
@@ -14,10 +14,8 @@ import org.gradle.api.tasks.*
import org.gradle.work.DisableCachingByDefault
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.ide.Idea222Api
import org.jetbrains.kotlin.gradle.plugin.ide.ideaImportDependsOn
import org.jetbrains.kotlin.gradle.plugin.launch
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ArtifactMetadataProvider
@@ -27,8 +25,9 @@ import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.tasks.dependsOn
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.withType
import org.jetbrains.kotlin.gradle.utils.contains
import org.jetbrains.kotlin.gradle.utils.currentBuild
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.isProjectComponentIdentifierInCurrentBuild
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
import java.io.File
@@ -121,6 +120,8 @@ internal open class CInteropMetadataDependencyTransformationTask @Inject constru
objectFactory: ObjectFactory,
) : DefaultTask() {
private val currentBuild = project.currentBuild
private val parameters = GranularMetadataTransformation.Params(project, sourceSet)
sealed class Cleaning : Serializable {
@@ -195,7 +196,7 @@ internal open class CInteropMetadataDependencyTransformationTask @Inject constru
private fun Iterable<MetadataDependencyResolution>.resolutionsToTransform(): List<ChooseVisibleSourceSets> {
return filterIsInstance<ChooseVisibleSourceSets>()
.applyIf(!transformProjectDependencies) {
filterNot { it.dependency.id.isProjectComponentIdentifierInCurrentBuild }
filterNot { it.dependency in currentBuild }
}
}
}
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.utils
import org.gradle.api.Project
import org.gradle.api.artifacts.component.BuildIdentifier
import org.gradle.api.artifacts.component.ComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.jetbrains.kotlin.gradle.plugin.extraProperties
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.currentBuildId
internal val Project.currentBuild: CurrentBuildIdentifier
get() = extraProperties.getOrPut("org.jetbrains.kotlin.gradle.utils.currentBuild") { CurrentBuildIdentifierImpl(this.currentBuildId()) }
/**
* Utility that can be used to test if a certain project or [ComponentIdentifier] belongs
* to the associated Gradle build in a composite build setup
*/
internal interface CurrentBuildIdentifier {
operator fun contains(project: Project): Boolean
operator fun contains(id: ComponentIdentifier): Boolean
}
internal operator fun CurrentBuildIdentifier.contains(component: ResolvedComponentResult): Boolean {
return component.id in this
}
/* Implementation */
private class CurrentBuildIdentifierImpl(private val currentBuildIdentifier: BuildIdentifier) : CurrentBuildIdentifier {
override fun contains(project: Project): Boolean {
return project.currentBuildId() == currentBuildIdentifier
}
override fun contains(id: ComponentIdentifier): Boolean {
return id.buildOrNull == currentBuildIdentifier
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is CurrentBuildIdentifierImpl) return false
return this.currentBuildIdentifier == other.currentBuildIdentifier
}
override fun hashCode(): Int {
return currentBuildIdentifier.hashCode()
}
}
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.gradle.utils
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.artifacts.component.BuildIdentifier
import org.gradle.api.artifacts.component.ComponentIdentifier
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.invocation.Gradle
import org.gradle.api.provider.Provider
import org.gradle.api.services.BuildService
@@ -56,9 +58,15 @@ internal val BuildIdentifier.buildPathCompat: String
/**
* Will return [BuildIdentifier.isCurrentBuild] for Gradle versions less than 8.2
* Will use the [BuildIdentifier.getBuildPath] to check if the buildIdentifier is the 'current' build
* Will return the [ProjectComponentIdentifier.getBuild] if the component
* represents a project.
*/
internal val BuildIdentifier.isCurrentBuildCompat: Boolean
get() = if (GradleVersion.current() >= GradleVersion.version("8.2")) buildPath == ":"
else @Suppress("DEPRECATION") isCurrentBuild
internal val ComponentIdentifier.buildOrNull: BuildIdentifier?
get() = (this as? ProjectComponentIdentifier)?.build
/**
* Returns the associated 'projectPath' if the component represents a project
* null, otherwise
*/
internal val ComponentIdentifier.projectPathOrNull: String?
get() = (this as? ProjectComponentIdentifier)?.projectPath
@@ -1,28 +0,0 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.utils
import org.gradle.api.artifacts.component.ComponentIdentifier
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.result.ResolvedComponentResult
/**
* For composite builds gradle replaces [ModuleComponentIdentifier] with [ProjectComponentIdentifier]
* for which [build.isCurrentBuild] is false
* Often, these dependencies needs to be handled differently not as usual ProjectDependencies
* Since included build *has to* produce their artifacts on which "current build projects" will depend on.
*/
internal val ComponentIdentifier.isProjectComponentIdentifierInCurrentBuild: Boolean
get() = currentBuildProjectIdOrNull != null
internal val ComponentIdentifier.currentBuildProjectIdOrNull
get(): ProjectComponentIdentifier? = when {
this is ProjectComponentIdentifier && build.isCurrentBuildCompat -> this
else -> null
}
internal val ResolvedComponentResult.currentBuildProjectIdOrNull get() = id.currentBuildProjectIdOrNull