From b347ff2c531ddbc5b1c85e2f423a8c0c8ea9e50a Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Thu, 2 Nov 2023 17:20:18 +0100 Subject: [PATCH] [Gradle] Migrate KotlinNativeTargetConfigurator.warnAboutIncorrectDependencies to KotlinGradleProjectChecker KT-61634 --- .../diagnostics/KotlinToolingDiagnostics.kt | 13 ++++ .../IncorrectNativeDependenciesChecker.kt | 55 ++++++++++++++++ .../plugin/registerKotlinPluginExtensions.kt | 3 + .../native/KotlinNativeTargetConfigurator.kt | 65 ------------------- ...orrectNativeDependenciesDiagnosticsTest.kt | 34 ++++++++++ .../IncorrectNativeDependencies.txt | 11 ++++ 6 files changed, 116 insertions(+), 65 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectNativeDependenciesChecker.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/IncorrectNativeDependenciesDiagnosticsTest.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/IncorrectNativeDependencies.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 af8aac56e9e..0a8b53415fa 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,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) = 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 { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectNativeDependenciesChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectNativeDependenciesChecker.kt new file mode 100644 index 00000000000..c600cbfb64a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/checkers/IncorrectNativeDependenciesChecker.kt @@ -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().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() } + ) + ) + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt index 3561bff2a70..e94f7ea1a7e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/registerKotlinPluginExtensions.kt @@ -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) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt index d98c2993917..a5b0a1d6df4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt @@ -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 : AbstractKotlinTargetConfigurator( 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 : AbstractKotl companion object { const val INTEROP_GROUP = "interop" const val RUN_GROUP = "run" - - } } - diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/IncorrectNativeDependenciesDiagnosticsTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/IncorrectNativeDependenciesDiagnosticsTest.kt new file mode 100644 index 00000000000..ea7345eb6c8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/IncorrectNativeDependenciesDiagnosticsTest.kt @@ -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") + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/IncorrectNativeDependencies.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/IncorrectNativeDependencies.txt new file mode 100644 index 00000000000..311f9dbb9cd --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/IncorrectNativeDependencies.txt @@ -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