[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() {
@Suppress("DEPRECATION_ERROR")
val factories = VariantImplementationFactories.get(project.gradle)
val factories = VariantImplementationFactoriesConfigurator.get(project.gradle)
factories.putIfAbsent(
MavenPluginConfigurator.MavenPluginConfiguratorVariantFactory::class,
MavenPluginConfigurator.DefaultMavenPluginConfiguratorVariantFactory()
@@ -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<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
/**
* 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<BuildServiceParameters.None> {
private val factories: MutableMap<KClass<*>, VariantImplementationFactory> = ConcurrentHashMap()
operator fun <T : VariantImplementationFactory> set(
type: KClass<T>,
factory: T
) {
factories[type] = factory
}
fun <T : VariantImplementationFactory> putIfAbsent(
type: KClass<T>,
factory: T
) {
factories.putIfAbsent(type, factory)
abstract class VariantImplementationFactories : BuildService<VariantImplementationFactories.Parameters> {
interface Parameters : BuildServiceParameters {
val factories: MapProperty<String, VariantImplementationFactory>
}
@Suppress("UNCHECKED_CAST")
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.
*/
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<VariantImplementationFactories> {
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<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()
}
}
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.gradle.util
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.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
*/
fun Gradle.registerConfigurationTimePropertiesAccessorForTests() {
@Suppress("DEPRECATION_ERROR")
VariantImplementationFactories.get(gradle).putIfAbsent(
VariantImplementationFactoriesConfigurator.get(gradle).putIfAbsent(
ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class,
DefaultConfigurationTimePropertiesAccessorVariantFactory()
)
@@ -136,8 +136,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
}
private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR")
val factories = VariantImplementationFactories.get(gradle)
val factories = VariantImplementationFactoriesConfigurator.get(gradle)
factories[JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory::class] =
JavaSourceSetsAccessorG70.JavaSourceSetAccessorVariantFactoryG70()
factories[BasePluginConfiguration.BasePluginConfigurationVariantFactory::class] =
@@ -141,8 +141,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
}
private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR")
val factories = VariantImplementationFactories.get(gradle)
val factories = VariantImplementationFactoriesConfigurator.get(gradle)
factories[IdeaSyncDetector.IdeaSyncDetectorVariantFactory::class] =
IdeaSyncDetectorG71.IdeaSyncDetectorVariantFactoryG71()
factories[ConfigurationTimePropertiesAccessor.ConfigurationTimePropertiesAccessorVariantFactory::class] =
@@ -139,8 +139,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
}
private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR")
val factories = VariantImplementationFactories.get(gradle)
val factories = VariantImplementationFactoriesConfigurator.get(gradle)
factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] =
MppTestReportHelperG74.MppTestReportHelperVariantFactoryG74()
}
@@ -140,8 +140,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
}
private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR")
val factories = VariantImplementationFactories.get(gradle)
val factories = VariantImplementationFactoriesConfigurator.get(gradle)
factories[MppTestReportHelper.MppTestReportHelperVariantFactory::class] =
MppTestReportHelperG75.MppTestReportHelperVariantFactoryG75()
}
@@ -140,8 +140,7 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") {
}
private fun Project.registerVariantImplementations() {
@Suppress("DEPRECATION_ERROR")
val factories = VariantImplementationFactories.get(gradle)
val factories = VariantImplementationFactoriesConfigurator.get(gradle)
factories[MavenPluginConfigurator.MavenPluginConfiguratorVariantFactory::class] =
MavenPluginConfiguratorG6.Gradle6MavenPluginConfiguratorVariantFactory()
factories[JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory::class] =