From 7cc42d3fe990171d67b61b7227e83efd92453227 Mon Sep 17 00:00:00 2001 From: Alexander Likhachev Date: Thu, 4 Aug 2022 23:43:46 +0200 Subject: [PATCH] [Gradle] Implement IDEA sync detection via ValueSource for Gradle 7.5+ #KT-53374 Fixed --- .../jetbrains/kotlin/gradle/internal/idea.kt | 23 ++---- .../gradle/plugin/KotlinPluginWrapper.kt | 5 ++ .../plugin/internal/IdeaSyncDetector.kt | 71 +++++++++++++++++++ .../kotlin/gradle/plugin/PluginWrappers.kt | 5 +- .../plugin/internal/IdeaSyncDetectorG70.kt | 22 ++++++ .../kotlin/gradle/plugin/PluginWrappers.kt | 9 ++- .../plugin/internal/IdeaSyncDetectorG71.kt | 22 ++++++ .../kotlin/gradle/plugin/PluginWrappers.kt | 4 +- .../plugin/internal/IdeaSyncDetectorG6.kt | 22 ++++++ 9 files changed, 162 insertions(+), 21 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetector.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG70.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG71.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG6.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/idea.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/idea.kt index 17bae3e574e..8005eef3cc3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/idea.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/idea.kt @@ -6,20 +6,11 @@ package org.jetbrains.kotlin.gradle.internal import org.gradle.api.Project -import org.jetbrains.kotlin.gradle.utils.getSystemProperty +import org.jetbrains.kotlin.gradle.plugin.internal.IdeaSyncDetector +import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory -internal val Project.isInIdeaSync: Boolean - get() { - // "idea.sync.active" was introduced in 2019.1 - if (getSystemProperty("idea.sync.active")?.toBoolean() == true) return true - - // before 2019.1 there is "idea.active" that was true only on sync, - // but since 2019.1 "idea.active" present in task execution too. - // So let's check Idea version - val majorIdeaVersion = getSystemProperty("idea.version") - ?.split(".") - ?.getOrNull(0) - val isBeforeIdea2019 = majorIdeaVersion == null || majorIdeaVersion.toInt() < 2019 - - return isBeforeIdea2019 && getSystemProperty("idea.active")?.toBoolean() == true - } \ No newline at end of file +internal val Project.isInIdeaSync + get() = gradle + .variantImplementationFactory() + .getInstance(this) + .isInIdeaSync \ No newline at end of file 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 6dabde22a86..8449336a159 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 @@ -204,6 +204,11 @@ abstract class KotlinBasePluginWrapper : DefaultKotlinBasePlugin() { BasePluginConfiguration.BasePluginConfigurationVariantFactory::class, DefaultBasePluginConfigurationVariantFactory() ) + + factories.putIfAbsent( + IdeaSyncDetector.IdeaSyncDetectorVariantFactory::class, + DefaultIdeaSyncDetectorVariantFactory() + ) } internal open fun createTestRegistry(project: Project) = KotlinTestsRegistry(project) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetector.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetector.kt new file mode 100644 index 00000000000..8c600038605 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetector.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2022 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.internal + +import org.gradle.api.Project +import org.gradle.api.provider.Property +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.provider.ValueSource +import org.gradle.api.provider.ValueSourceParameters +import org.jetbrains.kotlin.gradle.plugin.VariantImplementationFactories +import java.io.Serializable + +internal abstract class IdeaPropertiesEvaluator { + protected abstract fun readSystemPropertyValue(key: String): String? + + internal fun isInIdeaSync(): Boolean { + // "idea.sync.active" was introduced in 2019.1 + if (readSystemPropertyValue("idea.sync.active")?.toBoolean() == true) return true + + // before 2019.1 there is "idea.active" that was true only on sync, + // but since 2019.1 "idea.active" present in task execution too. + // So let's check Idea version + val majorIdeaVersion = readSystemPropertyValue("idea.version") + ?.split(".") + ?.getOrNull(0) + val isBeforeIdea2019 = majorIdeaVersion == null || majorIdeaVersion.toInt() < 2019 + + return isBeforeIdea2019 && readSystemPropertyValue("idea.active")?.toBoolean() == true + } +} + +internal interface IdeaSyncDetector { + val isInIdeaSync: Boolean + + fun createIdeaPropertiesEvaluator(): IdeaPropertiesEvaluator + + interface IdeaSyncDetectorVariantFactory : VariantImplementationFactories.VariantImplementationFactory { + fun getInstance(project: Project): IdeaSyncDetector + } +} + +internal class DefaultIdeaSyncDetectorVariantFactory : IdeaSyncDetector.IdeaSyncDetectorVariantFactory { + override fun getInstance(project: Project): IdeaSyncDetector = DefaultIdeaSyncDetector(project.providers) +} + +internal abstract class IdeaPropertiesValueSource : ValueSource { + interface Parameters : ValueSourceParameters { + val propertiesEvaluator: Property + } + + override fun obtain(): Boolean { + return parameters.propertiesEvaluator.get().isInIdeaSync() + } +} + +internal class DefaultIdeaSyncDetector( + providerFactory: ProviderFactory +) : IdeaSyncDetector { + override val isInIdeaSync: Boolean = providerFactory.of(IdeaPropertiesValueSource::class.java) { + it.parameters.propertiesEvaluator.set(createIdeaPropertiesEvaluator()) + }.get() + + override fun createIdeaPropertiesEvaluator(): IdeaPropertiesEvaluator = object : IdeaPropertiesEvaluator(), Serializable { + // since Gradle 7.5 we shouldn't declare system property read + // and also now we can read system properties inside ValueSource without configuration cache invalidation + override fun readSystemPropertyValue(key: String) = System.getProperty(key) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt index 880183ccef7..e8f66febce2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt @@ -12,9 +12,8 @@ import org.gradle.api.Project import org.gradle.api.file.SourceDirectorySet import org.gradle.api.model.ObjectFactory import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry -import org.jetbrains.kotlin.gradle.plugin.internal.BasePluginConfiguration +import org.jetbrains.kotlin.gradle.plugin.internal.* import org.jetbrains.kotlin.gradle.plugin.internal.BasePluginConfigurationG70 -import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessorG70 import javax.inject.Inject @@ -142,4 +141,6 @@ private fun Project.registerVariantImplementations() { JavaSourceSetsAccessorG70.JavaSourceSetAccessorVariantFactoryG70() factories[BasePluginConfiguration.BasePluginConfigurationVariantFactory::class] = BasePluginConfigurationG70.BasePluginConfigurationVariantFactoryG70() + factories[IdeaSyncDetector.IdeaSyncDetectorVariantFactory::class] = + IdeaSyncDetectorG70.IdeaSyncDetectorVariantFactoryG70() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG70.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG70.kt new file mode 100644 index 00000000000..cb293a670e5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle70/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG70.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2022 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.internal + +import org.gradle.api.Project +import org.gradle.api.provider.ProviderFactory + +internal class IdeaSyncDetectorG70(private val providerFactory: ProviderFactory) : IdeaSyncDetector { + override val isInIdeaSync = createIdeaPropertiesEvaluator().isInIdeaSync() + + override fun createIdeaPropertiesEvaluator() = object : IdeaPropertiesEvaluator() { + // we should declare system property read for Gradle < 7.4 + override fun readSystemPropertyValue(key: String) = providerFactory.systemProperty(key).forUseAtConfigurationTime().orNull + } + + internal class IdeaSyncDetectorVariantFactoryG70 : IdeaSyncDetector.IdeaSyncDetectorVariantFactory { + override fun getInstance(project: Project): IdeaSyncDetector = IdeaSyncDetectorG70(project.providers) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt index 75e10cff437..a3c4cc4f4bf 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt @@ -12,6 +12,8 @@ import org.gradle.api.Project import org.gradle.api.file.SourceDirectorySet import org.gradle.api.model.ObjectFactory import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry +import org.jetbrains.kotlin.gradle.plugin.internal.IdeaSyncDetector +import org.jetbrains.kotlin.gradle.plugin.internal.IdeaSyncDetectorG71 import javax.inject.Inject private const val PLUGIN_VARIANT_NAME = "gradle71" @@ -137,5 +139,8 @@ open class KotlinPlatformCommonPlugin : KotlinPlatformPluginBase("common") { } } -@Suppress("unused") -private fun Project.registerVariantImplementations() {} +private fun Project.registerVariantImplementations() { + val factories = VariantImplementationFactories.get(gradle) + factories[IdeaSyncDetector.IdeaSyncDetectorVariantFactory::class] = + IdeaSyncDetectorG71.IdeaSyncDetectorVariantFactoryG71() +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG71.kt b/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG71.kt new file mode 100644 index 00000000000..a475c572770 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/gradle71/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG71.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2022 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.internal + +import org.gradle.api.Project +import org.gradle.api.provider.ProviderFactory + +internal class IdeaSyncDetectorG71(private val providerFactory: ProviderFactory) : IdeaSyncDetector { + override val isInIdeaSync = createIdeaPropertiesEvaluator().isInIdeaSync() + + override fun createIdeaPropertiesEvaluator() = object : IdeaPropertiesEvaluator() { + // we should declare system property read for Gradle < 7.4 + override fun readSystemPropertyValue(key: String) = providerFactory.systemProperty(key).forUseAtConfigurationTime().orNull + } + + internal class IdeaSyncDetectorVariantFactoryG71 : IdeaSyncDetector.IdeaSyncDetectorVariantFactory { + override fun getInstance(project: Project): IdeaSyncDetector = IdeaSyncDetectorG71(project.providers) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt index 17427bdf918..65877f2e316 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/PluginWrappers.kt @@ -144,7 +144,9 @@ private fun Project.registerVariantImplementations() { factories[MavenPluginConfigurator.MavenPluginConfiguratorVariantFactory::class] = MavenPluginConfiguratorG6.Gradle6MavenPluginConfiguratorVariantFactory() factories[JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory::class] = - JavaSourceSetsAccessorG6.JavaSourceSetAccessorVariantFactoryG70() + JavaSourceSetsAccessorG6.JavaSourceSetAccessorVariantFactoryG6() factories[BasePluginConfiguration.BasePluginConfigurationVariantFactory::class] = BasePluginConfigurationG6.BasePluginConfigurationVariantFactoryG6() + factories[IdeaSyncDetector.IdeaSyncDetectorVariantFactory::class] = + IdeaSyncDetectorG6.IdeaSyncDetectorVariantFactoryG6() } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG6.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG6.kt new file mode 100644 index 00000000000..acad93bc770 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/internal/IdeaSyncDetectorG6.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2022 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.internal + +import org.gradle.api.Project +import org.gradle.api.provider.ProviderFactory + +internal class IdeaSyncDetectorG6(private val providerFactory: ProviderFactory) : IdeaSyncDetector { + override val isInIdeaSync = createIdeaPropertiesEvaluator().isInIdeaSync() + + override fun createIdeaPropertiesEvaluator() = object : IdeaPropertiesEvaluator() { + // we should declare system property read for Gradle < 7.4 + override fun readSystemPropertyValue(key: String) = providerFactory.systemProperty(key).forUseAtConfigurationTime().orNull + } + + internal class IdeaSyncDetectorVariantFactoryG6 : IdeaSyncDetector.IdeaSyncDetectorVariantFactory { + override fun getInstance(project: Project): IdeaSyncDetector = IdeaSyncDetectorG6(project.providers) + } +} \ No newline at end of file