[Gradle] Rename KotlinTargetHierarchy.ModuleName to .SourceSetTree

^KT-58209 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-04-24 16:04:48 +02:00
committed by Space Team
parent 1d23d7de17
commit 16369bc008
9 changed files with 123 additions and 47 deletions
@@ -7,11 +7,60 @@ package org.jetbrains.kotlin.gradle.plugin
interface KotlinTargetHierarchy {
class ModuleName(val name: String) {
/**
* When applying any [KotlinTargetHierarchyDescriptor] (e.g. by calling `targetHierarchy.default()`), the descriptor will
* be applied on individual compilations, creating multiple trees of shared SourceSets.
*
* The name of given shared source set within the target hierarchy will be built by
* `lowerCamelCase(nameOfGroup, nameOfSourceSetTree)`
* So for the 'common' group within the 'main' tree the shared SourceSet name will be 'commonMain'
*
* The most default case will create two well known SourceSetTrees:
* - The `main` tree with `commonMain` as its root SourceSet
* - The `test` tree with `commonTest` as its root SourceSet
*
* e.g.
* ```kotlin
* kotlin {
* targetHierarchy.default()
* jvm()
* iosX64()
* iosArm64()
* }
* ```
*
* will create two SourceSetTrees: "main" and "test"
* ```
* "main" "test"
*
* commonMain commonTest
* | |
* | |
* +----------+----------+ +----------+----------+
* | | | |
* ... jvmMain ... jvmTest
* | |
* | |
* iosMain iosTest
* | |
* +----+-----+ +----+-----+
* | | | |
* iosX64Main iosArm64Main iosX64Test iosArm64Test
* ```
*
*
* Usually, the name of the compilation correlates to the name of the SourceSetTree:
* As seen in the previous example, the "main" tree under the "commonMain" root contains all 'main' compilations of the projects
* targets. The "test" tree under the "commonTest" root contains all 'test' compilations of the projects targets.
*
* There are some exceptions, where the name of the compilations cannot be chosen by the user directly (Android)
* In this case, the name of the SourceSet can be configured outside the target hierarchy DSL.
*/
class SourceSetTree(val name: String) {
override fun toString(): String = name
override fun equals(other: Any?): Boolean {
if (other !is ModuleName) return false
if (other !is SourceSetTree) return false
return this.name == other.name
}
@@ -20,11 +69,34 @@ interface KotlinTargetHierarchy {
}
companion object {
val main = ModuleName("main")
val test = ModuleName("test")
val unitTest = ModuleName("unitTest")
val integrationTest = ModuleName("integrationTest")
val instrumentedTest = ModuleName("instrumentedTest")
/**
* The 'main' SourceSetTree. Typically, with 'commonMain' as the root SourceSet
*/
val main = SourceSetTree("main")
/**
* The 'test' SourceSetTree. Typically, with 'commonTest' as the root SourceSet
*/
val test = SourceSetTree("test")
/**
* Special pre-defined SourceSetTree: Can be used to introduce a new tree with 'commonUnitTest' as the root SourceSet
* e.g. relevant for organising Android unitTest compilations/SourceSets
*/
val unitTest = SourceSetTree("unitTest")
/**
* Special pre-defined SourceSetTree: Can be used to introduce a new tree with 'commonInstrumentedTest' as the root SourceSet
* e.g. relevant for organising Android instrumented compilations/SourceSets
*/
val instrumentedTest = SourceSetTree("instrumentedTest")
/**
* Special pre-defined SourceSetTree: Can be used to introduce a new tree with 'commonIntegrationTest' as root SourceSEt
*/
val integrationTest = SourceSetTree("integrationTest")
}
}
}
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.konan.target.DEPRECATED_TARGET_MESSAGE
interface KotlinTargetHierarchyBuilder {
interface Root : KotlinTargetHierarchyBuilder {
fun modules(vararg module: KotlinTargetHierarchy.ModuleName)
fun withModule(vararg module: KotlinTargetHierarchy.ModuleName)
fun excludeModule(vararg module: KotlinTargetHierarchy.ModuleName)
fun sourceSetTrees(vararg tree: KotlinTargetHierarchy.SourceSetTree)
fun withSourceSetTree(vararg tree: KotlinTargetHierarchy.SourceSetTree)
fun excludeSourceSetTree(vararg tree: KotlinTargetHierarchy.SourceSetTree)
}
/* Declaring groups */
@@ -6,32 +6,32 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.ModuleName
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
import org.jetbrains.kotlin.gradle.plugin.awaitFinalValue
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
import org.jetbrains.kotlin.gradle.plugin.sources.android.AndroidVariantType
import org.jetbrains.kotlin.gradle.plugin.sources.android.type
internal suspend fun ModuleName.Companion.orNull(compilation: KotlinCompilation<*>): ModuleName? =
internal suspend fun SourceSetTree.Companion.orNull(compilation: KotlinCompilation<*>): SourceSetTree? =
when (compilation) {
is KotlinJvmAndroidCompilation -> orNull(compilation.target, compilation.androidVariant.type)
else -> when (compilation.name) {
"main" -> main
"test" -> test
else -> ModuleName(compilation.name)
else -> SourceSetTree(compilation.name)
}
}
internal suspend fun ModuleName.Companion.orNull(
internal suspend fun SourceSetTree.Companion.orNull(
target: KotlinAndroidTarget,
variantType: AndroidVariantType
): ModuleName? = when (variantType) {
): SourceSetTree? = when (variantType) {
AndroidVariantType.Main ->
target.main.targetHierarchy.module.awaitFinalValue() ?: main
target.main.targetHierarchy.sourceSetTree.awaitFinalValue() ?: main
AndroidVariantType.UnitTest ->
target.unitTest.targetHierarchy.module.awaitFinalValue() ?: test
target.unitTest.targetHierarchy.sourceSetTree.awaitFinalValue() ?: test
AndroidVariantType.InstrumentedTest ->
target.instrumentedTest.targetHierarchy.module.awaitFinalValue() ?: instrumentedTest
target.instrumentedTest.targetHierarchy.sourceSetTree.awaitFinalValue() ?: instrumentedTest
AndroidVariantType.Unknown -> null
}
@@ -60,16 +60,16 @@ private class KotlinTargetHierarchyBuilderRootImpl(
) : KotlinTargetHierarchyBuilder.Root, KotlinTargetHierarchyBuilder by builder {
override fun modules(vararg module: KotlinTargetHierarchy.ModuleName) {
builder.modules = module.toHashSet()
override fun sourceSetTrees(vararg tree: KotlinTargetHierarchy.SourceSetTree) {
builder.modules = tree.toHashSet()
}
override fun withModule(vararg module: KotlinTargetHierarchy.ModuleName) {
builder.modules = builder.modules.orEmpty().plus(module)
override fun withSourceSetTree(vararg tree: KotlinTargetHierarchy.SourceSetTree) {
builder.modules = builder.modules.orEmpty().plus(tree)
}
override fun excludeModule(vararg module: KotlinTargetHierarchy.ModuleName) {
val modules = module.toHashSet()
override fun excludeSourceSetTree(vararg tree: KotlinTargetHierarchy.SourceSetTree) {
val modules = tree.toHashSet()
if (modules.isEmpty()) return
builder.modules = builder.modules.orEmpty() - modules
}
@@ -84,7 +84,7 @@ private class KotlinTargetHierarchyBuilderImpl(
val children = mutableSetOf<KotlinTargetHierarchyBuilderImpl>()
val childrenClosure get() = closure { it.children }
var modules: Set<KotlinTargetHierarchy.ModuleName>? = null
var modules: Set<KotlinTargetHierarchy.SourceSetTree>? = null
private var includePredicate: ((KotlinCompilation<*>) -> Boolean) = { false }
private var excludePredicate: ((KotlinCompilation<*>) -> Boolean) = { false }
@@ -105,7 +105,7 @@ private class KotlinTargetHierarchyBuilderImpl(
suspend fun contains(compilation: KotlinCompilation<*>): Boolean {
modules?.let { modules ->
val module = KotlinTargetHierarchy.ModuleName.orNull(compilation) ?: return false
val module = KotlinTargetHierarchy.SourceSetTree.orNull(compilation) ?: return false
if (module !in modules) return false
}
@@ -26,8 +26,8 @@ internal data class KotlinTargetHierarchyTree(
data class Group(val name: String) : Node() {
override suspend fun sharedSourceSetName(compilation: KotlinCompilation<*>): String? {
val moduleName = KotlinTargetHierarchy.ModuleName.orNull(compilation)?.name ?: return null
return lowerCamelCaseName(name, moduleName)
val sourceSetTree = KotlinTargetHierarchy.SourceSetTree.orNull(compilation)?.name ?: return null
return lowerCamelCaseName(name, sourceSetTree)
}
}
@@ -5,12 +5,12 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.ModuleName
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchyDescriptor
internal val defaultKotlinTargetHierarchy = KotlinTargetHierarchyDescriptor {
/* natural hierarchy is only applied to default 'main'/'test' compilations (by default) */
withModule(ModuleName.main, ModuleName.test)
withSourceSetTree(SourceSetTree.main, SourceSetTree.test)
common {
/* All compilations shall be added to the common group by default */
@@ -38,8 +38,8 @@ internal object MultiplatformLayoutV2DependsOnConfigurator : KotlinAndroidSource
return@launchInStage
}
val module = KotlinTargetHierarchy.ModuleName.orNull(target, variantType) ?: return@launchInStage
val commonSourceSetName = lowerCamelCaseName("common", module.name)
val sourceSetTree = KotlinTargetHierarchy.SourceSetTree.orNull(target, variantType) ?: return@launchInStage
val commonSourceSetName = lowerCamelCaseName("common", sourceSetTree.name)
val commonSourceSet = target.project.kotlinExtension.sourceSets.findByName(commonSourceSetName) ?: return@launchInStage
kotlinSourceSet.dependsOn(commonSourceSet)
}
@@ -16,7 +16,10 @@ import org.jetbrains.kotlin.gradle.plugin.newKotlinPluginLifecycleAwareProperty
@ExperimentalKotlinGradlePluginApi
interface KotlinAndroidTargetVariantTypeDsl {
interface TargetHierarchyDsl {
val module: Property<KotlinTargetHierarchy.ModuleName>
/**
* See [KotlinTargetHierarchy.SourceSetTree]
*/
val sourceSetTree: Property<KotlinTargetHierarchy.SourceSetTree>
}
val targetHierarchy: TargetHierarchyDsl
@@ -27,7 +30,8 @@ interface KotlinAndroidTargetVariantTypeDsl {
internal class KotlinAndroidTargetVariantTypeDslImpl(private val project: Project) : KotlinAndroidTargetVariantTypeDsl {
internal inner class TargetHierarchyDslImpl : KotlinAndroidTargetVariantTypeDsl.TargetHierarchyDsl {
override val module: Property<KotlinTargetHierarchy.ModuleName> by project.newKotlinPluginLifecycleAwareProperty(FinaliseDsl)
override val sourceSetTree: Property<KotlinTargetHierarchy.SourceSetTree>
by project.newKotlinPluginLifecycleAwareProperty(FinaliseDsl)
}
override val targetHierarchy: KotlinAndroidTargetVariantTypeDsl.TargetHierarchyDsl = TargetHierarchyDslImpl()
@@ -29,27 +29,27 @@ class KotlinAndroidTargetVariantTypeDslImplTest {
@Test
fun `test - module - not set`() = project.runLifecycleAwareTest {
project.kotlinPluginLifecycle.launch {
assertNull(dsl.targetHierarchy.module.orNull)
assertNull(dsl.targetHierarchy.module.awaitFinalValue())
assertNull(dsl.targetHierarchy.sourceSetTree.orNull)
assertNull(dsl.targetHierarchy.sourceSetTree.awaitFinalValue())
}
}
@Test
fun `test - module - can be set in users afterEvaluate`() = project.runLifecycleAwareTest {
afterEvaluate { dsl.targetHierarchy.module.set(KotlinTargetHierarchy.ModuleName("x")) }
dsl.targetHierarchy.module.set(KotlinTargetHierarchy.ModuleName("-set-before-after-evaluate-"))
assertEquals("x", dsl.targetHierarchy.module.awaitFinalValue()?.name)
afterEvaluate { dsl.targetHierarchy.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("x")) }
dsl.targetHierarchy.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("-set-before-after-evaluate-"))
assertEquals("x", dsl.targetHierarchy.sourceSetTree.awaitFinalValue()?.name)
assertEquals(KotlinPluginLifecycle.Stage.FinaliseDsl, currentKotlinPluginLifecycle().stage)
}
@Test
fun `test - module - cannot be set after FinaliseDsl`() = project.runLifecycleAwareTest {
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl.previousOrThrow) {
dsl.targetHierarchy.module.set(KotlinTargetHierarchy.ModuleName("x"))
dsl.targetHierarchy.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("x"))
}
launchInStage(KotlinPluginLifecycle.Stage.FinaliseDsl) {
assertFails { dsl.targetHierarchy.module.set(KotlinTargetHierarchy.ModuleName("y")) }
assertFails { dsl.targetHierarchy.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("y")) }
}
}
@@ -64,8 +64,8 @@ class KotlinAndroidTargetVariantTypeDslImplTest {
val kotlin = project.multiplatformExtension
project.runLifecycleAwareTest {
kotlin.android {
unitTest.targetHierarchy.module.set(KotlinTargetHierarchy.ModuleName.test)
instrumentedTest.targetHierarchy.module.set(KotlinTargetHierarchy.ModuleName.test)
unitTest.targetHierarchy.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree.test)
instrumentedTest.targetHierarchy.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree.test)
}
AfterFinaliseRefinesEdges.await()
@@ -86,13 +86,13 @@ class KotlinAndroidTargetVariantTypeDslImplTest {
val kotlin = project.multiplatformExtension
project.runLifecycleAwareTest {
kotlin.android {
unitTest.targetHierarchy.module.set(KotlinTargetHierarchy.ModuleName("xxx"))
instrumentedTest.targetHierarchy.module.set(KotlinTargetHierarchy.ModuleName("yyy"))
unitTest.targetHierarchy.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("xxx"))
instrumentedTest.targetHierarchy.sourceSetTree.set(KotlinTargetHierarchy.SourceSetTree("yyy"))
}
kotlin.targetHierarchy.default {
withModule(KotlinTargetHierarchy.ModuleName("xxx"))
withModule(KotlinTargetHierarchy.ModuleName("yyy"))
withSourceSetTree(KotlinTargetHierarchy.SourceSetTree("xxx"))
withSourceSetTree(KotlinTargetHierarchy.SourceSetTree("yyy"))
}
AfterFinaliseRefinesEdges.await()