From 1565c800d956cbcb1ad5557bd6f84344cb604055 Mon Sep 17 00:00:00 2001 From: "Alexander.Likhachev" Date: Thu, 12 Jan 2023 09:47:05 +0100 Subject: [PATCH] [Gradle] Pass factories to VariantImplementationFactories as parameters These changes are required to make the factories persistent to work properly with configuration cache #KT-55241 Fixed --- .../gradle/plugin/KotlinPluginWrapper.kt | 3 +- .../plugin/VariantImplementationFactories.kt | 81 ++++++++++++++----- .../jetbrains/kotlin/gradle/util/variants.kt | 5 +- .../kotlin/gradle/plugin/PluginWrappers.kt | 3 +- .../kotlin/gradle/plugin/PluginWrappers.kt | 3 +- .../kotlin/gradle/plugin/PluginWrappers.kt | 3 +- .../kotlin/gradle/plugin/PluginWrappers.kt | 3 +- .../kotlin/gradle/plugin/PluginWrappers.kt | 3 +- 8 files changed, 67 insertions(+), 37 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index aca614bfc84..badbab21238 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -127,8 +127,7 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin { } private fun Project.registerDefaultVariantImplementations() { - @Suppress("DEPRECATION_ERROR") - val factories = VariantImplementationFactories.get(project.gradle) + val factories = VariantImplementationFactoriesConfigurator.get(project.gradle) factories.putIfAbsent( MavenPluginConfigurator.MavenPluginConfiguratorVariantFactory::class, MavenPluginConfigurator.DefaultMavenPluginConfiguratorVariantFactory() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/VariantImplementationFactories.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/VariantImplementationFactories.kt index 523fb6253ca..eeeddd3a444 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/VariantImplementationFactories.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/VariantImplementationFactories.kt @@ -8,56 +8,96 @@ package org.jetbrains.kotlin.gradle.plugin import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.invocation.Gradle +import org.gradle.api.provider.MapProperty import org.gradle.api.provider.Provider import org.gradle.api.services.BuildService import org.gradle.api.services.BuildServiceParameters +import java.io.Serializable import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject import java.util.concurrent.ConcurrentHashMap import kotlin.reflect.KClass +/** + * A build service for configuring the [VariantImplementationFactories] build service. + * Provides a way for Gradle plugin variants to register specific implementation factories, + * that could be used inside the common code. + * + * We cannot register them directly in [VariantImplementationFactories] as we would lose the factories after + * the service reinitialization on configuration cache retrieval. Thus, this service should be used to register factories + * and [VariantImplementationFactories] should be used to use them. + */ +internal abstract class VariantImplementationFactoriesConfigurator : BuildService { + val factories: MutableMap = ConcurrentHashMap() + + fun putIfAbsent( + type: KClass, + factory: T + ) { + factories.putIfAbsent(type.java.name, factory) + } + + operator fun set( + type: KClass, + factory: T + ) { + factories[type.java.name] = factory + } + + companion object { + fun getProvider( + gradle: Gradle + ): Provider { + // Use class loader hashcode in case there are multiple class loaders in the same build + return gradle.sharedServices + .registerIfAbsent( + "variant_impl_factories_configurator_${VariantImplementationFactoriesConfigurator::class.java.classLoader.hashCode()}", + VariantImplementationFactoriesConfigurator::class.java + ) {} + } + + fun get(gradle: Gradle): VariantImplementationFactoriesConfigurator = getProvider(gradle).get() + } +} + internal interface UsesVariantImplementationFactories : Task /** - * Provides a way for Gradle plugin variants to register specific implementation factories, - * that could be used inside common code. + * Provides a way for Gradle plugin variants to use specific implementation factories in the common code */ -abstract class VariantImplementationFactories : BuildService { - private val factories: MutableMap, VariantImplementationFactory> = ConcurrentHashMap() - operator fun set( - type: KClass, - factory: T - ) { - factories[type] = factory - } - - fun putIfAbsent( - type: KClass, - factory: T - ) { - factories.putIfAbsent(type, factory) +abstract class VariantImplementationFactories : BuildService { + interface Parameters : BuildServiceParameters { + val factories: MapProperty } @Suppress("UNCHECKED_CAST") operator fun get(type: KClass): T { - return factories[type] as? T ?: throw IllegalArgumentException("${type.simpleName} type is not known for plugin variants") + return parameters.factories.get()[type.java.name] as? T + ?: throw IllegalArgumentException("${type.simpleName} type is not known for plugin variants") } /** * Marker interface for actual implementation factories. */ - interface VariantImplementationFactory + interface VariantImplementationFactory : Serializable companion object { + /** + * Please don't change the visibility modifier. This method isn't intended to be used directly. + * This method doesn't declare the service usage from Gradle tasks. + */ private fun getProvider( gradle: Gradle ): Provider { + val configProvider = VariantImplementationFactoriesConfigurator.getProvider(gradle) // Use class loader hashcode in case there are multiple class loaders in the same build return gradle.sharedServices .registerIfAbsent( "variant_impl_factories_${VariantImplementationFactories::class.java.classLoader.hashCode()}", VariantImplementationFactories::class.java - ) {} + ) { + it.parameters.factories.value(configProvider.get().factories) + } } fun getProvider( @@ -70,9 +110,6 @@ abstract class VariantImplementationFactories : BuildService