[MPP] Report deprecation warnings for HMPP-related Gradle properties

KT-55891
This commit is contained in:
Pavel Kirpichenkov
2023-01-17 13:58:33 +02:00
committed by Space Team
parent 4e13b7a202
commit ec5f56584c
6 changed files with 112 additions and 4 deletions
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2023 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.mpp
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.*
import kotlin.io.path.appendText
import kotlin.test.assertFalse
import kotlin.test.assertTrue
@MppGradlePluginTests
class MppDeprecatedPropertiesIt : KGPBaseTest() {
@GradleTest
fun testDeprecations(gradleVersion: GradleVersion) {
project("mppDeprecatedProperties", gradleVersion) {
checkDeprecations(isDeprecationExpected = false)
this.gradleProperties.appendText(
defaultFlags.entries.joinToString(
prefix = System.lineSeparator(),
postfix = System.lineSeparator(),
separator = System.lineSeparator(),
) { (prop, value) -> "$prop=$value" }
)
checkDeprecations(isDeprecationExpected = true)
}
}
private fun TestProject.checkDeprecations(isDeprecationExpected: Boolean) {
build {
val assert: (Boolean, String) -> Unit = if (isDeprecationExpected) ::assertTrue else ::assertFalse
val warnings = output.lines().filter { it.startsWith("w:") }.toSet()
defaultFlags.keys.forEach { flag ->
assert(
warnings.any { warning -> Regex(".*$flag.*is deprecated.*").matches(warning) },
"A deprecation warning for the '$flag' should have been reported",
)
}
}
}
private val defaultFlags: Map<String, String>
get() = mapOf(
"kotlin.mpp.enableGranularSourceSetsMetadata" to "true",
"kotlin.mpp.enableCompatibilityMetadataVariant" to "false",
"kotlin.internal.mpp.hierarchicalStructureByDefault" to "true",
"kotlin.mpp.hierarchicalStructureSupport" to "true",
"kotlin.native.enableDependencyPropagation" to "false",
)
}
@@ -0,0 +1,7 @@
plugins {
kotlin("multiplatform")
}
kotlin {
jvm()
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLI
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION_1_NO_WARN
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_INTRANSITIVE_METADATA_CONFIGURATION
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION
@@ -216,7 +217,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
val enableCompatibilityMetadataVariant: Boolean
get() {
return (booleanProperty("kotlin.mpp.enableCompatibilityMetadataVariant") ?: !mppHierarchicalStructureByDefault)
return (booleanProperty(KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT) ?: !mppHierarchicalStructureByDefault)
}
val enableKotlinToolingMetadataArtifact: Boolean
@@ -522,7 +523,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
* 1. Project properties (-P, gradle.properties, etc...)
* 2. `local.properties`
*/
private fun property(propName: String): String? =
internal fun property(propName: String): String? =
if (project.hasProperty(propName)) {
project.property(propName) as? String
} else {
@@ -549,6 +550,7 @@ internal class PropertiesProvider private constructor(private val project: Proje
const val KOTLIN_STDLIB_DEFAULT_DEPENDENCY = "kotlin.stdlib.default.dependency"
const val KOTLIN_STDLIB_JDK_VARIANTS_VERSION_ALIGNMENT = "kotlin.stdlib.jdk.variants.version.alignment"
const val KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA = "kotlin.mpp.enableGranularSourceSetsMetadata"
const val KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT = "kotlin.mpp.enableCompatibilityMetadataVariant"
const val KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION = "kotlin.mpp.enableCInteropCommonization"
const val KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT = "kotlin.internal.mpp.hierarchicalStructureByDefault"
const val KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT = "kotlin.mpp.hierarchicalStructureSupport"
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.gradle.plugin.ide.kotlinIdeMultiplatformImport
import org.jetbrains.kotlin.gradle.plugin.ide.locateOrRegisterIdeResolveDependenciesTask
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin.Companion.sourceSetFreeCompilerArgsPropertyName
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.addBuildListenerForXcode
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.checkAndReportDeprecatedMppProperties
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.checkAndReportDeprecatedNativeTargets
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.handleHierarchicalStructureFlagsMigration
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
@@ -49,6 +50,7 @@ class KotlinMultiplatformPlugin : Plugin<Project> {
override fun apply(project: Project) {
checkGradleCompatibility("the Kotlin Multiplatform plugin", GradleVersion.version("6.0"))
checkAndReportDeprecatedMppProperties(project)
handleHierarchicalStructureFlagsMigration(project)
checkAndReportDeprecatedNativeTargets(project)
@@ -7,8 +7,16 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.internal
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_DEPENDENCY_PROPAGATION
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
import org.jetbrains.kotlin.gradle.utils.hasSyncErrors
import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheckWhenEvaluated
import org.jetbrains.kotlin.konan.target.KonanTarget
@@ -22,4 +30,35 @@ internal fun checkAndReportDeprecatedNativeTargets(project: Project) {
"w: The following deprecated kotlin native targets were used in the project: ${usedDeprecatedTargets.joinToString { it.targetName }}"
)
}
}
}
/**
* Declared properties have to be captured during plugin application phase before the HMPP migration util sets them.
* Warnings have to be reported only for successfully evaluated projects without errors.
*/
internal fun checkAndReportDeprecatedMppProperties(project: Project) {
val projectProperties = project.kotlinPropertiesProvider
val warnings = deprecatedMppProperties.mapNotNull { propertyName ->
projectProperties.property(propertyName)?.let { getMppDeprecationWarningMessageForProperty(propertyName) }
}
project.whenEvaluated {
if (!project.hasSyncErrors()) {
warnings.forEach { message ->
SingleWarningPerBuild.show(project, message)
}
}
}
}
internal val deprecatedMppProperties: List<String> = listOf(
KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT,
KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA,
KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT,
KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT,
KOTLIN_NATIVE_DEPENDENCY_PROPAGATION,
)
internal fun getMppDeprecationWarningMessageForProperty(property: String): String =
"w: The property '$property' is deprecated and is scheduled for removal in the stable Kotlin Multiplatform."
@@ -60,13 +60,16 @@ import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
*/
internal inline fun Project.runProjectConfigurationHealthCheck(check: Project.() -> Unit) {
/* Running configuration checks on a failed project will only lead to false positive error messages */
if (state.failure != null || (inLenientMode() && syncExceptionsAreNotEmpty())) {
if (project.hasSyncErrors()) {
return
}
check()
}
internal fun Project.hasSyncErrors(): Boolean =
state.failure != null || (inLenientMode() && syncExceptionsAreNotEmpty())
// ClassPathModeExceptionCollector is available only via 'gradleKotlinDsl()' dependency which brings in full Gradle jar
private fun Project.syncExceptionsAreNotEmpty(): Boolean {
val classPathModeExceptionCollectionClass = Class.forName("org.gradle.kotlin.dsl.provider.ClassPathModeExceptionCollector")