From b9cf47858d678d7190bd9914738d1bedfcfe6ef5 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 6 Jan 2023 15:59:11 +0100 Subject: [PATCH] [Gradle, JS] Add module kotlin-dom-compat-api as dependency with opt-out This reverts commit c73b6ac352ec557ead2c3b379bf444db4696d71a. --- .../internal/KotlinDependenciesManagement.kt | 4 + .../kotlinDomApiDependencyManagement.kt | 139 ++++++++++++++++++ .../internal/stdlibDependencyManagement.kt | 4 +- .../gradle/plugin/PropertiesProvider.kt | 5 + 4 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kotlinDomApiDependencyManagement.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt index a2d3fe36af8..b015381873f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinDependenciesManagement.kt @@ -43,6 +43,10 @@ internal fun customizeKotlinDependencies(project: Project) { ) } + if (propertiesProvider.stdlibDefaultDependency && propertiesProvider.stdlibDomApiIncluded) { + project.configureKotlinDomApiDefaultDependency(topLevelExtension, coreLibrariesVersion) + } + project.configurations.configureDefaultVersionsResolutionStrategy( coreLibrariesVersion ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kotlinDomApiDependencyManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kotlinDomApiDependencyManagement.kt new file mode 100644 index 00000000000..f1e5881c3e2 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kotlinDomApiDependencyManagement.kt @@ -0,0 +1,139 @@ +/* + * 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()}") diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt index ab47bfb2421..81007d3cd49 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/stdlibDependencyManagement.kt @@ -171,7 +171,7 @@ private fun KotlinTarget.addStdlibDependency( } } -private fun isStdlibAddedByUser( +internal fun isStdlibAddedByUser( configurations: ConfigurationContainer, stdlibModules: Set, vararg sourceSets: KotlinSourceSet @@ -220,7 +220,7 @@ private fun KotlinSourceSet.isRelatedToAndroidTestSourceSet(): Boolean { return androidVariant in androidTestVariants } -private val stdlibModules = setOf( +internal val stdlibModules = setOf( "kotlin-stdlib-common", "kotlin-stdlib", "kotlin-stdlib-jdk7", diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt index d89f554af27..fdab76c1e51 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/PropertiesProvider.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind import org.jetbrains.kotlin.gradle.dsl.NativeCacheOrchestration import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessageOutputStreamHandler.Companion.IGNORE_TCSM_OVERFLOW import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompilerProperty +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_JS_STDLIB_DOM_API_INCLUDED import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_ABI_SNAPSHOT import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_COMPILER_USE_PRECISE_COMPILATION_RESULTS_BACKUP import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_JS_KARMA_BROWSERS @@ -474,6 +475,9 @@ internal class PropertiesProvider private constructor(private val project: Proje val stdlibJdkVariantsVersionAlignment: Boolean get() = booleanProperty(KOTLIN_STDLIB_JDK_VARIANTS_VERSION_ALIGNMENT) ?: true + val stdlibDomApiIncluded: Boolean + get() = booleanProperty(KOTLIN_JS_STDLIB_DOM_API_INCLUDED) ?: true + val kotlinTestInferJvmVariant: Boolean get() = booleanProperty("kotlin.test.infer.jvm.variant") ?: true @@ -562,6 +566,7 @@ internal class PropertiesProvider private constructor(private val project: Proje object PropertyNames { const val KOTLIN_STDLIB_DEFAULT_DEPENDENCY = "kotlin.stdlib.default.dependency" const val KOTLIN_STDLIB_JDK_VARIANTS_VERSION_ALIGNMENT = "kotlin.stdlib.jdk.variants.version.alignment" + const val KOTLIN_JS_STDLIB_DOM_API_INCLUDED = "kotlin.js.stdlib.dom.api.included" const val KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA = "kotlin.mpp.enableGranularSourceSetsMetadata" const val KOTLIN_MPP_ENABLE_COMPATIBILITY_METADATA_VARIANT = "kotlin.mpp.enableCompatibilityMetadataVariant" const val KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION = "kotlin.mpp.enableCInteropCommonization"