Introduce a container for the KPM model for different kinds of projects

This commit is contained in:
Sergey Igushkin
2022-02-01 15:27:07 +04:00
committed by Space
parent a998e2d291
commit d495c5b604
10 changed files with 81 additions and 27 deletions
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsSingleTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.DefaultKpmGradleProjectModelContainer
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModuleFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
@@ -118,8 +119,11 @@ open class KotlinProjectExtension @Inject constructor(project: Project) : Kotlin
DslObject(this).extensions.add("sourceSets", value)
}
internal val kpmModules: NamedDomainObjectContainer<KotlinGradleModule> =
project.objects.domainObjectContainer(KotlinGradleModule::class.java, KotlinGradleModuleFactory(project))
internal val kpmModelContainer by lazy {
if (PropertiesProvider(project).experimentalKpmModelMapping) {
DefaultKpmGradleProjectModelContainer.create(project)
} else error("Model mapping is not enabled.")
}
}
abstract class KotlinSingleTargetExtension(project: Project) : KotlinProjectExtension(project) {
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.getSourceSetCompiledMetadata
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.FragmentGranularMetadataResolverFactory
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleFragment
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule.Companion.moduleName
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toModuleDependency
import org.jetbrains.kotlin.gradle.plugin.sources.SourceSetMetadataStorageForIde
import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier
@@ -49,7 +50,7 @@ private class IdeFragmentDependencyResolverImpl(
private val fragmentGranularMetadataResolverFactory: FragmentGranularMetadataResolverFactory
) : IdeFragmentDependencyResolver {
override fun resolveDependencies(moduleName: String, fragmentName: String): List<IdeFragmentDependency> {
val fragment = project.pm20Extension.modules.getByName(moduleName).fragments.getByName(fragmentName)
val fragment = project.kpmModules.getByName(moduleName).fragments.getByName(fragmentName)
val fragmentGranularMetadataResolver = fragmentGranularMetadataResolverFactory.getOrCreate(fragment)
return fragmentGranularMetadataResolver.resolutions.flatMap { resolution ->
resolveDependenciesForIde(fragment, resolution)
@@ -121,7 +121,7 @@ private fun detectModules(targets: Iterable<KotlinTarget>, sourceSets: Iterable<
@Suppress("unused")
class GradleProjectModuleBuilder(private val addInferredSourceSetVisibilityAsExplicit: Boolean) {
private fun getModulesFromPm20Project(project: Project) = project.pm20Extension.modules.toList()
private fun getModulesFromPm20Project(project: Project) = project.kpmModules.toList()
fun buildModulesFromProject(project: Project): List<KotlinModule> {
if (project.topLevelExtension is KotlinPm20ProjectExtension)
@@ -119,19 +119,13 @@ abstract class KotlinPm20GradlePlugin @Inject constructor(
fun rootPublicationComponentName(module: KotlinGradleModule) =
module.disambiguateName("root")
internal val Project.kpmModules: NamedDomainObjectContainer<KotlinGradleModule>
get() = when (val ext = project.topLevelExtensionOrNull) {
is KotlinPm20ProjectExtension -> ext.modules
is KotlinProjectExtension -> ext.kpmModules
else -> error("can't find Kotlin KPM modules in $project")
}
open class KotlinPm20ProjectExtension(project: Project) :
KotlinTopLevelExtension(project) {
open class KotlinPm20ProjectExtension(project: Project) : KotlinTopLevelExtension(project) {
val modules: NamedDomainObjectContainer<KotlinGradleModule> =
project.objects.domainObjectContainer(
KotlinGradleModule::class.java,
KotlinGradleModuleFactory(project)
)
internal val kpmModelContainer = DefaultKpmGradleProjectModelContainer.create(project)
val modules: NamedDomainObjectContainer<KotlinGradleModule>
get() = project.kpmModules
@Suppress("unused") // DSL function
fun mainAndTest(configure: KotlinGradleModule.() -> Unit) {
@@ -148,11 +142,6 @@ open class KotlinPm20ProjectExtension(project: Project) : KotlinTopLevelExtensio
fun main(configure: KotlinGradleModule.() -> Unit = { }) = main.apply(configure)
fun test(configure: KotlinGradleModule.() -> Unit = { }) = test.apply(configure)
internal val metadataCompilationRegistryByModuleId: MutableMap<KotlinModuleIdentifier, MetadataCompilationRegistry> =
mutableMapOf()
internal var rootPublication: MavenPublication? = null
@PublishedApi
@JvmName("isAllowCommonizer")
internal fun isAllowCommonizerForIde(@Suppress("UNUSED_PARAMETER") project: Project): Boolean = false
@@ -31,12 +31,12 @@ interface KotlinVariantCompilationDataInternal<T : KotlinCommonOptions> : Kotlin
get() {
// FIXME support compiling against the artifact task outputs
// TODO note for Android: see the friend artifacts code in KotlinAndroidCompilation
return owner.containingModule.project.pm20Extension.modules.flatMap { it.variants.map { it.compilationOutputs.classesDirs } }
return owner.containingModule.project.kpmModules.flatMap { it.variants.map { it.compilationOutputs.classesDirs } }
}
override val moduleName: String
get() = // TODO accurate module names that don't rely on all variants having a main counterpart
owner.containingModule.project.pm20Extension.modules
owner.containingModule.project.kpmModules
.getByName(KotlinGradleModule.MAIN_MODULE_NAME).variants.findByName(owner.name)?.ownModuleName() ?: ownModuleName
override val ownModuleName: String
@@ -25,7 +25,7 @@ val KotlinFragmentHostSpecificMetadataArtifact = FragmentArtifacts<KotlinNativeV
val hostSpecificMetadataJar = project.registerTask<Jar>(fragment.disambiguateName("hostSpecificMetadataJar")) { jar ->
jar.archiveClassifier.set("metadata")
jar.archiveAppendix.set(fragment.disambiguateName(""))
project.pm20Extension.metadataCompilationRegistryByModuleId.getValue(fragment.containingModule.moduleIdentifier)
project.metadataCompilationRegistryByModuleId.getValue(fragment.containingModule.moduleIdentifier)
.withAll { metadataCompilation ->
val metadataFragment = metadataCompilation.fragment
if (metadataCompilation is KotlinNativeFragmentMetadataCompilationData) {
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2021 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.plugin.mpp.pm20
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.publish.maven.MavenPublication
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.dsl.topLevelExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier
internal interface KpmGradleProjectModelContainer {
val modules: NamedDomainObjectContainer<KotlinGradleModule>
val metadataCompilationRegistryByModuleId: MutableMap<KotlinModuleIdentifier, MetadataCompilationRegistry>
val rootPublication: MavenPublication?
}
internal val Project.kpmModelContainer: KpmGradleProjectModelContainer
get() = kpmModelContainerOrNull ?: error("Couldn't find KPM container for $project")
internal val Project.kpmModelContainerOrNull: KpmGradleProjectModelContainer?
get() = when (val ext = project.topLevelExtensionOrNull) {
is KotlinPm20ProjectExtension -> ext.kpmModelContainer
is KotlinProjectExtension -> if (PropertiesProvider(project).experimentalKpmModelMapping) ext.kpmModelContainer else null
else -> null
}
internal val Project.hasKpmModel: Boolean
get() = kpmModelContainerOrNull != null
internal val Project.kpmModules: NamedDomainObjectContainer<KotlinGradleModule>
get() = kpmModelContainer.modules
internal val Project.metadataCompilationRegistryByModuleId: MutableMap<KotlinModuleIdentifier, MetadataCompilationRegistry>
get() = kpmModelContainer.metadataCompilationRegistryByModuleId
internal class DefaultKpmGradleProjectModelContainer(
override val modules: NamedDomainObjectContainer<KotlinGradleModule>,
override val metadataCompilationRegistryByModuleId: MutableMap<KotlinModuleIdentifier, MetadataCompilationRegistry>,
) : KpmGradleProjectModelContainer {
override var rootPublication: MavenPublication? = null
companion object {
fun create(project: Project): DefaultKpmGradleProjectModelContainer {
return DefaultKpmGradleProjectModelContainer(createKpmModulesContainer(project), mutableMapOf())
}
private fun createKpmModulesContainer(project: Project): NamedDomainObjectContainer<KotlinGradleModule> =
project.objects.domainObjectContainer(
KotlinGradleModule::class.java,
KotlinGradleModuleFactory(project)
)
}
}
@@ -34,7 +34,7 @@ internal fun configureMetadataResolutionAndBuild(module: KotlinGradleModule) {
createResolvableMetadataConfigurationForModule(module)
val metadataCompilationRegistry = MetadataCompilationRegistry()
project.pm20Extension.metadataCompilationRegistryByModuleId[module.moduleIdentifier] =
project.metadataCompilationRegistryByModuleId[module.moduleIdentifier] =
metadataCompilationRegistry
configureMetadataCompilationsAndCreateRegistry(module, metadataCompilationRegistry)
@@ -9,6 +9,7 @@ import org.gradle.api.NamedDomainObjectFactory
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
class FragmentMappedKotlinSourceSetFactory constructor(private val project: Project) :
NamedDomainObjectFactory<KotlinSourceSet> {
@@ -17,7 +18,7 @@ class FragmentMappedKotlinSourceSetFactory constructor(private val project: Proj
val locator = SourceSetMappedFragmentLocator.get(project)
val location = locator.locateFragmentForSourceSet(project, name) ?: error("Couldn't map the source set name $name to KPM fragment")
val (moduleName, fragmentName) = location
val modules = project.multiplatformExtension.kpmModules
val modules = project.kpmModules
val fragment = modules.maybeCreate(moduleName).fragments.maybeCreate(fragmentName)
/** TODO setup JS-specific attributes similar to [org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory]*/
return FragmentMappedKotlinSourceSet(project, fragment)
@@ -9,6 +9,7 @@ import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.dsl.topLevelExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
interface SourceSetMappedFragmentLocator {
data class FragmentLocation(val moduleName: String, val fragmentName: String) {
@@ -37,7 +38,7 @@ private class MultiplatformSourceSetMappedFragmentLocator : SourceSetMappedFragm
}
val candidateModuleNames = (1..camelCaseParts.size).asSequence().map { camelCaseParts.takeLast(it).joinToString("").decapitalize() }
val moduleName =
candidateModuleNames.firstOrNull { project.kotlinExtension.kpmModules.findByName(it) != null } ?: candidateModuleNames.first()
candidateModuleNames.firstOrNull { project.kpmModules.findByName(it) != null } ?: candidateModuleNames.first()
val fragmentName = sourceSetName.dropLast(moduleName.length)
return SourceSetMappedFragmentLocator.FragmentLocation(moduleName, fragmentName)