From c31c5ea0be3eb9afc5707e495fe13c9a7688f541 Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Fri, 23 Jun 2023 14:38:50 +0200 Subject: [PATCH] [Gradle] Implement IosSourceSetConventionUsedWithoutIosTarget diagnostic ... in case when iosMain, iosTest conventions are used w/o any ios target being applied ^KT-58676 Verification Pending --- ...KotlinMultiplatformSourceSetConventions.kt | 29 ++++++++++++++++- .../diagnostics/KotlinGradleProjectChecker.kt | 2 ++ .../diagnostics/KotlinToolingDiagnostics.kt | 23 +++++++++++++- .../MppSourceSetConventionsDiagnosticTests.kt | 14 +++++++++ ...ourceSetConventionUsedWithoutIosTarget.txt | 31 +++++++++++++++++++ 5 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/IosSourceSetConventionUsedWithoutIosTarget.txt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformSourceSetConventions.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformSourceSetConventions.kt index b184cda63eb..0e89f608dc6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformSourceSetConventions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformSourceSetConventions.kt @@ -8,16 +8,22 @@ package org.jetbrains.kotlin.gradle.dsl import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.NamedDomainObjectProvider import org.jetbrains.kotlin.gradle.dsl.KotlinSourceSetConvention.isRegisteredByKotlinSourceSetConventionAt -import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.plugin.KotlinTarget +import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectChecker import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinGradleProjectCheckerContext import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.AndroidMainSourceSetConventionUsedWithoutAndroidTarget +import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.IosSourceSetConventionUsedWithoutIosTarget import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.PlatformSourceSetConventionUsedWithCustomTargetName import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnostics.PlatformSourceSetConventionUsedWithoutCorrespondingTarget import org.jetbrains.kotlin.gradle.plugin.diagnostics.KotlinToolingDiagnosticsCollector import org.jetbrains.kotlin.gradle.plugin.diagnostics.reportDiagnostic +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget +import org.jetbrains.kotlin.konan.target.Family @KotlinGradlePluginDsl interface KotlinMultiplatformSourceSetConventions { @@ -152,3 +158,24 @@ internal object AndroidMainSourceSetConventionsChecker : KotlinGradleProjectChec } } } + +internal object IosSourceSetConventionChecker : KotlinGradleProjectChecker { + override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) { + val kotlin = project.multiplatformExtensionOrNull ?: return + + val iosSourceSets = listOf("iosMain", "iosTest") + .mapNotNull { sourceSetName -> kotlin.awaitSourceSets().findByName(sourceSetName) } + .filter { it.isRegisteredByKotlinSourceSetConventionAt != null } + + + val hasIosTarget = kotlin.awaitTargets() + .any { target -> target is KotlinNativeTarget && target.konanTarget.family == Family.IOS } + + if (!hasIosTarget) { + iosSourceSets.forEach { sourceSet -> + project.reportDiagnostic(IosSourceSetConventionUsedWithoutIosTarget(sourceSet)) + } + } + + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt index 9ffef0ea590..148d388f298 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/diagnostics/KotlinGradleProjectChecker.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.diagnostics import org.gradle.api.Plugin import org.gradle.api.Project import org.jetbrains.kotlin.gradle.dsl.AndroidMainSourceSetConventionsChecker +import org.jetbrains.kotlin.gradle.dsl.IosSourceSetConventionChecker import org.jetbrains.kotlin.gradle.dsl.PlatformSourceSetConventionsChecker import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle @@ -112,6 +113,7 @@ internal interface KotlinGradleProjectChecker { KotlinSourceSetTreeDependsOnMismatchChecker, PlatformSourceSetConventionsChecker, AndroidMainSourceSetConventionsChecker, + IosSourceSetConventionChecker ) } } 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 52be4747cfc..e8efdef2f27 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 @@ -425,7 +425,28 @@ object KotlinToolingDiagnostics { | kotlin { | androidTarget() /* <- register the androidTarget */ | } - """.trimMargin() + """.trimMargin(), + throwable = sourceSet.isRegisteredByKotlinSourceSetConventionAt + ) + } + + object IosSourceSetConventionUsedWithoutIosTarget : ToolingDiagnosticFactory(WARNING) { + operator fun invoke(sourceSet: KotlinSourceSet) = build( + """ + |Accessed '$sourceSet' without registering any ios target: + | kotlin { + | /* Register at least one of the following targets */ + | iosX64() + | iosArm64() + | iosSimulatorArm64() + | + | /* Use convention + | sourceSets.${sourceSet.name}.dependencies { + | + | } + | } + """.trimMargin(), + throwable = sourceSet.isRegisteredByKotlinSourceSetConventionAt ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/MppSourceSetConventionsDiagnosticTests.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/MppSourceSetConventionsDiagnosticTests.kt index d21417f67c1..8a960703136 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/MppSourceSetConventionsDiagnosticTests.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/diagnosticsTests/MppSourceSetConventionsDiagnosticTests.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.gradle.unitTests.diagnosticsTests +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformSourceSetConventionsImpl.iosMain +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformSourceSetConventionsImpl.iosTest import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.plugin.configurationResult import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP @@ -86,4 +88,16 @@ class MppSourceSetConventionsDiagnosticTests { checkDiagnostics("AndroidMainSourceSetConventionUsedWithoutAndroidTarget") } } + + @Test + fun `test - iosMain and iosTest - without any ios target`() = buildProjectWithMPP().runLifecycleAwareTest { + multiplatformExtension.linuxX64() + multiplatformExtension.jvm() + + multiplatformExtension.sourceSets.iosMain + multiplatformExtension.sourceSets.iosTest + + configurationResult.await() + checkDiagnostics("IosSourceSetConventionUsedWithoutIosTarget") + } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/IosSourceSetConventionUsedWithoutIosTarget.txt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/IosSourceSetConventionUsedWithoutIosTarget.txt new file mode 100644 index 00000000000..bdc91933998 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/resources/expectedDiagnostics/IosSourceSetConventionUsedWithoutIosTarget.txt @@ -0,0 +1,31 @@ +[IosSourceSetConventionUsedWithoutIosTarget | WARNING] Accessed 'source set iosMain' without registering any ios target: + kotlin { + /* Register at least one of the following targets */ + iosX64() + iosArm64() + iosSimulatorArm64() + + /* Use convention + sourceSets.iosMain.dependencies { + + } + } +---- +[IosSourceSetConventionUsedWithoutIosTarget | WARNING] Accessed 'source set iosTest' without registering any ios target: + kotlin { + /* Register at least one of the following targets */ + iosX64() + iosArm64() + iosSimulatorArm64() + + /* Use convention + sourceSets.iosTest.dependencies { + + } + } +---- +[UnusedSourceSetsWarning | WARNING] The following Kotlin source sets were configured but not added to any Kotlin compilation: + * iosMain + * iosTest +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