From b08d12e47799367f6a52d33b84b9a3a21f940629 Mon Sep 17 00:00:00 2001 From: Anton Lakotka Date: Mon, 17 Jul 2023 23:10:21 +0200 Subject: [PATCH] [Gradle] Report KotlinTargetAlreadyDeclared from checker Rephrase diagnostic message and add kotl.in link for details. ^KT-59316 Verification Pending --- .../dsl/KotlinMultiplatformExtension.kt | 23 ---------- .../diagnostics/KotlinGradleProjectChecker.kt | 3 +- .../diagnostics/KotlinToolingDiagnostics.kt | 24 +++------- .../KotlinTargetAlreadyDeclaredChecker.kt | 46 +++++++++++++++++++ .../KotlinTargetAlreadyDeclaredTest.kt | 20 ++------ 5 files changed, 58 insertions(+), 58 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/KotlinTargetAlreadyDeclaredChecker.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt index f6195563c5a..ff0c4264f9a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt @@ -14,11 +14,8 @@ import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.AfterFinaliseDsl import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider -import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinTargetAlreadyDeclared -import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.hierarchy.KotlinHierarchyDslImpl import org.jetbrains.kotlin.gradle.plugin.mpp.* -import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTargetPreset import javax.inject.Inject @Suppress("DEPRECATION") @@ -217,9 +214,6 @@ internal fun KotlinTargetsContainerWithPresets.configureOrCre } existingTarget == null -> { - if (this is KotlinMultiplatformExtension) { - project.reportIfTargetOfTheSameTypeAlreadyCreated(targets, targetPreset, targetName) - } val newTarget = targetPreset.createTarget(targetName) targets.add(newTarget) configure(newTarget) @@ -237,20 +231,3 @@ internal fun KotlinTargetsContainerWithPresets.configureOrCre } } -private fun Project.reportIfTargetOfTheSameTypeAlreadyCreated( - targets: NamedDomainObjectCollection, - preset: KotlinTargetPreset<*>, - targetName: String, -) { - val existingTargets = targets.matching { it.preset?.name == preset.name } - val targetDslFunctionName = when(preset) { - is KotlinJsIrTargetPreset -> "js" - is KotlinJsTargetPreset -> "js" - is KotlinAndroidTargetPreset -> "androidTarget" - else -> preset.name - } - if (existingTargets.isNotEmpty()) { - kotlinToolingDiagnosticsCollector.report(this, KotlinTargetAlreadyDeclared(targetDslFunctionName, targetName, Throwable())) - } -} - diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt index 8acc7f0623e..f52b9d380b1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt @@ -9,8 +9,8 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.jetbrains.kotlin.gradle.dsl.AndroidMainSourceSetConventionsChecker import org.jetbrains.kotlin.gradle.dsl.IosSourceSetConventionChecker -import org.jetbrains.kotlin.gradle.dsl.PlatformSourceSetConventionsChecker import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.dsl.PlatformSourceSetConventionsChecker import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.* @@ -114,6 +114,7 @@ internal interface KotlinGradleProjectChecker { PlatformSourceSetConventionsChecker, AndroidMainSourceSetConventionsChecker, IosSourceSetConventionChecker, + KotlinTargetAlreadyDeclaredChecker, ) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt index 725ef497428..bee3bf4d31b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinToolingDiagnostics.kt @@ -548,27 +548,15 @@ object KotlinToolingDiagnostics { } object KotlinTargetAlreadyDeclared : ToolingDiagnosticFactory(WARNING) { - operator fun invoke(targetDslFunctionName: String, targetName: String, trace: Throwable?) = build( + operator fun invoke(targetDslFunctionName: String) = build( """ Kotlin Target '$targetDslFunctionName()' is already declared. - Declaring multiple Kotlin Targets of the same type is deprecated. + + Declaring multiple Kotlin Targets of the same type is not recommended + and will become an error in the upcoming Kotlin releases. - i.e. - kotlin { - $targetDslFunctionName() - $targetDslFunctionName("$targetName") /* <- second '$targetDslFunctionName' target in the project is deprecated */ - } - - Please use different Gradle Projects or create Kotlin Compilations. - For example: - - kotlin { - $targetDslFunctionName() { - val $targetName by compilations.creating - } - } - """.trimIndent(), - throwable = trace + Read https://kotl.in/04i2n7 for details. + """.trimIndent() ) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/KotlinTargetAlreadyDeclaredChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/KotlinTargetAlreadyDeclaredChecker.kt new file mode 100644 index 00000000000..7fe8153cca8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/KotlinTargetAlreadyDeclaredChecker.kt @@ -0,0 +1,46 @@ +/* + * 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.KotlinTarget +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectCheckerContext +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinTargetAlreadyDeclared +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTargetPreset +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsTargetPreset +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget +import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTargetPreset + +internal object KotlinTargetAlreadyDeclaredChecker : KotlinGradleProjectChecker { + override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) { + val targets = multiplatformExtension?.awaitTargets() ?: return + val duplicatedTargets = targets + .filter { it !is KotlinMetadataTarget } + .groupBy { it.preset?.name } + .filterValues { it.size > 1 } + + for (targetsGroup in duplicatedTargets.values) { + val targetDslFunctionName = targetsGroup.first() + .targetDslFunctionName + // skip targets without known dsl function such as external targets + ?: continue + + collector.report(project, KotlinTargetAlreadyDeclared(targetDslFunctionName)) + } + } + + /** + * DSL names are taken from [org.jetbrains.kotlin.gradle.dsl.KotlinTargetContainerWithPresetFunctions] + */ + private val KotlinTarget.targetDslFunctionName + get() = when (preset) { + is KotlinJsIrTargetPreset -> "js" + is KotlinJsTargetPreset -> "js" + is KotlinAndroidTargetPreset -> "androidTarget" + else -> preset?.name + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/KotlinTargetAlreadyDeclaredTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/KotlinTargetAlreadyDeclaredTest.kt index 19631f77c34..5f15b5ded89 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/KotlinTargetAlreadyDeclaredTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/KotlinTargetAlreadyDeclaredTest.kt @@ -67,10 +67,7 @@ class KotlinTargetAlreadyDeclaredTest { } project.evaluate() - project.assertContainsDiagnostic( - KotlinTargetAlreadyDeclared("jvm", "jvm2", null), - ignoreThrowable = true - ) + project.assertContainsDiagnostic(KotlinTargetAlreadyDeclared("jvm")) } @Test @@ -83,10 +80,7 @@ class KotlinTargetAlreadyDeclaredTest { } project.evaluate() - project.assertContainsDiagnostic( - KotlinTargetAlreadyDeclared("linuxArm64", "linux", null), - ignoreThrowable = true - ) + project.assertContainsDiagnostic(KotlinTargetAlreadyDeclared("linuxArm64")) } @Test @@ -101,10 +95,7 @@ class KotlinTargetAlreadyDeclaredTest { } project.evaluate() - project.assertContainsDiagnostic( - KotlinTargetAlreadyDeclared("androidTarget", "android2", null), - ignoreThrowable = true - ) + project.assertContainsDiagnostic(KotlinTargetAlreadyDeclared("androidTarget")) } @Test @@ -117,9 +108,6 @@ class KotlinTargetAlreadyDeclaredTest { } project.evaluate() - project.assertContainsDiagnostic( - KotlinTargetAlreadyDeclared("js", "nodejs", null), - ignoreThrowable = true - ) + project.assertContainsDiagnostic(KotlinTargetAlreadyDeclared("js")) } } \ No newline at end of file