diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinBrowserJs.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinBrowserJs.kt index c0f2fc4a9f9..7d4c69d07ad 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinBrowserJs.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinBrowserJs.kt @@ -15,9 +15,7 @@ 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 -) : KotlinJsInnerTargetConfigurator(target) { +class KotlinBrowserJs(target: KotlinOnlyTarget) : KotlinJsInnerTargetConfigurator(target, "browser") { private val versions = project.nodeJs.versions override fun configureDefaultTestFramework(it: KotlinJsTest) { @@ -32,16 +30,6 @@ class KotlinBrowserJs( val npmProject = project.npmProject val compileKotlinTask = compilation.compileKotlinTask - compilation.dependencies { - runtimeOnly(versions.webpack) - runtimeOnly(versions.webpackCli) - runtimeOnly(versions.webpackBundleAnalyzer) - - // for source map support - runtimeOnly(versions.sourceMapLoader.npm(project)) - runtimeOnly(versions.sourceMapSupport.npm(project)) - } - project.createOrRegisterTask(disambiguateCamelCased("webpack")) { it.dependsOn(compileKotlinTask) @@ -50,10 +38,6 @@ class KotlinBrowserJs( project.tasks.getByName(LifecycleBasePlugin.ASSEMBLE_TASK_NAME).dependsOn(it) } - compilation.dependencies { - runtimeOnly(npm("webpack-dev-server", "3.3.1")) - } - project.createOrRegisterTask(disambiguateCamelCased("run")) { it.dependsOn(compileKotlinTask) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsInnerTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsInnerTargetConfigurator.kt index 8d4f1438c6d..90c41bce798 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsInnerTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/KotlinJsInnerTargetConfigurator.kt @@ -16,9 +16,11 @@ 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) { +abstract class KotlinJsInnerTargetConfigurator( + val target: KotlinOnlyTarget, + private val disambiguationClassifier: String +) { val project get() = target.project - private val disambiguationClassifier get() = "browser" fun configure() { configureTests() @@ -64,7 +66,6 @@ abstract class KotlinJsInnerTargetConfigurator(val target: KotlinOnlyTarget if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesBuilder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesBuilder.kt index e20243d712c..2f3f40c4595 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesBuilder.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.gradle.targets.js.npm import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.artifacts.ResolvedDependency import org.gradle.api.artifacts.component.ProjectComponentIdentifier @@ -27,30 +28,21 @@ internal class GradleNodeModulesBuilder(val project: Project) : AutoCloseable { GradleNodeModule(it, dir.resolve(it)) } - fun visitCompilation(compilation: KotlinCompilation) { - val project = compilation.target.project - - // classpath - compilation.relatedConfigurationNames.forEach { configurationName -> - val configuration = project.configurations.getByName(configurationName) - if (configuration.isCanBeResolved) { - configuration.resolvedConfiguration.firstLevelModuleDependencies.forEach { - visitDependency(compilation, it) - } + fun visitConfiguration(configuration: Configuration) { + if (configuration.isCanBeResolved) { + configuration.resolvedConfiguration.firstLevelModuleDependencies.forEach { + visitDependency(it) } } } - private fun visitDependency( - compilation: KotlinCompilation, - dependency: ResolvedDependency - ) { + private fun visitDependency(dependency: ResolvedDependency) { if (!visited.add(dependency)) return visitArtifacts(dependency, dependency.moduleArtifacts) dependency.children.forEach { - visitDependency(compilation, it) + visitDependency(it) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmPackages.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmPackages.kt index 179261f2e3e..062661c87ac 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmPackages.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmPackages.kt @@ -6,6 +6,8 @@ package org.jetbrains.kotlin.gradle.targets.js.npm import org.gradle.api.Project +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ExternalModuleDependency class NpmPackages { val webpack = NpmPackageVersion("webpack", "4.29.6") @@ -17,6 +19,7 @@ class NpmPackages { val sourceMapSupport = NpmPackageVersion("source-map-support", "0.5.12") val mocha = NpmPackageVersion("mocha", "6.1.2") + val mochaTeamCityReporter = NpmPackageVersion("mocha-teamcity-reporter", ">=2.0.0") val karma = NpmPackageVersion("karma", "4.0.1") val karmaTeamcityReporter = NpmPackageVersion("karma-teamcity-reporter", "1.1.0") @@ -32,8 +35,19 @@ class NpmPackages { val karmaWebpack = NpmPackageVersion("karma-webpack", "*") val karmaSourceMapSupport = NpmPackageVersion("karma-source-map-support", "1.4.0") + + val kotlinNodeJsTestRunner = KotlinGradleNpmPackage("test-nodejs-runner") } -data class NpmPackageVersion(val name: String, var version: String) { - fun npm(project: Project) = NpmDependency(project, null, name, version) +interface RequiredKotlinJsDependency { + fun createDependency(project: Project): Dependency +} + +data class NpmPackageVersion(val name: String, var version: String) : RequiredKotlinJsDependency { + override fun createDependency(project: Project) = NpmDependency(project, null, name, version) +} + +data class KotlinGradleNpmPackage(val simpleModuleName: String): RequiredKotlinJsDependency { + override fun createDependency(project: Project): Dependency = + project.dependencies.create("org.jetbrains.kotlin:kotlin-$simpleModuleName") } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolver.kt index 0d1cbb7617f..fb3bbed41bf 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolver.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.gradle.targets.js.npm import com.google.gson.Gson import com.google.gson.GsonBuilder import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.execution.TaskExecutionGraph import org.gradle.api.file.CopySpec import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension @@ -46,7 +48,23 @@ internal class NpmResolver private constructor(val rootProject: Project) { else { val resolver = NpmResolver(rootProject) check(resolver.resolve(rootProject, null)) - ResolvedNow(ResolvedProject(resolver.npmPackages)) + ResolvedNow(ResolvedProject(resolver.npmPackages, resolver.requiredByTasks)) + } + } + + fun checkRequiredDependencies(project: Project, target: RequiresNpmDependencies) { + val required = ProjectData[project.rootProject]?.resolved?.requiredByTasks + check(required != null) { + "NPM dependencies should be resolved before $target execution" + } + + val targetRequired = required!![target]?.toSet() ?: setOf() + + target.requiredNpmDependencies.forEach { + check(it in targetRequired) { + "$it required by $target after npm dependencies was resolved. " + + "This may be caused by changing $target configuration after npm dependencies resolution." + } } } } @@ -62,9 +80,17 @@ internal class NpmResolver private constructor(val rootProject: Project) { private val packageManager = nodeJs.packageManager private val hoistGradleNodeModules = npmProject.hoistGradleNodeModules private val npmPackages = mutableListOf() + private val requiredByTasks = mutableMapOf>() private val gson = GsonBuilder() .setPrettyPrinting() .create() + private val readyTaskGraph: TaskExecutionGraph? + + init { + var readyTaskGraph: TaskExecutionGraph? = null + rootProject.gradle.taskGraph.whenReady { readyTaskGraph = it } + this.readyTaskGraph = readyTaskGraph + } class ProjectData(var resolved: ResolvedProject? = null) { companion object { @@ -74,7 +100,10 @@ internal class NpmResolver private constructor(val rootProject: Project) { } } - class ResolvedProject(val npmPackages: Collection) { + class ResolvedProject( + val npmPackages: Collection, + val requiredByTasks: Map> + ) { val dependencies by lazy { npmPackages.flatMapTo(mutableSetOf()) { it.npmDependencies } } @@ -157,6 +186,8 @@ internal class NpmResolver private constructor(val rootProject: Project) { val packageJson = PackageJson(project.name, project.version.toString()) val npmDependencies = mutableSetOf() + visitTasksRequiredDependencies(project, npmDependencies, gradleComponents) + visitNpmDependencies(project, npmDependencies, gradleComponents, packageJson) if (!hoistGradleNodeModules || project == project.rootProject) { @@ -178,6 +209,36 @@ internal class NpmResolver private constructor(val rootProject: Project) { else NpmPackage(project, packageJson, npmDependencies) } + private fun visitTasksRequiredDependencies( + project: Project, + npmDependencies: MutableSet, + gradleComponents: GradleNodeModulesBuilder + ) { + var toolsDependenciesConfiguration: Configuration? = project.configurations.create("jsTools") + + project.tasks.toList().forEach { task -> + if (task is RequiresNpmDependencies) { + if (readyTaskGraph?.hasTask(task) ?: task.enabled) { + val list = task.requiredNpmDependencies.toList() + + requiredByTasks[task] = list + list.forEach { requiredDependency -> + val configuration: Configuration = toolsDependenciesConfiguration + ?: project.configurations.create("jsTools").also { new -> + toolsDependenciesConfiguration = new + } + + configuration.dependencies.add(requiredDependency.createDependency(project)) + } + } + } + } + + if (toolsDependenciesConfiguration != null) { + visitConfiguration(toolsDependenciesConfiguration!!, npmDependencies, gradleComponents) + } + } + private fun visitNpmDependencies( project: Project, npmDependencies: MutableSet, @@ -213,15 +274,10 @@ internal class NpmResolver private constructor(val rootProject: Project) { if (target.platformType == KotlinPlatformType.js) { target.compilations.toList().forEach { compilation -> compilation.relatedConfigurationNames.forEach { - project.configurations.getByName(it).allDependencies.forEach { dependency -> - when (dependency) { - is NpmDependency -> npmDependencies.add(dependency) - } - } + val configuration = project.configurations.getByName(it) + visitConfiguration(configuration, npmDependencies, gradleComponents) } - gradleComponents.visitCompilation(compilation) - if (compilation is KotlinJsCompilation) { visitKotlinJsCompilation(project, compilation) @@ -233,6 +289,20 @@ internal class NpmResolver private constructor(val rootProject: Project) { } } + private fun visitConfiguration( + configuration: Configuration, + npmDependencies: MutableSet, + gradleComponents: GradleNodeModulesBuilder + ) { + gradleComponents.visitConfiguration(configuration) + + configuration.allDependencies.forEach { dependency -> + when (dependency) { + is NpmDependency -> npmDependencies.add(dependency) + } + } + } + private fun visitKotlinJsCompilation( project: Project, compilation: KotlinJsCompilation diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/RequiresNpmDependencies.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/RequiresNpmDependencies.kt new file mode 100644 index 00000000000..a9ddff2e0b5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/RequiresNpmDependencies.kt @@ -0,0 +1,10 @@ +/* + * 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 + +interface RequiresNpmDependencies { + val requiredNpmDependencies: Collection +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTest.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTest.kt index d0f1bc20eb0..849a2787519 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTest.kt @@ -12,14 +12,14 @@ import org.gradle.process.internal.DefaultProcessForkOptions import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin -import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectLayout +import org.jetbrains.kotlin.gradle.targets.js.npm.* import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolver import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha import org.jetbrains.kotlin.gradle.targets.js.testing.nodejs.KotlinNodeJsTestRunner import org.jetbrains.kotlin.gradle.tasks.KotlinTest -open class KotlinJsTest : KotlinTest() { +open class KotlinJsTest : KotlinTest(), RequiresNpmDependencies { @Internal @SkipWhenEmpty internal var testFramework: KotlinJsTestFramework? = null @@ -27,17 +27,17 @@ open class KotlinJsTest : KotlinTest() { @Input var debug: Boolean = false - @Internal - var runtimeDependencyHandler: HasKotlinDependencies? = null - @Input var nodeModulesToLoad: MutableList = mutableListOf() + override val requiredNpmDependencies: Collection + get() = testFramework!!.requiredNpmDependencies + fun useNodeJs(body: KotlinNodeJsTestRunner.() -> Unit) = use(KotlinNodeJsTestRunner(), body) - fun useMocha(body: KotlinMocha.() -> Unit) = use(KotlinMocha(), body) + fun useMocha(body: KotlinMocha.() -> Unit) = use(KotlinMocha(project), body) - fun useKarma(body: KotlinKarma.() -> Unit) = use(KotlinKarma(), body) + fun useKarma(body: KotlinKarma.() -> Unit) = use(KotlinKarma(project), body) private inline fun use(runner: T, body: T.() -> Unit): T { check(testFramework == null) { @@ -47,16 +47,12 @@ open class KotlinJsTest : KotlinTest() { val testFramework = runner.also(body) this.testFramework = testFramework - val dependenciesHolder = runtimeDependencyHandler - if (dependenciesHolder != null) { - testFramework.configure(dependenciesHolder) - } - return testFramework } override fun executeTests() { NpmResolver.resolve(project) + NpmResolver.checkRequiredDependencies(project, this) super.executeTests() } @@ -65,7 +61,7 @@ open class KotlinJsTest : KotlinTest() { NpmResolver.resolve(project) - forkOptions.workingDir = NpmProjectLayout[project].nodeWorkDir + forkOptions.workingDir = NpmProject[project].nodeWorkDir forkOptions.executable = NodeJsPlugin.apply(project).root.environment.nodeExecutable val nodeJsArgs = mutableListOf() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTestFramework.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTestFramework.kt index e7f72efcadd..d67c3039f7d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTestFramework.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTestFramework.kt @@ -8,15 +8,12 @@ package org.jetbrains.kotlin.gradle.targets.js.testing import org.gradle.process.ProcessForkOptions import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies +import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies -interface KotlinJsTestFramework { +interface KotlinJsTestFramework : RequiresNpmDependencies { fun createTestExecutionSpec( task: KotlinJsTest, forkOptions: ProcessForkOptions, nodeJsArgs: MutableList ): TCServiceMessagesTestExecutionSpec - - fun configure(dependenciesHolder: HasKotlinDependencies) { - - } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt index 6731793878b..f9895cfa6a3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs import org.jetbrains.kotlin.gradle.targets.js.npm.NpmPackageVersion +import org.jetbrains.kotlin.gradle.targets.js.npm.RequiredKotlinJsDependency 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.testing.KotlinJsTestFramework @@ -24,6 +25,9 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework { private val versions = project.nodeJs.versions + override val requiredNpmDependencies: Collection + get() = requiredDependencies.toList() + init { requiredDependencies.add(versions.karma) @@ -49,7 +53,7 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework { fun useIe() = useBrowser("Ie", versions.karmaIeLauncher) - fun useBrowser(id: String, dependency: NpmPackageVersion) { + private fun useBrowser(id: String, dependency: NpmPackageVersion) { config.browsers.add(id) requiredDependencies.add(dependency) } @@ -68,14 +72,6 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework { requiredDependencies.add(versions.karmaSourceMapSupport) } - override fun configure(dependenciesHolder: HasKotlinDependencies) { - dependenciesHolder.dependencies { - requiredDependencies.forEach { - npm(it.name, it.version) - } - } - } - override fun createTestExecutionSpec( task: KotlinJsTest, forkOptions: ProcessForkOptions, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt index dc1b66c4177..fbd735ea49f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt @@ -5,23 +5,28 @@ package org.jetbrains.kotlin.gradle.targets.js.testing.mocha +import org.gradle.api.Project import org.gradle.process.ProcessForkOptions import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm -import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectLayout +import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs +import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinGradleNpmPackage +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject +import org.jetbrains.kotlin.gradle.targets.js.npm.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework -class KotlinMocha : KotlinJsTestFramework { - override fun configure(dependenciesHolder: HasKotlinDependencies) { - dependenciesHolder.dependencies { - runtimeOnly(kotlin("test-nodejs-runner")) - runtimeOnly(npm("mocha", "6.1.2")) - runtimeOnly(npm("mocha-teamcity-reporter", ">=2.0.0")) - } - } +class KotlinMocha(val project: Project) : KotlinJsTestFramework { + private val versions = project.nodeJs.versions + + override val requiredNpmDependencies: Collection + get() = listOf( + KotlinGradleNpmPackage("test-nodejs-runner"), + versions.mocha, + versions.mochaTeamCityReporter + ) override fun createTestExecutionSpec( task: KotlinJsTest, @@ -31,7 +36,7 @@ class KotlinMocha : KotlinJsTestFramework { val clientSettings = TCServiceMessagesClientSettings( task.name, testNameSuffix = task.targetName, - prepandSuiteName = true, + prependSuiteName = true, stackTraceParser = ::parseNodeJsStackTraceAsJvm, ignoreOutOfRootNodes = true ) @@ -41,7 +46,7 @@ class KotlinMocha : KotlinJsTestFramework { task.nodeModulesToLoad.single() ) - val npmProjectLayout = NpmProjectLayout[task.project] + val npmProjectLayout = NpmProject[task.project] val args = nodeJsArgs + nodeModules.map { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/nodejs/KotlinNodeJsTestRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/nodejs/KotlinNodeJsTestRunner.kt index b7ce1d74fd3..81f3fc0a2a5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/nodejs/KotlinNodeJsTestRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/nodejs/KotlinNodeJsTestRunner.kt @@ -11,7 +11,10 @@ import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSetti import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm -import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectLayout +import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinGradleNpmPackage +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmPackageVersion +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject +import org.jetbrains.kotlin.gradle.targets.js.npm.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.testing.IgnoredTestSuites @@ -20,11 +23,8 @@ class KotlinNodeJsTestRunner : KotlinJsTestFramework { @Input var ignoredTestSuites: IgnoredTestSuites = IgnoredTestSuites.showWithContents - override fun configure(dependenciesHolder: HasKotlinDependencies) { - dependenciesHolder.dependencies { - runtimeOnly(kotlin("test-nodejs-runner")) - } - } + override val requiredNpmDependencies: Collection + get() = listOf(KotlinGradleNpmPackage("test-nodejs-runner")) override fun createTestExecutionSpec( task: KotlinJsTest, @@ -41,16 +41,16 @@ class KotlinNodeJsTestRunner : KotlinJsTestFramework { val clientSettings = TCServiceMessagesClientSettings( task.name, testNameSuffix = task.targetName, - prepandSuiteName = true, + prependSuiteName = true, stackTraceParser = ::parseNodeJsStackTraceAsJvm ) val testRuntimeNodeModules = listOf( - "kotlin-test-nodejs-runner.js", - "kotlin-nodejs-source-map-support.js" + "kotlin-test-nodejs-runner/kotlin-test-nodejs-runner.js", + "kotlin-test-nodejs-runner/kotlin-nodejs-source-map-support.js" ) - val npmProjectLayout = NpmProjectLayout[task.project] + val npmProjectLayout = NpmProject[task.project] val args = nodeJsArgs + testRuntimeNodeModules.map { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt index b766a450720..8a0a6e33877 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt @@ -13,16 +13,19 @@ import org.gradle.deployment.internal.DeploymentHandle import org.gradle.deployment.internal.DeploymentRegistry import org.gradle.process.internal.ExecHandle import org.gradle.process.internal.ExecHandleFactory -import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles +import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmPackageVersion +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolver +import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject -import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile -import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask import org.jetbrains.kotlin.gradle.testing.internal.reportsDir import org.jetbrains.kotlin.gradle.utils.injected import java.io.File import javax.inject.Inject -open class KotlinWebpack : DefaultTask() { +open class KotlinWebpack : DefaultTask(), RequiresNpmDependencies { + private val versions by lazy { project.nodeJs.versions } + @get:Inject open val fileResolver: FileResolver get() = injected @@ -66,7 +69,26 @@ open class KotlinWebpack : DefaultTask() { @Optional var devServer: KotlinWebpackConfig.DevServer? = null - internal fun createRunner() = KotlinWebpackRunner( + override val requiredNpmDependencies: Collection + get() = mutableListOf().also { + it.add(versions.webpack) + it.add(versions.webpackCli) + + if (report) { + it.add(versions.webpackBundleAnalyzer) + } + + if (sourceMaps) { + it.add(versions.sourceMapLoader) + it.add(versions.sourceMapSupport) + } + + if (devServer != null) { + it.add(versions.webpackDevServer) + } + } + + private fun createRunner() = KotlinWebpackRunner( project, configFile, execHandleFactory, @@ -84,6 +106,9 @@ open class KotlinWebpack : DefaultTask() { @TaskAction fun execute() { + NpmResolver.resolve(project) + NpmResolver.checkRequiredDependencies(project, this) + val runner = createRunner() if (project.gradle.startParameter.isContinuous) {