[Gradle] deprecate android and introduce androidTarget preset

Android preset needs to be removed in favor of Android Pluggable Target

Changes were originally introduced by commit:
becf50ee0f
but then, unfortunately, reverted due to binary compatibility issues

^KT-59049 Verification Pending
^KT-57903 Verification Pending
This commit is contained in:
Anton Lakotka
2023-06-02 18:55:25 +02:00
committed by Space Team
parent 5a8b6e9603
commit e5d35f7d1a
4 changed files with 131 additions and 42 deletions
@@ -20,9 +20,7 @@ private val presetsProperty = KotlinTargetsContainerWithPresets::presets.name
private fun generateKotlinTargetContainerWithPresetFunctionsInterface() {
// Generate KotlinMultiplatformExtension subclass with member functions for the presets:
val functions = allPresetEntries.map { kotlinPreset ->
// magic indent is needed to make the result look pretty
val funPrefix = kotlinPreset.deprecation?.let { "\n $it\n @Suppress(\"DEPRECATION_ERROR\")\n " } ?: ""
generatePresetFunctions(kotlinPreset, presetsProperty, "configureOrCreate", funPrefix)
generatePresetFunctions(kotlinPreset, presetsProperty, "configureOrCreate")
}
val parentInterfaceName =
@@ -45,10 +43,13 @@ private fun generateKotlinTargetContainerWithPresetFunctionsInterface() {
val generatedCodeWarning = "// DO NOT EDIT MANUALLY! Generated by ${object {}.javaClass.enclosingClass.name}"
val extraTopLevelDeclarations = allPresetEntries.flatMap { it.extraTopLevelDeclarations }.joinToString("\n")
val code = listOf(
"package ${className.packageName()}",
imports,
generatedCodeWarning,
extraTopLevelDeclarations,
"interface ${className.renderShort()} : ${parentInterfaceName.renderShort()} {",
functions.joinToString("\n\n") { it.indented(4) },
"}"
@@ -62,23 +63,59 @@ private fun generatePresetFunctions(
presetEntry: KotlinPresetEntry,
getPresetsExpression: String,
configureOrCreateFunctionName: String,
funPrefix: String = ""
): String {
fun deprecated(replaceWithArguments: List<String>? = null): String {
val deprecation = presetEntry.deprecation ?: return ""
val deprecationAnnotation = if (deprecation.replaceWithOtherPreset != null && replaceWithArguments != null) {
val replaceWith = "ReplaceWith(\"${deprecation.replaceWithOtherPreset}(${replaceWithArguments.joinToString(",")})\")"
"@Deprecated(${deprecation.message}, level = DeprecationLevel.${deprecation.level.name}, replaceWith = $replaceWith)"
} else {
"@Deprecated(${deprecation.message}, level = DeprecationLevel.${deprecation.level.name})"
}
// magic indent is needed to make the result look pretty
return "\n $deprecationAnnotation\n "
}
val suppress = if (presetEntry.deprecation != null) {
val suppressDeprecationId = when (presetEntry.deprecation.level) {
DeprecationLevel.WARNING -> "DEPRECATION"
DeprecationLevel.ERROR -> "DEPRECATION_ERROR"
DeprecationLevel.HIDDEN -> "DEPRECATION_HIDDEN"
}
"@Suppress(\"$suppressDeprecationId\")\n "
} else {
""
}
val alsoBlockAfterConfiguration = if (presetEntry.alsoBlockAfterConfiguration != null) {
"""
.also {
${presetEntry.alsoBlockAfterConfiguration.indented(16, skipFirstLine = true)}
}
""".trimIndent().indented(8, skipFirstLine = true)
} else {
""
}
val presetName = presetEntry.presetName
val entityName = presetEntry.entityName
return """
${funPrefix}fun $presetName(
name: String = "$presetName",
${deprecated()}fun $presetName(
name: String = "$entityName",
configure: ${presetEntry.targetType.renderShort()}.() -> Unit = { }
): ${presetEntry.targetType.renderShort()} =
$configureOrCreateFunctionName(
name,
$getPresetsExpression.getByName("$presetName") as ${presetEntry.presetType.renderShort()},
$getPresetsExpression.getByName("$entityName") as ${presetEntry.presetType.renderShort()},
configure
)
)$alsoBlockAfterConfiguration
${funPrefix}fun $presetName() = $presetName("$presetName") { }
${funPrefix}fun $presetName(name: String) = $presetName(name) { }
${funPrefix}fun $presetName(name: String, configure: Action<${presetEntry.targetType.renderShort()}>) = $presetName(name) { configure.execute(this) }
${funPrefix}fun $presetName(configure: Action<${presetEntry.targetType.renderShort()}>) = $presetName { configure.execute(this) }
${deprecated(emptyList())}${suppress}fun $presetName() = $presetName("$entityName") { }
${deprecated(listOf("name"))}${suppress}fun $presetName(name: String) = $presetName(name) { }
${deprecated()}${suppress}fun $presetName(name: String, configure: Action<${presetEntry.targetType.renderShort()}>) = $presetName(name) { configure.execute(this) }
${deprecated()}${suppress}fun $presetName(configure: Action<${presetEntry.targetType.renderShort()}>) = $presetName { configure.execute(this) }
""".trimIndent()
}
@@ -15,8 +15,19 @@ internal class KotlinPresetEntry(
val presetName: String,
val presetType: TypeName,
val targetType: TypeName,
val deprecation: String? = null
)
val deprecation: Deprecation? = null,
val entityName: String = presetName,
// Adds `.also { $alsoBlockAfterConfiguration }` after configureOrCreate(...)
val alsoBlockAfterConfiguration: String? = null,
// Extra declarations will be inserted before functions are generated
val extraTopLevelDeclarations: List<String> = emptyList(),
) {
class Deprecation(
val message: String,
val level: DeprecationLevel,
val replaceWithOtherPreset: String? = null // when set, it will generate ReplaceWith with related argument names
)
}
internal fun KotlinPresetEntry.typeNames(): Set<TypeName> = setOf(presetType, targetType)
@@ -42,10 +53,34 @@ internal val jvmPresetEntry = KotlinPresetEntry(
typeName("org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget")
)
internal val androidTargetPresetEntry = KotlinPresetEntry(
"androidTarget",
typeName("$MPP_PACKAGE.KotlinAndroidTargetPreset"),
typeName("$MPP_PACKAGE.KotlinAndroidTarget"),
entityName = "android",
)
internal val androidPresetEntry = KotlinPresetEntry(
"android",
typeName("$MPP_PACKAGE.KotlinAndroidTargetPreset"),
typeName("$MPP_PACKAGE.KotlinAndroidTarget")
typeName("$MPP_PACKAGE.KotlinAndroidTarget"),
deprecation = KotlinPresetEntry.Deprecation(
message = "ANDROID_TARGET_MIGRATION_MESSAGE",
level = DeprecationLevel.WARNING,
replaceWithOtherPreset = "androidTarget"
),
extraTopLevelDeclarations = listOf(
"private const val ANDROID_TARGET_MIGRATION_MESSAGE" +
" = \"Please use androidTarget() instead. Learn more here: https://kotl.in/android-target-dsl\""
),
alsoBlockAfterConfiguration = """
it.project.logger.warn(
""${'"'}
w: Please use `androidTarget` function instead of `android` to configure android target inside `kotlin { }` block.
See the details here: https://kotl.in/android-target-dsl
""${'"'}.trimIndent()
)
""".trimIndent()
)
// Note: modifying these sets should also be reflected in the MPP plugin code, see 'setupDefaultPresets'
@@ -75,12 +110,16 @@ internal val nativePresetEntries = HostManager().targets
else ->
Presets.simple to Targets.base
}
val deprecation = "@Deprecated(DEPRECATED_TARGET_MESSAGE, level = DeprecationLevel.ERROR)".takeIf { target in KonanTarget.deprecatedTargets }
val deprecation = KotlinPresetEntry.Deprecation(
message = "DEPRECATED_TARGET_MESSAGE",
level = DeprecationLevel.ERROR
).takeIf { target in KonanTarget.deprecatedTargets }
KotlinPresetEntry(target.presetName, typeName(presetType), typeName(targetType), deprecation)
}
internal val allPresetEntries = listOf(
jvmPresetEntry,
androidTargetPresetEntry,
androidPresetEntry
) + nativePresetEntries