Replace transitiveClosure (commonizer-api) with closure (tooling-core)

This commit is contained in:
sebastian.sellmair
2022-03-05 13:18:19 +01:00
committed by Space
parent 530a3bb6ea
commit 14046b81ff
31 changed files with 99 additions and 237 deletions
@@ -13,7 +13,7 @@ import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
import org.jetbrains.kotlin.project.model.KotlinModuleFragment
import org.jetbrains.kotlin.project.model.refinesClosure
import org.jetbrains.kotlin.project.model.withRefinesClosure
interface KotlinGradleFragment : KotlinModuleFragment, HasKotlinDependencies, KotlinFragmentDependencyConfigurations, Named {
override val kotlinSourceRoots: SourceDirectorySet
@@ -59,4 +59,4 @@ interface KotlinGradleFragment : KotlinModuleFragment, HasKotlinDependencies, Ko
}
val KotlinGradleFragment.refinesClosure: Set<KotlinGradleFragment>
get() = (this as KotlinModuleFragment).refinesClosure.mapTo(mutableSetOf()) { it as KotlinGradleFragment }
get() = (this as KotlinModuleFragment).withRefinesClosure.mapTo(mutableSetOf()) { it as KotlinGradleFragment }
@@ -11,8 +11,8 @@ package org.jetbrains.kotlin.gradle
import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllSourceSetsDependingOn
import org.jetbrains.kotlin.gradle.plugin.sources.dependsOnClosure
import org.jetbrains.kotlin.gradle.plugin.sources.findSourceSetsDependingOn
import org.junit.Test
import kotlin.test.BeforeTest
import kotlin.test.assertEquals
@@ -45,17 +45,17 @@ class ResolveKotlinSourceSetsTest {
assertEquals(
setOf(nativeMain, linuxMain, macosMain, jvmMain),
kotlin.resolveAllSourceSetsDependingOn(commonMain)
kotlin.findSourceSetsDependingOn(commonMain)
)
assertEquals(
setOf(linuxMain, macosMain),
kotlin.resolveAllSourceSetsDependingOn(nativeMain)
kotlin.findSourceSetsDependingOn(nativeMain)
)
assertEquals(emptySet(), kotlin.resolveAllSourceSetsDependingOn(linuxMain))
assertEquals(emptySet(), kotlin.resolveAllSourceSetsDependingOn(macosMain))
assertEquals(emptySet(), kotlin.resolveAllSourceSetsDependingOn(jvmMain))
assertEquals(emptySet(), kotlin.findSourceSetsDependingOn(linuxMain))
assertEquals(emptySet(), kotlin.findSourceSetsDependingOn(macosMain))
assertEquals(emptySet(), kotlin.findSourceSetsDependingOn(jvmMain))
}
@Test
@@ -72,19 +72,19 @@ class ResolveKotlinSourceSetsTest {
macosMain.dependsOn(nativeMain)
assertEquals(
setOf(nativeMain, commonMain), linuxMain.resolveAllDependsOnSourceSets()
setOf(nativeMain, commonMain), linuxMain.dependsOnClosure
)
assertEquals(
setOf(commonMain), nativeMain.resolveAllDependsOnSourceSets()
setOf(commonMain), nativeMain.dependsOnClosure
)
assertEquals(
emptySet(), commonMain.resolveAllDependsOnSourceSets()
emptySet(), commonMain.dependsOnClosure
)
assertEquals(
setOf(commonMain), jvmMain.resolveAllDependsOnSourceSets()
setOf(commonMain), jvmMain.dependsOnClosure
)
}
}
@@ -27,9 +27,9 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.kpmModules
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.dependsOnClosure
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
import org.jetbrains.kotlin.gradle.plugin.sources.withAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure
import org.jetbrains.kotlin.gradle.targets.android.findAndroidTarget
import org.jetbrains.kotlin.gradle.targets.jvm.JvmCompilationsTestRunSource
import org.jetbrains.kotlin.gradle.tasks.locateTask
@@ -166,7 +166,7 @@ private fun chooseAndAddStdlibDependency(
val sourceSetDependencyConfigurations =
KotlinDependencyScope.values().map { project.sourceSetDependencyConfigurationByScope(kotlinSourceSet, it) }
val hierarchySourceSetsDependencyConfigurations = kotlinSourceSet.resolveAllDependsOnSourceSets().flatMap { hierarchySourceSet ->
val hierarchySourceSetsDependencyConfigurations = kotlinSourceSet.dependsOnClosure.flatMap { hierarchySourceSet ->
KotlinDependencyScope.values().map { scope ->
project.sourceSetDependencyConfigurationByScope(hierarchySourceSet, scope)
}
@@ -281,7 +281,7 @@ internal fun configureKotlinTestDependency(project: Project) {
project.tryWithDependenciesIfUnresolved(configuration) { dependencies ->
val parentOrOwnVersions: List<String?> =
kotlinSourceSet.withAllDependsOnSourceSets().filter(versionOrNullBySourceSet::contains)
kotlinSourceSet.withDependsOnClosure.filter(versionOrNullBySourceSet::contains)
.map(versionOrNullBySourceSet::get)
finalizingDependencies = true
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.gradle.model.impl.SourceSetImpl
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.getConvention
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
/**
@@ -15,7 +15,6 @@ import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
import org.jetbrains.kotlin.gradle.plugin.*
@@ -28,8 +27,8 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.unambiguousNameInProject
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
import org.jetbrains.kotlin.gradle.plugin.sources.getVisibleSourceSetsFromAssociateCompilations
import org.jetbrains.kotlin.gradle.plugin.sources.kpm.FragmentMappedKotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.withAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.dependsOnClosure
import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
@@ -37,6 +36,7 @@ import org.jetbrains.kotlin.gradle.targets.metadata.getMetadataCompilationForSou
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.project.model.LanguageSettings
import org.jetbrains.kotlin.tooling.core.closure
import java.util.*
import java.util.concurrent.Callable
@@ -69,8 +69,8 @@ interface CompilationDetailsWithRuntime<T : KotlinCommonOptions> : CompilationDe
val runtimeDependencyFilesHolder: DependencyFilesHolder
}
internal val CompilationDetails<*>.associateWithTransitiveClosure: Iterable<CompilationDetails<*>>
get() = transitiveClosure(this) { associateCompilations }
internal val CompilationDetails<*>.associateCompilationsClosure: Iterable<CompilationDetails<*>>
get() = closure { it.associateCompilations }
open class DefaultCompilationDetails<T : KotlinCommonOptions>(
final override val target: KotlinTarget,
@@ -122,8 +122,7 @@ open class DefaultCompilationDetails<T : KotlinCommonOptions>(
get() = target.disambiguationClassifier
override val kotlinSourceDirectoriesByFragmentName: Map<String, SourceDirectorySet>
get() = directlyIncludedKotlinSourceSets.plus(directlyIncludedKotlinSourceSets.resolveAllDependsOnSourceSets())
.associate { it.name to it.kotlin }
get() = directlyIncludedKotlinSourceSets.withDependsOnClosure.associate { it.name to it.kotlin }
override val compileKotlinTaskName: String
get() = lowerCamelCaseName(
@@ -163,12 +162,12 @@ open class DefaultCompilationDetails<T : KotlinCommonOptions>(
override val friendPaths: Iterable<FileCollection>
get() = mutableListOf<FileCollection>().also { allCollections ->
associateWithTransitiveClosure.forEach { allCollections.add(it.compilationData.output.classesDirs) }
associateCompilationsClosure.forEach { allCollections.add(it.compilationData.output.classesDirs) }
allCollections.add(friendArtifacts)
}
private val friendArtifactsTask: TaskProvider<AbstractArchiveTask>? by lazy {
if (associateWithTransitiveClosure.any { it.compilationData.isMainCompilationData() }) {
if (associateCompilationsClosure.any { it.compilationData.isMainCompilationData() }) {
val archiveTasks = target.project.tasks.withType(AbstractArchiveTask::class.java)
if (!archiveTasks.isEmpty()) {
try {
@@ -270,7 +269,7 @@ open class DefaultCompilationDetails<T : KotlinCommonOptions>(
override fun source(sourceSet: KotlinSourceSet) {
if (directlyIncludedKotlinSourceSets.add(sourceSet)) {
target.project.whenEvaluated {
addExactSourceSetsEagerly(sourceSet.withAllDependsOnSourceSets())
addExactSourceSetsEagerly(sourceSet.withDependsOnClosure)
}
}
}
@@ -389,7 +388,7 @@ internal open class SharedNativeCompilationDetails(
val friendSourceSets = getVisibleSourceSetsFromAssociateCompilations(project, defaultSourceSet).toMutableSet().apply {
// TODO: implement proper dependsOn/refines compiler args for Kotlin/Native and pass the dependsOn klibs separately;
// But for now, those dependencies don't have any special semantics, so passing all them as friends works, too
addAll(defaultSourceSet.resolveAllDependsOnSourceSets())
addAll(defaultSourceSet.dependsOnClosure)
}
project.files(friendSourceSets.mapNotNull { project.getMetadataCompilationForSourceSet(it)?.output?.classesDirs })
})
@@ -671,4 +670,4 @@ internal class KotlinDependencyConfigurationsHolder(
override fun dependencies(configureClosure: Closure<Any?>) =
dependencies f@{ project.configure(this@f, configureClosure) }
}
}
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope.*
import org.jetbrains.kotlin.gradle.plugin.sources.withAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
import org.jetbrains.kotlin.gradle.targets.metadata.ResolvedMetadataFilesProvider
@@ -42,7 +42,7 @@ open class TransformKotlinGranularMetadata
}
private val participatingSourceSets: Set<KotlinSourceSet>
get() = transformation.kotlinSourceSet.withAllDependsOnSourceSets().toMutableSet().apply {
get() = transformation.kotlinSourceSet.withDependsOnClosure.toMutableSet().apply {
if (any { it.name == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME })
add(project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME))
}
@@ -19,11 +19,12 @@ import org.gradle.api.tasks.TaskState
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.locateTask
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.project.model.LanguageSettings
import org.jetbrains.kotlin.tooling.core.closure
import java.util.*
import java.util.concurrent.Callable
@@ -137,8 +138,7 @@ abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
get() = target
override val allKotlinSourceSets: Set<KotlinSourceSet>
get() = compilationDetails.directlyIncludedKotlinSourceSets +
compilationDetails.directlyIncludedKotlinSourceSets.resolveAllDependsOnSourceSets()
get() = compilationDetails.directlyIncludedKotlinSourceSets.withDependsOnClosure
override val relatedConfigurationNames: List<String>
get() = compilationDetails.kotlinDependenciesHolder.relatedConfigurationNames + compileDependencyConfigurationName
@@ -181,15 +181,8 @@ internal fun addSourcesToKotlinCompileTask(
}
}
internal val KotlinCompilation<*>.associateWithTransitiveClosure: Iterable<KotlinCompilation<*>>
get() = mutableSetOf<KotlinCompilation<*>>().apply {
fun visit(other: KotlinCompilation<*>) {
if (add(other)) {
other.associateWith.forEach(::visit)
}
}
associateWith.forEach(::visit)
}
internal val KotlinCompilation<*>.associateWithClosure: Iterable<KotlinCompilation<*>>
get() = this.closure { it.associateWith }
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>(
override val compilationDetails: CompilationDetailsWithRuntime<T>,
@@ -292,4 +285,4 @@ internal object CompilationSourceSetUtil {
private val invalidModuleNameCharactersRegex = """[\\/\r\n\t]""".toRegex()
internal fun filterModuleName(moduleName: String): String =
moduleName.replace(invalidModuleNameCharactersRegex, "_")
moduleName.replace(invalidModuleNameCharactersRegex, "_")
@@ -157,7 +157,7 @@ internal class FragmentGranularMetadataResolver(
val relevantVariantResolution = variantResolutions
.filterIsInstance<VariantResolution.VariantMatch>()
// find some of our variants that resolved a dependency's variant containing the fragment
.find { hostSpecificFragment in it.chosenVariant.refinesClosure }
.find { hostSpecificFragment in it.chosenVariant.withRefinesClosure }
// resolve the dependencies of that variant getting the host-specific metadata artifact
relevantVariantResolution?.let { resolution ->
val configurationResolvingPlatformVariant =
@@ -9,7 +9,6 @@ import org.gradle.api.artifacts.component.ProjectComponentIdentifier
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.GradleModuleVariantResolver
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
@@ -18,7 +17,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.project.model.VariantResolution
import org.jetbrains.kotlin.project.model.refinesClosure
import org.jetbrains.kotlin.project.model.withRefinesClosure
interface KotlinVariantCompilationDataInternal<T : KotlinCommonOptions> : KotlinVariantCompilationData<T> {
override val compileKotlinTaskName: String
@@ -28,7 +27,7 @@ interface KotlinVariantCompilationDataInternal<T : KotlinCommonOptions> : Kotlin
get() = owner.disambiguateName("classes")
override val kotlinSourceDirectoriesByFragmentName: Map<String, SourceDirectorySet>
get() = owner.refinesClosure.filterIsInstance<KotlinGradleVariant>().associate { it.disambiguateName("") to it.kotlinSourceRoots }
get() = owner.withRefinesClosure.filterIsInstance<KotlinGradleVariant>().associate { it.disambiguateName("") to it.kotlinSourceRoots }
override val friendPaths: Iterable<FileCollection>
get() {
@@ -7,12 +7,11 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.artifacts.Dependency
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName
import org.jetbrains.kotlin.gradle.targets.metadata.filesWithUnpackedArchives
import org.jetbrains.kotlin.gradle.tasks.registerTask
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.project.model.refinesClosure
import org.jetbrains.kotlin.project.model.withRefinesClosure
/**
* Will register a 'hostSpecificMetadataJar' [Jar] task containing compilation outputs of host specific metadata.
@@ -30,7 +29,7 @@ val KotlinFragmentHostSpecificMetadataArtifact = FragmentArtifacts<KotlinNativeV
val metadataFragment = metadataCompilation.fragment
if (metadataCompilation is KotlinNativeFragmentMetadataCompilationData) {
jar.from(project.files(project.provider {
if (metadataFragment in fragment.refinesClosure && metadataFragment.isNativeHostSpecific())
if (metadataFragment in fragment.withRefinesClosure && metadataFragment.isNativeHostSpecific())
project.filesWithUnpackedArchives(metadataCompilation.output.allOutputs, setOf(KLIB_FILE_EXTENSION))
else emptyList<Any>()
})) { spec -> spec.into(metadataFragment.name) }
@@ -11,13 +11,11 @@ import org.gradle.api.Project
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.provider.Provider
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
import org.jetbrains.kotlin.gradle.kpm.KotlinExternalModelContainer
import org.jetbrains.kotlin.gradle.kpm.KotlinMutableExternalModelContainer
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinDependencyConfigurationsHolder
import org.jetbrains.kotlin.gradle.plugin.mpp.toModuleDependency
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.plugin.sources.FragmentConsistencyChecker
@@ -26,7 +24,7 @@ import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheckWhenEvaluated
import org.jetbrains.kotlin.project.model.KotlinModuleDependency
import org.jetbrains.kotlin.project.model.KotlinModuleFragment
import org.jetbrains.kotlin.project.model.refinesClosure
import org.jetbrains.kotlin.project.model.withRefinesClosure
import javax.inject.Inject
open class KotlinGradleFragmentInternal @Inject constructor(
@@ -118,4 +116,4 @@ open class KotlinGradleFragmentInternal @Inject constructor(
}
val KotlinGradleFragment.refinesClosure: Set<KotlinGradleFragment>
get() = (this as KotlinModuleFragment).refinesClosure.map { it as KotlinGradleFragment }.toSet()
get() = (this as KotlinModuleFragment).withRefinesClosure.map { it as KotlinGradleFragment }.toSet()
@@ -5,13 +5,13 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleDependencyGraph
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleDependencyGraphNode
import org.jetbrains.kotlin.project.model.KotlinModule
import org.jetbrains.kotlin.tooling.core.withClosure
internal val GradleDependencyGraph.allDependencyNodes: Iterable<GradleDependencyGraphNode>
get() = transitiveClosure(root) { dependenciesByFragment.values.flatten() }
get() = root.withClosure { it.dependenciesByFragment.values.flatten() }
internal val GradleDependencyGraph.allDependencyModules: Iterable<KotlinModule>
get() = allDependencyNodes.map { it.module }
@@ -11,13 +11,14 @@ import org.gradle.api.Project
import org.gradle.api.file.SourceDirectorySet
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.tooling.core.closure
import org.jetbrains.kotlin.tooling.core.withClosure
import java.io.File
import java.util.*
@@ -252,28 +253,15 @@ internal fun KotlinSourceSet.disambiguateName(simpleName: String): String {
internal fun createDefaultSourceDirectorySet(project: Project, name: String?): SourceDirectorySet =
project.objects.sourceDirectorySet(name!!, name)
/**
* Like [resolveAllDependsOnSourceSets] but will include the receiver source set also!
*/
internal fun KotlinSourceSet.withAllDependsOnSourceSets(): Set<KotlinSourceSet> {
return this + this.resolveAllDependsOnSourceSets()
}
internal operator fun KotlinSourceSet.plus(sourceSets: Set<KotlinSourceSet>): Set<KotlinSourceSet> {
return HashSet<KotlinSourceSet>(sourceSets.size + 1).also { set ->
set.add(this)
set.addAll(sourceSets)
}
}
val KotlinSourceSet.dependsOnClosure get() = closure { it.dependsOn }
internal fun KotlinSourceSet.resolveAllDependsOnSourceSets(): Set<KotlinSourceSet> {
return transitiveClosure(this) { dependsOn }
}
val KotlinSourceSet.withDependsOnClosure get() = withClosure { it.dependsOn }
internal fun Iterable<KotlinSourceSet>.resolveAllDependsOnSourceSets(): Set<KotlinSourceSet> {
return flatMapTo(mutableSetOf()) { it.resolveAllDependsOnSourceSets() }
}
val Iterable<KotlinSourceSet>.dependsOnClosure get() = closure<KotlinSourceSet> { it.dependsOn }
internal fun KotlinMultiplatformExtension.resolveAllSourceSetsDependingOn(sourceSet: KotlinSourceSet): Set<KotlinSourceSet> {
return transitiveClosure(sourceSet) { sourceSets.filter { otherSourceSet -> this in otherSourceSet.dependsOn } }
val Iterable<KotlinSourceSet>.withDependsOnClosure get() = withClosure<KotlinSourceSet> { it.dependsOn }
internal fun KotlinMultiplatformExtension.findSourceSetsDependingOn(sourceSet: KotlinSourceSet): Set<KotlinSourceSet> {
return sourceSet.closure { seedSourceSet -> sourceSets.filter { otherSourceSet -> seedSourceSet in otherSourceSet.dependsOn } }
}
@@ -11,10 +11,10 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithClosure
fun getSourceSetsFromAssociatedCompilations(fromCompilation: KotlinCompilation<*>): Map<KotlinCompilation<*>, Set<KotlinSourceSet>> =
fromCompilation.associateWithTransitiveClosure.associate { it to it.allKotlinSourceSets }
fromCompilation.associateWithClosure.associate { it to it.allKotlinSourceSets }
fun getVisibleSourceSetsFromAssociateCompilations(
project: Project,
@@ -140,7 +140,7 @@ internal fun checkSourceSetVisibilityRequirements(
val inferredVisibility =
getVisibleSourceSetsFromAssociateCompilations(compilationsBySourceSet[sourceSet].orEmpty())
val requiredButNotVisible = requiredVisibility - inferredVisibility - sourceSet.withAllDependsOnSourceSets()
val requiredButNotVisible = requiredVisibility - inferredVisibility - sourceSet.withDependsOnClosure
if (requiredButNotVisible.isNotEmpty()) {
val compilations = compilationsBySourceSet.getValue(sourceSet)
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil.compilationsBySourceSets
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.hasKpmModel
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.metadataCompilationRegistryByModuleId
import org.jetbrains.kotlin.gradle.plugin.sources.*
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
import org.jetbrains.kotlin.gradle.targets.native.internal.*
@@ -257,7 +256,7 @@ class KotlinMetadataTargetConfigurator :
* See also: [buildKotlinProjectStructureMetadata], where these dependencies must be included into the source set exported deps.
*/
if (isSharedNativeCompilation) {
sourceSet.withAllDependsOnSourceSets().forEach { hierarchySourceSet ->
sourceSet.withDependsOnClosure.forEach { hierarchySourceSet ->
apiElementsConfiguration.extendsFrom(
sourceSetDependencyConfigurationByScope(hierarchySourceSet, KotlinDependencyScope.IMPLEMENTATION_SCOPE)
)
@@ -438,14 +437,14 @@ class KotlinMetadataTargetConfigurator :
val sourceSet = compilation.defaultSourceSet
val dependsOnCompilationOutputs = lazy {
sourceSet.withAllDependsOnSourceSets().mapNotNull { hierarchySourceSet ->
sourceSet.withDependsOnClosure.mapNotNull { hierarchySourceSet ->
val dependencyCompilation = project.getMetadataCompilationForSourceSet(hierarchySourceSet)
dependencyCompilation?.output?.classesDirs.takeIf { hierarchySourceSet != sourceSet }
}
}
val resolvedMetadataFilesProviders = lazy {
val transformationTaskHolders = sourceSet.withAllDependsOnSourceSets().mapNotNull { hierarchySourceSet ->
val transformationTaskHolders = sourceSet.withDependsOnClosure.mapNotNull { hierarchySourceSet ->
project.locateTask<TransformKotlinGranularMetadata>(transformGranularMetadataTaskName(hierarchySourceSet.name))
}
transformationTaskHolders.map { SourceSetResolvedMetadataProvider(it) }
@@ -565,7 +564,7 @@ internal fun isSharedNativeSourceSet(project: Project, sourceSet: KotlinSourceSe
}
internal fun dependsOnClosureWithInterCompilationDependencies(project: Project, sourceSet: KotlinSourceSet): Set<KotlinSourceSet> =
sourceSet.resolveAllDependsOnSourceSets().toMutableSet().apply {
sourceSet.dependsOnClosure.toMutableSet().apply {
addAll(getVisibleSourceSetsFromAssociateCompilations(project, sourceSet))
}
@@ -10,19 +10,13 @@ import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.TaskProvider
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformCommonOptionsImpl
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinNativeCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinNativeFragmentMetadataCompilationData
import org.jetbrains.kotlin.gradle.plugin.sources.getVisibleSourceSetsFromAssociateCompilations
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.targets.metadata.getMetadataCompilationForSourceSet
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.File
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.CompilationSourceSetUtil.compilationsBySourceSets
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithClosure
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropIdentifier.Scope
import org.jetbrains.kotlin.gradle.utils.UnsafeApi
@@ -59,7 +59,7 @@ internal fun CInteropCommonizerDependent.Factory.from(
This relationship should not be declared, but we try to be lenient towards it here.
*/
val filteredCompilations = compilations.filter { compilation ->
compilation.associateWithTransitiveClosure.none { associateCompilation -> associateCompilation in compilations }
compilation.associateWithClosure.none { associateCompilation -> associateCompilation in compilations }
}.ifEmpty { return null }.toSet()
val scopes: Set<Scope> = filteredCompilations
@@ -95,7 +95,7 @@ internal fun CInteropCommonizerDependent.Factory.fromAssociateCompilations(
target = project.getCommonizerTarget(sourceSet) as? SharedCommonizerTarget ?: return null,
compilations = (compilationsBySourceSets(project)[sourceSet] ?: return null)
.filterIsInstance<KotlinNativeCompilation>()
.flatMap { compilation -> compilation.associateWithTransitiveClosure }
.flatMap { compilation -> compilation.associateWithClosure }
.filterIsInstance<KotlinNativeCompilation>()
.toSet()
)
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.kotlinSourceSetsIncludingDefault
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure
import org.jetbrains.kotlin.gradle.targets.native.internal.CInteropCommonizerTask.CInteropGist
import org.jetbrains.kotlin.gradle.tasks.CInteropProcess
import org.jetbrains.kotlin.konan.target.KonanTarget
@@ -34,7 +34,8 @@ internal open class CInteropCommonizerTask : AbstractCInteropCommonizerTask() {
) {
@Suppress("unused") // Used for UP-TO-DATE check
@get:Input
val allSourceSetNames: Provider<List<String>> = sourceSets.map { it.resolveAllDependsOnSourceSets().map(Any::toString) }
val allSourceSetNames: Provider<List<String>> = sourceSets
.map { it.withDependsOnClosure.map(Any::toString) }
}
override val outputDirectory: File = project.buildDir.resolve("classes/kotlin/commonizer")
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.Choos
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toModuleIdentifiers
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.SourceSetMetadataStorageForIde
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.dependsOnClosure
import org.jetbrains.kotlin.gradle.tasks.dependsOn
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.withType
@@ -87,7 +87,7 @@ internal fun Project.locateOrRegisterCInteropMetadataDependencyTransformationTas
*/
private fun CInteropMetadataDependencyTransformationTask.configureTaskOrder() {
val tasksForVisibleSourceSets = Callable {
val allVisibleSourceSets = sourceSet.resolveAllDependsOnSourceSets() + sourceSet.getAdditionalVisibleSourceSets()
val allVisibleSourceSets = sourceSet.dependsOnClosure + sourceSet.getAdditionalVisibleSourceSets()
project.tasks.withType<CInteropMetadataDependencyTransformationTask>().matching { it.sourceSet in allVisibleSourceSets }
}
mustRunAfter(tasksForVisibleSourceSets)
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinSharedNativeCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.kotlinSourceSetsIncludingDefault
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.plugin.sources.withDependsOnClosure
internal fun KotlinSharedNativeCompilation.getImplicitlyDependingNativeCompilations(): Set<KotlinNativeCompilation> {
val multiplatformExtension = project.multiplatformExtensionOrNull ?: return emptySet()
@@ -30,5 +30,5 @@ internal fun KotlinSharedNativeCompilation.getImplicitlyDependingNativeCompilati
* see KT-45412
*/
private fun KotlinCompilation<*>.allParticipatingSourceSets(): Set<KotlinSourceSet> {
return kotlinSourceSetsIncludingDefault + kotlinSourceSetsIncludingDefault.resolveAllDependsOnSourceSets()
return kotlinSourceSetsIncludingDefault.withDependsOnClosure
}
@@ -38,8 +38,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.AbstractKotlinFragmentMetadat
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinMetadataCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.refinesClosure
import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets
import org.jetbrains.kotlin.gradle.report.BuildReportMode
import org.jetbrains.kotlin.gradle.plugin.sources.dependsOnClosure
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
import java.io.File
import javax.inject.Inject
@@ -65,7 +64,7 @@ abstract class KotlinCompileCommon @Inject constructor(
is KotlinCompilation<*> -> {
val defaultKotlinSourceSet: KotlinSourceSet = compilation.defaultSourceSet
val metadataTarget = compilation.owner as KotlinTarget
defaultKotlinSourceSet.resolveAllDependsOnSourceSets()
defaultKotlinSourceSet.dependsOnClosure
.mapNotNull { sourceSet -> metadataTarget.compilations.findByName(sourceSet.name)?.output?.classesDirs }
.flatten()
}
@@ -181,7 +181,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
task.friendPaths.from(project.provider { compilation.friendPaths })
if (compilation is KotlinCompilation<*>) {
task.friendSourceSets.set(project.provider { compilation.associateWithTransitiveClosure.map { it.name } })
task.friendSourceSets.set(project.provider { compilation.associateWithClosure.map { it.name } })
// FIXME support compiler plugins with PM20
task.pluginClasspath.from(project.configurations.getByName(compilation.pluginConfigurationName))
}
@@ -9,7 +9,7 @@ standardPublicJars()
dependencies {
implementation(kotlinStdlib())
implementation(project(":kotlin-tooling-core"))
testImplementation(kotlin("test-junit"))
}
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.project.model
import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment
import org.jetbrains.kotlin.tooling.core.closure
import org.jetbrains.kotlin.tooling.core.withClosure
import java.io.File
interface KotlinModuleFragment {
@@ -39,13 +41,10 @@ val KotlinModuleFragment.fragmentAttributeSets: Map<KotlinAttributeKey, Set<Stri
}
val KotlinModuleFragment.refinesClosure: Set<KotlinModuleFragment>
get() = mutableSetOf<KotlinModuleFragment>().apply {
fun visit(moduleFragment: KotlinModuleFragment) {
if (add(moduleFragment))
moduleFragment.directRefinesDependencies.forEach(::visit)
}
visit(this@refinesClosure)
}
get() = this.closure { it.directRefinesDependencies }
val KotlinModuleFragment.withRefinesClosure: Set<KotlinModuleFragment>
get() = this.withClosure { it.directRefinesDependencies }
val KotlinModuleVariant.platform get() = variantAttributes[KotlinPlatformTypeAttribute]
@@ -67,7 +66,7 @@ class BasicKotlinModuleVariant(
containingModule: KotlinModule,
fragmentName: String,
languageSettings: LanguageSettings? = null
) : BasicKotlinModuleFragment (
) : BasicKotlinModuleFragment(
containingModule,
fragmentName,
languageSettings
@@ -49,7 +49,7 @@ class DefaultModuleFragmentsResolver(
val chosenFragments = chosenVariants.map { variantResolution ->
when (variantResolution) {
is VariantResolution.VariantMatch -> variantResolution.chosenVariant.refinesClosure
is VariantResolution.VariantMatch -> variantResolution.chosenVariant.withRefinesClosure
else -> emptySet()
}
}
@@ -63,4 +63,4 @@ class DefaultModuleFragmentsResolver(
return FragmentResolution.ChosenFragments(requestingFragment, dependencyModule, result, chosenVariants)
}
}
}
@@ -8,22 +8,14 @@ package org.jetbrains.kotlin.project.model.utils
import org.jetbrains.kotlin.project.model.KotlinModule
import org.jetbrains.kotlin.project.model.KotlinModuleFragment
import org.jetbrains.kotlin.project.model.KotlinModuleVariant
import org.jetbrains.kotlin.project.model.refinesClosure
import org.jetbrains.kotlin.project.model.withRefinesClosure
import org.jetbrains.kotlin.tooling.core.closure
fun KotlinModule.variantsContainingFragment(fragment: KotlinModuleFragment): Iterable<KotlinModuleVariant> =
variants.filter { fragment in it.refinesClosure }
variants.filter { variant -> fragment in variant.withRefinesClosure }
fun KotlinModule.findRefiningFragments(fragment: KotlinModuleFragment): Iterable<KotlinModuleFragment> {
val refining = mutableSetOf<KotlinModuleFragment>()
val notRefining = mutableSetOf<KotlinModuleFragment>()
fun isRefining(other: KotlinModuleFragment): Boolean = when {
other in refining -> true
other in notRefining -> false
fragment in other.directRefinesDependencies -> true.also { refining.add(other) }
fragment.directRefinesDependencies.any { isRefining(it) } -> true.also { refining.add(other) }
else -> false.also { notRefining.add(other) }
return fragment.closure { seedFragment ->
fragments.filter { otherFragment -> seedFragment in otherFragment.directRefinesDependencies }
}
return fragments.filter(::isRefining)
}
}
@@ -1,32 +0,0 @@
/*
* 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.commonizer.util
public inline fun <reified T> transitiveClosure(seed: T, edges: T.() -> Iterable<T>): Set<T> {
// Fast path when initial edges are empty
val initialEdges = seed.edges()
if (initialEdges is Collection && initialEdges.isEmpty()) return emptySet()
val queue = deque<T>(initialEdges.count() * 2)
val results = mutableSetOf<T>()
queue.addAll(initialEdges)
while (queue.isNotEmpty()) {
// ArrayDeque implementation will optimize this call to 'removeFirst'
val resolved = queue.removeAt(0)
if (resolved != seed && results.add(resolved)) {
queue.addAll(resolved.edges())
}
}
return results.toSet()
}
@PublishedApi
internal inline fun <reified T> deque(initialSize: Int): MutableList<T> {
return if (KotlinVersion.CURRENT.isAtLeast(1, 4)) ArrayDeque(initialSize)
else ArrayList(initialSize)
}
@@ -1,60 +0,0 @@
/*
* 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.commonizer
import kotlin.test.Test
import kotlin.test.assertEquals
class TransitiveClosureTest {
private class Node(val value: String, val children: MutableList<Node> = mutableListOf()) {
override fun toString(): String {
return value
}
override fun equals(other: Any?): Boolean {
if (other !is Node) return false
return other.value == value
}
override fun hashCode(): Int {
return value.hashCode()
}
}
private fun Node.transitiveClosure() = org.jetbrains.kotlin.commonizer.util.transitiveClosure(this) { children }
@Test
fun `transitiveClosure does not include root node`() {
val closure = Node("a", mutableListOf(Node("b"), Node("c"))).transitiveClosure()
assertEquals(setOf(Node("b"), Node("c")), closure, "Expected transitiveClosure to not include root node")
}
@Test
fun `transitiveClosure handles loop and self references`() {
val nodeA = Node("a")
val nodeB = Node("b")
val nodeC = Node("c")
val nodeD = Node("d")
// a -> b -> c -> d
nodeA.children.add(nodeB)
nodeB.children.add(nodeC)
nodeC.children.add(nodeD)
// add self reference to b
nodeB.children.add(nodeB)
// add loop from c -> a
nodeC.children.add(nodeA)
val closure = nodeA.transitiveClosure()
assertEquals(
setOf(nodeB, nodeC, nodeD), closure,
"Expected transitiveClosure to be robust against loops and self references"
)
}
}
+3
View File
@@ -16,12 +16,14 @@ dependencies {
embedded(project(":kotlinx-metadata-klib")) { isTransitive = false }
embedded(project(":kotlinx-metadata")) { isTransitive = false }
embedded(project(":native:kotlin-klib-commonizer-api")) { isTransitive = false }
embedded(project(":kotlin-tooling-core")) { isTransitive = false }
// N.B. The order of "kotlinx-metadata*" dependencies makes sense for runtime classpath
// of the "runCommonizer" task. Please, don't mix them up.
compileOnly(project(":kotlinx-metadata-klib")) { isTransitive = false }
compileOnly(project(":kotlinx-metadata")) { isTransitive = false }
compileOnly(project(":native:kotlin-klib-commonizer-api")) { isTransitive = false }
compileOnly(project(":kotlin-tooling-core")) { isTransitive = false }
compileOnly(project(":compiler:cli-common"))
compileOnly(project(":compiler:ir.serialization.common"))
compileOnly(project(":compiler:frontend"))
@@ -40,6 +42,7 @@ dependencies {
testImplementation(project(":kotlinx-metadata-klib")) { isTransitive = false }
testImplementation(project(":kotlinx-metadata")) { isTransitive = false }
testImplementation(project(":native:kotlin-klib-commonizer-api"))
testImplementation(project(":kotlin-tooling-core"))
testApi(intellijCore())
}
@@ -5,16 +5,12 @@
package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.CirClassType
import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirType
import org.jetbrains.kotlin.commonizer.cir.SimpleCirSupertypesResolver
import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.CirClassifierIndex
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.commonizer.cir.CirProvided
import org.jetbrains.kotlin.commonizer.mergedtree.findClass
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.tooling.core.withClosure
private typealias Supertypes = List<CirType>
@@ -188,12 +184,8 @@ private class TypeNode(
val supertypes: List<TypeNode>,
var isConsumed: Boolean = false
) {
val allNodes: List<TypeNode> by lazy {
val allSupertypes = transitiveClosure(this, TypeNode::supertypes)
ArrayList<TypeNode>(allSupertypes.size + 1).also { list ->
list.add(this)
list.addAll(allSupertypes)
}
val allNodes: Set<TypeNode> by lazy {
this.withClosure(TypeNode::supertypes)
}
override fun toString(): String {
@@ -7,10 +7,10 @@ package org.jetbrains.kotlin.commonizer.tree.deserializer
import org.jetbrains.kotlin.commonizer.cir.CirClassType
import org.jetbrains.kotlin.commonizer.tree.CirTreeClass
import org.jetbrains.kotlin.commonizer.util.transitiveClosure
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.tooling.core.withClosure
import kotlin.test.*
class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
@@ -130,7 +130,7 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
)
val pkg = module.assertSinglePackage()
val xClass = pkg.classes.flatMap { transitiveClosure(it, CirTreeClass::classes) + it }
val xClass = pkg.classes.withClosure<CirTreeClass> { it.classes }
.singleOrNull { it.clazz.name.toStrippedString() == "X" } ?: kotlin.test.fail("Missing class 'X'")
val xSuperType = xClass.clazz.supertypes.singleOrNull()
?: kotlin.test.fail("Expected single supertype for 'X'. Found ${xClass.clazz.supertypes}")