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 062661c87ac..c9dd9e9435d 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 @@ -33,10 +33,13 @@ class NpmPackages { val karmaMocha = NpmPackageVersion("karma-mocha", "1.3.0") val karmaWebpack = NpmPackageVersion("karma-webpack", "*") + val karmaCoverage = NpmPackageVersion("karma-coverage", "*") val karmaSourceMapSupport = NpmPackageVersion("karma-source-map-support", "1.4.0") val kotlinNodeJsTestRunner = KotlinGradleNpmPackage("test-nodejs-runner") + + val istanbulInstrumenterLoader = NpmPackageVersion("istanbul-instrumenter-loader", "*") } interface RequiredKotlinJsDependency { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt index 885b33efa79..1899a43b4af 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt @@ -13,7 +13,7 @@ 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 import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack -import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig +import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfigWriter import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask class KotlinBrowserJs(target: KotlinJsTarget) : @@ -25,6 +25,7 @@ class KotlinBrowserJs(target: KotlinJsTarget) : override fun configureDefaultTestFramework(it: KotlinJsTest) { it.useKarma { + useMocha() useWebpack() useChromeHeadless() } @@ -62,7 +63,7 @@ class KotlinBrowserJs(target: KotlinJsTarget) : it.bin = "webpack-dev-server" it.entry = npmProject.compileOutput(compileKotlinTask) - it.devServer = KotlinWebpackConfig.DevServer( + it.devServer = KotlinWebpackConfigWriter.DevServer( open = true, contentBase = listOf(compilation.output.resourcesDir.canonicalPath) ) 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 31967154a4a..e4d301f8699 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 @@ -10,6 +10,7 @@ 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.targets.js.appendConfigsFromDir 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 @@ -17,12 +18,20 @@ 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 +import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KarmaConfig.CoverageReporter.Reporter +import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfigWriter +import org.jetbrains.kotlin.gradle.testing.internal.reportsDir +import java.io.File class KotlinKarma(val project: Project) : KotlinJsTestFramework { private val config: KarmaConfig = KarmaConfig() private val requiredDependencies = mutableSetOf() private val versions = project.nodeJs.versions + private val configurators = mutableListOf<(KotlinJsTest) -> Unit>() + private val confJsWriters = mutableListOf<(Appendable) -> Unit>() + private var sourceMaps = false + private var configDirectory: File? = project.projectDir.resolve("karma.config.d").takeIf { it.isDirectory } override val requiredNpmDependencies: Collection get() = requiredDependencies.toList() @@ -30,12 +39,20 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework { init { requiredDependencies.add(versions.karma) - requiredDependencies.add(versions.karmaTeamcityReporter) - config.reporters.add("teamcity") + useTeamcityReporter() config.singleRun = true } + private fun useTeamcityReporter() { + requiredDependencies.add(versions.karmaTeamcityReporter) + config.reporters.add("teamcity") + } + + fun useConfigDirectory(dir: File) { + configDirectory = dir + } + fun useChrome() = useBrowser("Chrome", versions.karmaChromeLauncher) fun useChromeCanary() = useBrowser("ChromeCanary", versions.karmaChromeLauncher) @@ -60,15 +77,85 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework { fun useMocha() { requiredDependencies.add(versions.karmaMocha) requiredDependencies.add(versions.mocha) + config.frameworks.add("mocha") } fun useWebpack() { requiredDependencies.add(versions.karmaWebpack) + + addPreprocessor("webpack") + confJsWriters.add { + it.appendln() + it.appendln("// webpack config") + it.appendln("function createWebpackConfig() {") + + KotlinWebpackConfigWriter( + sourceMaps = true, + export = false + ).appendTo(it) + + it.appendln(" return config;") + it.appendln("}") + it.appendln() + it.appendln("config.set({webpack: createWebpackConfig()});") + it.appendln() + } + } + + fun useCoverage( + html: Boolean = true, + lcov: Boolean = true, + cobertura: Boolean = false, + teamcity: Boolean = true, + text: Boolean = false, + textSummary: Boolean = false, + json: Boolean = false, + jsonSummary: Boolean = false + ) { + if (listOf( + html, lcov, cobertura, + teamcity, text, textSummary, + json, jsonSummary + ).all { !it } + ) return + + requiredDependencies.add(versions.karmaCoverage) + config.reporters.add("coverage") + addPreprocessor("coverage") { !it.endsWith("_test.js") } + + configurators.add { + val reportDir = project.reportsDir.resolve("coverage/${it.name}") + reportDir.mkdirs() + + config.coverageReporter = KarmaConfig.CoverageReporter(reportDir.canonicalPath).also { coverage -> + if (html) coverage.reporters.add(Reporter("html")) + if (lcov) coverage.reporters.add(Reporter("lcovonly")) + if (cobertura) coverage.reporters.add(Reporter("cobertura")) + if (teamcity) coverage.reporters.add(Reporter("teamcity")) + if (text) coverage.reporters.add(Reporter("text")) + if (textSummary) coverage.reporters.add(Reporter("text-summary")) + if (json) coverage.reporters.add(Reporter("json")) + if (jsonSummary) coverage.reporters.add(Reporter("json-summary")) + } + } } fun useSourceMapSupport() { config.frameworks.add("source-map-support") requiredDependencies.add(versions.karmaSourceMapSupport) + + sourceMaps = true + addPreprocessor("sourcemap") + } + + private fun addPreprocessor(name: String, predicate: (String) -> Boolean = { true }) { + configurators.add { + config.files.forEach { + if (predicate(it)) { + config.preprocessors.getOrPut(it) { mutableListOf() }.add(name) + } + } + } } override fun createTestExecutionSpec( @@ -86,19 +173,30 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework { val npmProject = task.project.npmProject - config.files.addAll(task.nodeModulesToLoad.map { - npmProject.require(it) - }) + val files = task.nodeModulesToLoad.map { npmProject.require(it) } + config.files.addAll(files) config.basePath = npmProject.nodeModulesDir.absolutePath + configurators.forEach { + it(task) + } + val karmaConfJs = npmProject.nodeWorkDir.resolve("karma.conf.js") - karmaConfJs.printWriter().use { - it.println("module.exports = function(config) {") - it.print(" config.set(") - GsonBuilder().setPrettyPrinting().create().toJson(config, it) - it.println(");") - it.println("}") + karmaConfJs.printWriter().use { confWriter -> + confWriter.println("module.exports = function(config) {") + confWriter.println() + + confWriter.print("config.set(") + GsonBuilder().setPrettyPrinting().create().toJson(config, confWriter) + confWriter.println(");") + + confJsWriters.forEach { it(confWriter) } + + confWriter.appendFromConfigDir() + + confWriter.println() + confWriter.println("}") } val nodeModules = listOf("karma/bin/karma") @@ -118,4 +216,16 @@ class KotlinKarma(val project: Project) : KotlinJsTestFramework { clientSettings ) } + + private fun Appendable.appendFromConfigDir() { + val configDirectory = configDirectory ?: return + + check(configDirectory.isDirectory) { + "\"$configDirectory\" is not a directory" + } + + appendln() + appendConfigsFromDir(configDirectory) + appendln() + } } \ 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/KramaConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KramaConfig.kt index 16456e31779..5591fc8b544 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KramaConfig.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KramaConfig.kt @@ -14,5 +14,16 @@ class KarmaConfig { val frameworks: MutableList = mutableListOf() val browsers: MutableList = mutableListOf() val reporters: MutableList = mutableListOf() - val preprocessors: MutableMap> = mutableMapOf() + val preprocessors: MutableMap> = mutableMapOf() + var coverageReporter: CoverageReporter? = null + + class CoverageReporter(var dir: String) { + val reporters = mutableListOf() + + class Reporter( + val type: String, + val subDir: String? = null, + val file: String? = null + ) + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/utils.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/utils.kt new file mode 100644 index 00000000000..bc2324cc00c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/utils.kt @@ -0,0 +1,22 @@ +/* + * 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 java.io.File + +fun Appendable.appendConfigsFromDir(confDir: File) { + if (!confDir.isDirectory) return + + confDir.listFiles() + ?.toList() + ?.filter { it.name.endsWith(".js") } + ?.forEach { + appendln("// ${it.name}") + append(it.readText()) + appendln() + appendln() + } +} 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 06d7113247f..97653bba503 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 @@ -67,7 +67,7 @@ open class KotlinWebpack : DefaultTask(), RequiresNpmDependencies { @Input @Optional - var devServer: KotlinWebpackConfig.DevServer? = null + var devServer: KotlinWebpackConfigWriter.DevServer? = null override val requiredNpmDependencies: Collection get() = mutableListOf().also { @@ -93,14 +93,15 @@ open class KotlinWebpack : DefaultTask(), RequiresNpmDependencies { configFile, execHandleFactory, bin, - KotlinWebpackConfig( - entry, - if (saveEvaluatedConfigFile) evaluatedConfigFile else null, - outputPath, - configDirectory, - if (report) reportDir else null, - devServer, - sourceMaps = sourceMaps + KotlinWebpackConfigWriter( + entry = entry, + reportEvaluatedConfigFile = if (saveEvaluatedConfigFile) evaluatedConfigFile else null, + outputPath = outputPath, + configDirectory = configDirectory, + bundleAnalyzerReportDir = if (report) reportDir else null, + devServer = devServer, + sourceMaps = sourceMaps, + sourceMapsRuntime = sourceMaps ) ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfig.kt deleted file mode 100644 index 95a2cbe9ccc..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfig.kt +++ /dev/null @@ -1,165 +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. - */ - -@file:Suppress("NodeJsCodingAssistanceForCoreModules", "JSUnresolvedFunction") - -package org.jetbrains.kotlin.gradle.targets.js.webpack - -import com.google.gson.GsonBuilder -import com.google.gson.stream.JsonWriter -import java.io.File -import java.io.Serializable -import java.io.StringWriter - -@Suppress("MemberVisibilityCanBePrivate") -class KotlinWebpackConfig( - val entry: File, - val reportEvaluatedConfigFile: File?, - val outputPath: File, - val configDirectory: File?, - val reportDir: File?, - var devServer: DevServer? = null, - val showProgress: Boolean = false, - val sourceMaps: Boolean = false -) { - @Suppress("unused") - data class BundleAnalyzerPlugin( - val analyzerMode: String, - val reportFilename: String, - val openAnalyzer: Boolean, - val generateStatsFile: Boolean, - val statsFilename: String - ) : Serializable - - @Suppress("unused") - data class DevServer( - val inline: Boolean = true, - val lazy: Boolean = false, - val noInfo: Boolean = true, - val open: Any = true, - val overlay: Any = false, - val port: Int = 8080, - val proxy: Map? = null, - val contentBase: List - ) : Serializable - - fun save(configFile: File) { - configFile.writeText(build()) - } - - fun build() = buildString { - //language=JavaScript 1.8 - appendln( - """ -var config = { - mode: 'development', - entry: ['${entry.canonicalPath}'], - output: { - path: '${outputPath.canonicalPath}', - filename: '${entry.name}' - }, - resolve: { - modules: [ - "node_modules" - ] - }, - plugins: [], - module: { - rules: [ - { - test: /\.js${'$'}/, - use: ["source-map-loader"], - enforce: "pre" - } - ] - }, - devtool: 'eval-source-map' -};""".trim() - ) - appendln() - - if (sourceMaps) { - //language=JavaScript 1.8 - appendln(""" -// source maps -config.entry.push('source-map-support/browser-source-map-support.js'); -config.module.rules.push({test: /\.js${'$'}/, use: ['source-map-loader'], enforce: 'pre'}); - """.trim()) - appendln() - } - - if (devServer != null) { - appendln("// dev server") - appendln("config.devServer = ${json(devServer!!)};") - appendln() - } - - if (reportDir != null) { - val reportBasePath = "${reportDir.canonicalPath}/${entry.name}" - val config = BundleAnalyzerPlugin( - "static", - "$reportBasePath.report.html", - false, - true, - "$reportBasePath.stats.json" - ) - - //language=JavaScript 1.8 - appendln( - """ -// save webpack-bundle-analyzer report -var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; -config.plugins.push(new BundleAnalyzerPlugin(${json(config)})); -""" - ) - } - - if (configDirectory != null) { - appendln() - loadConfigs(configDirectory) - } - - appendln() - - if (reportEvaluatedConfigFile != null) { - val filePath = jsQuotedString(reportEvaluatedConfigFile.canonicalPath) - - //language=JavaScript 1.8 - appendln( - """ -// save evaluated config file -var util = require('util'); -var fs = require("fs"); -var evaluatedConfig = util.inspect(config, {showHidden: false, depth: null, compact: false}); -fs.writeFile($filePath, evaluatedConfig, function (err) {}); -""" - ) - appendln() - } - - appendln("module.exports = config") - } - - private fun json(obj: Any) = StringWriter().also { - GsonBuilder().setPrettyPrinting().create().toJson(obj, it) - }.toString() - - private fun jsQuotedString(str: String) = StringWriter().also { - JsonWriter(it).value(str) - }.toString() - - private fun StringBuilder.loadConfigs(confDir: File) { - if (confDir.isDirectory) confDir - .listFiles() - ?.toList() - ?.filter { it.name.endsWith(".js") } - ?.forEach { - appendln("// ${it.name}") - append(it.readText()) - appendln() - appendln() - } - } -} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfigWriter.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfigWriter.kt new file mode 100644 index 00000000000..12e130d1de2 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackConfigWriter.kt @@ -0,0 +1,218 @@ +/* + * 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. + */ + +@file:Suppress("NodeJsCodingAssistanceForCoreModules", "JSUnresolvedFunction") + +package org.jetbrains.kotlin.gradle.targets.js.webpack + +import com.google.gson.GsonBuilder +import com.google.gson.stream.JsonWriter +import org.jetbrains.kotlin.gradle.targets.js.appendConfigsFromDir +import java.io.File +import java.io.Serializable +import java.io.StringWriter + +@Suppress("MemberVisibilityCanBePrivate") +class KotlinWebpackConfigWriter( + val mode: Mode = Mode.DEVELOPMENT, + val entry: File? = null, + val outputPath: File? = null, + val configDirectory: File? = null, + val bundleAnalyzerReportDir: File? = null, + val reportEvaluatedConfigFile: File? = null, + var devServer: DevServer? = null, + val showProgress: Boolean = false, + val sourceMaps: Boolean = false, + val sourceMapsRuntime: Boolean = false, + val export: Boolean = true +) { + enum class Mode(val code: String) { + DEVELOPMENT("development"), + PRODUCTION("production") + } + + @Suppress("unused") + data class BundleAnalyzerPlugin( + val analyzerMode: String, + val reportFilename: String, + val openAnalyzer: Boolean, + val generateStatsFile: Boolean, + val statsFilename: String + ) : Serializable + + @Suppress("unused") + data class DevServer( + val inline: Boolean = true, + val lazy: Boolean = false, + val noInfo: Boolean = true, + val open: Any = true, + val overlay: Any = false, + val port: Int = 8080, + val proxy: Map? = null, + val contentBase: List + ) : Serializable + + fun save(configFile: File) { + configFile.writer().use { + appendTo(it) + } + } + + fun appendTo(target: Appendable) { + with(target) { + //language=JavaScript 1.8 + appendln( + """ + var config = { + mode: '${mode.code}', + resolve: { + modules: [ + "node_modules" + ] + }, + plugins: [], + module: { + rules: [] + } + }; + + """.trimIndent() + ) + + appendEntry() + appendSourceMaps() + appendSourceMapsRuntime() + appendDevServer() + appendReport() + appendFromConfigDir() + appendEvaluatedFileReport() + + if (export) { + //language=JavaScript 1.8 + appendln("module.exports = config") + } + } + } + + private fun Appendable.appendEvaluatedFileReport() { + if (reportEvaluatedConfigFile == null) return + + val filePath = jsQuotedString(reportEvaluatedConfigFile.canonicalPath) + + //language=JavaScript 1.8 + appendln( + """ + // save evaluated config file + var util = require('util'); + var fs = require("fs"); + var evaluatedConfig = util.inspect(config, {showHidden: false, depth: null, compact: false}); + fs.writeFile($filePath, evaluatedConfig, function (err) {}); + + """.trimIndent() + ) + } + + private fun Appendable.appendFromConfigDir() { + if (configDirectory == null) return + + appendln() + appendConfigsFromDir(configDirectory) + appendln() + } + + private fun Appendable.appendReport() { + if (bundleAnalyzerReportDir == null) return + + entry ?: error("Entry should be defined for report") + + val reportBasePath = "${bundleAnalyzerReportDir.canonicalPath}/${entry.name}" + val config = BundleAnalyzerPlugin( + "static", + "$reportBasePath.report.html", + false, + true, + "$reportBasePath.stats.json" + ) + + //language=JavaScript 1.8 + appendln( + """ + // save webpack-bundle-analyzer report + var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; + config.plugins.push(new BundleAnalyzerPlugin(${json(config)})); + + """.trimIndent() + ) + appendln() + } + + private fun Appendable.appendDevServer() { + if (devServer == null) return + + appendln("// dev server") + appendln("config.devServer = ${json(devServer!!)};") + appendln() + } + + private fun Appendable.appendSourceMapsRuntime() { + if (!sourceMapsRuntime) return + + //language=JavaScript 1.8 + appendln( + """ + // source maps runtime + if (!config.entry) config.entry = []; + config.entry.push('source-map-support/browser-source-map-support.js'); + + """.trimIndent() + ) + } + + private fun Appendable.appendSourceMaps() { + if (!sourceMaps) return + + //language=JavaScript 1.8 + appendln( + """ + // source maps + config.module.rules.push({ + test: /\.js${'$'}/, + use: ["source-map-loader"], + enforce: "pre" + }); + config.module.rules.push({test: /\.js${'$'}/, use: ['source-map-loader'], enforce: 'pre'}); + config.devtool = 'eval-source-map'; + + """.trimIndent() + ) + } + + private fun Appendable.appendEntry() { + if (entry == null || outputPath == null) return + + //language=JavaScript 1.8 + appendln( + """ + // entry + if (!config.entry) config.entry = []; + config.entry.push('${entry.canonicalPath}'); + config.output = { + path: '${outputPath.canonicalPath}', + filename: '${entry.name}' + }; + + """.trimIndent() + ) + } + + + private fun json(obj: Any) = StringWriter().also { + GsonBuilder().setPrettyPrinting().create().toJson(obj, it) + }.toString() + + private fun jsQuotedString(str: String) = StringWriter().also { + JsonWriter(it).value(str) + }.toString() +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackRunner.kt index 6940f0d58a1..9a8d036c0bb 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpackRunner.kt @@ -25,7 +25,7 @@ internal class KotlinWebpackRunner( val configFile: File, val execHandleFactory: ExecHandleFactory, val bin: String, - val config: KotlinWebpackConfig + val configWriter: KotlinWebpackConfigWriter ) { fun execute(): ExecResult { val exec = start() @@ -37,20 +37,20 @@ internal class KotlinWebpackRunner( } fun start(): ExecHandle { - check(config.entry.isFile) { - "${this}: Entry file not existed \"${config.entry}\"" + check(configWriter.entry?.isFile == true) { + "${this}: Entry file not existed \"${configWriter.entry}\"" } NpmResolver.resolve(project) val npmProjectLayout = NpmProject[project] - config.save(configFile) + configWriter.save(configFile) val execFactory = execHandleFactory.newExec() val args = mutableListOf("--config", configFile.absolutePath) - if (config.showProgress) { + if (configWriter.showProgress) { args.add("--progress") }