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