From 7da220b0a2b5656c6577af81e787e428cbcb85ea Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Wed, 26 Feb 2020 14:28:42 +0300 Subject: [PATCH] [Gradle, JS] Check current chosen js compiler for targets in JS and MPP --- .../gradle/dsl/KotlinProjectExtension.kt | 25 +++-- ...linTargetContainerWithJsPresetFunctions.kt | 102 ++++++++++++++---- .../gradle/targets/js/KotlinJsTargets.kt | 19 ++++ 3 files changed, 120 insertions(+), 26 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargets.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt index 947abde7346..cd73510ba93 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinProjectExtension.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsSingleTargetPreset import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget +import org.jetbrains.kotlin.gradle.targets.js.calculateJsCompilerType import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrSingleTargetPreset import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName @@ -115,12 +116,19 @@ open class KotlinJsProjectExtension : override lateinit var defaultJsCompilerType: KotlinJsCompilerType - open fun js( - compiler: KotlinJsCompilerType = defaultJsCompilerType, - body: KotlinJsTargetDsl.() -> Unit = { } + private fun jsInternal( + compiler: KotlinJsCompilerType? = null, + body: KotlinJsTargetDsl.() -> Unit ): KotlinJsTargetDsl { + if (_target != null) { + val previousCompilerType = _target!!.calculateJsCompilerType() + check(compiler == null || previousCompilerType == compiler) { + "You already registered Kotlin/JS target with another compiler: ${previousCompilerType.lowerName}" + } + } + if (_target == null) { - val target: KotlinJsTargetDsl = when (compiler) { + val target: KotlinJsTargetDsl = when (compiler ?: defaultJsCompilerType) { LEGACY -> legacyPreset .also { it.irPreset = null } .createTarget("js") @@ -151,8 +159,13 @@ open class KotlinJsProjectExtension : } fun js( + compiler: KotlinJsCompilerType = defaultJsCompilerType, body: KotlinJsTargetDsl.() -> Unit = { } - ) = js(compiler = defaultJsCompilerType, body = body) + ): KotlinJsTargetDsl = jsInternal(compiler, body) + + fun js( + body: KotlinJsTargetDsl.() -> Unit = { } + ) = jsInternal(body = body) fun js() = js { } @@ -161,7 +174,7 @@ open class KotlinJsProjectExtension : ConfigureUtil.configure(configure, this) } - fun js(configure: Closure<*>) = js { + fun js(configure: Closure<*>) = jsInternal { ConfigureUtil.configure(configure, this) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetContainerWithJsPresetFunctions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetContainerWithJsPresetFunctions.kt index a6e4d902e89..9b9d0462ac6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetContainerWithJsPresetFunctions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinTargetContainerWithJsPresetFunctions.kt @@ -2,10 +2,8 @@ package org.jetbrains.kotlin.gradle.dsl import groovy.lang.Closure import org.gradle.util.ConfigureUtil -import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType -import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerTypeHolder -import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset -import org.jetbrains.kotlin.gradle.plugin.lowerName +import org.jetbrains.kotlin.gradle.plugin.* +import org.jetbrains.kotlin.gradle.targets.js.calculateJsCompilerType import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName @@ -16,17 +14,11 @@ interface KotlinTargetContainerWithJsPresetFunctions : name: String = "js", compiler: KotlinJsCompilerType = defaultJsCompilerType, configure: KotlinJsTargetDsl.() -> Unit = { } - ): KotlinJsTargetDsl = - configureOrCreate( - lowerCamelCaseName(name, if (compiler == KotlinJsCompilerType.BOTH) KotlinJsCompilerType.LEGACY.lowerName else null), - presets.getByName( - lowerCamelCaseName( - "js", - if (compiler == KotlinJsCompilerType.LEGACY) null else compiler.lowerName - ) - ) as KotlinTargetPreset, - configure - ) + ): KotlinJsTargetDsl = jsInternal( + name, + compiler, + configure + ) fun js( name: String, @@ -44,18 +36,18 @@ interface KotlinTargetContainerWithJsPresetFunctions : fun js( name: String = "js", configure: KotlinJsTargetDsl.() -> Unit = { } - ) = js(name = name, compiler = defaultJsCompilerType, configure = configure) + ) = jsInternal(name = name, configure = configure) fun js( compiler: KotlinJsCompilerType, configure: KotlinJsTargetDsl.() -> Unit = { } ) = js(name = "js", compiler = compiler, configure = configure) - fun js() = js(name = "js") { } - fun js(name: String) = js(name = name) { } - fun js(name: String, configure: Closure<*>) = js(name = name) { ConfigureUtil.configure(configure, this) } + fun js() = jsInternal(name = "js") { } + fun js(name: String) = jsInternal(name = name) { } + fun js(name: String, configure: Closure<*>) = jsInternal(name = name) { ConfigureUtil.configure(configure, this) } fun js(compiler: KotlinJsCompilerType, configure: Closure<*>) = js(compiler = compiler) { ConfigureUtil.configure(configure, this) } - fun js(configure: Closure<*>) = js { ConfigureUtil.configure(configure, this) } + fun js(configure: Closure<*>) = jsInternal { ConfigureUtil.configure(configure, this) } fun js( name: String, @@ -78,4 +70,74 @@ interface KotlinTargetContainerWithJsPresetFunctions : ) { ConfigureUtil.configure(configure, this) } +} + +private fun KotlinTargetContainerWithJsPresetFunctions.jsInternal( + name: String = "js", + compiler: KotlinJsCompilerType? = null, + configure: KotlinJsTargetDsl.() -> Unit +): KotlinJsTargetDsl { + val existingTarget = getExistingTarget(name, compiler) + + val compilerOrDefault = compiler + ?: existingTarget?.calculateJsCompilerType() + ?: defaultJsCompilerType + + val targetName = getTargetName(name, compilerOrDefault) + + if (existingTarget != null) { + val previousCompilerType = existingTarget.calculateJsCompilerType() + check(compiler == null || previousCompilerType == compiler) { + "You already registered Kotlin/JS target '$targetName' with another compiler: ${previousCompilerType.lowerName}" + } + } + + return configureOrCreate( + targetName, + presets.getByName( + lowerCamelCaseName( + "js", + if (compilerOrDefault == KotlinJsCompilerType.LEGACY) null else compilerOrDefault.lowerName + ) + ) as KotlinTargetPreset, + configure + ) +} + +// Try to find existing target with exact name +// and with append suffix Legacy in case when compiler for found target is BOTH, +// and removed suffix Legacy in case when current compiler is BOTH +private fun KotlinTargetContainerWithJsPresetFunctions.getExistingTarget( + name: String, + compiler: KotlinJsCompilerType? +): KotlinJsTargetDsl? { + + fun getPreviousTarget( + targetName: String, + currentBoth: Boolean + ): KotlinJsTargetDsl? { + val singleTarget = targets.findByName( + targetName + ) as KotlinJsTargetDsl? + + return singleTarget?.let { + val previousCompiler = it.calculateJsCompilerType() + if (compiler == KotlinJsCompilerType.BOTH && currentBoth || previousCompiler == KotlinJsCompilerType.BOTH && !currentBoth) { + it + } else null + } + } + + val targetNameCandidate = getTargetName(name, compiler) + + return targets.findByName(targetNameCandidate) as KotlinJsTargetDsl? + ?: getPreviousTarget(targetNameCandidate.removeJsCompilerSuffix(KotlinJsCompilerType.LEGACY), true) + ?: getPreviousTarget(lowerCamelCaseName(targetNameCandidate, KotlinJsCompilerType.LEGACY.lowerName), false) +} + +private fun getTargetName(name: String, compiler: KotlinJsCompilerType?): String { + return lowerCamelCaseName( + name, + if (compiler == KotlinJsCompilerType.BOTH) KotlinJsCompilerType.LEGACY.lowerName else null + ) } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargets.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargets.kt new file mode 100644 index 00000000000..d984bd7b9e5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsTargets.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2010-2020 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.targets.js + +import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType +import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl +import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget + +fun KotlinJsTargetDsl.calculateJsCompilerType(): KotlinJsCompilerType { + return when { + this is KotlinJsTarget && this.irTarget == null -> KotlinJsCompilerType.LEGACY + this is KotlinJsIrTarget && !this.mixedMode -> KotlinJsCompilerType.IR + this is KotlinJsTarget && this.irTarget != null -> KotlinJsCompilerType.BOTH + else -> throw IllegalStateException("Unable to find previous Kotlin/JS compiler type for $this") + } +} \ No newline at end of file