[Gradle] Migrate KotlinNativeTargetConfigurator.warnAboutIncorrectDependencies to KotlinGradleProjectChecker

KT-61634
This commit is contained in:
Sebastian Sellmair
2023-11-02 17:20:18 +01:00
committed by Space Team
parent faecd7f772
commit b347ff2c53
6 changed files with 116 additions and 65 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle.plugin.diagnostics
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.PRESETS_DEPRECATION_MESSAGE_SUFFIX
import org.jetbrains.kotlin.gradle.dsl.KotlinSourceSetConvention.isRegisteredByKotlinSourceSetConventionAt
@@ -678,6 +679,18 @@ object KotlinToolingDiagnostics {
)
}
}
object IncorrectNativeDependenciesWarning : ToolingDiagnosticFactory(WARNING) {
operator fun invoke(targetName: String, compilationName: String, dependencies: List<String>) = build(
"""
A compileOnly dependency is used in the Kotlin/Native target '${targetName}':
Compilation: $compilationName
Dependencies:
${dependencies.joinToString(separator = "\n")}
""".trimIndent()
)
}
}
private fun String.indentLines(nSpaces: Int = 4, skipFirstLine: Boolean = true): String {
@@ -0,0 +1,55 @@
/*
* 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.plugin.diagnostics.checkers
import org.gradle.api.artifacts.Dependency
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.await
import org.jetbrains.kotlin.gradle.plugin.diagnostics.*
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectCheckerContext
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector
import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
internal object IncorrectNativeDependenciesChecker : KotlinGradleProjectChecker {
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
KotlinPluginLifecycle.Stage.AfterFinaliseDsl.await()
if (PropertiesProvider(project).ignoreIncorrectNativeDependencies == true) return
KotlinPluginLifecycle.Stage.ReadyForExecution.await()
val multiplatform = multiplatformExtension ?: return
multiplatform.targets.filterIsInstance<KotlinNativeTarget>().forEach { target ->
checkIncorrectDependencies(target)
}
}
private fun KotlinGradleProjectCheckerContext.checkIncorrectDependencies(target: KotlinNativeTarget) {
val compileOnlyDependencies = target.compilations.mapNotNull {
val dependencies = project.configurations.getByName(it.compileOnlyConfigurationName).allDependencies
if (dependencies.isNotEmpty()) {
it to dependencies
} else null
}
fun Dependency.stringCoordinates(): String = buildString {
group?.let { append(it).append(':') }
append(name)
version?.let { append(':').append(it) }
}
compileOnlyDependencies.forEach { (compilation, dependencies) ->
project.reportDiagnostic(
KotlinToolingDiagnostics.IncorrectNativeDependenciesWarning(
targetName = target.name,
compilationName = compilation.name,
dependencies = dependencies.map { it.stringCoordinates() }
)
)
}
}
}
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.internal.CustomizeKotlinDependenciesSetupAction
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsSetupAction
import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.*
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.AndroidPluginWithoutAndroidTargetChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.AndroidSourceSetLayoutV1SourceSetsNotFoundChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.CommonMainOrTestWithDependsOnChecker
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.DisabledCinteropC
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.DisabledNativeTargetsChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.DuplicateSourceSetChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.ExperimentalK2UsageChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.IncorrectNativeDependenciesChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.InternalGradlePropertiesUsageChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.JsEnvironmentChecker
import org.jetbrains.kotlin.gradle.plugin.diagnostics.checkers.KotlinSourceSetTreeDependsOnMismatchChecker
@@ -163,6 +165,7 @@ internal fun Project.registerKotlinPluginExtensions() {
register(project, InternalGradlePropertiesUsageChecker)
register(project, WasmSourceSetsNotFoundChecker)
register(project, DuplicateSourceSetChecker)
register(project, IncorrectNativeDependenciesChecker)
if (isMultiplatform) {
register(project, KotlinMultiplatformAndroidGradlePluginCompatibilityChecker)
@@ -6,73 +6,11 @@
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.artifacts.Dependency
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.ReadyForExecution
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.KOTLIN_NATIVE_IGNORE_INCORRECT_DEPENDENCIES
import org.jetbrains.kotlin.gradle.plugin.mpp.Framework
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.registerEmbedAndSignAppleFrameworkTask
open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotlinTargetConfigurator<T>(
createTestCompilation = true
) {
// FIXME support creating interop tasks for PM20
// endregion.
// region Configuration.
override fun configurePlatformSpecificModel(target: T) {
if (PropertiesProvider(target.project).ignoreIncorrectNativeDependencies != true) {
warnAboutIncorrectDependencies(target)
}
}
private fun warnAboutIncorrectDependencies(target: KotlinNativeTarget) = target.project.launchInStage(ReadyForExecution) {
val compileOnlyDependencies = target.compilations.mapNotNull {
val dependencies = project.configurations.getByName(it.compileOnlyConfigurationName).allDependencies
if (dependencies.isNotEmpty()) {
it to dependencies
} else null
}
fun Dependency.stringCoordinates(): String = buildString {
group?.let { append(it).append(':') }
append(name)
version?.let { append(':').append(it) }
}
if (compileOnlyDependencies.isNotEmpty()) {
with(target.project.logger) {
warn("A compileOnly dependency is used in the Kotlin/Native target '${target.name}':")
compileOnlyDependencies.forEach {
warn(
"""
Compilation: ${it.first.name}
Dependencies:
${it.second.joinToString(separator = "\n") { it.stringCoordinates() }}
""".trimIndent()
)
}
warn(
"""
Such dependencies are not applicable for Kotlin/Native, consider changing the dependency type to 'implementation' or 'api'.
To disable this warning, set the $KOTLIN_NATIVE_IGNORE_INCORRECT_DEPENDENCIES=true project property
""".trimIndent()
)
}
}
}
// endregion.
object NativeArtifactFormat {
const val KLIB = "org.jetbrains.kotlin.klib"
const val FRAMEWORK = "org.jetbrains.kotlin.framework"
@@ -81,8 +19,5 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget> : AbstractKotl
companion object {
const val INTEROP_GROUP = "interop"
const val RUN_GROUP = "run"
}
}
@@ -0,0 +1,34 @@
/*
* 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.
*/
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.unitTests.diagnosticsTests
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformSourceSetConventionsImpl.commonMain
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformSourceSetConventionsImpl.dependencies
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP
import org.jetbrains.kotlin.gradle.util.checkDiagnostics
import kotlin.test.Test
class IncorrectNativeDependenciesDiagnosticsTest {
@Test
fun `test - dependencies in compileOnly scope declared`() {
val project = buildProjectWithMPP()
val kotlin = project.multiplatformExtension
kotlin.linuxArm64()
kotlin.linuxX64()
kotlin.jvm()
kotlin.sourceSets.commonMain.dependencies {
compileOnly("my:library:1.0.0")
}
project.evaluate()
project.checkDiagnostics("IncorrectNativeDependencies")
}
}
@@ -0,0 +1,11 @@
[IncorrectNativeDependenciesWarning | WARNING] A compileOnly dependency is used in the Kotlin/Native target 'linuxArm64':
Compilation: main
Dependencies:
my:library:1.0.0
----
[IncorrectNativeDependenciesWarning | WARNING] A compileOnly dependency is used in the Kotlin/Native target 'linuxX64':
Compilation: main
Dependencies:
my:library:1.0.0