[Gradle] Move KotlinSourceSet metadata configuration into separate source file

^KT-56431 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-02-07 13:31:35 +01:00
committed by Space Team
parent f21e08f6b9
commit 8f4dd86788
6 changed files with 107 additions and 98 deletions
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.gradle.plugin.ide.dependencyResolvers
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
import org.jetbrains.kotlin.gradle.plugin.mpp.metadataDependencyResolutionsOrEmpty
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.plugin.sources.metadataTransformation
internal inline fun <reified T : MetadataDependencyResolution> KotlinSourceSet.resolveMetadata(): List<T> {
if (this !is DefaultKotlinSourceSet) return emptyList()
return compileDependenciesTransformation.metadataDependencyResolutionsOrEmpty.filterIsInstance<T>()
return internal.metadataTransformation.metadataDependencyResolutionsOrEmpty.filterIsInstance<T>()
}
@@ -9,16 +9,13 @@ package org.jetbrains.kotlin.gradle.plugin.sources
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
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.targets.metadata.dependsOnClosureWithInterCompilationDependencies
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.closure
@@ -124,13 +121,6 @@ abstract class DefaultKotlinSourceSet @Inject constructor(
explicitlyAddedCustomSourceFilesExtensions.addAll(extensions)
}
/**
* Returns [GranularMetadataTransformation] for all requested compile dependencies
* scopes: API, IMPLEMENTATION, COMPILE_ONLY; See [KotlinDependencyScope.compileScopes]
*/
internal val compileDependenciesTransformation: GranularMetadataTransformation? by lazy {
createAndConfigureDependencyTransformationForSourceSet()
}
private val _requiresVisibilityOf = mutableSetOf<KotlinSourceSet>()
@@ -163,7 +153,7 @@ abstract class DefaultKotlinSourceSet @Inject constructor(
internal fun getDependenciesTransformation(): Iterable<MetadataDependencyTransformation> {
val metadataDependencyResolutionByModule =
compileDependenciesTransformation.metadataDependencyResolutionsOrEmpty
metadataTransformation.metadataDependencyResolutionsOrEmpty
.associateBy { ModuleIds.fromComponent(project, it.dependency) }
return metadataDependencyResolutionByModule.mapNotNull { (groupAndName, resolution) ->
@@ -193,7 +183,6 @@ abstract class DefaultKotlinSourceSet @Inject constructor(
//endregion
}
internal val defaultSourceSetLanguageSettingsChecker =
FragmentConsistencyChecker<KotlinSourceSet>(
unitsName = "source sets",
@@ -230,76 +219,3 @@ val Iterable<KotlinSourceSet>.withDependsOnClosure: Set<KotlinSourceSet>
fun KotlinMultiplatformExtension.findSourceSetsDependingOn(sourceSet: KotlinSourceSet): Set<KotlinSourceSet> {
return sourceSet.closure { seedSourceSet -> sourceSets.filter { otherSourceSet -> seedSourceSet in otherSourceSet.dependsOn } }
}
private fun DefaultKotlinSourceSet.createAndConfigureDependencyTransformationForSourceSet(): GranularMetadataTransformation? {
// Create only for source sets in multiplatform plugin
project.multiplatformExtensionOrNull ?: return null
val parentSourceSetVisibilityProvider = ParentSourceSetVisibilityProvider { componentIdentifier ->
dependsOnClosureWithInterCompilationDependencies(this).filterIsInstance<DefaultKotlinSourceSet>()
.mapNotNull { it.compileDependenciesTransformation }
.flatMap { it.visibleSourceSetsByComponentId[componentIdentifier].orEmpty() }
.toSet()
}
val granularMetadataTransformation = GranularMetadataTransformation(
params = GranularMetadataTransformation.Params(project, this),
parentSourceSetVisibilityProvider = parentSourceSetVisibilityProvider
)
/**
*
* This method is only intended to be called on deprecated DependenciesMetadata configurations to ensure
* correct behaviour in import.
*
* KGP based dependency resolution is therefore unaffected.
*
* Ensure that the [configuration] excludes the dependencies that are classified by this [GranularMetadataTransformation] as
* [MetadataDependencyResolution.Exclude], and uses exactly the same versions as were resolved for the requested
* dependencies during the transformation.
*/
fun applyTransformationToLegacyDependenciesMetadataConfiguration(
configuration: Configuration,
transformation: GranularMetadataTransformation
) {
// Run this action immediately before the configuration first takes part in dependency resolution:
configuration.withDependencies {
val (unrequested, requested) = transformation.metadataDependencyResolutions
.partition { it is MetadataDependencyResolution.Exclude }
unrequested.forEach {
val (group, name) = it.projectDependency(project)?.run {
/** Note: the project dependency notation here should be exactly this, group:name,
* not from [ModuleIds.fromProjectPathDependency], as `exclude` checks it against the project's group:name */
ModuleDependencyIdentifier(group.toString(), name)
} ?: ModuleIds.fromComponent(project, it.dependency)
configuration.exclude(mapOf("group" to group, "module" to name))
}
requested.filter { it.dependency.currentBuildProjectIdOrNull == null }.forEach {
val (group, name) = ModuleIds.fromComponent(project, it.dependency)
val notation = listOfNotNull(group.orEmpty(), name, it.dependency.moduleVersion?.version).joinToString(":")
configuration.resolutionStrategy.force(notation)
}
}
}
@Suppress("DEPRECATION")
/*
Older IDEs still rely on resolving the metadata configurations explicitly.
Dependencies will be coming from extending the newer 'resolvableMetadataConfiguration'.
the intransitiveMetadataConfigurationName will not extend this mechanism, since it only
relies on dependencies being added explicitly by the Kotlin Gradle Plugin
*/
listOf(
apiMetadataConfigurationName,
implementationMetadataConfigurationName,
compileOnlyMetadataConfigurationName
).forEach { configurationName ->
val configuration = project.configurations.getByName(configurationName)
applyTransformationToLegacyDependenciesMetadataConfiguration(configuration, granularMetadataTransformation)
}
return granularMetadataTransformation
}
@@ -0,0 +1,96 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.plugin.sources
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.GranularMetadataTransformation
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution
import org.jetbrains.kotlin.gradle.plugin.mpp.ModuleIds
import org.jetbrains.kotlin.gradle.plugin.mpp.projectDependency
import org.jetbrains.kotlin.gradle.targets.metadata.dependsOnClosureWithInterCompilationDependencies
import org.jetbrains.kotlin.tooling.core.extrasNullableLazyProperty
/**
* Returns [GranularMetadataTransformation] for all requested compile dependencies
* scopes: API, IMPLEMENTATION, COMPILE_ONLY; See [KotlinDependencyScope.compileScopes]
*
* Used only for IDE import (w/o KGP based dependency resolution).
* Scheduled for removal after 1.9.20
*/
internal val InternalKotlinSourceSet.metadataTransformation: GranularMetadataTransformation? by extrasNullableLazyProperty lazy@{
// Create only for source sets in multiplatform plugin
project.multiplatformExtensionOrNull ?: return@lazy null
val parentSourceSetVisibilityProvider = ParentSourceSetVisibilityProvider { componentIdentifier ->
dependsOnClosureWithInterCompilationDependencies(this).filterIsInstance<DefaultKotlinSourceSet>()
.mapNotNull { it.metadataTransformation }
.flatMap { it.visibleSourceSetsByComponentId[componentIdentifier].orEmpty() }
.toSet()
}
val granularMetadataTransformation = GranularMetadataTransformation(
params = GranularMetadataTransformation.Params(project, this),
parentSourceSetVisibilityProvider = parentSourceSetVisibilityProvider
)
@Suppress("DEPRECATION")
/*
Older IDEs still rely on resolving the metadata configurations explicitly.
Dependencies will be coming from extending the newer 'resolvableMetadataConfiguration'.
the intransitiveMetadataConfigurationName will not extend this mechanism, since it only
relies on dependencies being added explicitly by the Kotlin Gradle Plugin
*/
listOf(
apiMetadataConfigurationName,
implementationMetadataConfigurationName,
compileOnlyMetadataConfigurationName
).forEach { configurationName ->
val configuration = project.configurations.getByName(configurationName)
project.applyTransformationToLegacyDependenciesMetadataConfiguration(configuration, granularMetadataTransformation)
}
granularMetadataTransformation
}
/**
*
* This method is only intended to be called on deprecated DependenciesMetadata configurations to ensure
* correct behaviour in import.
*
* KGP based dependency resolution is therefore unaffected.
*
* Ensure that the [configuration] excludes the dependencies that are classified by this [GranularMetadataTransformation] as
* [MetadataDependencyResolution.Exclude], and uses exactly the same versions as were resolved for the requested
* dependencies during the transformation.
*/
private fun Project.applyTransformationToLegacyDependenciesMetadataConfiguration(
configuration: Configuration, transformation: GranularMetadataTransformation
) {
// Run this action immediately before the configuration first takes part in dependency resolution:
configuration.withDependencies {
val (unrequested, requested) = transformation.metadataDependencyResolutions
.partition { it is MetadataDependencyResolution.Exclude }
unrequested.forEach {
val (group, name) = it.projectDependency(project)?.run {
/** Note: the project dependency notation here should be exactly this, group:name,
* not from [ModuleIds.fromProjectPathDependency], as `exclude` checks it against the project's group:name */
ModuleDependencyIdentifier(group.toString(), name)
} ?: ModuleIds.fromComponent(project, it.dependency)
configuration.exclude(mapOf("group" to group, "module" to name))
}
requested.filter { it.dependency.currentBuildProjectIdOrNull == null }.forEach {
val (group, name) = ModuleIds.fromComponent(project, it.dependency)
val notation = listOfNotNull(group.orEmpty(), name, it.dependency.moduleVersion?.version).joinToString(":")
configuration.resolutionStrategy.force(notation)
}
}
}
@@ -162,10 +162,8 @@ class KotlinMetadataTargetConfigurator :
private fun configureMetadataDependenciesConfigurationsForCommonSourceSets(target: KotlinMetadataTarget) {
target.project.whenEvaluated {
kotlinExtension.sourceSets.all {
if (it is DefaultKotlinSourceSet) {
configureMetadataDependenciesConfigurations(target.project, it)
}
kotlinExtension.sourceSets.all { sourceSet ->
configureMetadataDependenciesConfigurations(target.project, sourceSet.internal)
}
}
}
@@ -352,10 +350,7 @@ class KotlinMetadataTargetConfigurator :
}
}
private fun configureMetadataDependenciesConfigurations(
project: Project,
sourceSet: DefaultKotlinSourceSet
) {
private fun configureMetadataDependenciesConfigurations(project: Project, sourceSet: InternalKotlinSourceSet) {
/*
Older IDEs still rely on resolving the metadata configurations explicitly.
Dependencies will be coming from extending the newer 'resolvableMetadataConfiguration'.
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.Choos
import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.ChooseVisibleSourceSets.MetadataProvider.ProjectMetadataProvider.MetadataConsumer.Ide
import org.jetbrains.kotlin.gradle.plugin.mpp.metadataDependencyResolutionsOrEmpty
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.metadataTransformation
import org.jetbrains.kotlin.gradle.utils.filesProvider
import java.io.File
@@ -51,7 +52,7 @@ private fun Project.createCInteropMetadataDependencyClasspathFromProjectDependen
forIde: Boolean
): FileCollection {
return filesProvider {
sourceSet.compileDependenciesTransformation
sourceSet.metadataTransformation
.metadataDependencyResolutionsOrEmpty
.filterIsInstance<ChooseVisibleSourceSets>()
.flatMap { chooseVisibleSourceSets ->
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.MetadataDependencyResolution.Choos
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.toKpmModuleIdentifiers
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.plugin.sources.metadataTransformation
import org.jetbrains.kotlin.gradle.tasks.dependsOn
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
import org.jetbrains.kotlin.gradle.tasks.withType
@@ -155,7 +156,7 @@ internal open class CInteropMetadataDependencyTransformationTask @Inject constru
@get:Internal
protected val chooseVisibleSourceSets
get() = sourceSet
.compileDependenciesTransformation
.metadataTransformation
.metadataDependencyResolutionsOrEmpty
.resolutionsToTransform()