[KPM] Replace 'fun interface' in favor of factory functions

This commit is contained in:
sebastian.sellmair
2022-01-21 10:40:54 +01:00
committed by Space
parent c684588ebb
commit 6720742b84
17 changed files with 222 additions and 130 deletions
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.external.createExternalJvmVariant
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.* import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
fun KotlinGradleModule.createKotlinAndroidVariant(androidVariant: BaseVariant) { fun KotlinGradleModule.createKotlinAndroidVariant(androidVariant: BaseVariant) {
val androidOutgoingArtifacts = FragmentArtifacts<KotlinJvmVariant> { fragment -> val androidOutgoingArtifacts = FragmentArtifacts<KotlinJvmVariant> {
variants.create("classes") { variant -> variants.create("classes") { variant ->
variant.attributes.attribute(AndroidArtifacts.ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.CLASSES_JAR.type) variant.attributes.attribute(AndroidArtifacts.ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.CLASSES_JAR.type)
variant.artifact(project.provider { fragment.compilationOutputs.classesDirs.singleFile }) { variant.artifact(project.provider { fragment.compilationOutputs.classesDirs.singleFile }) {
@@ -26,14 +26,14 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
) )
} }
private val testFragment by lazy { private val dummyFragment by lazy {
KotlinCommonFragmentFactory(kotlin.main).create("testFragment") KotlinCommonFragmentFactory(kotlin.main).create("testFragment")
} }
@Test @Test
fun `test withProvider`() { fun `test withProvider`() {
val testDefinition = ConfigurationDefinition<KotlinGradleFragment>( val testDefinition = ConfigurationDefinition<KotlinGradleFragment>(
provider = { project.configurations.create("a") } provider = ConfigurationProvider { project.configurations.create("a") }
).withConfigurationProvider { project.configurations.create("b") } ).withConfigurationProvider { project.configurations.create("b") }
assertEquals( assertEquals(
@@ -60,14 +60,14 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
val testConfiguration = project.configurations.create("dummy") val testConfiguration = project.configurations.create("dummy")
val fragmentAttributes1 = FragmentAttributes<KotlinGradleFragment> { val fragmentAttributes1 = FragmentAttributes<KotlinGradleFragment> {
assertSame(testConfiguration.attributes, this) assertSame(testConfiguration.attributes, attributes)
assertNull(attributes.getAttribute(testAttribute1)) assertNull(attributes.getAttribute(testAttribute1))
assertNull(attributes.getAttribute(testAttribute2)) assertNull(attributes.getAttribute(testAttribute2))
attribute(testAttribute1, "value1") attribute(testAttribute1, "value1")
} }
val fragmentAttributes2 = FragmentAttributes<KotlinGradleFragment> { val fragmentAttributes2 = FragmentAttributes<KotlinGradleFragment> {
assertSame(testConfiguration.attributes, this) assertSame(testConfiguration.attributes, attributes)
assertEquals(attributes.getAttribute(testAttribute1), "value1") assertEquals(attributes.getAttribute(testAttribute1), "value1")
assertNull(attributes.getAttribute(testAttribute2)) assertNull(attributes.getAttribute(testAttribute2))
attribute(testAttribute2, "value2") attribute(testAttribute2, "value2")
@@ -81,7 +81,7 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
listOf(fragmentAttributes1, fragmentAttributes2), composite.children listOf(fragmentAttributes1, fragmentAttributes2), composite.children
) )
testConfiguration.attributes.attributes(composite, testFragment) composite.setAttributes(testConfiguration.attributes, dummyFragment)
assertEquals( assertEquals(
"value1", testConfiguration.attributes.getAttribute(testAttribute1), "value1", testConfiguration.attributes.getAttribute(testAttribute1),
@@ -97,7 +97,7 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
@Test @Test
fun `test definition + attributes`() { fun `test definition + attributes`() {
val definition = ConfigurationDefinition<KotlinGradleFragment>( val definition = ConfigurationDefinition<KotlinGradleFragment>(
provider = { project.configurations.create("a") } provider = ConfigurationProvider { project.configurations.create("a") }
) )
val attributes1 = FragmentAttributes<KotlinGradleFragment> { } val attributes1 = FragmentAttributes<KotlinGradleFragment> { }
@@ -131,7 +131,7 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
) )
project.configurations.create("dummy").apply { project.configurations.create("dummy").apply {
outgoing.artifacts(composite, testFragment) composite.addArtifacts(outgoing, dummyFragment)
assertEquals( assertEquals(
project.files("artifact1.jar", "artifact2-a.jar", "artifact2-b.jar").toSet(), project.files("artifact1.jar", "artifact2-a.jar", "artifact2-b.jar").toSet(),
outgoing.artifacts.files.toSet() outgoing.artifacts.files.toSet()
@@ -142,7 +142,7 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
@Test @Test
fun `test definition + artifacts`() { fun `test definition + artifacts`() {
val definition = ConfigurationDefinition<KotlinGradleFragment>( val definition = ConfigurationDefinition<KotlinGradleFragment>(
provider = { throw NotImplementedError() } provider = ConfigurationProvider { throw NotImplementedError() }
) )
val artifacts1 = FragmentArtifacts<KotlinGradleFragment> {} val artifacts1 = FragmentArtifacts<KotlinGradleFragment> {}
@@ -174,7 +174,7 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
listOf(capabilities1, capabilities2), composite.children listOf(capabilities1, capabilities2), composite.children
) )
val dummyContext = object : KotlinGradleFragmentConfigurationCapabilities.Context { val testCapabilitiesContainer = object : KotlinGradleFragmentConfigurationCapabilities.CapabilitiesContainer {
val setCapabilities = mutableListOf<Any>() val setCapabilities = mutableListOf<Any>()
override fun capability(notation: Any) { override fun capability(notation: Any) {
setCapabilities.add(notation) setCapabilities.add(notation)
@@ -184,9 +184,10 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
} }
dummyContext.capabilities(composite, testFragment) composite.setCapabilities(testCapabilitiesContainer, dummyFragment)
assertEquals( assertEquals(
listOf<Any>("capability1", "capability2"), dummyContext.setCapabilities, listOf<Any>("capability1", "capability2"), testCapabilitiesContainer.setCapabilities,
"Expected 'dummyContext' to receive all capabilities" "Expected 'dummyContext' to receive all capabilities"
) )
} }
@@ -194,7 +195,7 @@ class KotlinFragmentConfigurationDefinitionTest : AbstractKpmExtensionTest() {
@Test @Test
fun `test definition + capability`() { fun `test definition + capability`() {
val definition = ConfigurationDefinition<KotlinGradleFragment>( val definition = ConfigurationDefinition<KotlinGradleFragment>(
provider = { throw NotImplementedError() } provider = ConfigurationProvider { throw NotImplementedError() }
) )
val capabilities1 = FragmentCapabilities<KotlinGradleFragment> {} val capabilities1 = FragmentCapabilities<KotlinGradleFragment> {}
@@ -87,8 +87,8 @@ class KotlinJvmVariantFactoryTest : AbstractKpmExtensionTest() {
fun `test custom configure compileDependenciesConfiguration`() { fun `test custom configure compileDependenciesConfiguration`() {
val variant = KotlinJvmVariantFactory( val variant = KotlinJvmVariantFactory(
kotlin.main, KotlinJvmVariantConfig( kotlin.main, KotlinJvmVariantConfig(
compileDependencies = DefaultKotlinCompileDependenciesDefinition + FragmentAttributes { fragment -> compileDependencies = DefaultKotlinCompileDependenciesDefinition + FragmentAttributes {
assertSame(fragment.compileDependenciesConfiguration.attributes, this) assertSame(fragment.compileDependenciesConfiguration.attributes, attributes)
attribute(testAttribute, "compileDependencies") attribute(testAttribute, "compileDependencies")
} }
) )
@@ -103,8 +103,8 @@ class KotlinJvmVariantFactoryTest : AbstractKpmExtensionTest() {
fun `test custom configure runtimeDependenciesConfiguration`() { fun `test custom configure runtimeDependenciesConfiguration`() {
val variant = KotlinJvmVariantFactory( val variant = KotlinJvmVariantFactory(
kotlin.main, KotlinJvmVariantConfig( kotlin.main, KotlinJvmVariantConfig(
runtimeDependencies = DefaultKotlinRuntimeDependenciesDefinition + FragmentAttributes { fragment -> runtimeDependencies = DefaultKotlinRuntimeDependenciesDefinition + FragmentAttributes {
assertSame(fragment.runtimeDependenciesConfiguration.attributes, this) assertSame(fragment.runtimeDependenciesConfiguration.attributes, attributes)
attribute(testAttribute, "runtimeDependencies") attribute(testAttribute, "runtimeDependencies")
} }
) )
@@ -119,8 +119,8 @@ class KotlinJvmVariantFactoryTest : AbstractKpmExtensionTest() {
fun `test custom configure apiElementsConfiguration`() { fun `test custom configure apiElementsConfiguration`() {
val variant = KotlinJvmVariantFactory( val variant = KotlinJvmVariantFactory(
kotlin.main, KotlinJvmVariantConfig( kotlin.main, KotlinJvmVariantConfig(
apiElements = DefaultKotlinApiElementsDefinition + FragmentAttributes { fragment -> apiElements = DefaultKotlinApiElementsDefinition + FragmentAttributes {
assertSame(fragment.apiElementsConfiguration.attributes, this) assertSame(fragment.apiElementsConfiguration.attributes, attributes)
attribute(testAttribute, "apiElements") attribute(testAttribute, "apiElements")
} }
) )
@@ -135,8 +135,8 @@ class KotlinJvmVariantFactoryTest : AbstractKpmExtensionTest() {
fun `test custom configure runtimeElementsConfiguration`() { fun `test custom configure runtimeElementsConfiguration`() {
val variant = KotlinJvmVariantFactory( val variant = KotlinJvmVariantFactory(
kotlin.main, KotlinJvmVariantConfig( kotlin.main, KotlinJvmVariantConfig(
runtimeElements = DefaultKotlinRuntimeElementsDefinition + FragmentAttributes { fragment -> runtimeElements = DefaultKotlinRuntimeElementsDefinition + FragmentAttributes {
assertSame(fragment.runtimeElementsConfiguration.attributes, this) assertSame(fragment.runtimeElementsConfiguration.attributes, attributes)
attribute(testAttribute, "runtimeElements") attribute(testAttribute, "runtimeElements")
} }
) )
@@ -10,7 +10,6 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE
import org.gradle.api.attributes.java.TargetJvmEnvironment import org.gradle.api.attributes.java.TargetJvmEnvironment
import org.gradle.api.attributes.java.TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE import org.gradle.api.attributes.java.TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE
import org.gradle.kotlin.dsl.named
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
@@ -21,34 +20,34 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages.producerRuntimeUsage
import org.jetbrains.kotlin.gradle.plugin.usageByName import org.jetbrains.kotlin.gradle.plugin.usageByName
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
val KotlinFragmentPlatformAttributes = FragmentAttributes<KotlinGradleVariant> { fragment -> val KotlinFragmentPlatformAttributes = FragmentAttributes<KotlinGradleVariant> {
if (isGradleVersionAtLeast(7, 0) && fragment.platformType == KotlinPlatformType.jvm) { if (isGradleVersionAtLeast(7, 0) && fragment.platformType == KotlinPlatformType.jvm) {
attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, fragment.project.objects.named(TargetJvmEnvironment.STANDARD_JVM)) namedAttribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, TargetJvmEnvironment.STANDARD_JVM)
} }
attribute(KotlinPlatformType.attribute, fragment.platformType) attribute(KotlinPlatformType.attribute, fragment.platformType)
} }
val KotlinFragmentConsumerApiUsageAttribute = FragmentAttributes<KotlinGradleVariant> { fragment -> val KotlinFragmentConsumerApiUsageAttribute = FragmentAttributes<KotlinGradleVariant> {
attribute(USAGE_ATTRIBUTE, consumerApiUsage(fragment.project, fragment.platformType)) attribute(USAGE_ATTRIBUTE, consumerApiUsage(project, fragment.platformType))
} }
val KotlinFragmentProducerApiUsageAttribute = FragmentAttributes<KotlinGradleVariant> { fragment -> val KotlinFragmentProducerApiUsageAttribute = FragmentAttributes<KotlinGradleVariant> {
attribute(USAGE_ATTRIBUTE, producerApiUsage(fragment.project, fragment.platformType)) attribute(USAGE_ATTRIBUTE, producerApiUsage(fragment.project, fragment.platformType))
} }
val KotlinFragmentConsumerRuntimeUsageAttribute = FragmentAttributes<KotlinGradleVariant> { fragment -> val KotlinFragmentConsumerRuntimeUsageAttribute = FragmentAttributes<KotlinGradleVariant> {
attribute(USAGE_ATTRIBUTE, consumerRuntimeUsage(fragment.project, fragment.platformType)) attribute(USAGE_ATTRIBUTE, consumerRuntimeUsage(fragment.project, fragment.platformType))
} }
val KotlinFragmentProducerRuntimeUsageAttribute = FragmentAttributes<KotlinGradleVariant> { fragment -> val KotlinFragmentProducerRuntimeUsageAttribute = FragmentAttributes<KotlinGradleVariant> {
attribute(USAGE_ATTRIBUTE, producerRuntimeUsage(fragment.project, fragment.platformType)) attribute(USAGE_ATTRIBUTE, producerRuntimeUsage(fragment.project, fragment.platformType))
} }
val KotlinFragmentMetadataUsageAttribute = FragmentAttributes<KotlinGradleVariant> { fragment -> val KotlinFragmentMetadataUsageAttribute = FragmentAttributes<KotlinGradleFragment> {
attribute(USAGE_ATTRIBUTE, fragment.project.usageByName(KotlinUsages.KOTLIN_METADATA)) attribute(USAGE_ATTRIBUTE, fragment.project.usageByName(KotlinUsages.KOTLIN_METADATA))
} }
val KotlinFragmentKonanTargetAttribute = FragmentAttributes<KotlinNativeVariantInternal> { fragment -> val KotlinFragmentKonanTargetAttribute = FragmentAttributes<KotlinNativeVariantInternal> {
attribute(KotlinNativeTarget.konanTargetAttribute, fragment.konanTarget.name) attributes.attribute(KotlinNativeTarget.konanTargetAttribute, fragment.konanTarget.name)
} }
@@ -10,70 +10,70 @@ import org.gradle.api.attributes.Category
val DefaultKotlinCompileDependenciesDefinition = KotlinGradleFragmentConfigurationDefinition( val DefaultKotlinCompileDependenciesDefinition = KotlinGradleFragmentConfigurationDefinition(
provider = { provider = ConfigurationProvider {
project.configurations.maybeCreate(disambiguateName("compileDependencies")).apply { project.configurations.maybeCreate(disambiguateName("compileDependencies")).apply {
isCanBeConsumed = false isCanBeConsumed = false
isCanBeResolved = true isCanBeResolved = true
} }
}, },
relations = { configuration -> relations = FragmentConfigurationRelation {
configuration.extendsFrom(dependencies.transitiveApiConfiguration) extendsFrom(dependencies.transitiveApiConfiguration)
configuration.extendsFrom(dependencies.transitiveImplementationConfiguration) extendsFrom(dependencies.transitiveImplementationConfiguration)
}, },
attributes = KotlinFragmentPlatformAttributes + KotlinFragmentConsumerApiUsageAttribute attributes = KotlinFragmentPlatformAttributes + KotlinFragmentConsumerApiUsageAttribute
) )
val DefaultKotlinRuntimeDependenciesDefinition = ConfigurationDefinition( val DefaultKotlinRuntimeDependenciesDefinition = ConfigurationDefinition(
provider = { provider = ConfigurationProvider {
project.configurations.maybeCreate(disambiguateName("runtimeDependencies")).apply { project.configurations.maybeCreate(disambiguateName("runtimeDependencies")).apply {
isCanBeConsumed = false isCanBeConsumed = false
isCanBeResolved = true isCanBeResolved = true
} }
}, },
attributes = KotlinFragmentPlatformAttributes + KotlinFragmentConsumerRuntimeUsageAttribute, attributes = KotlinFragmentPlatformAttributes + KotlinFragmentConsumerRuntimeUsageAttribute,
relations = { configuration -> relations = FragmentConfigurationRelation {
configuration.extendsFrom(dependencies.transitiveApiConfiguration) extendsFrom(dependencies.transitiveApiConfiguration)
configuration.extendsFrom(dependencies.transitiveImplementationConfiguration) extendsFrom(dependencies.transitiveImplementationConfiguration)
} }
) )
val DefaultKotlinApiElementsDefinition = ConfigurationDefinition( val DefaultKotlinApiElementsDefinition = ConfigurationDefinition(
provider = { provider = ConfigurationProvider {
module.project.configurations.maybeCreate(disambiguateName("apiElements")).apply { project.configurations.maybeCreate(disambiguateName("apiElements")).apply {
isCanBeResolved = false isCanBeResolved = false
isCanBeConsumed = false isCanBeConsumed = false
module.ifMadePublic { isCanBeConsumed = true } module.ifMadePublic { isCanBeConsumed = true }
} }
}, },
relations = { configuration -> configuration.extendsFrom(dependencies.transitiveApiConfiguration) }, relations = FragmentConfigurationRelation { extendsFrom(dependencies.transitiveApiConfiguration) },
capabilities = KotlinFragmentModuleCapability, capabilities = KotlinFragmentModuleCapability,
attributes = KotlinFragmentPlatformAttributes + KotlinFragmentProducerApiUsageAttribute + { fragment -> attributes = KotlinFragmentPlatformAttributes + KotlinFragmentProducerApiUsageAttribute + FragmentAttributes {
attribute(Category.CATEGORY_ATTRIBUTE, fragment.project.objects.named(Category::class.java, Category.LIBRARY)) attribute(Category.CATEGORY_ATTRIBUTE, fragment.project.objects.named(Category::class.java, Category.LIBRARY))
attribute(Bundling.BUNDLING_ATTRIBUTE, fragment.project.objects.named(Bundling::class.java, Bundling.EXTERNAL)) attribute(Bundling.BUNDLING_ATTRIBUTE, fragment.project.objects.named(Bundling::class.java, Bundling.EXTERNAL))
}, },
) )
val DefaultKotlinRuntimeElementsDefinition = ConfigurationDefinition( val DefaultKotlinRuntimeElementsDefinition = ConfigurationDefinition(
provider = { provider = ConfigurationProvider {
module.project.configurations.maybeCreate(disambiguateName("runtimeElements")).apply { project.configurations.maybeCreate(disambiguateName("runtimeElements")).apply {
isCanBeResolved = false isCanBeResolved = false
isCanBeConsumed = false isCanBeConsumed = false
module.ifMadePublic { isCanBeConsumed = true } module.ifMadePublic { isCanBeConsumed = true }
} }
}, },
relations = { configuration -> relations = FragmentConfigurationRelation {
configuration.extendsFrom(dependencies.transitiveApiConfiguration) extendsFrom(dependencies.transitiveApiConfiguration)
configuration.extendsFrom(dependencies.transitiveImplementationConfiguration) extendsFrom(dependencies.transitiveImplementationConfiguration)
}, },
attributes = KotlinFragmentPlatformAttributes + KotlinFragmentProducerRuntimeUsageAttribute + { fragment -> attributes = KotlinFragmentPlatformAttributes + KotlinFragmentProducerRuntimeUsageAttribute + FragmentAttributes {
attributes.attribute(Category.CATEGORY_ATTRIBUTE, fragment.project.objects.named(Category::class.java, Category.LIBRARY)) attribute(Category.CATEGORY_ATTRIBUTE, fragment.project.objects.named(Category::class.java, Category.LIBRARY))
attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, fragment.project.objects.named(Bundling::class.java, Bundling.EXTERNAL)) attribute(Bundling.BUNDLING_ATTRIBUTE, fragment.project.objects.named(Bundling::class.java, Bundling.EXTERNAL))
}, },
capabilities = KotlinFragmentModuleCapability.onlyIfMadePublic() capabilities = KotlinFragmentModuleCapability.onlyIfMadePublic()
) )
val DefaultKotlinHostSpecificMetadataElementsDefinition = ConfigurationDefinition( val DefaultKotlinHostSpecificMetadataElementsDefinition = ConfigurationDefinition(
provider = { provider = ConfigurationProvider {
project.configurations.maybeCreate(disambiguateName("hostSpecificMetadataElements")).apply { project.configurations.maybeCreate(disambiguateName("hostSpecificMetadataElements")).apply {
isCanBeResolved = false isCanBeResolved = false
isCanBeConsumed = false isCanBeConsumed = false
@@ -82,4 +82,3 @@ val DefaultKotlinHostSpecificMetadataElementsDefinition = ConfigurationDefinitio
attributes = KotlinFragmentPlatformAttributes + KotlinFragmentKonanTargetAttribute + KotlinFragmentMetadataUsageAttribute, attributes = KotlinFragmentPlatformAttributes + KotlinFragmentKonanTargetAttribute + KotlinFragmentMetadataUsageAttribute,
artifacts = KotlinFragmentHostSpecificMetadataArtifact artifacts = KotlinFragmentHostSpecificMetadataArtifact
) )
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
/** /**
* Registers a [Jar] task with the variant's compilation outputs and attaches this artifact to the given configuration. * Registers a [Jar] task with the variant's compilation outputs and attaches this artifact to the given configuration.
*/ */
val KotlinFragmentCompilationOutputsJarArtifact = FragmentArtifacts<KotlinGradleVariant> { fragment -> val KotlinFragmentCompilationOutputsJarArtifact = FragmentArtifacts<KotlinGradleVariant> {
artifact(fragment.project.locateOrRegisterTask<Jar>(fragment.disambiguateName("jar")) { artifact(project.locateOrRegisterTask<Jar>(fragment.disambiguateName("jar")) {
it.from(fragment.compilationOutputs.allOutputs) it.from(fragment.compilationOutputs.allOutputs)
it.archiveClassifier.set(dashSeparatedName(fragment.name, fragment.containingModule.moduleClassifier)) it.archiveClassifier.set(dashSeparatedName(fragment.name, fragment.containingModule.moduleClassifier))
}) })
@@ -19,8 +19,7 @@ import org.jetbrains.kotlin.project.model.refinesClosure
* Will add this jar artifact to the given configuration * Will add this jar artifact to the given configuration
*/ */
val KotlinFragmentHostSpecificMetadataArtifact = FragmentArtifacts<KotlinNativeVariantInternal> artifacts@{ fragment -> val KotlinFragmentHostSpecificMetadataArtifact = FragmentArtifacts<KotlinNativeVariantInternal> artifacts@{
val project = fragment.project
val hostSpecificMetadataElements = fragment.hostSpecificMetadataElementsConfiguration ?: return@artifacts val hostSpecificMetadataElements = fragment.hostSpecificMetadataElementsConfiguration ?: return@artifacts
val hostSpecificMetadataJar = project.registerTask<Jar>(fragment.disambiguateName("hostSpecificMetadataJar")) { jar -> val hostSpecificMetadataJar = project.registerTask<Jar>(fragment.disambiguateName("hostSpecificMetadataJar")) { jar ->
@@ -9,7 +9,7 @@ import org.gradle.api.artifacts.Configuration
import org.gradle.api.capabilities.Capability import org.gradle.api.capabilities.Capability
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability
val KotlinFragmentModuleCapability = FragmentCapabilities<KotlinGradleFragment> { fragment -> val KotlinFragmentModuleCapability = FragmentCapabilities<KotlinGradleFragment> {
capability(fragment.containingModule.moduleCapability ?: return@FragmentCapabilities) capability(fragment.containingModule.moduleCapability ?: return@FragmentCapabilities)
} }
@@ -5,31 +5,47 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.Project
import org.gradle.api.artifacts.ConfigurationPublications import org.gradle.api.artifacts.ConfigurationPublications
/* Internal abbreviation */ /* Internal abbreviation */
internal typealias FragmentArtifacts<T> = KotlinGradleFragmentConfigurationArtifacts<T> internal typealias FragmentArtifacts<T> = KotlinGradleFragmentConfigurationArtifacts<T>
fun interface KotlinGradleFragmentConfigurationArtifacts<in T : KotlinGradleFragment> { interface KotlinGradleFragmentConfigurationArtifacts<in T : KotlinGradleFragment> {
fun ConfigurationPublications.addArtifacts(fragment: T) fun addArtifacts(outgoing: ConfigurationPublications, fragment: T)
companion object { object None : KotlinGradleFragmentConfigurationArtifacts<KotlinGradleFragment> {
val None = FragmentArtifacts<KotlinGradleFragment> {} override fun addArtifacts(outgoing: ConfigurationPublications, fragment: KotlinGradleFragment) = Unit
} }
} }
fun <T : KotlinGradleFragment> ConfigurationPublications.artifacts( class KotlinGradleFragmentConfigurationArtifactsContext<T : KotlinGradleFragment> internal constructor(
artifacts: FragmentArtifacts<T>, fragment: T internal val outgoing: ConfigurationPublications,
) = with(artifacts) { addArtifacts(fragment) } val fragment: T
) : ConfigurationPublications by outgoing {
val project: Project get() = fragment.project
}
@Suppress("FunctionName")
fun <T : KotlinGradleFragment> FragmentArtifacts(
addArtifacts: KotlinGradleFragmentConfigurationArtifactsContext<T>.() -> Unit
): KotlinGradleFragmentConfigurationArtifacts<T> {
return object : KotlinGradleFragmentConfigurationArtifacts<T> {
override fun addArtifacts(outgoing: ConfigurationPublications, fragment: T) {
val context = KotlinGradleFragmentConfigurationArtifactsContext(outgoing, fragment)
context.addArtifacts()
}
}
}
operator fun <T : KotlinGradleFragment> FragmentArtifacts<T>.plus(other: FragmentArtifacts<T>): FragmentArtifacts<T> { operator fun <T : KotlinGradleFragment> FragmentArtifacts<T>.plus(other: FragmentArtifacts<T>): FragmentArtifacts<T> {
if (this === KotlinGradleFragmentConfigurationArtifacts.None) return other
if (other === KotlinGradleFragmentConfigurationArtifacts.None) return this
if (this is CompositeFragmentArtifacts && other is CompositeFragmentArtifacts) { if (this is CompositeFragmentArtifacts && other is CompositeFragmentArtifacts) {
return CompositeFragmentArtifacts(this.children + other.children) return CompositeFragmentArtifacts(this.children + other.children)
} }
if (this === FragmentArtifacts.None) return other
if (other === FragmentArtifacts.None) return this
if (this is CompositeFragmentArtifacts) { if (this is CompositeFragmentArtifacts) {
return CompositeFragmentArtifacts(this.children + other) return CompositeFragmentArtifacts(this.children + other)
} }
@@ -43,7 +59,8 @@ operator fun <T : KotlinGradleFragment> FragmentArtifacts<T>.plus(other: Fragmen
internal class CompositeFragmentArtifacts<in T : KotlinGradleFragment>(val children: List<FragmentArtifacts<T>>) : internal class CompositeFragmentArtifacts<in T : KotlinGradleFragment>(val children: List<FragmentArtifacts<T>>) :
FragmentArtifacts<T> { FragmentArtifacts<T> {
override fun ConfigurationPublications.addArtifacts(fragment: T) {
children.forEach { child -> artifacts(child, fragment) } override fun addArtifacts(outgoing: ConfigurationPublications, fragment: T) {
children.forEach { child -> child.addArtifacts(outgoing, fragment) }
} }
} }
@@ -5,31 +5,58 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.Named
import org.gradle.api.Project
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeContainer import org.gradle.api.attributes.AttributeContainer
/* Internal abbreviation */ /* Internal abbreviation */
internal typealias FragmentAttributes<T> = KotlinGradleFragmentConfigurationAttributes<T> internal typealias FragmentAttributes<T> = KotlinGradleFragmentConfigurationAttributes<T>
fun interface KotlinGradleFragmentConfigurationAttributes<in T : KotlinGradleFragment> { interface KotlinGradleFragmentConfigurationAttributes<in T : KotlinGradleFragment> {
fun AttributeContainer.setAttributes(fragment: T)
companion object { fun setAttributes(attributes: AttributeContainer, fragment: T)
val None = FragmentAttributes<KotlinGradleFragment> {}
object None : FragmentAttributes<KotlinGradleFragment> {
override fun setAttributes(attributes: AttributeContainer, fragment: KotlinGradleFragment) = Unit
} }
} }
fun <T : KotlinGradleFragment> AttributeContainer.attributes(attributes: FragmentAttributes<T>, fragment: T) = with(attributes) { class KotlinGradleFragmentConfigurationAttributesContext<T : KotlinGradleFragment> internal constructor(
setAttributes(fragment) internal val attributes: AttributeContainer,
val fragment: T,
) : AttributeContainer by attributes {
val project: Project get() = fragment.project
inline fun <reified T : Named> named(name: String): T = project.objects.named(T::class.java, name)
inline fun <reified T : Named> namedAttribute(key: Attribute<T>, name: String) = apply { attribute(key, named(name)) }
override fun <K : Any> attribute(key: Attribute<K>, value: K): KotlinGradleFragmentConfigurationAttributesContext<T> = apply {
attributes.attribute(key, value)
}
}
@Suppress("FunctionName")
fun <T : KotlinGradleFragment> FragmentAttributes(
setAttributes: KotlinGradleFragmentConfigurationAttributesContext<T>.() -> Unit
): KotlinGradleFragmentConfigurationAttributes<T> {
return object : KotlinGradleFragmentConfigurationAttributes<T> {
override fun setAttributes(attributes: AttributeContainer, fragment: T) {
val context = KotlinGradleFragmentConfigurationAttributesContext(attributes, fragment)
context.setAttributes()
}
}
} }
operator fun <T : KotlinGradleFragment> FragmentAttributes<T>.plus(other: FragmentAttributes<T>): FragmentAttributes<T> { operator fun <T : KotlinGradleFragment> FragmentAttributes<T>.plus(other: FragmentAttributes<T>): FragmentAttributes<T> {
if (this === KotlinGradleFragmentConfigurationAttributes.None) return other
if (other === KotlinGradleFragmentConfigurationAttributes.None) return this
if (this is CompositeFragmentAttributes && other is CompositeFragmentAttributes) { if (this is CompositeFragmentAttributes && other is CompositeFragmentAttributes) {
return CompositeFragmentAttributes(this.children + other.children) return CompositeFragmentAttributes(this.children + other.children)
} }
if (this === FragmentAttributes.None) return other
if (other === FragmentAttributes.None) return this
if (this is CompositeFragmentAttributes) { if (this is CompositeFragmentAttributes) {
return CompositeFragmentAttributes(this.children + other) return CompositeFragmentAttributes(this.children + other)
} }
@@ -43,7 +70,7 @@ operator fun <T : KotlinGradleFragment> FragmentAttributes<T>.plus(other: Fragme
internal class CompositeFragmentAttributes<in T : KotlinGradleFragment>(val children: List<FragmentAttributes<T>>) : internal class CompositeFragmentAttributes<in T : KotlinGradleFragment>(val children: List<FragmentAttributes<T>>) :
FragmentAttributes<T> { FragmentAttributes<T> {
override fun AttributeContainer.setAttributes(fragment: T) { override fun setAttributes(attributes: AttributeContainer, fragment: T) {
children.forEach { attribute -> attributes(attribute, fragment) } children.forEach { child -> child.setAttributes(attributes, fragment) }
} }
} }
@@ -3,52 +3,80 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationPublications
import org.gradle.api.capabilities.Capability import org.gradle.api.capabilities.Capability
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleFragmentConfigurationCapabilities.CapabilitiesContainer
/* Internal abbreviation */ /* Internal abbreviation */
internal typealias FragmentCapabilities<T> = KotlinGradleFragmentConfigurationCapabilities<T> internal typealias FragmentCapabilities<T> = KotlinGradleFragmentConfigurationCapabilities<T>
fun interface KotlinGradleFragmentConfigurationCapabilities<in T : KotlinGradleFragment> { interface KotlinGradleFragmentConfigurationCapabilities<in T : KotlinGradleFragment> {
interface Context { interface CapabilitiesContainer {
fun capability(notation: Any) fun capability(notation: Any)
val capabilities: List<Capability> val capabilities: List<Capability>
} }
class ContextImpl internal constructor( fun setCapabilities(container: CapabilitiesContainer, fragment: T)
private val configuration: Configuration
) : Context {
override fun capability(notation: Any) = configuration.outgoing.capability(notation)
override val capabilities: List<Capability> get() = configuration.outgoing.capabilities.orEmpty().toList()
}
fun Context.setCapabilities(fragment: T) object None : KotlinGradleFragmentConfigurationCapabilities<KotlinGradleFragment> {
override fun setCapabilities(container: CapabilitiesContainer, fragment: KotlinGradleFragment) = Unit
companion object {
val None = FragmentCapabilities<KotlinGradleFragment> {}
} }
} }
fun <T : KotlinGradleFragment> KotlinGradleFragmentConfigurationCapabilities<T>.onlyIfMadePublic(): KotlinGradleFragmentConfigurationCapabilities<T> { fun <T : KotlinGradleFragment> KotlinGradleFragmentConfigurationCapabilities<T>.setCapabilities(
return KotlinGradleFragmentConfigurationCapabilities { fragment -> publications: ConfigurationPublications, fragment: T
fragment.containingModule.ifMadePublic { capabilities(this@onlyIfMadePublic, fragment) } ) = setCapabilities(CapabilitiesContainer(publications), fragment)
fun CapabilitiesContainer(configuration: ConfigurationPublications): CapabilitiesContainer =
CapabilitiesContainerImpl(configuration)
fun CapabilitiesContainer(configuration: Configuration): CapabilitiesContainer =
CapabilitiesContainerImpl(configuration.outgoing)
private class CapabilitiesContainerImpl(
private val publications: ConfigurationPublications
) : CapabilitiesContainer {
override fun capability(notation: Any) = publications.capability(notation)
override val capabilities: List<Capability> get() = publications.capabilities.orEmpty().toList()
}
class KotlinGradleFragmentConfigurationCapabilitiesContext<T : KotlinGradleFragment> internal constructor(
internal val container: CapabilitiesContainer, val fragment: T
) : CapabilitiesContainer by container {
val project: Project get() = fragment.project
}
fun <T : KotlinGradleFragment> FragmentCapabilities(
setCapabilities: KotlinGradleFragmentConfigurationCapabilitiesContext<T>.() -> Unit
): KotlinGradleFragmentConfigurationCapabilities<T> = object : KotlinGradleFragmentConfigurationCapabilities<T> {
override fun setCapabilities(container: CapabilitiesContainer, fragment: T) {
val context = KotlinGradleFragmentConfigurationCapabilitiesContext(container, fragment)
context.setCapabilities()
} }
} }
fun <T : KotlinGradleFragment> KotlinGradleFragmentConfigurationCapabilities.Context.capabilities( fun <T : KotlinGradleFragment> KotlinGradleFragmentConfigurationCapabilities<T>.onlyIfMadePublic():
capabilities: KotlinGradleFragmentConfigurationCapabilities<T>, fragment: T KotlinGradleFragmentConfigurationCapabilities<T> {
) = with(capabilities) { setCapabilities(fragment) } val decorated = this
return FragmentCapabilities {
fragment.containingModule.ifMadePublic { decorated.setCapabilities(this, fragment) }
}
}
operator fun <T : KotlinGradleFragment> FragmentCapabilities<T>.plus(other: FragmentCapabilities<T>): FragmentCapabilities<T> { operator fun <T : KotlinGradleFragment> FragmentCapabilities<T>.plus(other: FragmentCapabilities<T>): FragmentCapabilities<T> {
if (this === KotlinGradleFragmentConfigurationCapabilities.None) return other
if (other === KotlinGradleFragmentConfigurationCapabilities.None) return this
if (this is CompositeFragmentCapabilities && other is CompositeFragmentCapabilities) { if (this is CompositeFragmentCapabilities && other is CompositeFragmentCapabilities) {
return CompositeFragmentCapabilities(this.children + other.children) return CompositeFragmentCapabilities(this.children + other.children)
} }
if (this === FragmentCapabilities.None) return other
if (other === FragmentCapabilities.None) return this
if (this is CompositeFragmentCapabilities) { if (this is CompositeFragmentCapabilities) {
return CompositeFragmentCapabilities(this.children + other) return CompositeFragmentCapabilities(this.children + other)
} }
@@ -62,7 +90,7 @@ operator fun <T : KotlinGradleFragment> FragmentCapabilities<T>.plus(other: Frag
internal class CompositeFragmentCapabilities<in T : KotlinGradleFragment>(val children: List<FragmentCapabilities<T>>) : internal class CompositeFragmentCapabilities<in T : KotlinGradleFragment>(val children: List<FragmentCapabilities<T>>) :
FragmentCapabilities<T> { FragmentCapabilities<T> {
override fun KotlinGradleFragmentConfigurationCapabilities.Context.setCapabilities(fragment: T) { override fun setCapabilities(container: CapabilitiesContainer, fragment: T) {
children.forEach { capability -> capabilities(capability, fragment) } children.forEach { child -> child.setCapabilities(container, fragment) }
} }
} }
@@ -37,7 +37,7 @@ internal class KotlinGradleFragmentConfigurationContextImpl(
fun <T : KotlinGradleFragment> KotlinGradleFragmentConfigurationDefinition<T>.withConfigurationProvider( fun <T : KotlinGradleFragment> KotlinGradleFragmentConfigurationDefinition<T>.withConfigurationProvider(
provider: KotlinGradleFragmentConfigurationContext.() -> Configuration provider: KotlinGradleFragmentConfigurationContext.() -> Configuration
) = copy(provider = provider) ) = copy(provider = ConfigurationProvider(provider))
operator fun <T : KotlinGradleFragment> KotlinGradleFragmentConfigurationDefinition<T>.plus(other: FragmentAttributes<T>): operator fun <T : KotlinGradleFragment> KotlinGradleFragmentConfigurationDefinition<T>.plus(other: FragmentAttributes<T>):
KotlinGradleFragmentConfigurationDefinition<T> = copy(attributes = attributes + other) KotlinGradleFragmentConfigurationDefinition<T> = copy(attributes = attributes + other)
@@ -3,14 +3,17 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Configuration
fun interface KotlinGradleFragmentConfigurationProvider { interface KotlinGradleFragmentConfigurationProvider {
fun KotlinGradleFragmentConfigurationContext.getConfiguration(): Configuration fun getConfiguration(context: KotlinGradleFragmentConfigurationContext): Configuration
} }
internal fun KotlinGradleFragmentConfigurationProvider.getConfiguration(context: KotlinGradleFragmentConfigurationContext): Configuration { fun ConfigurationProvider(provider: KotlinGradleFragmentConfigurationContext.() -> Configuration):
return with(context) { getConfiguration() } KotlinGradleFragmentConfigurationProvider = object : KotlinGradleFragmentConfigurationProvider {
override fun getConfiguration(context: KotlinGradleFragmentConfigurationContext): Configuration = context.provider()
} }
@@ -3,17 +3,37 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Configuration
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
/* Internal abbreviation */ /* Internal abbreviation */
internal typealias FragmentRelation = KotlinGradleFragmentConfigurationRelation internal typealias FragmentConfigurationRelation = KotlinGradleFragmentConfigurationRelation
fun interface KotlinGradleFragmentConfigurationRelation { interface KotlinGradleFragmentConfigurationRelation {
fun KotlinGradleFragmentConfigurationContext.setupExtendsFromRelations(configuration: Configuration) fun setExtendsFrom(configuration: Configuration, context: KotlinGradleFragmentConfigurationContext)
companion object { object None : KotlinGradleFragmentConfigurationRelation {
val None = FragmentRelation {} override fun setExtendsFrom(configuration: Configuration, context: KotlinGradleFragmentConfigurationContext) = Unit
}
}
class KotlinGradleFragmentConfigurationRelationContext internal constructor(
val configuration: Configuration,
context: KotlinGradleFragmentConfigurationContext
) : KotlinGradleFragmentConfigurationContext by context {
fun extendsFrom(configuration: Configuration) = this.configuration.extendsFrom(configuration)
fun extendsFrom(configuration: String) = project.addExtendsFromRelation(this.configuration.name, configuration)
}
fun FragmentConfigurationRelation(
setExtendsFrom: KotlinGradleFragmentConfigurationRelationContext.() -> Unit
): KotlinGradleFragmentConfigurationRelation = object : KotlinGradleFragmentConfigurationRelation {
override fun setExtendsFrom(configuration: Configuration, context: KotlinGradleFragmentConfigurationContext) {
val relationContext = KotlinGradleFragmentConfigurationRelationContext(configuration, context)
relationContext.setExtendsFrom()
} }
} }
@@ -51,12 +51,9 @@ class KotlinGradleFragmentFactory<T : KotlinGradleFragment>(
} }
internal fun <T : KotlinGradleFragment> Configuration.configure( internal fun <T : KotlinGradleFragment> Configuration.configure(
definition: KotlinGradleFragmentConfigurationDefinition<T>, definition: KotlinGradleFragmentConfigurationDefinition<T>, fragment: T
fragment: T
) { ) {
attributes.attributes(definition.attributes, fragment) definition.attributes.setAttributes(attributes, fragment)
outgoing.artifacts(definition.artifacts, fragment) definition.artifacts.addArtifacts(outgoing, fragment)
definition.capabilities.setCapabilities(outgoing, fragment)
KotlinGradleFragmentConfigurationCapabilities.ContextImpl(this)
.capabilities(definition.capabilities, fragment)
} }
@@ -54,23 +54,25 @@ class KotlinJvmVariantInstantiator internal constructor(
override fun create(name: String): KotlinJvmVariant { override fun create(name: String): KotlinJvmVariant {
val names = FragmentNameDisambiguation(module, name) val names = FragmentNameDisambiguation(module, name)
val context = KotlinGradleFragmentConfigurationContextImpl(module, config.dependenciesConfigurationFactory.create(module, names), names) val context = KotlinGradleFragmentConfigurationContextImpl(
module, config.dependenciesConfigurationFactory.create(module, names), names
)
return KotlinJvmVariant( return KotlinJvmVariant(
containingModule = module, containingModule = module,
fragmentName = name, fragmentName = name,
dependencyConfigurations = context.dependencies, dependencyConfigurations = context.dependencies,
compileDependenciesConfiguration = config.compileDependencies.provider.getConfiguration(context).also { configuration -> compileDependenciesConfiguration = config.compileDependencies.provider.getConfiguration(context).also { configuration ->
config.compileDependencies.relations.run { context.setupExtendsFromRelations(configuration) } config.compileDependencies.relations.setExtendsFrom(configuration, context)
}, },
runtimeDependenciesConfiguration = config.runtimeDependencies.provider.getConfiguration(context).also { configuration -> runtimeDependenciesConfiguration = config.runtimeDependencies.provider.getConfiguration(context).also { configuration ->
config.runtimeDependencies.relations.run { context.setupExtendsFromRelations(configuration) } config.runtimeElements.relations.setExtendsFrom(configuration, context)
}, },
apiElementsConfiguration = config.apiElements.provider.getConfiguration(context).also { configuration -> apiElementsConfiguration = config.apiElements.provider.getConfiguration(context).also { configuration ->
config.apiElements.relations.run { context.setupExtendsFromRelations(configuration) } config.apiElements.relations.setExtendsFrom(configuration, context)
}, },
runtimeElementsConfiguration = config.runtimeElements.provider.getConfiguration(context).also { configuration -> runtimeElementsConfiguration = config.runtimeElements.provider.getConfiguration(context).also { configuration ->
config.runtimeElements.relations.run { context.setupExtendsFromRelations(configuration) } config.runtimeElements.relations.setExtendsFrom(configuration, context)
} }
) )
} }
@@ -61,14 +61,14 @@ class KotlinNativeVariantInstantiator<T : KotlinNativeVariantInternal>(
fragmentName = name, fragmentName = name,
dependencyConfigurations = dependencies, dependencyConfigurations = dependencies,
compileDependencyConfiguration = config.compileDependencies.provider.getConfiguration(context).also { configuration -> compileDependencyConfiguration = config.compileDependencies.provider.getConfiguration(context).also { configuration ->
config.compileDependencies.relations.run { context.setupExtendsFromRelations(configuration) } config.compileDependencies.relations.setExtendsFrom(configuration, context)
}, },
apiElementsConfiguration = config.apiElements.provider.getConfiguration(context).also { configuration -> apiElementsConfiguration = config.apiElements.provider.getConfiguration(context).also { configuration ->
config.apiElements.relations.run { context.setupExtendsFromRelations(configuration) } config.apiElements.relations.setExtendsFrom(configuration, context)
}, },
hostSpecificMetadataElementsConfiguration = hostSpecificMetadataElementsConfiguration =
config.hostSpecificMetadataElements.provider.getConfiguration(context).also { configuration -> config.hostSpecificMetadataElements.provider.getConfiguration(context).also { configuration ->
config.hostSpecificMetadataElements.relations.run { context.setupExtendsFromRelations(configuration) } config.hostSpecificMetadataElements.relations.setExtendsFrom(configuration, context)
} }
) )
} }