[Gradle] Implement KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected diagnostic

^KT-58676 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-06-23 19:13:07 +02:00
committed by Space Team
parent 8d6c4019c5
commit 4d91229d79
7 changed files with 185 additions and 5 deletions
@@ -8,6 +8,7 @@
package org.jetbrains.kotlin.gradle.dsl
import org.gradle.api.Action
import org.jetbrains.kotlin.gradle.dsl.NativeTargetShortcutTrace.Companion.nativeTargetShortcutTrace
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet.Companion.COMMON_MAIN_
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet.Companion.COMMON_TEST_SOURCE_SET_NAME
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetContainer
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.tooling.core.extrasReadWriteProperty
private const val SHORTCUTS_DEPRECATION_MESSAGE = "Use applyDefaultHierarchyTemplate() instead. " +
@@ -52,12 +54,22 @@ interface KotlinTargetContainerWithNativeShortcuts : KotlinTargetContainerWithPr
}
private fun createIntermediateSourceSets(
trace: NativeTargetShortcutTrace,
namePrefix: String,
children: List<DefaultSourceSets>,
parent: DefaultSourceSets? = null,
): DefaultSourceSets {
val main = createIntermediateSourceSet("${namePrefix}Main", children.map { it.main }, parent?.main)
val test = createIntermediateSourceSet("${namePrefix}Test", children.map { it.test }, parent?.test)
main.nativeTargetShortcutTrace = trace
test.nativeTargetShortcutTrace = trace
children.forEach { child ->
child.main.nativeTargetShortcutTrace = trace
child.test.nativeTargetShortcutTrace = trace
}
return DefaultSourceSets(main, test)
}
@@ -70,7 +82,9 @@ interface KotlinTargetContainerWithNativeShortcuts : KotlinTargetContainerWithPr
iosArm64("${namePrefix}Arm64"),
iosX64("${namePrefix}X64")
)
createIntermediateSourceSets(namePrefix, targets.defaultSourceSets(), mostCommonSourceSets())
createIntermediateSourceSets(
NativeTargetShortcutTrace("ios"), namePrefix, targets.defaultSourceSets(), mostCommonSourceSets()
)
targets.forEach { it.configure() }
}
@@ -108,7 +122,10 @@ interface KotlinTargetContainerWithNativeShortcuts : KotlinTargetContainerWithPr
tvosArm64("${namePrefix}Arm64"),
tvosX64("${namePrefix}X64")
)
createIntermediateSourceSets(namePrefix, targets.defaultSourceSets(), mostCommonSourceSets())
createIntermediateSourceSets(
NativeTargetShortcutTrace("tvos"),
namePrefix, targets.defaultSourceSets(), mostCommonSourceSets()
)
targets.forEach { it.configure() }
}
@@ -149,12 +166,16 @@ interface KotlinTargetContainerWithNativeShortcuts : KotlinTargetContainerWithPr
val simulatorX64 = watchosX64("${namePrefix}X64")
val deviceTargets = listOf(device32, device64)
val trace = NativeTargetShortcutTrace("watchos")
val deviceSourceSets = createIntermediateSourceSets(
trace,
"${namePrefix}Device",
deviceTargets.defaultSourceSets()
)
createIntermediateSourceSets(
trace,
namePrefix,
listOf(deviceSourceSets, simulatorX64.defaultSourceSets()),
mostCommonSourceSets()
@@ -192,3 +213,9 @@ interface KotlinTargetContainerWithNativeShortcuts : KotlinTargetContainerWithPr
@Deprecated(SHORTCUTS_DEPRECATION_MESSAGE)
fun watchos(configure: Action<KotlinNativeTarget>) = watchos { configure.execute(this) }
}
internal class NativeTargetShortcutTrace(val shortcut: String) : Throwable() {
companion object {
var KotlinSourceSet.nativeTargetShortcutTrace by extrasReadWriteProperty<NativeTargetShortcutTrace>()
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.diagnostics
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.KotlinSourceSetConvention.isRegisteredByKotlinSourceSetConventionAt
import org.jetbrains.kotlin.gradle.dsl.NativeTargetShortcutTrace
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
@@ -464,6 +465,33 @@ object KotlinToolingDiagnostics {
)
}
object KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected : ToolingDiagnosticFactory(WARNING) {
internal operator fun invoke(project: Project, trace: NativeTargetShortcutTrace) = build(
"""
The Default Kotlin Hierarchy was not applied to '${project.displayName}':
Deprecated '${trace.shortcut}()' shortcut was used:
kotlin {
${trace.shortcut}()
}
Could be replaced by declaring the supported ${trace.shortcut} targets directly:
kotlin {
${trace.shortcut}X64()
${trace.shortcut}Arm64()
${trace.shortcut}SimulatorArm64() /* <- Note: Was not previously applied */
/* ... */
}
To suppress the 'Default Hierarchy Template' add
'$KOTLIN_MPP_APPLY_DEFAULT_HIERARCHY_TEMPLATE=false'
to your gradle.properties
""".trimIndent(),
throwable = trace
)
}
object KotlinDefaultHierarchyFallbackIllegalTargetNames : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(project: Project, illegalTargetNamesUsed: Iterable<String>) = build(
"""
@@ -6,15 +6,19 @@
package org.jetbrains.kotlin.gradle.plugin.hierarchy
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.NativeTargetShortcutTrace.Companion.nativeTargetShortcutTrace
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin.Companion.dynamicallyApplyWhenAndroidPluginIsApplied
import org.jetbrains.kotlin.gradle.plugin.KotlinHierarchyTemplate
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.FinaliseRefinesEdges
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinDefaultHierarchyFallbackDependsOnUsageDetected
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinDefaultHierarchyFallbackIllegalTargetNames
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected
import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
import org.jetbrains.kotlin.gradle.plugin.requiredStage
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
internal suspend fun Project.setupDefaultKotlinHierarchy() = requiredStage(FinaliseRefinesEdges) setup@{
@@ -29,6 +33,23 @@ internal suspend fun Project.setupDefaultKotlinHierarchy() = requiredStage(Final
return@setup
}
/*
User used ios(), tvos(), ... shortcuts.
This will be incompatible with the default template, as it sets dependsOn edges.
We detect this case manually to give even better diagnostic
*/
run check@{
extension.sourceSets
.mapNotNull { it.nativeTargetShortcutTrace }
.toSet()
.ifEmpty { return@check }
.onEach { trace -> project.reportDiagnostic(KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected(project, trace)) }
setupPreMultiplatformStableDefaultDependsOnEdges()
return@setup
}
/*
User manually added a .dependsOn:
We fall back to the old behaviour and add the commonMain/commonTest default edges
@@ -15,6 +15,8 @@ import org.jetbrains.kotlin.gradle.plugin.launchInStage
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
import org.jetbrains.kotlin.gradle.util.checkDiagnostics
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
import org.jetbrains.kotlin.konan.target.HostManager
import org.junit.Assume
import kotlin.test.Test
class DefaultHierarchySetupDiagnosticTest {
@@ -44,4 +46,49 @@ class DefaultHierarchySetupDiagnosticTest {
project.checkDiagnostics("KotlinDefaultHierarchyFallbackIllegalTargetNames")
}
}
}
@Test
fun `test - warning - ios shortcut`() {
Assume.assumeTrue(HostManager.hostIsMac)
buildProjectWithMPP().runLifecycleAwareTest {
val kotlin = multiplatformExtension
@Suppress("DEPRECATION")
kotlin.ios()
project.launchInStage(KotlinPluginLifecycle.Stage.ReadyForExecution) {
project.checkDiagnostics("KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected-ios")
}
}
}
@Test
fun `test - warning - watchos shortcut`() {
Assume.assumeTrue(HostManager.hostIsMac)
buildProjectWithMPP().runLifecycleAwareTest {
val kotlin = multiplatformExtension
@Suppress("DEPRECATION")
kotlin.watchos()
project.launchInStage(KotlinPluginLifecycle.Stage.ReadyForExecution) {
project.checkDiagnostics("KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected-watchos")
}
}
}
@Test
fun `test - warning - tvos shortcut`() {
Assume.assumeTrue(HostManager.hostIsMac)
buildProjectWithMPP().runLifecycleAwareTest {
val kotlin = multiplatformExtension
@Suppress("DEPRECATION")
kotlin.tvos()
project.launchInStage(KotlinPluginLifecycle.Stage.ReadyForExecution) {
project.checkDiagnostics("KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected-tvos")
}
}
}
}
@@ -0,0 +1,19 @@
[KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected | WARNING] The Default Kotlin Hierarchy was not applied to 'root project 'test'':
Deprecated 'ios()' shortcut was used:
kotlin {
ios()
}
Could be replaced by declaring the supported ios targets directly:
kotlin {
iosX64()
iosArm64()
iosSimulatorArm64() /* <- Note: Was not previously applied */
/* ... */
}
To suppress the 'Default Hierarchy Template' add
'kotlin.mpp.applyDefaultHierarchyTemplate=false'
to your gradle.properties
@@ -0,0 +1,19 @@
[KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected | WARNING] The Default Kotlin Hierarchy was not applied to 'root project 'test'':
Deprecated 'tvos()' shortcut was used:
kotlin {
tvos()
}
Could be replaced by declaring the supported tvos targets directly:
kotlin {
tvosX64()
tvosArm64()
tvosSimulatorArm64() /* <- Note: Was not previously applied */
/* ... */
}
To suppress the 'Default Hierarchy Template' add
'kotlin.mpp.applyDefaultHierarchyTemplate=false'
to your gradle.properties
@@ -0,0 +1,19 @@
[KotlinDefaultHierarchyFallbackNativeTargetShortcutUsageDetected | WARNING] The Default Kotlin Hierarchy was not applied to 'root project 'test'':
Deprecated 'watchos()' shortcut was used:
kotlin {
watchos()
}
Could be replaced by declaring the supported watchos targets directly:
kotlin {
watchosX64()
watchosArm64()
watchosSimulatorArm64() /* <- Note: Was not previously applied */
/* ... */
}
To suppress the 'Default Hierarchy Template' add
'kotlin.mpp.applyDefaultHierarchyTemplate=false'
to your gradle.properties