diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/diagnosticsTests/DiagnosticsReportingFunctionalTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/diagnosticsTests/DiagnosticsReportingFunctionalTest.kt new file mode 100644 index 00000000000..0f35b77a995 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/diagnosticsTests/DiagnosticsReportingFunctionalTest.kt @@ -0,0 +1,186 @@ +/* + * 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.diagnosticsTests + +import org.gradle.api.Project +import org.gradle.api.internal.project.ProjectInternal +import org.jetbrains.kotlin.gradle.plugin.diagnostics.* +import org.jetbrains.kotlin.gradle.util.applyKotlinJvmPlugin +import org.jetbrains.kotlin.gradle.util.buildProject +import org.jetbrains.kotlin.gradle.util.checkDiagnostics +import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic +import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity +import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.ERROR +import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.WARNING +import org.junit.Test + +class DiagnosticsReportingFunctionalTest { + + @Test + fun testNonDuplicatedReporting() { + buildProjectWithMockedCheckers { + applyKotlinJvmPlugin() + evaluate() + reportTestDiagnostic() + reportTestDiagnostic() + checkDiagnostics("nonDuplicatedReporting") + } + } + + + @Test + fun testOncePerProjectReporting() { + buildProjectWithMockedCheckers { + applyKotlinJvmPlugin() + evaluate() + + reportOnePerProjectTestDiagnostic() + reportOnePerProjectTestDiagnostic() + + checkDiagnostics("oncePerProjectReporting") + } + } + + @Test + fun testOncePerBuildReporting() { + val root = buildProjectWithMockedCheckers() + + root.applyKotlinJvmPlugin() + root.evaluate() + + buildProjectWithMockedCheckers("subproject-a", root) { + applyKotlinJvmPlugin() + evaluate() + reportOnePerBuildTestDiagnostic() + reportOnePerBuildTestDiagnostic() + } + + buildProjectWithMockedCheckers("subproject-b", root) { + applyKotlinJvmPlugin() + evaluate() + reportOnePerBuildTestDiagnostic() + reportOnePerBuildTestDiagnostic() + } + + root.checkDiagnostics("oncePerBuildReporting") + } + + // Known quirk: deduplicated diagnostics use internalId as a default key of deduplication, + // meaning that subsequent reported diagnostics with the same ID will be dropped even if + // they have different message/severity + @Test + fun testOncePerBuildWithDifferentSeverities() { + val root = buildProject() + + root.applyKotlinJvmPlugin() + root.evaluate() + + buildProject( + { + withName("subproject") + withParent(root) + } + ).run { + applyKotlinJvmPlugin() + evaluate() + reportOnePerBuildTestDiagnostic() + reportOnePerBuildTestDiagnostic(severity = ERROR) // NB: will be lost! + } + + root.checkDiagnostics("deduplicationWithDifferentSeverities", compactRendering = false) + } + + @Test + fun testOncePerProjectAndPerBuildAreEquivalentForRoot() { + val root = buildProject() + + root.applyKotlinJvmPlugin() + root.reportOnePerProjectTestDiagnostic() + + // using same diagnostic with same ID as in "per-project". They should be deduplicated properly. + root.reportDiagnosticOncePerBuild( + ToolingDiagnostic( + "TEST_DIAGNOSTIC_ONE_PER_PROJECT", + "This is a test diagnostics that should be reported once per project\n\nIt has multiple lines of text", + WARNING + ) + ) + root.evaluate() + + root.checkDiagnostics("oncePerProjectAndOncePerBuildAreEquivalentForRoot") + } +} + +private fun buildProjectWithMockedCheckers( + name: String? = null, + parent: ProjectInternal? = null, + block: ProjectInternal.() -> Unit = { } +): ProjectInternal { + val project = buildProject( + { + if (name != null) withName(name) + if (parent != null) withParent(parent) + } + ) + + project.allprojects { + project.extensions.extraProperties.set( + KOTLIN_GRADLE_PROJECT_CHECKERS_OVERRIDE, + listOf(MockChecker, MockPerProjectChecker, MockPerBuildChecker) + ) + } + + project.block() + return project +} + + +private fun Project.reportTestDiagnostic(severity: Severity = WARNING) { + kotlinToolingDiagnosticsCollector.report( + project, + ToolingDiagnostic("TEST_DIAGNOSTIC", "This is a test diagnostic\n\nIt has multiple lines of text", severity) + ) +} + +private fun Project.reportOnePerProjectTestDiagnostic(severity: Severity = WARNING) { + kotlinToolingDiagnosticsCollector.reportOncePerGradleProject( + project, + ToolingDiagnostic( + "TEST_DIAGNOSTIC_ONE_PER_PROJECT", + "This is a test diagnostics that should be reported once per project\n\nIt has multiple lines of text", + severity + ) + ) +} + +private fun Project.reportOnePerBuildTestDiagnostic(severity: Severity = WARNING) { + kotlinToolingDiagnosticsCollector.reportOncePerGradleBuild( + project, + ToolingDiagnostic( + "TEST_DIAGNOSTIC_ONE_PER_BUILD", + "This is a test diagnostics that should be reported once per build\n\nIt has multiple lines of text", + severity + ) + ) +} + +internal object MockChecker : KotlinGradleProjectChecker { + override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) { + project.reportTestDiagnostic() + } +} + +internal object MockPerProjectChecker : KotlinGradleProjectChecker { + override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) { + project.reportOnePerProjectTestDiagnostic() + } +} + +internal object MockPerBuildChecker : KotlinGradleProjectChecker { + override fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) { + project.reportOnePerBuildTestDiagnostic() + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/diagnosticsTests/MppDiagnosticsFunctionalTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/diagnosticsTests/MppDiagnosticsFunctionalTest.kt new file mode 100644 index 00000000000..e551e59f1a6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/diagnosticsTests/MppDiagnosticsFunctionalTest.kt @@ -0,0 +1,125 @@ +/* + * 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.diagnosticsTests + +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmWithJavaTargetPreset +import org.jetbrains.kotlin.gradle.util.* +import org.junit.Test + +class MppDiagnosticsFunctionalTest { + + @Test + fun testKmmLibrary() { + checkDiagnosticsWithMppProject("kmmLibrary") { + androidLibrary { + compileSdk = 32 + } + + kotlin { + androidTarget() + ios() + } + } + } + + @Test + fun testKmmApplication() { + checkDiagnosticsWithMppProject("kmmApplication") { + androidApplication { + compileSdk = 32 + } + + kotlin { + androidTarget() + ios() + } + } + } + + @Test + fun testCommonMainWithDependsOn() { + checkDiagnosticsWithMppProject("commonMainWithDependsOn") { + kotlin { + jvm() + linuxX64() + + sourceSets.apply { + val myCustomCommonMain = create("myCustomCommonMain") + val myCustomCommonMain2 = create("myCustomCommonMain2") + + commonMain { + dependsOn(myCustomCommonMain) + dependsOn(myCustomCommonMain2) // check that diagnostic isn't duplicated + } + } + } + } + } + + @Test + fun testDeprecatedJvmWithJavaPreset() { + checkDiagnosticsWithMppProject("deprecatedJvmWithJavaPreset") { + kotlin { + targetFromPreset(presets.getByName(KotlinJvmWithJavaTargetPreset.PRESET_NAME)) + } + } + } + + @Test + fun testUnusedSourceSets() { + checkDiagnosticsWithMppProject("unusedSourceSets") { + kotlin { + jvm() + linuxX64() + + sourceSets.apply { + val unused1 = create("unused1") + // Check that dependsOn doesn't make source set "used" + create("unused2").dependsOn(unused1) + // Check that depending on used source sets doesn't make source set "used" + create("unusedWithDependsOnUsed").dependsOn(commonMain) + + // Check that custom intermediate source set isn't reported as unused + val intermediate = create("intermediate") + jvmMain.dependsOn(intermediate) + intermediate.dependsOn(commonMain) + } + } + } + } + + @Test + fun unusedSourceSetsAndroid() { + checkDiagnosticsWithMppProject("unusedSourceSetsAndroid") { + androidLibrary { + compileSdk = 32 + + // Check that source sets of custom build types are not reported as unused + buildTypes { + create("staging") + } + + // Check that source sets of custom product flavors are not reported as unused + flavorDimensions += "version" + productFlavors { + create("demo") + create("paid") + } + } + + kotlin { + androidTarget() + linuxX64() + + sourceSets.apply { + val intermediateBetweenAndroid = create("intermediate") + androidMain.dependsOn(intermediateBetweenAndroid) + intermediateBetweenAndroid.dependsOn(commonMain) + } + } + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/commonMainWithDependsOn.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/commonMainWithDependsOn.txt new file mode 100644 index 00000000000..c350fd3a88e --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/commonMainWithDependsOn.txt @@ -0,0 +1 @@ +[CommonMainWithDependsOnDiagnostic | WARNING] commonMain can't declare dependsOn on other source sets diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deduplicationWithDifferentSeverities.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deduplicationWithDifferentSeverities.txt new file mode 100644 index 00000000000..0cb5d8a856b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deduplicationWithDifferentSeverities.txt @@ -0,0 +1,7 @@ +PROJECT: + + +PROJECT: subproject +[TEST_DIAGNOSTIC_ONE_PER_BUILD | WARNING] This is a test diagnostics that should be reported once per build + +It has multiple lines of text diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deprecatedHmppProperties.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deprecatedHmppProperties.txt new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deprecatedHmppProperties.txt @@ -0,0 +1 @@ + diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deprecatedJvmWithJavaPreset.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deprecatedJvmWithJavaPreset.txt new file mode 100644 index 00000000000..5d0b68126bb --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/deprecatedJvmWithJavaPreset.txt @@ -0,0 +1,12 @@ +[DeprecatedJvmWithJavaPresetDiagnostic | WARNING] The 'jvmWithJava' preset is deprecated and will be removed soon. Please use an ordinary JVM target with Java support: + + kotlin { + jvm { + withJava() + } + } + +After this change, please move the Java sources to the Kotlin source set directories. +For example, if the JVM target is given the default name 'jvm': + * instead of 'src/main/java', use 'src/jvmMain/java' + * instead of 'src/test/java', use 'src/jvmTest/java' diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/nonDuplicatedReporting.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/nonDuplicatedReporting.txt new file mode 100644 index 00000000000..d0e0fca1d64 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/nonDuplicatedReporting.txt @@ -0,0 +1,19 @@ +[TEST_DIAGNOSTIC | WARNING] This is a test diagnostic + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC_ONE_PER_PROJECT | WARNING] This is a test diagnostics that should be reported once per project + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC_ONE_PER_BUILD | WARNING] This is a test diagnostics that should be reported once per build + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC | WARNING] This is a test diagnostic + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC | WARNING] This is a test diagnostic + +It has multiple lines of text diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerBuildReporting.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerBuildReporting.txt new file mode 100644 index 00000000000..cbe2af4d2a4 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerBuildReporting.txt @@ -0,0 +1,30 @@ +PROJECT: +[TEST_DIAGNOSTIC | WARNING] This is a test diagnostic + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC_ONE_PER_PROJECT | WARNING] This is a test diagnostics that should be reported once per project + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC_ONE_PER_BUILD | WARNING] This is a test diagnostics that should be reported once per build + +It has multiple lines of text + +PROJECT: subproject-a +[TEST_DIAGNOSTIC | WARNING] This is a test diagnostic + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC_ONE_PER_PROJECT | WARNING] This is a test diagnostics that should be reported once per project + +It has multiple lines of text + +PROJECT: subproject-b +[TEST_DIAGNOSTIC | WARNING] This is a test diagnostic + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC_ONE_PER_PROJECT | WARNING] This is a test diagnostics that should be reported once per project + +It has multiple lines of text diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerProjectAndOncePerBuildAreEquivalentForRoot.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerProjectAndOncePerBuildAreEquivalentForRoot.txt new file mode 100644 index 00000000000..0f9c15549b9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerProjectAndOncePerBuildAreEquivalentForRoot.txt @@ -0,0 +1,3 @@ +[TEST_DIAGNOSTIC_ONE_PER_PROJECT | WARNING] This is a test diagnostics that should be reported once per project + +It has multiple lines of text diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerProjectReporting.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerProjectReporting.txt new file mode 100644 index 00000000000..ec229d269bd --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/oncePerProjectReporting.txt @@ -0,0 +1,11 @@ +[TEST_DIAGNOSTIC | WARNING] This is a test diagnostic + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC_ONE_PER_PROJECT | WARNING] This is a test diagnostics that should be reported once per project + +It has multiple lines of text +---- +[TEST_DIAGNOSTIC_ONE_PER_BUILD | WARNING] This is a test diagnostics that should be reported once per build + +It has multiple lines of text diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/redundantExplicitSettingForDeprecatedProperty.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/redundantExplicitSettingForDeprecatedProperty.txt new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/redundantExplicitSettingForDeprecatedProperty.txt @@ -0,0 +1 @@ + diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/unusedSourceSets.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/unusedSourceSets.txt new file mode 100644 index 00000000000..5ae43363bb5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/unusedSourceSets.txt @@ -0,0 +1,6 @@ +[UnusedSourceSetsWarning | WARNING] The following Kotlin source sets were configured but not added to any Kotlin compilation: + * unused1 + * unused2 + * unusedWithDependsOnUsed +You can add a source set to a target's compilation by connecting it with the compilation's default source set using 'dependsOn'. +See https://kotl.in/connecting-source-sets