[Gradle] Implement AndroidSourceSetLayoutV1SourceSetsNotFoundChecker...

... in order to provide better guidance for projects
migrating to Multiplatform/SourceSetLayout v2 which will suffer from
`UnknownDomainObjectException` when requesting old Android source sets
like

```
sourceSets.getByName("androidTest") // renamed to androidUnitTest
sourceSets.getByName("androidAndroidTest") // renamed to androidInstrumentedTest
```

^KT-58488 Verification Pending
This commit is contained in:
Sebastian Sellmair
2023-05-11 10:47:17 +02:00
committed by Space Team
parent 25c0725da9
commit 484863d8c6
3 changed files with 60 additions and 4 deletions
@@ -10,10 +10,7 @@ import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.CommonMainWithDependsOnChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.DeprecatedKotlinNativeTargetsChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.MissingNativeStdlibChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.UnusedSourceSetsChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.*
/**
* Interface for generic checks of a Gradle Project with any Kotlin Gradle Plugin applied.
@@ -101,6 +98,7 @@ internal interface KotlinGradleProjectChecker {
DeprecatedKotlinNativeTargetsChecker,
MissingNativeStdlibChecker,
UnusedSourceSetsChecker,
AndroidSourceSetLayoutV1SourceSetsNotFoundChecker,
)
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.plugin.diagnostics
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.ERROR
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.WARNING
import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV1
import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV2
@@ -161,4 +162,20 @@ object KotlinToolingDiagnostics {
object FailedToGetAgpVersionWarning : ToolingDiagnosticFactory(WARNING) {
operator fun invoke() = build("Failed to get AndroidGradlePluginVersion")
}
object AndroidSourceSetLayoutV1SourceSetsNotFoundError : ToolingDiagnosticFactory(ERROR) {
operator fun invoke(nameOfRequestedSourceSet: String) = build(
"""
KotlinSourceSet with name '$nameOfRequestedSourceSet' not found:
The SourceSet requested ('$nameOfRequestedSourceSet') was renamed in Kotlin 1.9.0
In order to migrate you might want to replace:
sourceSets.getByName("androidTest") -> sourceSets.getByName("androidUnitTest")
sourceSets.getByName("androidAndroidTest") -> sourceSets.getByName("androidInstrumentedTest")
Learn more about the new Kotlin/Android SourceSet Layout:
https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout
""".trimIndent()
)
}
}
@@ -0,0 +1,41 @@
/*
* 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.gradle.api.UnknownDomainObjectException
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
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.AndroidSourceSetLayoutV1SourceSetsNotFoundError
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.plugin.sources.android.kotlinAndroidSourceSetLayout
import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV2
import org.jetbrains.kotlin.tooling.core.withClosure
internal object AndroidSourceSetLayoutV1SourceSetsNotFoundChecker : KotlinGradleProjectChecker {
private val androidSourceSetRegex by lazy { Regex("""(androidTest|androidAndroidTest)\w*""") }
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
/* Checker will only try to provide additional diagnostics if the project configuration failed */
val failure = project.configurationResult.await() as? KotlinPluginLifecycle.ProjectConfigurationResult.Failure ?: return
/* Checker is only relevant if multiplatformAndroidSourceSetLayoutV2 is applied */
if (project.kotlinAndroidSourceSetLayout != multiplatformAndroidSourceSetLayoutV2) return
val allReasons = failure.failures.withClosure<Throwable> { listOfNotNull(it.cause) }
val unknownAndroidSourceSetNames = allReasons.filterIsInstance<UnknownDomainObjectException>()
.filter { it.message.orEmpty().contains("KotlinSourceSet") }
.mapNotNull { androidSourceSetRegex.find(it.message.orEmpty()) }
.map { it.value }
unknownAndroidSourceSetNames.forEach { unknownAndroidSourceSetName ->
collector.report(project, AndroidSourceSetLayoutV1SourceSetsNotFoundError(unknownAndroidSourceSetName))
}
}
}