[Gradle][MPP] Introduce DiagnosticReporter and Diagnostic APIs...
... for KotlinAndroidSourceSetLayoutChecker KT-53709
This commit is contained in:
committed by
Space
parent
776b68f2fe
commit
5a447a823f
+4
-2
@@ -11,13 +11,15 @@ 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.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
|
||||
|
||||
internal class KotlinAndroidSourceSetFactory(
|
||||
private val target: KotlinAndroidTarget,
|
||||
private val kotlin: KotlinProjectExtension,
|
||||
private val layout: KotlinAndroidSourceSetLayout
|
||||
private val layout: KotlinAndroidSourceSetLayout,
|
||||
private val diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter,
|
||||
) {
|
||||
private val configuredKotlinSourceSets = mutableSetOf<KotlinSourceSet>()
|
||||
|
||||
@@ -27,7 +29,7 @@ internal class KotlinAndroidSourceSetFactory(
|
||||
layout.sourceSetConfigurator.configure(target, kotlinSourceSet, androidSourceSet)
|
||||
target.project.runProjectConfigurationHealthCheck {
|
||||
val layout = this@KotlinAndroidSourceSetFactory.layout
|
||||
layout.checker.checkCreatedSourceSet(target, layout, kotlinSourceSet, androidSourceSet)
|
||||
layout.checker.checkCreatedSourceSet(diagnosticReporter, target, layout, kotlinSourceSet, androidSourceSet)
|
||||
}
|
||||
}
|
||||
return kotlinSourceSet
|
||||
|
||||
+4
-2
@@ -9,6 +9,7 @@ import org.gradle.api.logging.Logging
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.forEachVariant
|
||||
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.runProjectConfigurationHealthCheck
|
||||
|
||||
@@ -23,10 +24,11 @@ internal object KotlinAndroidSourceSets {
|
||||
logger.debug("Applying ${KotlinAndroidSourceSetLayout::class.java.simpleName}: ${layout.name}")
|
||||
|
||||
val android = target.project.androidExtension
|
||||
val factory = KotlinAndroidSourceSetFactory(target, target.project.kotlinExtension, layout)
|
||||
val diagnosticReporter = KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter.create(target.project, logger, layout)
|
||||
val factory = KotlinAndroidSourceSetFactory(target, target.project.kotlinExtension, layout, diagnosticReporter)
|
||||
|
||||
target.project.runProjectConfigurationHealthCheck {
|
||||
layout.checker.checkBeforeLayoutApplied(target, layout)
|
||||
layout.checker.checkBeforeLayoutApplied(diagnosticReporter, target, layout)
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+43
-3
@@ -6,19 +6,38 @@
|
||||
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.mpp.KotlinAndroidTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.android.KotlinAndroidSourceSetLayout
|
||||
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
|
||||
|
||||
internal interface KotlinAndroidSourceSetLayoutChecker {
|
||||
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,
|
||||
target: KotlinAndroidTarget,
|
||||
layout: KotlinAndroidSourceSetLayout
|
||||
) = Unit
|
||||
|
||||
fun checkCreatedSourceSet(
|
||||
diagnosticReporter: DiagnosticReporter,
|
||||
target: KotlinAndroidTarget,
|
||||
layout: KotlinAndroidSourceSetLayout,
|
||||
kotlinSourceSet: KotlinSourceSet,
|
||||
@@ -26,6 +45,22 @@ 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(
|
||||
vararg checkers: KotlinAndroidSourceSetLayoutChecker?
|
||||
): KotlinAndroidSourceSetLayoutChecker {
|
||||
@@ -36,18 +71,23 @@ private class CompositeKotlinAndroidSourceSetLayoutChecker(
|
||||
private val checkers: List<KotlinAndroidSourceSetLayoutChecker>
|
||||
) : KotlinAndroidSourceSetLayoutChecker {
|
||||
|
||||
override fun checkBeforeLayoutApplied(target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout) {
|
||||
checkers.forEach { checker -> checker.checkBeforeLayoutApplied(target, layout) }
|
||||
override fun checkBeforeLayoutApplied(
|
||||
diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter,
|
||||
target: KotlinAndroidTarget,
|
||||
layout: KotlinAndroidSourceSetLayout
|
||||
) {
|
||||
checkers.forEach { checker -> checker.checkBeforeLayoutApplied(diagnosticReporter, target, layout) }
|
||||
}
|
||||
|
||||
override fun checkCreatedSourceSet(
|
||||
diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter,
|
||||
target: KotlinAndroidTarget,
|
||||
layout: KotlinAndroidSourceSetLayout,
|
||||
kotlinSourceSet: KotlinSourceSet,
|
||||
androidSourceSet: AndroidSourceSet
|
||||
) {
|
||||
checkers.forEach { checker ->
|
||||
checker.checkCreatedSourceSet(target, layout, kotlinSourceSet, androidSourceSet)
|
||||
checker.checkCreatedSourceSet(diagnosticReporter, target, layout, kotlinSourceSet, androidSourceSet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-16
@@ -5,36 +5,39 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.sources.android.checker
|
||||
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames
|
||||
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
|
||||
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
|
||||
|
||||
/**
|
||||
* Promotes MultiplatformAndroidSourceSetLayoutV2 when requirements are met
|
||||
*/
|
||||
internal object MultiplatformLayoutV1PromoteV2Checker : KotlinAndroidSourceSetLayoutChecker {
|
||||
private val logger = Logging.getLogger(this.javaClass)
|
||||
|
||||
override fun checkBeforeLayoutApplied(target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout) {
|
||||
override fun checkBeforeLayoutApplied(
|
||||
diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter,
|
||||
target: KotlinAndroidTarget,
|
||||
layout: KotlinAndroidSourceSetLayout
|
||||
) {
|
||||
if (target.project.kotlinPropertiesProvider.ignoreMppAndroidSourceSetLayoutVersion) return
|
||||
runCatching {
|
||||
if (MultiplatformLayoutV2AgpRequirementChecker.isAgpRequirementMet()) {
|
||||
SingleWarningPerBuild.show(
|
||||
target.project, logger,
|
||||
"""
|
||||
w: ${layout.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
|
||||
""".trimIndent()
|
||||
)
|
||||
diagnosticReporter.warning(PromoteV2LayoutDiagnostic())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class 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
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
+17
-7
@@ -14,18 +14,28 @@ internal object MultiplatformLayoutV2AgpRequirementChecker : KotlinAndroidSource
|
||||
|
||||
private const val AGP_VERSION_MIN = "7.0.0"
|
||||
|
||||
override fun checkBeforeLayoutApplied(target: KotlinAndroidTarget, layout: KotlinAndroidSourceSetLayout) {
|
||||
override fun checkBeforeLayoutApplied(
|
||||
diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter,
|
||||
target: KotlinAndroidTarget,
|
||||
layout: KotlinAndroidSourceSetLayout
|
||||
) {
|
||||
if (!isAgpRequirementMet()) {
|
||||
throw KotlinAndroidSourceSetLayoutChecker.ProjectMisconfiguredException(
|
||||
"""
|
||||
${layout.name} requires Android Gradle Plugin Version >= $AGP_VERSION_MIN.
|
||||
Found ${Version.ANDROID_GRADLE_PLUGIN_VERSION}
|
||||
""".trimIndent()
|
||||
)
|
||||
diagnosticReporter.error(AgpRequirementNotMetDiagnostic(AGP_VERSION_MIN, Version.ANDROID_GRADLE_PLUGIN_VERSION))
|
||||
}
|
||||
}
|
||||
|
||||
internal fun isAgpRequirementMet(): Boolean {
|
||||
return compareVersionNumbers(Version.ANDROID_GRADLE_PLUGIN_VERSION, AGP_VERSION_MIN) >= 0
|
||||
}
|
||||
|
||||
internal class AgpRequirementNotMetDiagnostic(
|
||||
val requiredMinAgpVersion: String,
|
||||
val currentAgpVersion: String
|
||||
) : KotlinAndroidSourceSetLayoutChecker.Diagnostic {
|
||||
override val message: String
|
||||
get() = """
|
||||
requires Android Gradle Plugin Version >= $requiredMinAgpVersion.
|
||||
Found $currentAgpVersion
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
+15
-8
@@ -10,15 +10,15 @@ import org.gradle.api.logging.Logging
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
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
|
||||
*/
|
||||
internal object MultiplatformLayoutV2AndroidStyleSourceDirUsageChecker : KotlinAndroidSourceSetLayoutChecker {
|
||||
|
||||
private val logger = Logging.getLogger(this.javaClass)
|
||||
|
||||
override fun checkCreatedSourceSet(
|
||||
diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter,
|
||||
target: KotlinAndroidTarget,
|
||||
layout: KotlinAndroidSourceSetLayout,
|
||||
kotlinSourceSet: KotlinSourceSet,
|
||||
@@ -26,12 +26,19 @@ internal object MultiplatformLayoutV2AndroidStyleSourceDirUsageChecker : KotlinA
|
||||
) {
|
||||
val androidStyleSourceDir = target.project.file("src/${androidSourceSet.name}/kotlin")
|
||||
if (androidStyleSourceDir in kotlinSourceSet.kotlin.srcDirs && androidStyleSourceDir.exists()) {
|
||||
logger.warn(
|
||||
"""
|
||||
w: ${layout.name}: Usage of 'Android Style' source directory $androidStyleSourceDir is deprecated.
|
||||
Use ${target.project.file("src/${kotlinSourceSet.name}/kotlin")} instead.
|
||||
""".trimIndent()
|
||||
)
|
||||
val kotlinStyleSourceDirToUse = target.project.file("src/${kotlinSourceSet.name}/kotlin")
|
||||
diagnosticReporter.warning(AndroidStyleSourceDirUsageDiagnostic(androidStyleSourceDir, kotlinStyleSourceDirToUse))
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidStyleSourceDirUsageDiagnostic(
|
||||
private val androidStyleSourceDirInUse: File,
|
||||
private val kotlinStyleSourceDirToUse: File
|
||||
) : KotlinAndroidSourceSetLayoutChecker.Diagnostic {
|
||||
override val message: String
|
||||
get() = """
|
||||
Usage of 'Android Style' source directory $androidStyleSourceDirInUse is deprecated.
|
||||
Use $kotlinStyleSourceDirToUse instead.
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
+22
-9
@@ -12,15 +12,15 @@ 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 java.io.File
|
||||
|
||||
/**
|
||||
* Detects and warns about usage of source directories from multiplatform layout version 1
|
||||
*/
|
||||
internal object MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChecker : KotlinAndroidSourceSetLayoutChecker {
|
||||
|
||||
private val logger = Logging.getLogger(this.javaClass)
|
||||
|
||||
override fun checkCreatedSourceSet(
|
||||
diagnosticReporter: KotlinAndroidSourceSetLayoutChecker.DiagnosticReporter,
|
||||
target: KotlinAndroidTarget,
|
||||
layout: KotlinAndroidSourceSetLayout,
|
||||
kotlinSourceSet: KotlinSourceSet,
|
||||
@@ -35,14 +35,27 @@ internal object MultiplatformLayoutV2MultiplatformLayoutV1StyleSourceDirUsageChe
|
||||
|
||||
val v1KotlinSourceDir = target.project.file("src/$v1kotlinSourceSetName/kotlin")
|
||||
if (v1KotlinSourceDir.exists()) {
|
||||
logger.warn(
|
||||
"""
|
||||
w: ${layout.name}: Found used source directory $v1KotlinSourceDir
|
||||
This source directory was supported by: ${multiplatformAndroidSourceSetLayoutV1.name}
|
||||
Current KotlinAndroidSourceSetLayout: ${layout.name}
|
||||
New source directory is: ${target.project.file("src/${kotlinSourceSet.name}/kotlin")}
|
||||
""".trimIndent()
|
||||
diagnosticReporter.warning(
|
||||
V1StyleSourceDirUsageDiagnostic(
|
||||
layout = layout,
|
||||
v1StyleSourceDirInUse = v1KotlinSourceDir,
|
||||
v2StyleSourceDirToUse = target.project.file("src/${kotlinSourceSet.name}/kotlin")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class V1StyleSourceDirUsageDiagnostic(
|
||||
private val layout: KotlinAndroidSourceSetLayout,
|
||||
private val v1StyleSourceDirInUse: File,
|
||||
private 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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user