From c34bfcdb1d05be05c4e839d7d1c67eb6df40828e Mon Sep 17 00:00:00 2001 From: Timofey Solonin Date: Thu, 7 Mar 2024 17:40:41 +0100 Subject: [PATCH] Emit a diagnostic if variant reselection is used pre Gradle 7.6 ^KT-66133 --- .../diagnostics/KotlinToolingDiagnostics.kt | 11 +++++ .../plugin/mpp/resources/GradleVersion.kt | 18 +++++++++ .../KotlinTargetResourcesPublicationImpl.kt | 31 ++++++++++++-- .../resourcesPublicationExtension.kt | 5 ++- ...tlinTargetResourcesPublicationImplTests.kt | 40 +++++++++++++++++++ 5 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/GradleVersion.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt index b8b35625b57..ec09edf8c5c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt @@ -806,6 +806,17 @@ object KotlinToolingDiagnostics { ) } + object ResourceMayNotBeResolvedWithGradleVersion : ToolingDiagnosticFactory(ERROR) { + operator fun invoke( + targetName: String, currentGradleVersion: String, minimumRequiredVersion: String) = build( + """ + Resources for target $targetName may not be resolved. Minimum required Gradle version is ${minimumRequiredVersion} but current is ${currentGradleVersion}. + + $resourcesBugReportRequest + """.trimIndent() + ) + } + object UnknownValueProvidedForResourcesStrategy : ToolingDiagnosticFactory(ERROR) { operator fun invoke(value: String) = build( """ diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/GradleVersion.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/GradleVersion.kt new file mode 100644 index 00000000000..a7b821eaa92 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/GradleVersion.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2024 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.mpp.resources + +import org.gradle.api.Project +import org.gradle.util.GradleVersion +import org.jetbrains.kotlin.gradle.plugin.extraProperties +import org.jetbrains.kotlin.gradle.plugin.getOrNull + +private const val OVERRIDE_GRADLE_VERSION_FOR_TESTS = "org.jetbrains.kotlin.internal.overriddenGradleVersionForTests" +internal var Project.overriddenGradleVersionForTests: GradleVersion? + set(value) = extraProperties.set(OVERRIDE_GRADLE_VERSION_FOR_TESTS, value) + get() = extraProperties.getOrNull(OVERRIDE_GRADLE_VERSION_FOR_TESTS) as? GradleVersion +internal val Project.gradleVersion: GradleVersion get() = overriddenGradleVersionForTests ?: GradleVersion.current() + diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/KotlinTargetResourcesPublicationImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/KotlinTargetResourcesPublicationImpl.kt index 2b1f5bc3c19..085b47ea8f7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/KotlinTargetResourcesPublicationImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/KotlinTargetResourcesPublicationImpl.kt @@ -8,11 +8,13 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.resources import org.gradle.api.Project import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider +import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic +import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnosticOncePerBuild import org.jetbrains.kotlin.gradle.plugin.launchInStage import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget @@ -29,7 +31,7 @@ import java.io.File import javax.inject.Inject internal abstract class KotlinTargetResourcesPublicationImpl @Inject constructor( - val project: Project + private val project: Project, ) : KotlinTargetResourcesPublication { internal data class TargetResources( @@ -126,9 +128,8 @@ internal abstract class KotlinTargetResourcesPublicationImpl @Inject constructor } override fun resolveResources(target: KotlinTarget): Provider { - if (!canResolveResources(target)) { - target.project.reportDiagnostic(KotlinToolingDiagnostics.ResourceMayNotBeResolvedForTarget(target.name)) - } + validateTargetResourcesAreResolvable(target) + validateGradleVersionIsCompatibleWithResolutionStrategy(target.name) val aggregateResourcesTaskName = target.disambiguateName("AggregateResources") project.locateTask(aggregateResourcesTaskName)?.let { @@ -201,12 +202,34 @@ internal abstract class KotlinTargetResourcesPublicationImpl @Inject constructor } } + private fun validateTargetResourcesAreResolvable(target: KotlinTarget) { + if (!canResolveResources(target)) { + target.project.reportDiagnostic(KotlinToolingDiagnostics.ResourceMayNotBeResolvedForTarget(target.name)) + } + } + + private fun validateGradleVersionIsCompatibleWithResolutionStrategy(targetName: String) { + if (project.kotlinPropertiesProvider.mppResourcesResolutionStrategy == KotlinTargetResourcesResolutionStrategy.VariantReselection) { + if (project.gradleVersion < minimumGradleVersionForVariantReselection) { + project.reportDiagnosticOncePerBuild( + KotlinToolingDiagnostics.ResourceMayNotBeResolvedWithGradleVersion( + targetName, + GradleVersion.current().toString(), + minimumGradleVersionForVariantReselection.toString(), + ) + ) + } + } + } + internal companion object { const val MULTIPLATFORM_RESOURCES_DIRECTORY = "kotlin-multiplatform-resources" const val RESOURCES_CLASSIFIER = "kotlin_resources" const val RESOURCES_ZIP_EXTENSION = "${RESOURCES_CLASSIFIER}.zip" const val RESOURCES_PATH = "ResourcesPath" + + val minimumGradleVersionForVariantReselection = GradleVersion.version("7.6") } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/resourcesPublicationExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/resourcesPublicationExtension.kt index 230cd18e9fd..2a0bfe7a544 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/resourcesPublicationExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/resources/resourcesPublicationExtension.kt @@ -16,7 +16,10 @@ internal val KotlinMultiplatformExtension.resourcesPublicationExtension: KotlinT get() { if (!project.kotlinPropertiesProvider.mppResourcesPublication) return null return project.extraProperties.getOrPut(KotlinTargetResourcesPublication.EXTENSION_NAME) { - project.objects.newInstance(KotlinTargetResourcesPublicationImpl::class.java, project) + project.objects.newInstance( + KotlinTargetResourcesPublicationImpl::class.java, + project, + ) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinTargetResourcesPublicationImplTests.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinTargetResourcesPublicationImplTests.kt index 3c61b42f737..624d1753ed2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinTargetResourcesPublicationImplTests.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/KotlinTargetResourcesPublicationImplTests.kt @@ -10,12 +10,15 @@ package org.jetbrains.kotlin.gradle.unitTests import com.android.build.gradle.LibraryExtension import org.gradle.api.Project import org.gradle.api.internal.project.ProjectInternal +import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinTarget import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnosticFactory import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.resources.KotlinTargetResourcesPublication +import org.jetbrains.kotlin.gradle.plugin.mpp.resources.overriddenGradleVersionForTests +import org.jetbrains.kotlin.gradle.plugin.mpp.resources.resolve.KotlinTargetResourcesResolutionStrategy import org.jetbrains.kotlin.gradle.plugin.mpp.resources.resourcesPublicationExtension import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.util.* @@ -164,6 +167,43 @@ class KotlinTargetResourcesPublicationImplTests { } } + @Test + fun `test resolution - emits diagnostic in first resolving project with variant reselection - when Gradle version is below 7_6`() { + val rootProject = buildProjectWithMPP( + projectBuilder = { withName("root") }, + preApplyCode = { + setMppResourcesResolutionStrategy(KotlinTargetResourcesResolutionStrategy.VariantReselection) + overriddenGradleVersionForTests = GradleVersion.version("7.5.1") + }, + ) { kotlin { linuxArm64() } } + val childProject = buildProjectWithMPP( + projectBuilder = { withParent(rootProject).withName("child") }, + preApplyCode = { + setMppResourcesResolutionStrategy(KotlinTargetResourcesResolutionStrategy.VariantReselection) + overriddenGradleVersionForTests = GradleVersion.version("7.5.1") + }, + ) { kotlin { linuxArm64() } } + + childProject.multiplatformExtension.resourcesPublicationExtension?.resolveResources(childProject.multiplatformExtension.linuxArm64()) + rootProject.multiplatformExtension.resourcesPublicationExtension?.resolveResources(rootProject.multiplatformExtension.linuxArm64()) + + childProject.assertContainsDiagnostic(KotlinToolingDiagnostics.ResourceMayNotBeResolvedWithGradleVersion) + rootProject.assertNoDiagnostics(KotlinToolingDiagnostics.ResourceMayNotBeResolvedWithGradleVersion) + } + + @Test + fun `test resolution - doesn't emit diagnostic with variant reselection - when Gradle version is above 7_6`() { + buildProjectWithMPP( + preApplyCode = { overriddenGradleVersionForTests = GradleVersion.version("7.6.1") } + ) { + setMppResourcesResolutionStrategy(KotlinTargetResourcesResolutionStrategy.VariantReselection) + kotlin { + linuxArm64() + resourcesPublicationExtension?.resolveResources(linuxArm64()) + } + }.assertNoDiagnostics() + } + private fun testCallbacksAfterApiCall( callback: ((Unit) -> Unit) -> Unit, apiCall: (Unit) -> Unit,