[Gradle] Add KotlinSourceSetDependsOnDefaultCompilationSourceSet diagnostic

Default Kotlin Source sets should not have any dependents.

^KT-47144 Verification Pending
This commit is contained in:
Anton Lakotka
2023-06-16 12:13:48 +02:00
committed by Space Team
parent 4084fc62ee
commit deb4ed5e39
3 changed files with 56 additions and 7 deletions
@@ -354,6 +354,16 @@ object KotlinToolingDiagnostics {
}
}
}
object KotlinSourceSetDependsOnDefaultCompilationSourceSet : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(dependeeName: String, dependencyName: String) = build(
"""
Kotlin Source Set '$dependeeName' can't depend on '$dependencyName' which is a default source set for compilation.
None of source sets can depend on the compilation default source sets.
Please remove this dependency edge.
""".trimIndent()
)
}
}
private fun String.indentLines(nSpaces: Int = 4, skipFirstLine: Boolean = true): String {
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetHierarchy.SourceSetTree
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectCheckerContext
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinSourceSetDependsOnDefaultCompilationSourceSet
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinSourceSetTreeDependsOnMismatch
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMetadataTarget
@@ -53,6 +54,8 @@ internal object KotlinSourceSetTreeDependsOnMismatchChecker : KotlinGradleProjec
}
}
reportAllDependentsOfLeafSourceSets(collector, leafSourceSets.keys, reverseSourceSetDependencies)
for ((badSourceSet, _) in badSourceSets) {
val dependents = reverseSourceSetDependencies[badSourceSet].orEmpty()
@@ -63,11 +66,8 @@ internal object KotlinSourceSetTreeDependsOnMismatchChecker : KotlinGradleProjec
// until underlying dependent source sets relations are fixed
if (dependents.any { it in badSourceSets }) continue
// If [badSourceSet] is also a leaf source set then all its dependents edges are incorrect
// Therefore report everything that depend on the leaf source set (i.e. iosX64Test -> iosX64Main)
// NB: Cyclic diagnostics such as iosX64Main -> commonMain -> iosX64Main is handled in [AbstractKotlinSourceSet::dependsOn]
if (badSourceSet in leafSourceSets) {
dependents.forEach { collector.report(project, KotlinSourceSetTreeDependsOnMismatch(it.name, badSourceSet.name)) }
// It should be reported in [reportAllDependentsOfLeafSourceSets]
continue
}
@@ -105,6 +105,22 @@ internal object KotlinSourceSetTreeDependsOnMismatchChecker : KotlinGradleProjec
}
}
private fun KotlinGradleProjectCheckerContext.reportAllDependentsOfLeafSourceSets(
collector: KotlinToolingDiagnosticsCollector,
leafSourceSets: Set<KotlinSourceSet>,
reverseSourceSetDependencies: Map<KotlinSourceSet, Set<KotlinSourceSet>>,
) {
for (leafSourceSet in leafSourceSets) {
val dependents = reverseSourceSetDependencies[leafSourceSet].orEmpty()
for (dependent in dependents) {
collector.report(
project,
KotlinSourceSetDependsOnDefaultCompilationSourceSet(dependent.name, leafSourceSet.name)
)
}
}
}
private fun KotlinGradleProjectCheckerContext.reportSingleSourceSetWithDifferentSourceSetTree(
collector: KotlinToolingDiagnosticsCollector,
badSourceSet: KotlinSourceSet,
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.unitTests.diagnosticsTests
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinSourceSetTreeDependsOnMismatch
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.KotlinSourceSetDependsOnDefaultCompilationSourceSet
import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic
import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.util.*
@@ -27,9 +28,13 @@ class KotlinSourceSetTreeDependsOnMismatchTest {
}
}
project.evaluate()
val expectedDiagnosticsIds = listOf(
KotlinSourceSetTreeDependsOnMismatch.id,
KotlinSourceSetDependsOnDefaultCompilationSourceSet.id
)
return project.kotlinToolingDiagnosticsCollector
.getDiagnosticsForProject(project)
.filter { it.id == KotlinSourceSetTreeDependsOnMismatch.id } // ignore other diagnostics that can appear as well
.filter { it.id in expectedDiagnosticsIds } // ignore other diagnostics that can appear as well
}
private fun checkSingleBadSourceSetDependency(
@@ -86,13 +91,31 @@ class KotlinSourceSetTreeDependsOnMismatchTest {
@Test
fun `iosX64Test cant depend on iosX64Main`() = checkSingleBadSourceSetDependency(
dependent = "iosX64Test",
dependency = "iosX64Main"
dependency = "iosX64Main",
KotlinSourceSetDependsOnDefaultCompilationSourceSet(dependeeName = "iosX64Test", dependencyName = "iosX64Main")
)
@Test
fun `iosX64Main cant depend on iosX64Test`() = checkSingleBadSourceSetDependency(
dependent = "iosX64Main",
dependency = "iosX64Test"
dependency = "iosX64Test",
KotlinSourceSetDependsOnDefaultCompilationSourceSet(dependeeName = "iosX64Main", dependencyName = "iosX64Test")
)
@Test
fun `iosX64Main cant depend on iosArm64Main`() = checkSingleBadSourceSetDependency(
dependent = "iosX64Main",
dependency = "iosArm64Main",
KotlinSourceSetDependsOnDefaultCompilationSourceSet(dependeeName = "iosX64Main", dependencyName = "iosArm64Main")
)
@Test
fun `iosX64Main cant depend on iosArm64Main -- mixed scenario`() = checkDiagnostics {
sourceSets.getByName("iosX64Main").dependsOn(sourceSets.getByName("iosArm64Main"))
sourceSets.getByName("iosArm64Test").dependsOn(sourceSets.getByName("iosArm64Main"))
}.assertDiagnostics(
KotlinSourceSetDependsOnDefaultCompilationSourceSet(dependeeName = "iosArm64Test", dependencyName = "iosArm64Main"),
KotlinSourceSetDependsOnDefaultCompilationSourceSet(dependeeName = "iosX64Main", dependencyName = "iosArm64Main")
)
@Test