[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
This commit is contained in:
Alexander.Likhachev
2023-01-12 09:47:05 +01:00
parent 393f880322
commit 1565c800d9
8 changed files with 67 additions and 37 deletions
@@ -127,8 +127,7 @@ abstract class DefaultKotlinBasePlugin : KotlinBasePlugin {
} }
private fun Project.registerDefaultVariantImplementations() { private fun Project.registerDefaultVariantImplementations() {
@Suppress("DEPRECATION_ERROR") val factories = VariantImplementationFactoriesConfigurator.get(project.gradle)
val factories = VariantImplementationFactories.get(project.gradle)
factories.putIfAbsent( factories.putIfAbsent(
MavenPluginConfigurator.MavenPluginConfiguratorVariantFactory::class, MavenPluginConfigurator.MavenPluginConfiguratorVariantFactory::class,
MavenPluginConfigurator.DefaultMavenPluginConfiguratorVariantFactory() MavenPluginConfigurator.DefaultMavenPluginConfiguratorVariantFactory()
@@ -8,56 +8,96 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.invocation.Gradle import org.gradle.api.invocation.Gradle
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.gradle.api.services.BuildService import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters import org.gradle.api.services.BuildServiceParameters
import java.io.Serializable
import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.tasks.withType
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass 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<BuildServiceParameters.None> {
val factories: MutableMap<String, VariantImplementationFactories.VariantImplementationFactory> = ConcurrentHashMap()
fun <T : VariantImplementationFactories.VariantImplementationFactory> putIfAbsent(
type: KClass<T>,
factory: T
) {
factories.putIfAbsent(type.java.name, factory)
}
operator fun <T : VariantImplementationFactories.VariantImplementationFactory> set(
type: KClass<T>,
factory: T
) {
factories[type.java.name] = factory
}
companion object {
fun getProvider(
gradle: Gradle
): Provider<VariantImplementationFactoriesConfigurator> {
// 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 internal interface UsesVariantImplementationFactories : Task
/** /**
* Provides a way for Gradle plugin variants to register specific implementation factories, * Provides a way for Gradle plugin variants to use specific implementation factories in the common code
* that could be used inside common code.
*/ */
abstract class VariantImplementationFactories : BuildService<BuildServiceParameters.None> { abstract class VariantImplementationFactories : BuildService<VariantImplementationFactories.Parameters> {
private val factories: MutableMap<KClass<*>, VariantImplementationFactory> = ConcurrentHashMap() interface Parameters : BuildServiceParameters {
operator fun <T : VariantImplementationFactory> set( val factories: MapProperty<String, VariantImplementationFactory>
type: KClass<T>,
factory: T
) {
factories[type] = factory
}
fun <T : VariantImplementationFactory> putIfAbsent(
type: KClass<T>,
factory: T
) {
factories.putIfAbsent(type, factory)
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
operator fun <T : VariantImplementationFactory> get(type: KClass<T>): T { operator fun <T : VariantImplementationFactory> get(type: KClass<T>): 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. * Marker interface for actual implementation factories.
*/ */
interface VariantImplementationFactory interface VariantImplementationFactory : Serializable
companion object { 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( private fun getProvider(
gradle: Gradle gradle: Gradle
): Provider<VariantImplementationFactories> { ): Provider<VariantImplementationFactories> {
val configProvider = VariantImplementationFactoriesConfigurator.getProvider(gradle)
// Use class loader hashcode in case there are multiple class loaders in the same build // Use class loader hashcode in case there are multiple class loaders in the same build
return gradle.sharedServices return gradle.sharedServices
.registerIfAbsent( .registerIfAbsent(
"variant_impl_factories_${VariantImplementationFactories::class.java.classLoader.hashCode()}", "variant_impl_factories_${VariantImplementationFactories::class.java.classLoader.hashCode()}",
VariantImplementationFactories::class.java VariantImplementationFactories::class.java
) {} ) {
it.parameters.factories.value(configProvider.get().factories)
}
} }
fun getProvider( fun getProvider(
@@ -70,9 +110,6 @@ abstract class VariantImplementationFactories : BuildService<BuildServiceParamet
} }
} }
@Deprecated("Should be used with `Project` instance to be able to declare usages in tasks", level = DeprecationLevel.ERROR)
fun get(gradle: Gradle): VariantImplementationFactories = getProvider(gradle).get()
fun get(project: Project): VariantImplementationFactories = getProvider(project).get() fun get(project: Project): VariantImplementationFactories = getProvider(project).get()
} }
} }
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.gradle.util package org.jetbrains.kotlin.gradle.util
import org.gradle.api.invocation.Gradle import org.gradle.api.invocation.Gradle
import org.jetbrains.kotlin.gradle.plugin.VariantImplementationFactories import org.jetbrains.kotlin.gradle.plugin.VariantImplementationFactoriesConfigurator
import org.jetbrains.kotlin.gradle.plugin.internal.ConfigurationTimePropertiesAccessor import org.jetbrains.kotlin.gradle.plugin.internal.ConfigurationTimePropertiesAccessor
import org.jetbrains.kotlin.gradle.plugin.internal.DefaultConfigurationTimePropertiesAccessorVariantFactory import org.jetbrains.kotlin.gradle.plugin.internal.DefaultConfigurationTimePropertiesAccessorVariantFactory
@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.gradle.plugin.internal.DefaultConfigurationTimePrope
* This helper function is for simple tests that are testing granular logic without applying Kotlin plugin * This helper function is for simple tests that are testing granular logic without applying Kotlin plugin
*/ */
fun Gradle.registerConfigurationTimePropertiesAccessorForTests() { fun Gradle.registerConfigurationTimePropertiesAccessorForTests() {
@Suppress("DEPRECATION_ERROR") VariantImplementationFactoriesConfigurator.get(gradle).putIfAbsent(
VariantImplementationFactories.get(gradle).putIfAbsent(
ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class, ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class,
DefaultConfigurationTimePropertiesAccessorVariantFactory() DefaultConfigurationTimePropertiesAccessorVariantFactory()
) )
@@ -136,8 +136,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
} }
private fun Project.registerVariantImplementations() { private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR") val factories = VariantImplementationFactoriesConfigurator.get(gradle)
val factories = VariantImplementationFactories.get(gradle)
factories[JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory::class] = factories[JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory::class] =
JavaSourceSetsAccessorG70.JavaSourceSetAccessorVariantFactoryG70() JavaSourceSetsAccessorG70.JavaSourceSetAccessorVariantFactoryG70()
factories[BasePluginConfiguration.BasePluginConfigurationVariantFactory::class] = factories[BasePluginConfiguration.BasePluginConfigurationVariantFactory::class] =
@@ -141,8 +141,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
} }
private fun Project.registerVariantImplementations() { private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR") val factories = VariantImplementationFactoriesConfigurator.get(gradle)
val factories = VariantImplementationFactories.get(gradle)
factories[IdeaSyncDetector.IdeaSyncDetectorVariantFactory::class] = factories[IdeaSyncDetector.IdeaSyncDetectorVariantFactory::class] =
IdeaSyncDetectorG71.IdeaSyncDetectorVariantFactoryG71() IdeaSyncDetectorG71.IdeaSyncDetectorVariantFactoryG71()
factories[ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class] = factories[ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class] =
@@ -139,8 +139,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
} }
private fun Project.registerVariantImplementations() { private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR") val factories = VariantImplementationFactoriesConfigurator.get(gradle)
val factories = VariantImplementationFactories.get(gradle)
factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] = factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] =
MppTestReportHelperG74.MppTestReportHelperVariantFactoryG74() MppTestReportHelperG74.MppTestReportHelperVariantFactoryG74()
} }
@@ -140,8 +140,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
} }
private fun Project.registerVariantImplementations() { private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR") val factories = VariantImplementationFactoriesConfigurator.get(gradle)
val factories = VariantImplementationFactories.get(gradle)
factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] = factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] =
MppTestReportHelperG75.MppTestReportHelperVariantFactoryG75() MppTestReportHelperG75.MppTestReportHelperVariantFactoryG75()
} }
@@ -140,8 +140,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
} }
private fun Project.registerVariantImplementations() { private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR") val factories = VariantImplementationFactoriesConfigurator.get(gradle)
val factories = VariantImplementationFactories.get(gradle)
factories[MavenPluginConfigurator.MavenPluginConfiguratorVariantFactory::class] = factories[MavenPluginConfigurator.MavenPluginConfiguratorVariantFactory::class] =
MavenPluginConfiguratorG6.Gradle6MavenPluginConfiguratorVariantFactory() MavenPluginConfiguratorG6.Gradle6MavenPluginConfiguratorVariantFactory()
factories[JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory::class] = factories[JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory::class] =