From bb3dc145e5a02bd3557025bdab13493179c37b04 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Wed, 15 Mar 2023 16:57:12 +0100 Subject: [PATCH] [mpp] Migrate AndroidSourceSetLayout checks to the new infra --- .../diagnostics/KotlinToolingDiagnostics.kt | 52 ++++++++++++++++++ .../android/KotlinAndroidSourceSetFactory.kt | 6 +- .../android/KotlinAndroidSourceSets.kt | 17 +++--- .../KotlinAndroidSourceSetLayoutChecker.kt | 46 +++------------- .../MultiplatformLayoutV1PromoteV2Checker.kt | 27 ++------- ...tiplatformLayoutV2AgpRequirementChecker.kt | 23 +++----- ...youtV2AndroidStyleSourceDirUsageChecker.kt | 32 ++++------- ...tformLayoutV1StyleSourceDirUsageChecker.kt | 36 +++++------- ...AndroidSourceSetLayoutV2DiagnosticsTest.kt | 55 +++---------------- .../android/TestDiagnosticsReporter.kt | 39 ------------- .../androidStyleSourceDirUsage.txt | 15 +++++ .../kt53709AndroidTest_kotlinInUse.txt | 7 +++ .../v1LayoutStyleSourceDirUsage.txt | 4 ++ 13 files changed, 144 insertions(+), 215 deletions(-) delete mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/android/TestDiagnosticsReporter.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/androidStyleSourceDirUsage.txt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/kt53709AndroidTest_kotlinInUse.txt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/v1LayoutStyleSourceDirUsage.txt 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 975ed680faf..020bee3ebc6 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 @@ -6,7 +6,10 @@ package org.jetbrains.kotlin.gradle.plugin.diagnostics import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.diagnostics.ToolingDiagnostic.Severity.WARNING +import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV1 +import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV2 @InternalKotlinGradlePluginApi // used in integration tests object KotlinToolingDiagnostics { @@ -75,4 +78,53 @@ object KotlinToolingDiagnostics { return build(cause + "\n" + details) } } + + object PromoteAndroidSourceSetLayoutV2Warning : ToolingDiagnosticFactory(WARNING) { + operator fun invoke() = build( + """ + ${multiplatformAndroidSourceSetLayoutV1.name} is deprecated. Use ${multiplatformAndroidSourceSetLayoutV2.name} instead. + To enable ${multiplatformAndroidSourceSetLayoutV2.name}: put the following in your gradle.properties: + ${PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION}=2 + + To suppress this warning: put the following in your gradle.properties: + ${PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION_1_NO_WARN}=true + + Learn more: https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout + """.trimIndent() + ) + } + + object AgpRequirementNotMetForAndroidSourceSetLayoutV2 : ToolingDiagnosticFactory(WARNING) { + operator fun invoke(minimumRequiredAgpVersion: String, currentAgpVersion: String) = build( + """ + ${multiplatformAndroidSourceSetLayoutV2.name} requires Android Gradle Plugin Version >= $minimumRequiredAgpVersion. + Found $currentAgpVersion + """.trimIndent() + ) + } + + object AndroidStyleSourceDirUsageWarning : ToolingDiagnosticFactory(WARNING) { + operator fun invoke(androidStyleSourceDirInUse: String, kotlinStyleSourceDirToUse: String) = build( + """ + Usage of 'Android Style' source directory $androidStyleSourceDirInUse is deprecated. + Use $kotlinStyleSourceDirToUse instead. + + To suppress this warning: put the following in your gradle.properties: + ${PropertiesProvider.PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_ANDROID_STYLE_NO_WARN}=true + + Learn more: https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout + """.trimIndent() + ) + } + + object SourceSetLayoutV1StyleDirUsageWarning : ToolingDiagnosticFactory(WARNING) { + operator fun invoke(v1StyleSourceDirInUse: String, currentLayoutName: String, v2StyleSourceDirToUse: String) = build( + """ + Found used source directory $v1StyleSourceDirInUse + This source directory was supported by: ${multiplatformAndroidSourceSetLayoutV1.name} + Current KotlinAndroidSourceSetLayout: $currentLayoutName + New source directory is: $v2StyleSourceDirToUse + """.trimIndent() + ) + } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/KotlinAndroidSourceSetFactory.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/KotlinAndroidSourceSetFactory.kt index 6820290b786..7c34b2ea124 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/KotlinAndroidSourceSetFactory.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/KotlinAndroidSourceSetFactory.kt @@ -10,8 +10,8 @@ import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget -import org.jetbrains.kotlin.gradle.plugin.sources.android.checker.KotlinAndroidSourceSetLayoutChecker import org.jetbrains.kotlin.gradle.utils.getOrCreate import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheck @@ -19,7 +19,7 @@ internal class KotlinAndroidSourceSetFactory( private val target: KotlinAndroidTarget, private val kotlin: KotlinProjectExtension, private val layout: KotlinAndroidSourceSetLayout, - private val diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter, + private val diagnosticsCollector: KotlinToolingDiagnosticsCollector ) { private val configuredKotlinSourceSets = mutableSetOf() @@ -29,7 +29,7 @@ internal class KotlinAndroidSourceSetFactory( layout.sourceSetConfigurator.configure(target, kotlinSourceSet, androidSourceSet) target.project.runProjectConfigurationHealthCheck { val layout = this@KotlinAndroidSourceSetFactory.layout - layout.checker.checkCreatedSourceSet(diagnosticReporter, target, layout, kotlinSourceSet, androidSourceSet) + layout.checker.checkCreatedSourceSet(diagnosticsCollector, target, layout, kotlinSourceSet, androidSourceSet) } } return kotlinSourceSet diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/KotlinAndroidSourceSets.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/KotlinAndroidSourceSets.kt index 8734062f6fb..79f6e99bdaa 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/KotlinAndroidSourceSets.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/KotlinAndroidSourceSets.kt @@ -7,8 +7,8 @@ package org.jetbrains.kotlin.gradle.plugin.sources.android import org.gradle.api.logging.Logging import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget -import org.jetbrains.kotlin.gradle.plugin.sources.android.checker.KotlinAndroidSourceSetLayoutChecker import org.jetbrains.kotlin.gradle.utils.androidExtension import org.jetbrains.kotlin.gradle.utils.forAllAndroidVariants import org.jetbrains.kotlin.gradle.utils.runProjectConfigurationHealthCheck @@ -23,12 +23,13 @@ internal object KotlinAndroidSourceSets { ) { logger.debug("Applying ${KotlinAndroidSourceSetLayout::class.java.simpleName}: ${layout.name}") - val android = target.project.androidExtension - val diagnosticReporter = KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter.create(target.project, logger, layout) - val factory = KotlinAndroidSourceSetFactory(target, target.project.kotlinExtension, layout, diagnosticReporter) + val project = target.project + val android = project.androidExtension + val diagnosticsCollector = project.kotlinToolingDiagnosticsCollector + val factory = KotlinAndroidSourceSetFactory(target, project.kotlinExtension, layout, diagnosticsCollector) - target.project.runProjectConfigurationHealthCheck { - layout.checker.checkBeforeLayoutApplied(diagnosticReporter, target, layout) + project.runProjectConfigurationHealthCheck { + layout.checker.checkBeforeLayoutApplied(diagnosticsCollector, target, layout) } /* @@ -46,7 +47,7 @@ internal object KotlinAndroidSourceSets { } /* Hook into Android's variant creation: This is invoked in 'afterEvaluate' */ - target.project.forAllAndroidVariants { variant -> + project.forAllAndroidVariants { variant -> variant.sourceSets.forEach { sourceProvider -> val androidSourceSet = android.sourceSets.findByName(sourceProvider.name) ?: return@forEach @@ -60,5 +61,3 @@ internal object KotlinAndroidSourceSets { } } } - - diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/KotlinAndroidSourceSetLayoutChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/KotlinAndroidSourceSetLayoutChecker.kt index 487f5185ac0..07a748f7c55 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/KotlinAndroidSourceSetLayoutChecker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/KotlinAndroidSourceSetLayoutChecker.kt @@ -6,38 +6,20 @@ package org.jetbrains.kotlin.gradle.plugin.sources.android.checker import com.android.build.gradle.api.AndroidSourceSet -import org.gradle.api.Project -import org.gradle.api.logging.Logger import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.sources.android.KotlinAndroidSourceSetLayout -import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild internal interface KotlinAndroidSourceSetLayoutChecker { - open class ProjectMisconfiguredException(message: String) : Exception(message) - - interface DiagnosticReporter { - fun error(diagnostic: Diagnostic): Nothing - fun warning(diagnostic: Diagnostic) - - companion object { - fun create(project: Project, logger: Logger, layout: KotlinAndroidSourceSetLayout): DiagnosticReporter = - DiagnosticReporterImpl(project, logger, layout) - } - } - - interface Diagnostic { - val message: String - } - fun checkBeforeLayoutApplied( - diagnosticReporter: DiagnosticReporter, + diagnosticsCollector: KotlinToolingDiagnosticsCollector, target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout ) = Unit fun checkCreatedSourceSet( - diagnosticReporter: DiagnosticReporter, + diagnosticsCollector: KotlinToolingDiagnosticsCollector, target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout, kotlinSourceSet: KotlinSourceSet, @@ -45,20 +27,6 @@ internal interface KotlinAndroidSourceSetLayoutChecker { ) = Unit } -private class DiagnosticReporterImpl( - private val project: Project, - private val logger: Logger, - private val layout: KotlinAndroidSourceSetLayout -) : KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter { - override fun error(diagnostic: KotlinAndroidSourceSetLayoutChecker.Diagnostic): Nothing { - throw KotlinAndroidSourceSetLayoutChecker.ProjectMisconfiguredException("${layout.name}: ${diagnostic.message}") - } - - override fun warning(diagnostic: KotlinAndroidSourceSetLayoutChecker.Diagnostic) { - SingleWarningPerBuild.show(project, logger, "w: ${layout.name}: ${diagnostic.message}\n") - } -} - /* Composite Implementation */ internal fun KotlinAndroidSourceSetLayoutChecker( @@ -72,22 +40,22 @@ private class CompositeKotlinAndroidSourceSetLayoutChecker( ) : KotlinAndroidSourceSetLayoutChecker { override fun checkBeforeLayoutApplied( - diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter, + diagnosticsCollector: KotlinToolingDiagnosticsCollector, target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout ) { - checkers.forEach { checker -> checker.checkBeforeLayoutApplied(diagnosticReporter, target, layout) } + checkers.forEach { checker -> checker.checkBeforeLayoutApplied(diagnosticsCollector, target, layout) } } override fun checkCreatedSourceSet( - diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter, + diagnosticsCollector: KotlinToolingDiagnosticsCollector, target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout, kotlinSourceSet: KotlinSourceSet, androidSourceSet: AndroidSourceSet ) { checkers.forEach { checker -> - checker.checkCreatedSourceSet(diagnosticReporter, target, layout, kotlinSourceSet, androidSourceSet) + checker.checkCreatedSourceSet(diagnosticsCollector, target, layout, kotlinSourceSet, androidSourceSet) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV1PromoteV2Checker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV1PromoteV2Checker.kt index e090b1365e8..9f10629ee54 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV1PromoteV2Checker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV1PromoteV2Checker.kt @@ -6,42 +6,27 @@ package org.jetbrains.kotlin.gradle.plugin.sources.android.checker import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider -import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.sources.android.KotlinAndroidSourceSetLayout -import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV1 -import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV2 /** * Promotes MultiplatformAndroidSourceSetLayoutV2 when requirements are met */ internal object MultiplatformLayoutV1PromoteV2Checker : KotlinAndroidSourceSetLayoutChecker { override fun checkBeforeLayoutApplied( - diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter, + diagnosticsCollector: KotlinToolingDiagnosticsCollector, target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout ) { if (target.project.kotlinPropertiesProvider.ignoreMppAndroidSourceSetLayoutVersion) return runCatching { if (MultiplatformLayoutV2AgpRequirementChecker.isAgpRequirementMet()) { - diagnosticReporter.warning(PromoteV2LayoutDiagnostic) + diagnosticsCollector.reportOncePerGradleBuild( + target.project, KotlinToolingDiagnostics.PromoteAndroidSourceSetLayoutV2Warning() + ) } } } - - object PromoteV2LayoutDiagnostic : KotlinAndroidSourceSetLayoutChecker.Diagnostic { - override val message: String - get() = """ - ${multiplatformAndroidSourceSetLayoutV1.name} is deprecated. Use ${multiplatformAndroidSourceSetLayoutV2.name} instead. - To enable ${multiplatformAndroidSourceSetLayoutV2.name}: put the following in your gradle.properties: - ${PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION}=2 - - To suppress this warning: put the following in your gradle.properties: - ${PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_VERSION_1_NO_WARN}=true - - Learn more: https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout - """.trimIndent() - - override fun toString(): String = "PromoteV2LayoutDiagnostic" - } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2AgpRequirementChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2AgpRequirementChecker.kt index 6abdf08acff..aa188505d37 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2AgpRequirementChecker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2AgpRequirementChecker.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.gradle.plugin.sources.android.checker import com.android.Version import org.jetbrains.kotlin.gradle.plugin.AndroidGradlePluginVersion +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.isAtLeast import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.sources.android.KotlinAndroidSourceSetLayout @@ -16,13 +18,17 @@ internal object MultiplatformLayoutV2AgpRequirementChecker : KotlinAndroidSource internal val minimumRequiredAgpVersion = AndroidGradlePluginVersion(7, 0, 0) override fun checkBeforeLayoutApplied( - diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter, + diagnosticsCollector: KotlinToolingDiagnosticsCollector, target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout ) { if (!isAgpRequirementMet()) { - diagnosticReporter.error( - AgpRequirementNotMetDiagnostic(minimumRequiredAgpVersion.toString(), Version.ANDROID_GRADLE_PLUGIN_VERSION) + diagnosticsCollector.reportOncePerGradleBuild( + target.project, + KotlinToolingDiagnostics.AgpRequirementNotMetForAndroidSourceSetLayoutV2( + minimumRequiredAgpVersion.toString(), + Version.ANDROID_GRADLE_PLUGIN_VERSION + ) ) } } @@ -30,15 +36,4 @@ internal object MultiplatformLayoutV2AgpRequirementChecker : KotlinAndroidSource internal fun isAgpRequirementMet(): Boolean { return AndroidGradlePluginVersion.currentOrNull.isAtLeast(minimumRequiredAgpVersion) } - - internal data class AgpRequirementNotMetDiagnostic( - val minimumRequiredAgpVersion: String, - val currentAgpVersion: String - ) : KotlinAndroidSourceSetLayoutChecker.Diagnostic { - override val message: String - get() = """ - requires Android Gradle Plugin Version >= $minimumRequiredAgpVersion. - Found $currentAgpVersion - """.trimIndent() - } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2AndroidStyleSourceDirUsageChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2AndroidStyleSourceDirUsageChecker.kt index 320e7deb8d6..60918bccd89 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2AndroidStyleSourceDirUsageChecker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2AndroidStyleSourceDirUsageChecker.kt @@ -6,13 +6,12 @@ package org.jetbrains.kotlin.gradle.plugin.sources.android.checker import com.android.build.gradle.api.AndroidSourceSet -import org.gradle.api.logging.Logging import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider -import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.sources.android.KotlinAndroidSourceSetLayout -import java.io.File /** * Will detect usage of "Android Style" source directories (like 'src/main/kotlin') and emit a warning @@ -20,33 +19,24 @@ import java.io.File internal object MultiplatformLayoutV2AndroidStyleSourceDirUsageChecker : KotlinAndroidSourceSetLayoutChecker { override fun checkCreatedSourceSet( - diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter, + diagnosticsCollector: KotlinToolingDiagnosticsCollector, target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout, kotlinSourceSet: KotlinSourceSet, androidSourceSet: AndroidSourceSet ) { if (target.project.kotlinPropertiesProvider.ignoreMppAndroidSourceSetLayoutV2AndroidStyleDirs) return + val projectRoot = target.project.rootDir val androidStyleSourceDir = target.project.file("src/${androidSourceSet.name}/kotlin") if (androidStyleSourceDir in kotlinSourceSet.kotlin.srcDirs && androidStyleSourceDir.exists()) { val kotlinStyleSourceDirToUse = target.project.file("src/${kotlinSourceSet.name}/kotlin") - diagnosticReporter.warning(AndroidStyleSourceDirUsageDiagnostic(androidStyleSourceDir, kotlinStyleSourceDirToUse)) + diagnosticsCollector.report( + target.project, + KotlinToolingDiagnostics.AndroidStyleSourceDirUsageWarning( + androidStyleSourceDir.relativeTo(projectRoot).toString(), + kotlinStyleSourceDirToUse.relativeTo(projectRoot).toString(), + ) + ) } } - - data class AndroidStyleSourceDirUsageDiagnostic( - val androidStyleSourceDirInUse: File, - val kotlinStyleSourceDirToUse: File - ) : KotlinAndroidSourceSetLayoutChecker.Diagnostic { - override val message: String - get() = """ - Usage of 'Android Style' source directory $androidStyleSourceDirInUse is deprecated. - Use $kotlinStyleSourceDirToUse instead. - - To suppress this warning: put the following in your gradle.properties: - ${PropertyNames.KOTLIN_MPP_ANDROID_SOURCE_SET_LAYOUT_ANDROID_STYLE_NO_WARN}=true - - Learn more: https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout - """.trimIndent() - } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChecker.kt index 3111a0f3fbb..ce7ae57c6bf 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChecker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/sources/android/checker/MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChecker.kt @@ -6,22 +6,25 @@ package org.jetbrains.kotlin.gradle.plugin.sources.android.checker import com.android.build.gradle.api.AndroidSourceSet -import org.gradle.api.logging.Logging import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.sources.android.KotlinAndroidSourceSetLayout import org.jetbrains.kotlin.gradle.plugin.sources.android.androidSourceSetInfo import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV1 import org.jetbrains.kotlin.gradle.utils.androidExtension -import java.io.File +import kotlin.io.path.ExperimentalPathApi +import kotlin.io.path.relativeTo /** * Detects and warns about usage of source directories from multiplatform layout version 1 */ internal object MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChecker : KotlinAndroidSourceSetLayoutChecker { + @OptIn(ExperimentalPathApi::class) override fun checkCreatedSourceSet( - diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter, + diagnosticsCollector: KotlinToolingDiagnosticsCollector, target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout, kotlinSourceSet: KotlinSourceSet, @@ -41,29 +44,18 @@ internal object MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChe */ if (target.project.androidExtension.sourceSets.findByName(v1kotlinSourceSetName) != null) return + val rootDirPath = target.project.rootDir.toPath() val v1KotlinSourceDir = target.project.file("src/$v1kotlinSourceSetName/kotlin") if (v1KotlinSourceDir.exists()) { - diagnosticReporter.warning( - V1StyleSourceDirUsageDiagnostic( - layout = layout, - v1StyleSourceDirInUse = v1KotlinSourceDir, - v2StyleSourceDirToUse = target.project.file("src/${kotlinSourceSet.name}/kotlin") + val v2SourceDirToUse = target.project.file("src/${kotlinSourceSet.name}/kotlin") + diagnosticsCollector.report( + target.project, + KotlinToolingDiagnostics.SourceSetLayoutV1StyleDirUsageWarning( + v1KotlinSourceDir.toPath().relativeTo(rootDirPath).toString(), + layout.name, + v2SourceDirToUse.toPath().relativeTo(rootDirPath).toString() ) ) } } - - data class V1StyleSourceDirUsageDiagnostic( - private val layout: KotlinAndroidSourceSetLayout, - val v1StyleSourceDirInUse: File, - val v2StyleSourceDirToUse: File - ) : KotlinAndroidSourceSetLayoutChecker.Diagnostic { - override val message: String - get() = """ - Found used source directory $v1StyleSourceDirInUse - This source directory was supported by: ${multiplatformAndroidSourceSetLayoutV1.name} - Current KotlinAndroidSourceSetLayout: ${layout.name} - New source directory is: $v2StyleSourceDirToUse - """.trimIndent() - } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/android/MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/android/MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest.kt index 01ac6c44408..f01251edf9f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/android/MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/android/MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest.kt @@ -12,19 +12,14 @@ import org.gradle.api.Project import org.gradle.api.internal.project.ProjectInternal import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider -import org.jetbrains.kotlin.gradle.plugin.sources.android.checker.MultiplatformLayoutV2AndroidStyleSourceDirUsageChecker.AndroidStyleSourceDirUsageDiagnostic -import org.jetbrains.kotlin.gradle.plugin.sources.android.checker.MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChecker.V1StyleSourceDirUsageDiagnostic +import org.jetbrains.kotlin.gradle.plugin.diagnostics.kotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.sources.android.findAndroidSourceSet import org.jetbrains.kotlin.gradle.plugin.sources.android.multiplatformAndroidSourceSetLayoutV2 import org.jetbrains.kotlin.gradle.util.* import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.fail class MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest { - private val diagnosticsReporter = TestDiagnosticsReporter() - private fun buildMinimalAndroidMultiplatformProject(): ProjectInternal = buildProjectWithMPP { setMultiplatformAndroidSourceSetLayoutVersion(2) plugins.apply(LibraryPlugin::class.java) @@ -36,14 +31,12 @@ class MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest { } } - private fun Project.checkCreatedSourceSets( - diagnosticsReporter: TestDiagnosticsReporter = this@MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest.diagnosticsReporter - ) { + private fun Project.checkCreatedSourceSets() { /* Invoke checkers on all source sets */ project.multiplatformExtension.sourceSets.forEach { kotlinSourceSet -> val androidSourceSet = project.findAndroidSourceSet(kotlinSourceSet) ?: return@forEach multiplatformAndroidSourceSetLayoutV2.checker.checkCreatedSourceSet( - diagnosticReporter = diagnosticsReporter, + diagnosticsCollector = project.kotlinToolingDiagnosticsCollector, target = project.multiplatformExtension.androidTarget(), layout = multiplatformAndroidSourceSetLayoutV2, kotlinSourceSet = kotlinSourceSet, @@ -63,10 +56,7 @@ class MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest { /* Invoke checkers on all source sets */ project.checkCreatedSourceSets() - - val diagnostic = assertIsInstance(diagnosticsReporter.assertSingleWarning()) - assertEquals(androidTestKotlinSourceDir, diagnostic.androidStyleSourceDirInUse) - assertEquals(project.file("src/androidInstrumentedTest/kotlin"), diagnostic.kotlinStyleSourceDirToUse) + project.checkDiagnostics("kt53709AndroidTest_kotlinInUse") } @Test @@ -80,25 +70,7 @@ class MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest { project.evaluate() project.checkCreatedSourceSets() - - val warnings = diagnosticsReporter.warnings - if (warnings.size != 2) fail("Expected exactly two warnings emitted. Found $warnings") - - val androidMainWarning = warnings.filterIsInstance() - .find { warning -> warning.androidStyleSourceDirInUse == androidStyleMain } - ?: fail("Missing warning for '$androidStyleMain'. Found $warnings") - - assertEquals( - project.file("src/androidMain/kotlin"), androidMainWarning.kotlinStyleSourceDirToUse - ) - - val androidUnitTestWarning = warnings.filterIsInstance() - .find { warning -> warning.androidStyleSourceDirInUse == androidStyleUnitTest } - ?: fail("Missing warning for '$androidStyleUnitTest'. Found $warnings") - - assertEquals( - project.file("src/androidUnitTest/kotlin"), androidUnitTestWarning.kotlinStyleSourceDirToUse - ) + project.checkDiagnostics("androidStyleSourceDirUsage") } @Test @@ -115,9 +87,7 @@ class MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest { project.evaluate() project.checkCreatedSourceSets() - - val warnings = diagnosticsReporter.warnings - if (warnings.isNotEmpty()) fail("Expected no warnings emitted. Found $warnings") + project.checkDiagnostics("androidStyleSourceDirUsageNoWarn") } @Test @@ -127,15 +97,6 @@ class MultiplatformAndroidSourceSetLayoutV2DiagnosticsTest { v1StyleInstrumentedTest.mkdirs() project.evaluate() project.checkCreatedSourceSets() - - val warning = assertIsInstance(diagnosticsReporter.assertSingleWarning()) - - assertEquals( - v1StyleInstrumentedTest, warning.v1StyleSourceDirInUse, - ) - - assertEquals( - project.file("src/androidInstrumentedTest/kotlin"), warning.v2StyleSourceDirToUse - ) + project.checkDiagnostics("v1LayoutStyleSourceDirUsage") } -} \ No newline at end of file +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/android/TestDiagnosticsReporter.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/android/TestDiagnosticsReporter.kt deleted file mode 100644 index eadbd47ab65..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/sources/android/TestDiagnosticsReporter.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2010-2022 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.sources.android - -import org.jetbrains.kotlin.gradle.plugin.sources.android.checker.KotlinAndroidSourceSetLayoutChecker -import kotlin.test.fail - -internal class TestDiagnosticsReporter : KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter { - - class ErrorDiagnosticException(diagnostic: KotlinAndroidSourceSetLayoutChecker.Diagnostic) : - KotlinAndroidSourceSetLayoutChecker.ProjectMisconfiguredException(diagnostic.message) - - private val _errors = mutableListOf() - - private val _warnings = mutableListOf() - - val errors get() = _errors.toList() - - val warnings get() = _warnings.toList() - - override fun error(diagnostic: KotlinAndroidSourceSetLayoutChecker.Diagnostic): Nothing { - _errors.add(diagnostic) - throw ErrorDiagnosticException(diagnostic) - } - - override fun warning(diagnostic: KotlinAndroidSourceSetLayoutChecker.Diagnostic) { - _warnings.add(diagnostic) - } -} - -internal fun TestDiagnosticsReporter.assertSingleWarning(): KotlinAndroidSourceSetLayoutChecker.Diagnostic { - if (errors.isNotEmpty()) fail("Expected just a single warning, but found errors: $errors") - if (warnings.isEmpty()) fail("Expected a single warning, but found none!") - if (warnings.size > 1) fail("Expected a single warning, but found multiple: $warnings") - return warnings.first() -} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/androidStyleSourceDirUsage.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/androidStyleSourceDirUsage.txt new file mode 100644 index 00000000000..7e27ec76c6f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/androidStyleSourceDirUsage.txt @@ -0,0 +1,15 @@ +[AndroidStyleSourceDirUsageWarning | WARNING] Usage of 'Android Style' source directory src/main/kotlin is deprecated. +Use src/androidMain/kotlin instead. + +To suppress this warning: put the following in your gradle.properties: +kotlin.mpp.androidSourceSetLayoutV2AndroidStyleDirs.nowarn=true + +Learn more: https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout +---- +[AndroidStyleSourceDirUsageWarning | WARNING] Usage of 'Android Style' source directory src/test/kotlin is deprecated. +Use src/androidUnitTest/kotlin instead. + +To suppress this warning: put the following in your gradle.properties: +kotlin.mpp.androidSourceSetLayoutV2AndroidStyleDirs.nowarn=true + +Learn more: https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/kt53709AndroidTest_kotlinInUse.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/kt53709AndroidTest_kotlinInUse.txt new file mode 100644 index 00000000000..b2247ac409b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/kt53709AndroidTest_kotlinInUse.txt @@ -0,0 +1,7 @@ +[AndroidStyleSourceDirUsageWarning | WARNING] Usage of 'Android Style' source directory src/androidTest/kotlin is deprecated. +Use src/androidInstrumentedTest/kotlin instead. + +To suppress this warning: put the following in your gradle.properties: +kotlin.mpp.androidSourceSetLayoutV2AndroidStyleDirs.nowarn=true + +Learn more: https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/v1LayoutStyleSourceDirUsage.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/v1LayoutStyleSourceDirUsage.txt new file mode 100644 index 00000000000..214d0a08da1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/v1LayoutStyleSourceDirUsage.txt @@ -0,0 +1,4 @@ +[SourceSetLayoutV1StyleDirUsageWarning | WARNING] Found used source directory src/androidAndroidTest/kotlin +This source directory was supported by: Multiplatform/Android-V1-SourceSetLayout +Current KotlinAndroidSourceSetLayout: Multiplatform/Android-V2-SourceSetLayout +New source directory is: src/androidInstrumentedTest/kotlin