diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/diagnosticUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/diagnosticUtils.kt new file mode 100644 index 00000000000..541babe6f40 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/diagnosticUtils.kt @@ -0,0 +1,74 @@ +/* + * 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.util + +import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic +import java.io.File +import java.nio.file.Path +import kotlin.test.assertTrue + +internal fun checkDiagnosticsWithMppProject(projectName: String, projectConfiguration: Project.() -> Unit) { + val project = buildProjectWithMPP(projectBuilder = { withName(projectName) }) + project.setMultiplatformAndroidSourceSetLayoutVersion(2) + project.projectConfiguration() + project.evaluate() + project.checkDiagnostics(projectName) +} + + +/** + * [compactRendering] == true will omit projects with no diagnostics from the report, as well as + * name of the project if it's a single one with diagnostics (useful for small one-project tests) + */ +internal fun Project.checkDiagnostics(testDataName: String, compactRendering: Boolean = true) { + val diagnosticsPerProject = rootProject.allprojects.mapNotNull { + val diagnostics = it.kotlinToolingDiagnosticsCollector.getDiagnosticsForProject(it) + if (diagnostics.isEmpty() && compactRendering) + null + else + it.name to diagnostics + }.toMap() + val expectedDiagnostics = expectedDiagnosticsFile(testDataName) + + if (diagnosticsPerProject.all { (_, diagnostics) -> diagnostics.isEmpty() }) { + if (expectedDiagnostics.exists()) + error("Expected to have some diagnostics in file://${expectedDiagnostics.canonicalPath}, but none were actually reported") + else + return // do not create empty file + } + + val actualRenderedText = if (diagnosticsPerProject.size == 1 && compactRendering) { + diagnosticsPerProject.entries.single().value.render() + } else { + diagnosticsPerProject + .entries + .joinToString(separator = "\n\n") { (projectName, diagnostics) -> + val nameSanitized = if (projectName == "test") "" else projectName + "PROJECT: $nameSanitized\n" + diagnostics.render() + } + } + + val sanitizedTest = actualRenderedText.replace(File.separator, "/") + + KotlinTestUtils.assertEqualsToFile(expectedDiagnostics, sanitizedTest) +} + +internal fun Project.assertNoDiagnostics() { + val actualDiagnostics = kotlinToolingDiagnosticsCollector.getDiagnosticsForProject(this) + assertTrue( + actualDiagnostics.isEmpty(), "Expected to have no diagnostics, but some were reported:\n ${actualDiagnostics.render()}" + ) +} + +private fun Collection.render(): String = joinToString(separator = "\n----\n") + +private val expectedDiagnosticsRoot: Path + get() = resourcesRoot.resolve("expectedDiagnostics") + +private fun expectedDiagnosticsFile(projectName: String): File = expectedDiagnosticsRoot.resolve("$projectName.txt").toFile() diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/fileUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/fileUtils.kt index 381143be602..088565278fa 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/fileUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/fileUtils.kt @@ -7,5 +7,10 @@ package org.jetbrains.kotlin.gradle.util import org.gradle.api.Project import java.io.File +import java.nio.file.Path +import java.nio.file.Paths -fun Set.relativeTo(project: Project): Set = map { it.relativeTo(project.projectDir) }.toSet() \ No newline at end of file +fun Set.relativeTo(project: Project): Set = map { it.relativeTo(project.projectDir) }.toSet() + +val resourcesRoot: Path + get() = Paths.get("src", "functionalTest", "resources") diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/mppProjectConfigurationUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/mppProjectConfigurationUtils.kt new file mode 100644 index 00000000000..775594f67d9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/util/mppProjectConfigurationUtils.kt @@ -0,0 +1,35 @@ +/* + * 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.util + +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet + +val KotlinMultiplatformExtension.commonMain: KotlinSourceSet + get() = sourceSets.getByName("commonMain") + +val KotlinMultiplatformExtension.commonTest: KotlinSourceSet + get() = sourceSets.getByName("commonTest") + +val KotlinMultiplatformExtension.jvmMain: KotlinSourceSet + get() = sourceSets.getByName("jvmMain") + +val KotlinMultiplatformExtension.jvmTest: KotlinSourceSet + get() = sourceSets.getByName("jvmTest") + +val KotlinMultiplatformExtension.androidMain: KotlinSourceSet + get() = sourceSets.getByName("androidMain") + +val KotlinMultiplatformExtension.androidTest: KotlinSourceSet + get() = sourceSets.getByName("androidTest") + +val KotlinMultiplatformExtension.iosMain: KotlinSourceSet + get() = sourceSets.getByName("iosMain") + +val KotlinMultiplatformExtension.iosTest: KotlinSourceSet + get() = sourceSets.getByName("iosTest") + +operator fun KotlinSourceSet.invoke(config: KotlinSourceSet.() -> Unit) = config()