Gradle, JS: resolve NPM dependencies inside task when possible

#KT-30530
This commit is contained in:
Sergey Rostov
2019-05-13 10:54:21 +03:00
parent a69881850b
commit c0deea33bb
13 changed files with 215 additions and 82 deletions
@@ -30,10 +30,7 @@ internal val jvmPresetEntry = KotlinPresetEntry(
internal val jsPresetEntry = KotlinPresetEntry(
"js",
typeName("$MPP_PACKAGE.KotlinJsTargetPreset"),
typeName(
"$MPP_PACKAGE.KotlinOnlyTarget",
"$MPP_PACKAGE.KotlinJsCompilation"
)
typeName("org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget")
)
internal val androidPresetEntry = KotlinPresetEntry(
@@ -5,12 +5,11 @@ import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetsContainerWithPresets
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetPreset
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
// DO NOT EDIT MANUALLY! Generated by org.jetbrains.kotlin.generators.gradle.dsl.MppPresetFunctionsCodegenKt
@@ -34,8 +33,8 @@ interface KotlinTargetContainerWithPresetFunctions : KotlinTargetsContainerWithP
fun js(
name: String = "js",
configure: KotlinOnlyTarget<KotlinJsCompilation>.() -> Unit = { }
): KotlinOnlyTarget<KotlinJsCompilation> =
configure: KotlinJsTarget.() -> Unit = { }
): KotlinJsTarget =
configureOrCreate(
name,
presets.getByName("js") as KotlinJsTargetPreset,
@@ -220,6 +220,7 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
companion object {
const val testTaskNameSuffix = "test"
const val runTaskNameSuffix = "run"
fun defineConfigurationsForCompilation(
compilation: KotlinCompilation<*>
@@ -6,25 +6,22 @@
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset
import org.jetbrains.kotlin.gradle.plugin.*
abstract class KotlinOnlyTargetPreset<R : KotlinOnlyTarget<T>, T : KotlinCompilation<*>>(
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation<*>>(
protected val project: Project,
protected val kotlinPluginVersion: String
) : KotlinTargetPreset<R> {
) : KotlinTargetPreset<KotlinOnlyTarget<T>> {
protected abstract fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<T>
protected open fun provideTargetDisambiguationClassifier(target: KotlinOnlyTarget<T>): String? =
target.targetName
abstract protected fun instantiateTarget(): R
protected open fun createKotlinOnlyTarget() = KotlinOnlyTarget<T>(project, platformType)
override fun createTarget(name: String): R {
val result = instantiateTarget().apply {
override fun createTarget(name: String): KotlinOnlyTarget<T> {
val result = createKotlinOnlyTarget().apply {
targetName = name
disambiguationClassifier = provideTargetDisambiguationClassifier(this@apply)
preset = this@KotlinOnlyTargetPreset
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2019 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.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator.Companion.runTaskNameSuffix
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator.Companion.testTaskNameSuffix
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsNodeDsl
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
import org.jetbrains.kotlin.gradle.targets.js.subtargets.KotlinBrowserJs
import org.jetbrains.kotlin.gradle.targets.js.subtargets.KotlinNodeJs
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
class KotlinJsTarget(project: Project, platformType: KotlinPlatformType) :
KotlinOnlyTarget<KotlinJsCompilation>(project, platformType), KotlinJsTargetDsl {
val testTaskName = lowerCamelCaseName(disambiguationClassifier, testTaskNameSuffix)
val testTask get() = project.tasks.maybeCreate(testTaskName)
val runTaskName = lowerCamelCaseName(disambiguationClassifier, runTaskNameSuffix)
val runTask get() = project.tasks.maybeCreate(runTaskName)
private var hasSubtargets = false
val browser by lazy {
hasSubtargets = true
KotlinBrowserJs(this).also {
it.configure()
}
}
val nodejs by lazy {
hasSubtargets = true
KotlinNodeJs(this).also {
it.configure()
}
}
override fun browser(body: KotlinJsBrowserDsl.() -> Unit) {
browser.body()
}
override fun nodejs(body: KotlinJsNodeDsl.() -> Unit) {
nodejs.body()
}
fun configureDefaults() {
if (!hasSubtargets) {
browser()
}
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.gradle.targets.js
import org.gradle.api.plugins.JavaBasePlugin
import org.jetbrains.kotlin.gradle.plugin.Kotlin2JsSourceSetProcessor
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetProcessor
@@ -15,10 +16,33 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
open class KotlinJsTargetConfigurator(kotlinPluginVersion: String) :
KotlinTargetConfigurator<KotlinJsCompilation>(true, true, kotlinPluginVersion) {
override fun configureTarget(target: KotlinOnlyTarget<KotlinJsCompilation>) {
target as KotlinJsTarget
target.configureDefaults()
super.configureTarget(target)
target.project.tasks.maybeCreate(runTaskNameSuffix).dependsOn(target.runTask)
}
override fun configureTest(target: KotlinOnlyTarget<KotlinJsCompilation>) {
// tests configured in KotlinJsSubTarget.configure
target as KotlinJsTarget
val tasks = target.project.tasks
val check = tasks.findByName(JavaBasePlugin.CHECK_TASK_NAME)
@Suppress("IfThenToSafeAccess")
if (check != null) {
check.dependsOn(target.testTask)
}
}
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> {
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
return Kotlin2JsSourceSetProcessor(compilation.target.project, tasksProvider, compilation, kotlinPluginVersion)
@@ -3,22 +3,27 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
@file:Suppress("PackageDirectoryMismatch")
// Old package for compatibility
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsSingleTargetConfigurator
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTargetConfigurator
open class KotlinJsTargetPreset(
project: Project,
kotlinPluginVersion: String
) : KotlinOnlyTargetPreset<KotlinOnlyTarget<KotlinJsCompilation>, KotlinJsCompilation>(
) : KotlinOnlyTargetPreset<KotlinJsCompilation>(
project,
kotlinPluginVersion
) {
override fun instantiateTarget() = KotlinOnlyTarget<KotlinJsCompilation>(project, KotlinPlatformType.js)
override val platformType: KotlinPlatformType
get() = KotlinPlatformType.js
override fun createKotlinOnlyTarget() = KotlinJsTarget(project, platformType)
override fun createKotlinTargetConfigurator() = KotlinJsTargetConfigurator(kotlinPluginVersion)
@@ -27,9 +32,6 @@ open class KotlinJsTargetPreset(
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJsCompilation>) =
KotlinJsCompilationFactory(project, forTarget)
override val platformType: KotlinPlatformType
get() = KotlinPlatformType.js
companion object {
const val PRESET_NAME = "js"
}
@@ -44,5 +46,5 @@ class KotlinJsSingleTargetPreset(
// In a Kotlin/JS single-platform project, we don't need any disambiguation suffixes or prefixes in the names:
override fun provideTargetDisambiguationClassifier(target: KotlinOnlyTarget<KotlinJsCompilation>): String? = null
override fun createKotlinTargetConfigurator() = KotlinJsSingleTargetConfigurator(kotlinPluginVersion)
override fun createKotlinTargetConfigurator() = KotlinJsTargetConfigurator(kotlinPluginVersion)
}
@@ -1,36 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. 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.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
class KotlinNodeJs(target: KotlinOnlyTarget<KotlinJsCompilation>) :
KotlinJsInnerTargetConfigurator(target) {
override fun configureDefaultTestFramework(it: KotlinJsTest) {
it.useNodeJs { }
}
override fun configureRun(compilation: KotlinJsCompilation) {
// source maps support
compilation.dependencies {
runtimeOnly(kotlin("test-nodejs-runner"))
}
val project = target.project
project.createOrRegisterTask<NodeJsExec>("run") {
it.args(project.npmProject.compileOutput(compilation.compileKotlinTask))
// source maps support
it.args("--require", "kotlin-test-nodejs-runner/kotlin-nodejs-source-map-support.js")
}
}
}
@@ -10,21 +10,22 @@ import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
interface KotlinJsTargetDsl {
fun browser()
fun browser() = browser { }
fun browser(body: KotlinJsBrowserDsl.() -> Unit)
fun nodejs()
fun nodejs() = nodejs { }
fun nodejs(body: KotlinJsNodeDsl.() -> Unit)
}
interface KotlinJsInnerTargetDsl {
interface KotlinJsSubTargetDsl {
fun testTask(body: KotlinJsTest.() -> Unit)
}
interface KotlinJsBrowserDsl : KotlinJsInnerTargetDsl {
interface KotlinJsBrowserDsl : KotlinJsSubTargetDsl {
fun runTask(body: KotlinWebpack.() -> Unit)
fun webpackTask(body: KotlinWebpack.() -> Unit)
}
interface KotlinJsNodeDsl : KotlinJsInnerTargetDsl {
interface KotlinJsNodeDsl : KotlinJsSubTargetDsl {
fun runTask(body: NodeJsExec.() -> Unit)
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2019 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.npm
import org.gradle.api.internal.AbstractTask
import org.gradle.api.tasks.TaskAction
open class NpmResolveTask : AbstractTask() {
@TaskAction
fun resolve() {
NpmResolver.resolve(project)
}
}
@@ -1,13 +1,15 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
* Copyright 2010-2019 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
package org.jetbrains.kotlin.gradle.targets.js.subtargets
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
@@ -15,8 +17,12 @@ import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
class KotlinBrowserJs(target: KotlinOnlyTarget<KotlinJsCompilation>) : KotlinJsInnerTargetConfigurator(target, "browser") {
class KotlinBrowserJs(target: KotlinJsTarget) :
KotlinJsSubTarget(target, "browser"),
KotlinJsBrowserDsl {
private val versions = project.nodeJs.versions
private val webpackTaskName = disambiguateCamelCased("webpack")
override fun configureDefaultTestFramework(it: KotlinJsTest) {
it.useKarma {
@@ -25,13 +31,21 @@ class KotlinBrowserJs(target: KotlinOnlyTarget<KotlinJsCompilation>) : KotlinJsI
}
}
override fun runTask(body: KotlinWebpack.() -> Unit) {
(project.tasks.getByName(runTaskName) as KotlinWebpack).body()
}
override fun webpackTask(body: KotlinWebpack.() -> Unit) {
(project.tasks.getByName(webpackTaskName) as KotlinWebpack).body()
}
override fun configureRun(compilation: KotlinJsCompilation) {
val project = compilation.target.project
val npmProject = project.npmProject
val compileKotlinTask = compilation.compileKotlinTask
project.createOrRegisterTask<KotlinWebpack>(disambiguateCamelCased("webpack")) {
it.dependsOn(compileKotlinTask)
it.dependsOn(npmResolveTask, compileKotlinTask)
it.entry = npmProject.compileOutput(compileKotlinTask)
@@ -39,7 +53,7 @@ class KotlinBrowserJs(target: KotlinOnlyTarget<KotlinJsCompilation>) : KotlinJsI
}
project.createOrRegisterTask<KotlinWebpack>(disambiguateCamelCased("run")) {
it.dependsOn(compileKotlinTask)
it.dependsOn(npmResolveTask, compileKotlinTask)
it.bin = "webpack-dev-server"
it.entry = npmProject.compileOutput(compileKotlinTask)
@@ -50,7 +64,7 @@ class KotlinBrowserJs(target: KotlinOnlyTarget<KotlinJsCompilation>) : KotlinJsI
)
it.outputs.upToDateWhen { false }
project.tasks.maybeCreate("run").dependsOn(it)
target.runTask.dependsOn(it)
}
}
}
@@ -1,27 +1,35 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
* Copyright 2010-2019 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
package org.jetbrains.kotlin.gradle.targets.js.subtargets
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetDsl
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolveTask
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
import org.jetbrains.kotlin.gradle.testing.internal.configureConventions
import org.jetbrains.kotlin.gradle.testing.internal.registerTestTask
import org.jetbrains.kotlin.utils.addIfNotNull
abstract class KotlinJsInnerTargetConfigurator(
val target: KotlinOnlyTarget<KotlinJsCompilation>,
abstract class KotlinJsSubTarget(
val target: KotlinJsTarget,
private val disambiguationClassifier: String
) {
) : KotlinJsSubTargetDsl {
val project get() = target.project
val npmResolveTask = project.createOrRegisterTask<NpmResolveTask>("npmResolve") {}
val runTaskName = disambiguateCamelCased("run")
val testTaskName = disambiguateCamelCased("test")
fun configure() {
configureTests()
configureRun()
@@ -52,7 +60,8 @@ abstract class KotlinJsInnerTargetConfigurator(
private fun configureTests(compilation: KotlinJsCompilation) {
val compileTask = compilation.compileKotlinTask
val testTaskName = disambiguateCamelCased("test")
compileTask.dependsOn(npmResolveTask)
// apply plugin (cannot be done at task instantiation time)
val nodeJs = NodeJsPlugin.apply(target.project).root
@@ -60,7 +69,7 @@ abstract class KotlinJsInnerTargetConfigurator(
val testJs = project.createOrRegisterTask<KotlinJsTest>(testTaskName) { testJs ->
testJs.group = LifecycleBasePlugin.VERIFICATION_GROUP
testJs.dependsOn(compileTask, nodeJs.nodeJsSetupTask)
testJs.dependsOn(npmResolveTask, compileTask, nodeJs.nodeJsSetupTask)
testJs.onlyIf {
compileTask.outputFile.exists()
@@ -71,7 +80,7 @@ abstract class KotlinJsInnerTargetConfigurator(
testJs.configureConventions()
project.tasks.maybeCreate("test").dependsOn(testJs)
target.testTask.dependsOn(testJs)
}
registerTestTask(testJs)
@@ -90,10 +99,15 @@ abstract class KotlinJsInnerTargetConfigurator(
fun configureRun() {
target.compilations.all { compilation ->
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
compilation.compileKotlinTask.dependsOn(npmResolveTask)
configureRun(compilation)
}
}
}
protected abstract fun configureRun(compilation: KotlinJsCompilation)
override fun testTask(body: KotlinJsTest.() -> Unit) {
(project.tasks.getByName(testTaskName) as KotlinJsTest).body()
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2019 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.subtargets
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsNodeDsl
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
class KotlinNodeJs(target: KotlinJsTarget) :
KotlinJsSubTarget(target, "nodeJs"),
KotlinJsNodeDsl {
override fun runTask(body: NodeJsExec.() -> Unit) {
(project.tasks.getByName(runTaskName) as NodeJsExec).body()
}
override fun configureDefaultTestFramework(it: KotlinJsTest) {
it.useNodeJs { }
}
override fun configureRun(compilation: KotlinJsCompilation) {
// source maps support
compilation.dependencies {
runtimeOnly(kotlin("test-nodejs-runner"))
}
val project = target.project
project.createOrRegisterTask<NodeJsExec>(disambiguateCamelCased("run")) {
val npmProject = project.npmProject
it.args(npmProject.compileOutput(compilation.compileKotlinTask))
// source maps support
it.args("--require", npmProject.getModuleEntryPath("kotlin-test-nodejs-runner"))
target.runTask.dependsOn(it)
}
}
}