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

org.jetbrains.kotlin.gradle.internal.kotlinDomApiDependencyManagement.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
Show newest version
/*
 * Copyright 2010-2022 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.internal

import org.gradle.api.Project
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.GradleKpmModule
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
import org.jetbrains.kotlin.gradle.targets.js.npm.SemVer

private const val KOTLIN_DOM_API_MODULE_NAME = "kotlin-dom-api-compat"

private val Dependency.isKotlinDomApiDependency: Boolean
    get() = group == KOTLIN_MODULE_GROUP && (name == KOTLIN_DOM_API_MODULE_NAME)

private val kotlin190Version = SemVer(1.toBigInteger(), 9.toBigInteger(), 0.toBigInteger())

private fun isAtLeast1_9_0(version: String) = SemVer.fromGradleRichVersion(version) >= kotlin190Version

internal fun Project.configureKotlinDomApiDefaultDependency(
    topLevelExtension: KotlinTopLevelExtension,
    coreLibrariesVersion: Provider
) {
    when (topLevelExtension) {
        is KotlinPm20ProjectExtension -> addKotlinDomApiToKpmProject(project, coreLibrariesVersion)

        is KotlinJsProjectExtension -> topLevelExtension.registerTargetObserver { target ->
            target?.addKotlinDomApiDependency(configurations, dependencies, coreLibrariesVersion)
        }

        is KotlinSingleTargetExtension<*> -> topLevelExtension
            .target
            .addKotlinDomApiDependency(configurations, dependencies, coreLibrariesVersion)

        is KotlinMultiplatformExtension -> topLevelExtension
            .targets
            .configureEach { target ->
                target.addKotlinDomApiDependency(configurations, dependencies, coreLibrariesVersion)
            }
    }
}

private fun addKotlinDomApiToKpmProject(
    project: Project,
    coreLibrariesVersion: Provider
) {
    project.pm20Extension.modules.named(GradleKpmModule.MAIN_MODULE_NAME) { main ->
        main.variants.configureEach { variant ->
            when (variant.platformType) {
                KotlinPlatformType.common -> error("variants are not expected to be common")
                KotlinPlatformType.js -> {
                    val dependencyHandler = project.dependencies
                    variant.dependencies {
                        api(dependencyHandler.kotlinDomApiDependency(coreLibrariesVersion.get()))
                    }
                }
                else -> {}
            }
        }
    }
}

private fun KotlinTarget.addKotlinDomApiDependency(
    configurations: ConfigurationContainer,
    dependencies: DependencyHandler,
    coreLibrariesVersion: Provider
) {
    if (this is KotlinJsTarget) {
        irTarget?.addKotlinDomApiDependency(configurations, dependencies, coreLibrariesVersion)
    }

    compilations.configureEach { compilation ->
        if (compilation.platformType != KotlinPlatformType.js) return@configureEach
        if (compilation !is KotlinJsIrCompilation) return@configureEach

        compilation.allKotlinSourceSets.forEach { kotlinSourceSet ->
            val scopeConfiguration = configurations
                .sourceSetDependencyConfigurationByScope(kotlinSourceSet, KotlinDependencyScope.API_SCOPE)

            scopeConfiguration.withDependencies { dependencySet ->
                if (isKotlinDomApiAddedByUser(configurations, kotlinSourceSet)) return@withDependencies

                val stdlibDependency = KotlinDependencyScope.values()
                    .map { scope ->
                        configurations.sourceSetDependencyConfigurationByScope(kotlinSourceSet, scope)
                    }
                    .flatMap { it.allNonProjectDependencies() }
                    .singleOrNull { dependency ->
                        dependency.group == KOTLIN_MODULE_GROUP && dependency.name in stdlibModules
                    }

                if (stdlibDependency != null) {
                    val depVersion = stdlibDependency.version ?: coreLibrariesVersion.get()
                    if (!isAtLeast1_9_0(depVersion)) return@withDependencies
                }

                // Check if stdlib is directly added to SourceSet

                dependencySet.addLater(
                    coreLibrariesVersion.map {
                        dependencies.kotlinDomApiDependency(it)
                    }
                )
            }
        }
    }
}

private fun isKotlinDomApiAddedByUser(
    configurations: ConfigurationContainer,
    vararg sourceSets: KotlinSourceSet
): Boolean {
    return sourceSets
        .asSequence()
        .flatMap { sourceSet ->
            KotlinDependencyScope.values().map { scope ->
                configurations.sourceSetDependencyConfigurationByScope(sourceSet, scope)
            }.asSequence()
        }
        .flatMap { it.allNonProjectDependencies().asSequence() }
        .any { it.isKotlinDomApiDependency }
}

internal fun DependencyHandler.kotlinDomApiDependency(versionOrNull: String?) =
    create("$KOTLIN_MODULE_GROUP:$KOTLIN_DOM_API_MODULE_NAME${versionOrNull?.prependIndent(":").orEmpty()}")




© 2015 - 2024 Weber Informatics LLC | Privacy Policy