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 ae5bc49dd31..af8aac56e9e 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 @@ -665,6 +665,19 @@ object KotlinToolingDiagnostics { """.trimIndent() ) } + + object DuplicateSourceSetsError : ToolingDiagnosticFactory(FATAL) { + operator fun invoke(duplicatedSourceSets: Map>): ToolingDiagnostic { + val duplicatesGroupsString = duplicatedSourceSets + .map { entry -> entry.value.joinToString(", ") } + .joinToString("], [", "[", "]") + return build( + "Duplicate Kotlin source sets have been detected: $duplicatesGroupsString." + + " Keep in mind that source set names are case-insensitive," + + " which means that `srcMain` and `sRcMain` are considered the same source set." + ) + } + } } private fun String.indentLines(nSpaces: Int = 4, skipFirstLine: Boolean = true): String { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/DuplicateSourceSetChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/DuplicateSourceSetChecker.kt new file mode 100644 index 00000000000..18618922363 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/DuplicateSourceSetChecker.kt @@ -0,0 +1,33 @@ +/* + * 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.dsl.multiplatformExtensionOrNull +import org.jetbrains.kotlin.gradle.plugin.diagnostics.* +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectCheckerContext +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector + +/** + * This checker is used to ensure that there are no duplicate source sets in MPP project. + * + * Examples of duplicated sourceSets: [jvmMain and jVmMain] or [macosMain and macOSMain] + * + */ +// TODO(Dmitrii Krasnov): Remove this checker once IDEA-317606 is resolved +internal object DuplicateSourceSetChecker : KotlinGradleProjectChecker { + override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) { + val kotlin = project.multiplatformExtensionOrNull ?: return + val sourceSetNames = kotlin.awaitSourceSets().map { it.name } + val duplicateSourceSets = sourceSetNames + .groupBy { it.toLowerCase() } + .filter { (_, values) -> values.size > 1 } + + if (duplicateSourceSets.isNotEmpty()) { + project.reportDiagnostic(KotlinToolingDiagnostics.DuplicateSourceSetsError(duplicateSourceSets)) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt index 31f9da5d3d4..10006135f02 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.CommonMainOrTestW import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.DeprecatedKotlinNativeTargetsChecker import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.DisabledCinteropCommonizationInHmppProjectChecker import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.DisabledNativeTargetsChecker +import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.DuplicateSourceSetChecker import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.ExperimentalK2UsageChecker import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.InternalGradlePropertiesUsageChecker import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.JsEnvironmentChecker @@ -148,6 +149,7 @@ internal fun Project.registerKotlinPluginExtensions() { register(project, KotlinTargetAlreadyDeclaredChecker) register(project, InternalGradlePropertiesUsageChecker) register(project, WasmSourceSetsNotFoundChecker) + register(project, DuplicateSourceSetChecker) if (isMultiplatform) { register(project, KotlinMultiplatformAndroidGradlePluginCompatibilityChecker) diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/DuplicateSourceSetCheckerTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/DuplicateSourceSetCheckerTest.kt new file mode 100644 index 00000000000..6771b523e95 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/DuplicateSourceSetCheckerTest.kt @@ -0,0 +1,47 @@ +/* + * 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.unitTests.diagnosticsTests + +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.util.assertNoDiagnostics +import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP +import org.jetbrains.kotlin.gradle.util.checkDiagnostics +import kotlin.test.Test +import kotlin.test.assertFails + +class DuplicateSourceSetCheckerTest { + + @Test + fun `target with custom name duplicates defualt name failes build`() { + val project = buildProjectWithMPP { + project.multiplatformExtension.applyDefaultHierarchyTemplate() + project.multiplatformExtension.linuxX64("linUX") + } + assertFails { project.evaluate() } + project.checkDiagnostics("DuplicateSourceSetChecker") + } + + @Test + fun `target with custom name does not produce any diagnostics`() { + val project = buildProjectWithMPP { + project.multiplatformExtension.applyDefaultHierarchyTemplate() + project.multiplatformExtension.linuxX64("custom") + } + project.evaluate() + project.assertNoDiagnostics() + } + + @Test + fun `several targets without custom name don't produce any diagnostics`() { + val project = buildProjectWithMPP { + project.multiplatformExtension.applyDefaultHierarchyTemplate() + project.multiplatformExtension.linuxX64() + project.multiplatformExtension.mingwX64() + } + project.evaluate() + project.assertNoDiagnostics() + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/DuplicateSourceSetChecker.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/DuplicateSourceSetChecker.txt new file mode 100644 index 00000000000..513c87d06ba --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/DuplicateSourceSetChecker.txt @@ -0,0 +1 @@ +[DuplicateSourceSetsError | FATAL] Duplicate Kotlin source sets have been detected: [linUXMain, linuxMain], [linUXTest, linuxTest]. Keep in mind that source set names are case-insensitive, which means that `srcMain` and `sRcMain` are considered the same source set. \ No newline at end of file