[Gradle] Migrate warning about missing Android-target to new infra
This commit is contained in:
-31
@@ -38,37 +38,6 @@ internal fun Project.runMissingKotlinTargetsProjectConfigurationHealthCheck() =
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Project.runMissingAndroidTargetProjectConfigurationHealthCheck(
|
||||
warningLogger: (warningMessage: String) -> Unit = project.logger::warn
|
||||
) = project.runProjectConfigurationHealthCheck check@{
|
||||
if (project.kotlinPropertiesProvider.ignoreAbsentAndroidMultiplatformTarget) {
|
||||
return@check
|
||||
}
|
||||
|
||||
val androidPluginId = findAppliedAndroidPluginIdOrNull() ?: return@check
|
||||
|
||||
if (findAndroidTarget() != null) return@check
|
||||
|
||||
warningLogger(
|
||||
"""
|
||||
Missing 'androidTarget()' Kotlin target in multiplatform project ${project.name} (${project.path})'.
|
||||
The Android Gradle plugin was applied without creating a corresponding 'androidTarget()' Kotlin Target:
|
||||
|
||||
```
|
||||
plugins {
|
||||
id("$androidPluginId")
|
||||
kotlin("multiplatform")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
androidTarget() // <-- please register this Android target
|
||||
}
|
||||
```
|
||||
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
internal fun Project.runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck(
|
||||
warningLogger: (warningMessage: String) -> Unit = project.logger::warn
|
||||
) {
|
||||
|
||||
-1
@@ -387,7 +387,6 @@ abstract class AbstractKotlinMultiplatformPluginWrapper : KotlinBasePluginWrappe
|
||||
get() = KotlinMultiplatformExtension::class
|
||||
|
||||
override fun whenBuildEvaluated(project: Project) {
|
||||
project.runMissingAndroidTargetProjectConfigurationHealthCheck()
|
||||
project.runMissingKotlinTargetsProjectConfigurationHealthCheck()
|
||||
project.runDisabledCInteropCommonizationOnHmppProjectConfigurationHealthCheck()
|
||||
}
|
||||
|
||||
+2
-1
@@ -99,7 +99,8 @@ internal interface KotlinGradleProjectChecker {
|
||||
MissingNativeStdlibChecker,
|
||||
UnusedSourceSetsChecker,
|
||||
AndroidSourceSetLayoutV1SourceSetsNotFoundChecker,
|
||||
TargetsWithAmbiguousConsumableConfigurationsChecker
|
||||
TargetsWithAmbiguousConsumableConfigurationsChecker,
|
||||
AndroidPluginWithoutAndroidTargetChecker
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+20
@@ -220,4 +220,24 @@ object KotlinToolingDiagnostics {
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
object AndroidTargetIsMissing : ToolingDiagnosticFactory(WARNING) {
|
||||
operator fun invoke(projectName: String, projectPath: String, androidPluginId: String) = build(
|
||||
"""
|
||||
Missing 'androidTarget()' Kotlin target in multiplatform project '$projectName ($projectPath)'.
|
||||
The Android Gradle plugin was applied without creating a corresponding 'android()' Kotlin Target:
|
||||
|
||||
```
|
||||
plugins {
|
||||
id("$androidPluginId")
|
||||
kotlin("multiplatform")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
androidTarget() // <-- please register this Android target
|
||||
}
|
||||
```
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.plugin.diagnostics.checkers
|
||||
|
||||
import org.jetbrains.kotlin.gradle.plugin.configurationResult
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectCheckerContext
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector
|
||||
import org.jetbrains.kotlin.gradle.targets.android.findAndroidTarget
|
||||
import org.jetbrains.kotlin.gradle.utils.findAppliedAndroidPluginIdOrNull
|
||||
|
||||
internal object AndroidPluginWithoutAndroidTargetChecker : KotlinGradleProjectChecker {
|
||||
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
|
||||
project.configurationResult.await()
|
||||
if (multiplatformExtension == null || kotlinPropertiesProvider.ignoreAbsentAndroidMultiplatformTarget) return
|
||||
|
||||
val androidPluginId = project.findAppliedAndroidPluginIdOrNull() ?: return
|
||||
if (project.findAndroidTarget() != null) return
|
||||
collector.reportOncePerGradleProject(
|
||||
project,
|
||||
KotlinToolingDiagnostics.AndroidTargetIsMissing(project.name, project.path, androidPluginId)
|
||||
)
|
||||
}
|
||||
}
|
||||
+47
-52
@@ -8,84 +8,79 @@
|
||||
package org.jetbrains.kotlin.gradle.regressionTests
|
||||
|
||||
import com.android.build.gradle.LibraryExtension
|
||||
import org.jetbrains.kotlin.gradle.util.MultiplatformExtensionTest
|
||||
import org.jetbrains.kotlin.gradle.plugin.runMissingAndroidTargetProjectConfigurationHealthCheck
|
||||
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
|
||||
import org.jetbrains.kotlin.gradle.targets.android.findAndroidTarget
|
||||
import org.jetbrains.kotlin.gradle.util.propertiesExtension
|
||||
import org.jetbrains.kotlin.gradle.util.*
|
||||
import org.jetbrains.kotlin.gradle.util.assertNoDiagnostics
|
||||
import org.junit.Test
|
||||
import kotlin.test.*
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertSame
|
||||
|
||||
class KT41641AbsentAndroidTarget : MultiplatformExtensionTest() {
|
||||
|
||||
@Test
|
||||
fun `test android plugin without android target`() {
|
||||
project.plugins.apply("kotlin-multiplatform")
|
||||
project.plugins.apply("android-library")
|
||||
|
||||
/* Arbitrary minimal Android setup */
|
||||
val android = project.extensions.getByName("android") as LibraryExtension
|
||||
android.compileSdk = 31
|
||||
|
||||
kotlin.jvm()
|
||||
|
||||
defaultSetupWithoutAndroidTarget()
|
||||
/* Previously failed with 'Collection is empty.' */
|
||||
assertNull(project.findAndroidTarget())
|
||||
assertSame(kotlin.androidTarget(), project.findAndroidTarget())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test runMissingAndroidTargetProjectConfigurationHealthCheck`() {
|
||||
project.plugins.apply("kotlin-multiplatform")
|
||||
project.plugins.apply("android-library")
|
||||
|
||||
/* Arbitrary minimal Android setup */
|
||||
val android = project.extensions.getByName("android") as LibraryExtension
|
||||
android.compileSdk = 31
|
||||
|
||||
kotlin.jvm()
|
||||
fun `test runMissingAndroidTargetProjectConfigurationHealthCheck - warning`() {
|
||||
defaultSetupWithoutAndroidTarget()
|
||||
|
||||
// Missing android target -> expect warning message
|
||||
var warningMessage: String? = null
|
||||
project.runMissingAndroidTargetProjectConfigurationHealthCheck(warningLogger = { warningMessage = it })
|
||||
assertNotNull(warningMessage, "Expected warning message to be logged")
|
||||
|
||||
// Present android target -> expect no warning message anymore
|
||||
kotlin.androidTarget()
|
||||
project.runMissingAndroidTargetProjectConfigurationHealthCheck(warningLogger = {
|
||||
fail("Expected no warning message to be logged. Received: $it")
|
||||
})
|
||||
project.evaluate()
|
||||
project.assertContainsDiagnostic(KotlinToolingDiagnostics.AndroidTargetIsMissing)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test kotlin-mpp-absentAndroidTarget-nowarn flag`() {
|
||||
fun `test runMissingAndroidTargetProjectConfigurationHealthCheck - no warning`() {
|
||||
defaultSetupWithoutAndroidTarget()
|
||||
kotlin.androidTarget()
|
||||
|
||||
// Present android target -> expect no warning message anymore
|
||||
project.evaluate()
|
||||
project.assertNoDiagnostics()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test kotlin-mpp-absentAndroidTarget-nowarn flag set to true`() {
|
||||
defaultSetupWithoutAndroidTarget()
|
||||
project.propertiesExtension["kotlin.mpp.absentAndroidTarget.nowarn"] = "true"
|
||||
|
||||
project.evaluate()
|
||||
project.assertNoDiagnostics()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test kotlin-mpp-absentAndroidTarget-nowarn flag set to false`() {
|
||||
defaultSetupWithoutAndroidTarget()
|
||||
project.propertiesExtension["kotlin.mpp.absentAndroidTarget.nowarn"] = null
|
||||
|
||||
project.evaluate()
|
||||
project.assertContainsDiagnostic(KotlinToolingDiagnostics.AndroidTargetIsMissing)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test kotlin-mpp-absentAndroidTarget-nowarn flag set to null`() {
|
||||
defaultSetupWithoutAndroidTarget()
|
||||
project.propertiesExtension["kotlin.mpp.absentAndroidTarget.nowarn"] = null
|
||||
|
||||
project.evaluate()
|
||||
project.assertContainsDiagnostic(KotlinToolingDiagnostics.AndroidTargetIsMissing)
|
||||
}
|
||||
|
||||
private fun defaultSetupWithoutAndroidTarget() {
|
||||
project.plugins.apply("kotlin-multiplatform")
|
||||
project.plugins.apply("android-library")
|
||||
|
||||
/* Arbitrary minimal Android setup */
|
||||
val android = project.extensions.getByName("android") as LibraryExtension
|
||||
android.compileSdk = 31
|
||||
|
||||
kotlin.jvm()
|
||||
|
||||
project.runMissingAndroidTargetProjectConfigurationHealthCheck(warningLogger = {
|
||||
fail("Expected no warning message to be logged. Received $it")
|
||||
})
|
||||
|
||||
// Test when nowarn is set to false
|
||||
run {
|
||||
var warningMessage: String? = null
|
||||
project.propertiesExtension["kotlin.mpp.absentAndroidTarget.nowarn"] = "false"
|
||||
project.runMissingAndroidTargetProjectConfigurationHealthCheck(warningLogger = { warningMessage = it })
|
||||
assertNotNull(warningMessage, "Expected warning message to be logged")
|
||||
}
|
||||
|
||||
// Test when nowarn is set to null
|
||||
run {
|
||||
var warningMessage: String? = null
|
||||
project.propertiesExtension["kotlin.mpp.absentAndroidTarget.nowarn"] = null
|
||||
project.runMissingAndroidTargetProjectConfigurationHealthCheck(warningLogger = { warningMessage = it })
|
||||
assertNotNull(warningMessage, "Expected warning message to be logged")
|
||||
}
|
||||
project.setMultiplatformAndroidSourceSetLayoutVersion(2)
|
||||
}
|
||||
}
|
||||
|
||||
+17
-4
@@ -68,15 +68,29 @@ internal fun Project.assertNoDiagnostics() {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that diagnostic with [factory.id] is reported. The exact parameters (if any)
|
||||
* are ignored. If you need to compare the parameters, refer to the overload accepting [ToolingDiagnostic]
|
||||
*/
|
||||
internal fun Project.assertContainsDiagnostic(factory: ToolingDiagnosticFactory) {
|
||||
kotlinToolingDiagnosticsCollector.getDiagnosticsForProject(this).assertContainsDiagnostic(factory)
|
||||
}
|
||||
|
||||
internal fun Project.assertContainsDiagnostic(diagnostic: ToolingDiagnostic) {
|
||||
kotlinToolingDiagnosticsCollector.getDiagnosticsForProject(this).assertContainsDiagnostic(diagnostic)
|
||||
}
|
||||
|
||||
internal fun Collection<ToolingDiagnostic>.assertContainsDiagnostic(factory: ToolingDiagnosticFactory) {
|
||||
if (!any { it.id == factory.id }) failDiagnosticNotFound("diagnostic with id ${factory.id} ", this)
|
||||
}
|
||||
|
||||
internal fun Collection<ToolingDiagnostic>.assertContainsDiagnostic(diagnostic: ToolingDiagnostic) {
|
||||
if (diagnostic !in this) failDiagnosticNotFound("diagnostic $diagnostic\n", this)
|
||||
}
|
||||
|
||||
private fun failDiagnosticNotFound(diagnosticDescription: String, notFoundInCollection: Collection<ToolingDiagnostic>) {
|
||||
fun Any.withIndent() = this.toString().prependIndent(" ")
|
||||
if (diagnostic !in this) {
|
||||
fail("Missing diagnostic\n${diagnostic.withIndent()} \nin:\n${this.render().withIndent()}")
|
||||
}
|
||||
fail("Missing ${diagnosticDescription}in:\n${notFoundInCollection.render().withIndent()}")
|
||||
}
|
||||
|
||||
internal fun Project.assertNoDiagnostics(id: String) {
|
||||
@@ -100,4 +114,3 @@ private val expectedDiagnosticsRoot: Path
|
||||
get() = resourcesRoot.resolve("expectedDiagnostics")
|
||||
|
||||
private fun expectedDiagnosticsFile(projectName: String): File = expectedDiagnosticsRoot.resolve("$projectName.txt").toFile()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user