All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformSourceSetConventions.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-RC
Show newest version
/*
 * 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.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.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.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.konan.target.Family

@KotlinGradlePluginPublicDsl
interface KotlinMultiplatformSourceSetConventions {
    val NamedDomainObjectContainer.commonMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.commonTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.nativeMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.nativeTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.appleMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.appleTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.iosMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.iosTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.tvosMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.tvosTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.watchosMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.watchosTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.macosMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.macosTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.linuxMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.linuxTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.mingwMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.mingwTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.androidNativeMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.androidNativeTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.jvmMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.jvmTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.jsMain: NamedDomainObjectProvider
    val NamedDomainObjectContainer.jsTest: NamedDomainObjectProvider
    val NamedDomainObjectContainer.androidMain: NamedDomainObjectProvider

    @ExperimentalWasmDsl
    val NamedDomainObjectContainer.wasmJsMain: NamedDomainObjectProvider

    @ExperimentalWasmDsl
    val NamedDomainObjectContainer.wasmJsTest: NamedDomainObjectProvider

    @ExperimentalWasmDsl
    val NamedDomainObjectContainer.wasmWasiMain: NamedDomainObjectProvider

    @ExperimentalWasmDsl
    val NamedDomainObjectContainer.wasmWasiTest: NamedDomainObjectProvider

    operator fun NamedDomainObjectProvider.invoke(
        configure: KotlinSourceSet.() -> Unit,
    ): Unit = get().run(configure)

    fun NamedDomainObjectProvider.dependencies(
        handler: KotlinDependencyHandler.() -> Unit,
    ): Unit = get().dependencies(handler)

    fun NamedDomainObjectProvider.languageSettings(
        configure: LanguageSettingsBuilder.() -> Unit,
    ): Unit = this { languageSettings(configure) }
}

/* Implementation */

internal object KotlinMultiplatformSourceSetConventionsImpl : KotlinMultiplatformSourceSetConventions {
    override val NamedDomainObjectContainer.commonMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.commonTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.nativeMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.nativeTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.appleMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.appleTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.iosMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.iosTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.tvosMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.tvosTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.watchosMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.watchosTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.macosMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.macosTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.linuxMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.linuxTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.mingwMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.mingwTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.androidNativeMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.androidNativeTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.jvmMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.jvmTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.jsMain by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.jsTest by KotlinSourceSetConvention
    override val NamedDomainObjectContainer.androidMain by KotlinSourceSetConvention

    @ExperimentalWasmDsl
    override val NamedDomainObjectContainer.wasmJsMain by KotlinSourceSetConvention

    @ExperimentalWasmDsl
    override val NamedDomainObjectContainer.wasmJsTest by KotlinSourceSetConvention

    @ExperimentalWasmDsl
    override val NamedDomainObjectContainer.wasmWasiMain by KotlinSourceSetConvention

    @ExperimentalWasmDsl
    override val NamedDomainObjectContainer.wasmWasiTest by KotlinSourceSetConvention
}

/* Checkers */

internal object PlatformSourceSetConventionsChecker : KotlinGradleProjectChecker {
    data class CheckedPlatformInfo(
        val expectedTargetName: String,
        val expectedTargetType: Class,
    )

    override suspend fun KotlinGradleProjectCheckerContext.runChecks(collector: KotlinToolingDiagnosticsCollector) {
        listOf(
            CheckedPlatformInfo("js", KotlinJsTargetDsl::class.java),
            CheckedPlatformInfo("jvm", KotlinJvmTarget::class.java)
        ).forEach { checkedPlatformInfo -> runChecks(checkedPlatformInfo) }
    }

    private suspend fun KotlinGradleProjectCheckerContext.runChecks(platform: CheckedPlatformInfo) {
        val kotlin = project.multiplatformExtensionOrNull ?: return
        val sourceSets = kotlin.awaitSourceSets()

        /* Find jvmMain and jvmTest source sets that have been registered by the convention */
        val platformSourceSets = listOfNotNull(
            sourceSets.findByName("${platform.expectedTargetName}Main"),
            sourceSets.findByName("${platform.expectedTargetName}Test")
        )
            .filter { it.isRegisteredByKotlinSourceSetConventionAt != null }
            .ifEmpty { return }

        /* Check if a custom target name was used */
        val customNamedTarget = kotlin.targets.withType(platform.expectedTargetType)
            .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.isRegisteredByKotlinSourceSetConventionAt == 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.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))
            }
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy