[Gradle] KGP Diagnostics: Run diagnostics launched & schedule report once Project is configured

KT-58275
This commit is contained in:
Sebastian Sellmair
2023-05-03 18:43:53 +02:00
committed by Space Team
parent d170897dbf
commit 287c431bc4
8 changed files with 29 additions and 38 deletions
@@ -42,7 +42,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultKotlinSourceSetFactory
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
import org.jetbrains.kotlin.gradle.report.BuildReportsService
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.addNpmDependencyExtension
@@ -246,7 +245,7 @@ abstract class KotlinBasePluginWrapper : DefaultKotlinBasePlugin() {
project.registerBuildKotlinToolingMetadataTask()
project.scheduleDiagnosticChecksAndReporting()
project.launchDiagnosticChecksAndReporting()
}
internal open fun createTestRegistry(project: Project) = KotlinTestsRegistry(project)
@@ -254,27 +253,17 @@ abstract class KotlinBasePluginWrapper : DefaultKotlinBasePlugin() {
internal abstract fun getPlugin(
project: Project,
): Plugin<Project>
}
private fun Project.scheduleDiagnosticChecksAndReporting() {
launchInStage(KotlinPluginLifecycle.Stage.ReadyForExecution) {
// Do not run checkers on projects which configuration finished with failure,
// as the internal state can not be trusted at this point (e.g. not entire of the
// user's buildscript could've been executed) and might produce bogus warnings
runProjectConfigurationHealthCheck {
project.runKotlinGradleProjectCheckers()
}
// TODO: this should run even if the application of KGP has finished with errors,
// because some diagnostics might indicate specifically the root cause of an
// exception.
renderReportedDiagnostics(
project.kotlinToolingDiagnosticsCollector.getDiagnosticsForProject(project),
project.logger,
project.kotlinPropertiesProvider.internalVerboseDiagnostics
)
}
private fun Project.launchDiagnosticChecksAndReporting() {
project.launchKotlinGradleProjectCheckers()
project.launch {
project.configured.await()
renderReportedDiagnostics(
project.kotlinToolingDiagnosticsCollector.getDiagnosticsForProject(project),
project.logger,
project.kotlinPropertiesProvider.internalVerboseDiagnostics
)
}
}
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.UnusedSourceSetsC
* threw an exception). If your check aims to prevent some exception, then code that check as soon as possible in the `apply`-block
* of the [org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper] or appropriate inheritor
*/
internal fun interface KotlinGradleProjectChecker {
fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector)
internal interface KotlinGradleProjectChecker {
suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector)
companion object {
val ALL_CHECKERS: List<KotlinGradleProjectChecker> = listOf(
@@ -9,8 +9,9 @@ import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.extraProperties
import org.jetbrains.kotlin.gradle.plugin.launch
internal fun Project.runKotlinGradleProjectCheckers() {
internal fun Project.launchKotlinGradleProjectCheckers() {
val checkers = kotlinGradleProjectCheckersOverride ?: KotlinGradleProjectChecker.ALL_CHECKERS
val context = KotlinGradleProjectCheckerContext(
@@ -21,7 +22,7 @@ internal fun Project.runKotlinGradleProjectCheckers() {
val collector = project.kotlinToolingDiagnosticsCollector
for (checker in checkers) {
with(checker) { context.runChecks(collector) }
with(checker) { launch { context.runChecks(collector) } }
}
}
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker
import org.jetbrains.kotlin.gradle.plugin.sources.internal
internal object CommonMainWithDependsOnChecker : KotlinGradleProjectChecker {
override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
multiplatformExtension?.sourceSets?.all {
if (it.name == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) {
it.internal.dependsOn.forAll {
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.konan.target.KonanTarget
internal object DeprecatedKotlinNativeTargetsChecker : KotlinGradleProjectChecker {
override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
val targets = multiplatformExtension?.targets ?: return
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
val targets = multiplatformExtension?.awaitTargets() ?: return
val usedDeprecatedTargets = targets
.filter { it is KotlinNativeTarget && it.konanTarget in KonanTarget.deprecatedTargets }
.map { it.name }
@@ -15,8 +15,8 @@ import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCo
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
internal object MissingNativeStdlibChecker : KotlinGradleProjectChecker {
override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
val targets = multiplatformExtension?.targets ?: return
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
val targets = multiplatformExtension?.awaitTargets() ?: return
if (targets.isEmpty() || // misconfigured project
targets.none { it is KotlinNativeTarget } || // no K/N targets
project.hasProperty("kotlin.native.nostdlib") || // suppressed
@@ -10,15 +10,16 @@ import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.plugin.sources.android.androidSourceSetInfoOrNull
import org.jetbrains.kotlin.gradle.plugin.sources.awaitPlatformCompilations
import org.jetbrains.kotlin.gradle.plugin.sources.internal
internal object UnusedSourceSetsChecker : KotlinGradleProjectChecker {
override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
val unusedSourceSets = multiplatformExtension?.sourceSets.orEmpty()
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
val unusedSourceSets = multiplatformExtension?.awaitSourceSets().orEmpty()
// Ignoring Android source sets
.filter { it.androidSourceSetInfoOrNull == null }
.filter { it.internal.compilations.isEmpty() }
.filter { it.internal.awaitPlatformCompilations().isEmpty() }
if (unusedSourceSets.isNotEmpty()) {
collector.report(project, KotlinToolingDiagnostics.UnusedSourceSetsWarning(unusedSourceSets.toSet().map { it.name }))
@@ -152,7 +152,7 @@ class DiagnosticsReportingFunctionalTest {
private fun buildProjectWithMockedCheckers(
name: String? = null,
parent: ProjectInternal? = null,
block: ProjectInternal.() -> Unit = { }
block: ProjectInternal.() -> Unit = { },
): ProjectInternal {
val project = buildProject(
{
@@ -203,19 +203,19 @@ private fun Project.reportOnePerBuildTestDiagnostic(severity: Severity = WARNING
}
internal object MockChecker : KotlinGradleProjectChecker {
override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
project.reportTestDiagnostic()
}
}
internal object MockPerProjectChecker : KotlinGradleProjectChecker {
override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
project.reportOnePerProjectTestDiagnostic()
}
}
internal object MockPerBuildChecker : KotlinGradleProjectChecker {
override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
project.reportOnePerBuildTestDiagnostic()
}
}