![JAR search and dependency download from the Maven repository](/logo.png)
org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformSourceSetCheckers.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2024 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.dsl
import org.jetbrains.kotlin.gradle.dsl.KotlinSourceSetConvention.isAccessedByKotlinSourceSetConventionAt
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
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.KotlinWasmTargetType
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.presetName
internal object PlatformSourceSetConventionsChecker : KotlinGradleProjectChecker {
data class CheckedPlatformInfo(
val expectedTargetName: String,
val expectedTargetType: Class,
val matches: (T) -> Boolean,
)
inline fun CheckedPlatformInfo(
expectedTargetName: String,
noinline matches: (T) -> Boolean = { true }
) = CheckedPlatformInfo(
expectedTargetName = expectedTargetName,
expectedTargetType = T::class.java,
matches = matches
)
private val nativeTargetPresets get() = HostManager()
.targetValues
.map { konanTarget -> CheckedPlatformInfo(konanTarget.presetName) { it.konanTarget == konanTarget } }
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
listOf(
CheckedPlatformInfo("js") {
it.wasmTargetType == null
},
CheckedPlatformInfo("jvm"),
CheckedPlatformInfo("wasmJs") {
it.wasmTargetType == KotlinWasmTargetType.JS
},
CheckedPlatformInfo("wasmWasi") {
it.wasmTargetType == KotlinWasmTargetType.WASI
},
).plus(nativeTargetPresets).forEach { checkedPlatformInfo ->
@Suppress("UNCHECKED_CAST")
runChecks(checkedPlatformInfo as CheckedPlatformInfo)
}
}
private suspend fun KotlinGradleProjectCheckerContext.runChecks(platform: CheckedPlatformInfo) {
val kotlin = project.multiplatformExtensionOrNull ?: return
val sourceSets = kotlin.awaitSourceSets()
/* Find Main and Test source sets that have been registered by the convention */
val platformSourceSets = listOfNotNull(
sourceSets.findByName("${platform.expectedTargetName}Main"),
sourceSets.findByName("${platform.expectedTargetName}Test")
)
.filter { it.isAccessedByKotlinSourceSetConventionAt != null }
.ifEmpty { return }
/* Check if a custom target name was used */
val customNamedTarget = kotlin.targets.withType(platform.expectedTargetType)
.filter { target -> platform.matches(target) }
.firstOrNull { target -> target.name != platform.expectedTargetName }
if (customNamedTarget != null) {
platformSourceSets.forEach { sourceSet ->
project.reportDiagnostic(
PlatformSourceSetConventionUsedWithCustomTargetName(sourceSet, customNamedTarget, platform.expectedTargetName)
)
}
} else if (kotlin.targets.findByName(platform.expectedTargetName) == null) {
platformSourceSets.forEach { sourceSet ->
project.reportDiagnostic(
PlatformSourceSetConventionUsedWithoutCorrespondingTarget(sourceSet, platform.expectedTargetName)
)
}
}
}
}
internal object AndroidMainSourceSetConventionsChecker : KotlinGradleProjectChecker {
override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
val kotlin = project.multiplatformExtensionOrNull ?: return
val androidMainSourceSet = kotlin.awaitSourceSets().findByName("androidMain") ?: return
if (androidMainSourceSet.isAccessedByKotlinSourceSetConventionAt == null) return
val androidTarget = kotlin.awaitTargets().findByName("android")
if (androidTarget == null) {
project.reportDiagnostic(AndroidMainSourceSetConventionUsedWithoutAndroidTarget(androidMainSourceSet))
}
}
}
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.isAccessedByKotlinSourceSetConventionAt != null }
val hasIosTarget = kotlin.awaitTargets()
.any { target -> target is KotlinNativeTarget && target.konanTarget.family == Family.IOS }
if (!hasIosTarget) {
iosSourceSets.forEach { sourceSet ->
project.reportDiagnostic(IosSourceSetConventionUsedWithoutIosTarget(sourceSet))
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy