diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetHierarchyDsl.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetHierarchyDsl.kt index 7d87303c3a9..5f064c019ce 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetHierarchyDsl.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetHierarchyDsl.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchyDescriptor interface KotlinTargetHierarchyDsl { fun apply( hierarchyDescriptor: KotlinTargetHierarchyDescriptor, - describeExtension: (KotlinTargetHierarchyBuilder.() -> Unit)? = null + describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)? = null ) /** @@ -80,6 +80,6 @@ interface KotlinTargetHierarchyDsl { * @param describeExtension: Additional groups can be described to extend the 'default'/'natural' hierarchy: * @see KotlinTargetHierarchyDescriptor.extend */ - fun default(describeExtension: (KotlinTargetHierarchyBuilder.() -> Unit)? = null) - fun custom(describe: KotlinTargetHierarchyBuilder.() -> Unit) + fun default(describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)? = null) + fun custom(describe: KotlinTargetHierarchyBuilder.Root.() -> Unit) } diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchy.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchy.kt new file mode 100644 index 00000000000..6e70bb592fd --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchy.kt @@ -0,0 +1,21 @@ +/* + * 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.plugin + +interface KotlinTargetHierarchy { + + data class ModuleName(val name: String) { + override fun toString(): String = name + + companion object { + val main = ModuleName("main") + val test = ModuleName("test") + val unitTest = ModuleName("unitTest") + val integrationTest = ModuleName("integrationTest") + val instrumentedTest = ModuleName("instrumentedTest") + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyBuilder.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyBuilder.kt index 11ed65376da..dc43fc29b69 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyBuilder.kt @@ -8,16 +8,27 @@ import org.jetbrains.kotlin.konan.target.DEPRECATED_TARGET_MESSAGE @KotlinTargetsDsl @ExperimentalKotlinGradlePluginApi interface KotlinTargetHierarchyBuilder { + + interface Root : KotlinTargetHierarchyBuilder { + fun modules(vararg module: KotlinTargetHierarchy.ModuleName) + fun withModule(vararg module: KotlinTargetHierarchy.ModuleName) + fun excludeModule(vararg module: KotlinTargetHierarchy.ModuleName) + } + /* Declaring groups */ fun common(build: KotlinTargetHierarchyBuilder.() -> Unit) = group("common", build) fun group(name: String, build: KotlinTargetHierarchyBuilder.() -> Unit = {}) /* low-level APIs */ fun withCompilations(predicate: suspend (KotlinCompilation<*>) -> Boolean) - fun withoutCompilations(predicate: suspend (KotlinCompilation<*>) -> Boolean) + + fun excludeCompilations(predicate: suspend (KotlinCompilation<*>) -> Boolean) + + @Deprecated("Use 'excludeCompilations' instead", ReplaceWith("excludeCompilations(predicate)")) + fun withoutCompilations(predicate: suspend (KotlinCompilation<*>) -> Boolean) = excludeCompilations(predicate) @Deprecated("Use plain 'withoutCompilations(!predicate) instead'", ReplaceWith("withoutCompilations { !predicate(it) }")) - fun filterCompilations(predicate: (KotlinCompilation<*>) -> Boolean) = withoutCompilations { !predicate(it) } + fun filterCompilations(predicate: (KotlinCompilation<*>) -> Boolean) = excludeCompilations { !predicate(it) } /* Convenient groups */ fun withNative() diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyDescriptor.kt b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyDescriptor.kt index df3b212d046..2d7e3f8ce91 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyDescriptor.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetHierarchyDescriptor.kt @@ -9,23 +9,23 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi @ExperimentalKotlinGradlePluginApi interface KotlinTargetHierarchyDescriptor { - fun describe(builder: KotlinTargetHierarchyBuilder) - fun extend(describe: KotlinTargetHierarchyBuilder.() -> Unit): KotlinTargetHierarchyDescriptor + fun describe(builder: KotlinTargetHierarchyBuilder.Root) + fun extend(describe: KotlinTargetHierarchyBuilder.Root.() -> Unit): KotlinTargetHierarchyDescriptor } @ExperimentalKotlinGradlePluginApi fun KotlinTargetHierarchyDescriptor( - describe: KotlinTargetHierarchyBuilder.() -> Unit + describe: KotlinTargetHierarchyBuilder.Root.() -> Unit ): KotlinTargetHierarchyDescriptor { return KotlinTargetHierarchyDescriptorImpl(describe) } @ExperimentalKotlinGradlePluginApi private class KotlinTargetHierarchyDescriptorImpl( - private val describe: KotlinTargetHierarchyBuilder.() -> Unit + private val describe: KotlinTargetHierarchyBuilder.Root.() -> Unit ) : KotlinTargetHierarchyDescriptor { - override fun extend(describe: KotlinTargetHierarchyBuilder.() -> Unit): KotlinTargetHierarchyDescriptor { + override fun extend(describe: KotlinTargetHierarchyBuilder.Root.() -> Unit): KotlinTargetHierarchyDescriptor { val sourceDescribe = this.describe return KotlinTargetHierarchyDescriptor { sourceDescribe() @@ -33,5 +33,5 @@ private class KotlinTargetHierarchyDescriptorImpl( } } - override fun describe(builder: KotlinTargetHierarchyBuilder) = builder.describe() + override fun describe(builder: KotlinTargetHierarchyBuilder.Root) = builder.describe() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchy.ModuleName+orNull.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchy.ModuleName+orNull.kt new file mode 100644 index 00000000000..0965e3faeda --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchy.ModuleName+orNull.kt @@ -0,0 +1,37 @@ +/* + * 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.plugin.mpp.targetHierarchy + +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.ModuleName +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? = + when (compilation) { + is KotlinJvmAndroidCompilation -> orNull(compilation.target, compilation.androidVariant.type) + else -> when (compilation.name) { + "main" -> main + "test" -> test + else -> ModuleName(compilation.name) + } + } + +internal suspend fun ModuleName.Companion.orNull( + target: KotlinAndroidTarget, + variantType: AndroidVariantType +): ModuleName? = when (variantType) { + AndroidVariantType.Main -> + target.main.targetHierarchy.module.awaitFinalValue() ?: main + AndroidVariantType.UnitTest -> + target.unitTest.targetHierarchy.module.awaitFinalValue() ?: test + AndroidVariantType.InstrumentedTest -> + target.instrumentedTest.targetHierarchy.module.awaitFinalValue() ?: ModuleName("instrumentedTest") + AndroidVariantType.Unknown -> null +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchy.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchy.kt deleted file mode 100644 index 7755c924ad7..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchy.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2010-2022 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.targetHierarchy - -import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation -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 -import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName -import org.jetbrains.kotlin.tooling.core.withClosure - -internal data class KotlinTargetHierarchy( - val node: Node, val children: Set = emptySet() -) { - - val childrenClosure: Set = - children.withClosure { it.children } - - sealed class Node { - abstract suspend fun sharedSourceSetName(compilation: KotlinCompilation<*>): String? - - object Root : Node() { - override suspend fun sharedSourceSetName(compilation: KotlinCompilation<*>): String? = null - } - - data class Group(val name: String) : Node() { - override suspend fun sharedSourceSetName(compilation: KotlinCompilation<*>): String? { - val moduleName = Module.orNull(compilation)?.name ?: return null - return lowerCamelCaseName(name, moduleName) - } - } - - final override fun toString(): String = when (this) { - is Group -> name - is Root -> "" - } - } - - data class Module(val name: String) { - override fun toString(): String = name - - companion object { - val main = Module("main") - val test = Module("test") - private val instrumentedTest = Module("instrumentedTest") - - suspend fun orNull(compilation: KotlinCompilation<*>): Module? = when (compilation) { - is KotlinJvmAndroidCompilation -> orNull(compilation.target, compilation.androidVariant.type) - else -> when (compilation.name) { - "main" -> main - "test" -> test - else -> Module(compilation.name) - } - } - - suspend fun orNull(target: KotlinAndroidTarget, variantType: AndroidVariantType): Module? { - return when (variantType) { - AndroidVariantType.Main -> - Module(target.main.kotlinModuleName.awaitFinalValue() ?: return main) - - AndroidVariantType.UnitTest -> - Module(target.unitTest.kotlinModuleName.awaitFinalValue() ?: return test) - - AndroidVariantType.InstrumentedTest -> - Module(target.instrumentedTest.kotlinModuleName.awaitFinalValue() ?: return instrumentedTest) - - AndroidVariantType.Unknown -> null - } - } - } - } - - override fun toString(): String { - if (children.isEmpty()) return node.toString() - return node.toString() + "\n" + children.joinToString("\n").prependIndent("----") - } -} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyBuilderImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyBuilderImpl.kt index 9382d35f70b..a72862b67eb 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyBuilderImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyBuilderImpl.kt @@ -10,30 +10,29 @@ import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget -import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl -import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWasmTargetDsl -import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget import org.jetbrains.kotlin.konan.target.DEPRECATED_TARGET_MESSAGE import org.jetbrains.kotlin.konan.target.Family import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.tooling.core.closure -internal suspend fun KotlinTargetHierarchyDescriptor.buildKotlinTargetHierarchy(compilation: KotlinCompilation<*>): KotlinTargetHierarchy? { +internal suspend fun KotlinTargetHierarchyDescriptor.buildKotlinTargetHierarchy(compilation: KotlinCompilation<*>): KotlinTargetHierarchyTree? { val context = KotlinTargetHierarchyBuilderImplContext(compilation) - describe(context.getOrCreateBuilder(KotlinTargetHierarchy.Node.Root)) - return context.build(KotlinTargetHierarchy.Node.Root) + describe(context.root) + return context.build(KotlinTargetHierarchyTree.Node.Root) } private class KotlinTargetHierarchyBuilderImplContext(private val compilation: KotlinCompilation<*>) { - private val builders = hashMapOf() - private val builtValues = hashMapOf() + val root by lazy { KotlinTargetHierarchyBuilderRootImpl(getOrCreateBuilder(KotlinTargetHierarchyTree.Node.Root)) } - fun getOrCreateBuilder(node: KotlinTargetHierarchy.Node): KotlinTargetHierarchyBuilderImpl = builders.getOrPut(node) { + private val builders = hashMapOf() + private val builtValues = hashMapOf() + + fun getOrCreateBuilder(node: KotlinTargetHierarchyTree.Node): KotlinTargetHierarchyBuilderImpl = builders.getOrPut(node) { KotlinTargetHierarchyBuilderImpl(this, node) } - suspend fun build(node: KotlinTargetHierarchy.Node): KotlinTargetHierarchy? { + suspend fun build(node: KotlinTargetHierarchyTree.Node): KotlinTargetHierarchyTree? { return builtValues.getOrPut(node) { val builder = getOrCreateBuilder(node) if (!builder.contains(compilation)) return@getOrPut null @@ -51,14 +50,44 @@ private class KotlinTargetHierarchyBuilderImplContext(private val compilation: K */ val children = builder.children.mapNotNull { child -> build(child.node) } val directChildren = children.toSet() - children.flatMap { child -> child.childrenClosure }.toSet() - KotlinTargetHierarchy(node, directChildren) + KotlinTargetHierarchyTree(node, directChildren) + } + } +} + +private class KotlinTargetHierarchyBuilderRootImpl( + private val builder: KotlinTargetHierarchyBuilder +) : KotlinTargetHierarchyBuilder.Root, KotlinTargetHierarchyBuilder by builder { + + private var modules: Set? = null + + override fun modules(vararg module: KotlinTargetHierarchy.ModuleName) { + this.modules = module.toHashSet() + } + + override fun withModule(vararg module: KotlinTargetHierarchy.ModuleName) { + this.modules = this.modules.orEmpty().plus(module) + } + + override fun excludeModule(vararg module: KotlinTargetHierarchy.ModuleName) { + val modules = module.toHashSet() + if (modules.isEmpty()) return + if (this.modules == null) return + this.modules = this.modules.orEmpty() - modules + } + + init { + builder.excludeCompilations exclude@{ compilation -> + val modules = this.modules ?: return@exclude false + val module = KotlinTargetHierarchy.ModuleName.orNull(compilation) ?: return@exclude false + module !in modules } } } private class KotlinTargetHierarchyBuilderImpl( val context: KotlinTargetHierarchyBuilderImplContext, - val node: KotlinTargetHierarchy.Node, + val node: KotlinTargetHierarchyTree.Node, ) : KotlinTargetHierarchyBuilder { val children = mutableSetOf() @@ -74,7 +103,7 @@ private class KotlinTargetHierarchyBuilderImpl( this.excludePredicate = { previousExcludePredicate(it) && !predicate(it) } } - override fun withoutCompilations(predicate: suspend (KotlinCompilation<*>) -> Boolean) { + override fun excludeCompilations(predicate: suspend (KotlinCompilation<*>) -> Boolean) { val previousIncludePredicate = this.includePredicate val previousExcludePredicate = this.excludePredicate this.includePredicate = { previousIncludePredicate(it) && !predicate(it) } @@ -95,7 +124,7 @@ private class KotlinTargetHierarchyBuilderImpl( private inline fun withTargets(crossinline predicate: (KotlinTarget) -> Boolean) = withCompilations { predicate(it.target) } override fun group(name: String, build: KotlinTargetHierarchyBuilder.() -> Unit) { - val node = KotlinTargetHierarchy.Node.Group(name) + val node = KotlinTargetHierarchyTree.Node.Group(name) val child = context.getOrCreateBuilder(node).also(build) children.add(child) checkCyclicHierarchy() @@ -273,6 +302,6 @@ private fun KotlinTargetHierarchyBuilderImpl.checkCyclicHierarchy(): Nothing? { return null } -internal class CyclicKotlinTargetHierarchyException(val cycle: List) : InvalidUserCodeException( +internal class CyclicKotlinTargetHierarchyException(val cycle: List) : InvalidUserCodeException( "KotlinTargetHierarchy cycle detected: ${cycle.joinToString(" -> ")}" ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyDslImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyDslImpl.kt index 880608f1672..a523cb33718 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyDslImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyDslImpl.kt @@ -23,21 +23,21 @@ internal class KotlinTargetHierarchyDslImpl( override fun apply( hierarchyDescriptor: KotlinTargetHierarchyDescriptor, - describeExtension: (KotlinTargetHierarchyBuilder.() -> Unit)? + describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)? ) { val descriptor = hierarchyDescriptor.extendIfNotNull(describeExtension) _appliedDescriptors.add(descriptor) applyKotlinTargetHierarchy(descriptor, targets, sourceSets) } - override fun default(describeExtension: (KotlinTargetHierarchyBuilder.() -> Unit)?) { + override fun default(describeExtension: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?) { apply(defaultKotlinTargetHierarchy, describeExtension) } - override fun custom(describe: KotlinTargetHierarchyBuilder.() -> Unit) { + override fun custom(describe: KotlinTargetHierarchyBuilder.Root.() -> Unit) { apply(KotlinTargetHierarchyDescriptor(describe)) } } -private fun KotlinTargetHierarchyDescriptor.extendIfNotNull(describe: (KotlinTargetHierarchyBuilder.() -> Unit)?) = +private fun KotlinTargetHierarchyDescriptor.extendIfNotNull(describe: (KotlinTargetHierarchyBuilder.Root.() -> Unit)?) = if (describe == null) this else extend(describe) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyTree.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyTree.kt new file mode 100644 index 00000000000..2c1b58cb28f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/KotlinTargetHierarchyTree.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2022 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.targetHierarchy + +import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation +import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy +import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName +import org.jetbrains.kotlin.tooling.core.withClosure + +internal data class KotlinTargetHierarchyTree( + val node: Node, val children: Set = emptySet() +) { + + val childrenClosure: Set = + children.withClosure { it.children } + + sealed class Node { + abstract suspend fun sharedSourceSetName(compilation: KotlinCompilation<*>): String? + + object Root : Node() { + override suspend fun sharedSourceSetName(compilation: KotlinCompilation<*>): String? = null + } + + 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) + } + } + + final override fun toString(): String = when (this) { + is Group -> name + is Root -> "" + } + } + + override fun toString(): String { + if (children.isEmpty()) return node.toString() + return node.toString() + "\n" + children.joinToString("\n").prependIndent("----") + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/applyKotlinTargetHierarchy.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/applyKotlinTargetHierarchy.kt index 316a795380d..c2fe490679c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/applyKotlinTargetHierarchy.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/applyKotlinTargetHierarchy.kt @@ -28,7 +28,7 @@ internal fun applyKotlinTargetHierarchy( } private suspend fun applyKotlinTargetHierarchy( - hierarchy: KotlinTargetHierarchy, + hierarchy: KotlinTargetHierarchyTree, compilation: KotlinCompilation<*>, sourceSets: NamedDomainObjectContainer ): KotlinSourceSet? { @@ -52,7 +52,7 @@ private suspend fun applyKotlinTargetHierarchy( private suspend fun createSharedSourceSetOrNull( sourceSets: NamedDomainObjectContainer, - node: KotlinTargetHierarchy.Node, + node: KotlinTargetHierarchyTree.Node, compilation: KotlinCompilation<*>, ): KotlinSourceSet? { val sharedSourceSetName = node.sharedSourceSetName(compilation) ?: return null diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/defaultKotlinTargetHierarchy.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/defaultKotlinTargetHierarchy.kt index a112b8c502e..e0a3a1d7684 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/defaultKotlinTargetHierarchy.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/targetHierarchy/defaultKotlinTargetHierarchy.kt @@ -5,16 +5,12 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy +import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.ModuleName import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchyDescriptor -private val defaultKotlinTargetHierarchyModules = hashSetOf( - KotlinTargetHierarchy.Module.main, - KotlinTargetHierarchy.Module.test -) - internal val defaultKotlinTargetHierarchy = KotlinTargetHierarchyDescriptor { /* natural hierarchy is only applied to default 'main'/'test' compilations (by default) */ - withoutCompilations { KotlinTargetHierarchy.Module.orNull(it) !in defaultKotlinTargetHierarchyModules } + withModule(ModuleName.main, ModuleName.test) common { /* All compilations shall receive be added to the common group by default */ diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinTargetHierarchyDescriptorTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinTargetHierarchyDescriptorTest.kt index 2c12c348714..a26402dd924 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinTargetHierarchyDescriptorTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinTargetHierarchyDescriptorTest.kt @@ -10,8 +10,8 @@ package org.jetbrains.kotlin.gradle.unitTests import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchyDescriptor import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.CyclicKotlinTargetHierarchyException -import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.KotlinTargetHierarchy -import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.KotlinTargetHierarchy.Node +import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.KotlinTargetHierarchyTree +import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.KotlinTargetHierarchyTree.Node import org.jetbrains.kotlin.gradle.plugin.mpp.targetHierarchy.buildKotlinTargetHierarchy import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest @@ -149,7 +149,7 @@ class KotlinTargetHierarchyDescriptorTest { }, hierarchy ) - fun KotlinTargetHierarchy.collectChildren(): List { + fun KotlinTargetHierarchyTree.collectChildren(): List { return children.toList() + children.flatMap { it.collectChildren() } } @@ -249,9 +249,9 @@ private class TestHierarchyBuilder(private val node: Node) { children.add(TestHierarchyBuilder(Node.Group(name)).also(builder)) } - fun build(): KotlinTargetHierarchy = KotlinTargetHierarchy(node, children.map { it.build() }.toSet()) + fun build(): KotlinTargetHierarchyTree = KotlinTargetHierarchyTree(node, children.map { it.build() }.toSet()) } -private fun hierarchy(build: TestHierarchyBuilder.() -> Unit): KotlinTargetHierarchy { +private fun hierarchy(build: TestHierarchyBuilder.() -> Unit): KotlinTargetHierarchyTree { return TestHierarchyBuilder(Node.Root).also(build).build() }