diff --git a/build-common/src/org/jetbrains/kotlin/compilerRunner/ArgumentUtils.java b/build-common/src/org/jetbrains/kotlin/compilerRunner/ArgumentUtils.java index 727bcf91442..2beef3faae1 100644 --- a/build-common/src/org/jetbrains/kotlin/compilerRunner/ArgumentUtils.java +++ b/build-common/src/org/jetbrains/kotlin/compilerRunner/ArgumentUtils.java @@ -18,7 +18,7 @@ package org.jetbrains.kotlin.compilerRunner; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.cli.common.arguments.Argument; -import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments; +import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments; import org.jetbrains.kotlin.cli.common.arguments.ParseCommandLineArgumentsKt; import org.jetbrains.kotlin.utils.StringsKt; @@ -32,7 +32,7 @@ public class ArgumentUtils { private ArgumentUtils() {} @NotNull - public static List convertArgumentsToStringList(@NotNull CommonCompilerArguments arguments) + public static List convertArgumentsToStringList(@NotNull CommonToolArguments arguments) throws InstantiationException, IllegalAccessException { List result = new ArrayList<>(); convertArgumentsToStringList(arguments, arguments.getClass().newInstance(), arguments.getClass(), result); @@ -41,8 +41,8 @@ public class ArgumentUtils { } private static void convertArgumentsToStringList( - @NotNull CommonCompilerArguments arguments, - @NotNull CommonCompilerArguments defaultArguments, + @NotNull CommonToolArguments arguments, + @NotNull CommonToolArguments defaultArguments, @NotNull Class clazz, @NotNull List result ) throws IllegalAccessException, InstantiationException { diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/DefaultValues.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/DefaultValues.kt index 976f5157f37..3e7707a3e34 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/DefaultValues.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/DefaultValues.kt @@ -28,6 +28,8 @@ open class DefaultValues(val defaultValue: String, val possibleValues: List") + object LanguageVersions : DefaultValues( "null", LanguageVersion.values().map { "\"${it.description}\"" } diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSDceArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSDceArguments.java similarity index 50% rename from compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSDceArguments.kt rename to compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSDceArguments.java index 1901f04d690..d55bd3dc816 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSDceArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSDceArguments.java @@ -14,27 +14,28 @@ * limitations under the License. */ -package org.jetbrains.kotlin.cli.common.arguments +package org.jetbrains.kotlin.cli.common.arguments; -class K2JSDceArguments : CommonToolArguments() { - companion object { - const val serialVersionUID = 0L - } +public class K2JSDceArguments extends CommonToolArguments { + private static final long serialVersionUID = 0; - @field:GradleOption(DefaultValues.StringNullDefault::class) - @field:Argument(value = "-output-dir", valueDescription = "", description = "Output directory") - @JvmField - var outputDirectory: String? = null + @Argument( + value = "-output-dir", + valueDescription = "", + description = "Output directory" + ) + public String outputDirectory; - @field:Argument( + @Argument( value = "-keep", valueDescription = "", - description = "List of fully-qualified names of declarations that shouldn't be eliminated") - @JvmField - var declarationsToKeep: Array? = null + description = "List of fully-qualified names of declarations that shouldn't be eliminated" + ) + public String[] declarationsToKeep; - @field:GradleOption(DefaultValues.BooleanFalseDefault::class) - @field:Argument(value = "-Xprint-reachability-info", description = "Print declarations marked as reachable") - @JvmField - var printReachabilityInfo: Boolean = false + @Argument( + value = "-Xprint-reachability-info", + description = "Print declarations marked as reachable" + ) + public boolean printReachabilityInfo; } diff --git a/generators/src/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt b/generators/src/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt index b4abbb13358..4c482cdf1d2 100644 --- a/generators/src/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt +++ b/generators/src/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt @@ -39,24 +39,35 @@ fun generateKotlinGradleOptions(withPrinterToFile: (targetFile: File, Printer.() val srcDir = File("libraries/tools/kotlin-gradle-plugin/src/main/kotlin") // common interface - val commonInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions") - val commonOptions = gradleOptions() + gradleOptions() + val commonInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions") + val commonOptions = gradleOptions() val additionalOptions = gradleOptions() withPrinterToFile(File(srcDir, commonInterfaceFqName)) { generateInterface(commonInterfaceFqName, commonOptions + additionalOptions) } - println("### Attributes common for 'kotlin' and 'kotlin2js'\n") + println("### Attributes common for 'kotlin', 'kotlin2js' and 'kotlin2jsDce\n") generateMarkdown(commonOptions + additionalOptions) + val commonCompilerInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions") + val commonCompilerOptions = gradleOptions() + withPrinterToFile(File(srcDir, commonCompilerInterfaceFqName)) { + generateInterface(commonCompilerInterfaceFqName, + commonCompilerOptions, + parentType = commonInterfaceFqName) + } + + println("\n### Attributes common for 'kotlin' and 'kotlin2js'\n") + generateMarkdown(commonCompilerOptions) + // generate jvm interface val jvmInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions") val jvmOptions = gradleOptions() withPrinterToFile(File(srcDir, jvmInterfaceFqName)) { generateInterface(jvmInterfaceFqName, jvmOptions, - parentType = commonInterfaceFqName) + parentType = commonCompilerInterfaceFqName) } // generate jvm impl @@ -66,7 +77,7 @@ fun generateKotlinGradleOptions(withPrinterToFile: (targetFile: File, Printer.() generateImpl(jvmImplFqName, jvmInterfaceFqName, k2JvmCompilerArgumentsFqName, - commonOptions + jvmOptions) + commonOptions + commonCompilerOptions + jvmOptions) } println("\n### Attributes specific for 'kotlin'\n") @@ -78,7 +89,7 @@ fun generateKotlinGradleOptions(withPrinterToFile: (targetFile: File, Printer.() withPrinterToFile(File(srcDir, jsInterfaceFqName)) { generateInterface(jsInterfaceFqName, jsOptions, - parentType = commonInterfaceFqName) + parentType = commonCompilerInterfaceFqName) } val k2JsCompilerArgumentsFqName = FqName(K2JSCompilerArguments::class.qualifiedName!!) @@ -87,11 +98,29 @@ fun generateKotlinGradleOptions(withPrinterToFile: (targetFile: File, Printer.() generateImpl(jsImplFqName, jsInterfaceFqName, k2JsCompilerArgumentsFqName, - commonOptions + jsOptions) + commonOptions + commonCompilerOptions + jsOptions) } println("\n### Attributes specific for 'kotlin2js'\n") generateMarkdown(jsOptions) + + // generate JS DCE interface and implementation + val jsDceInterfaceFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptions") + val jsDceOptions = gradleOptions() + withPrinterToFile(File(srcDir, jsDceInterfaceFqName)) { + generateInterface(jsDceInterfaceFqName, + jsDceOptions, + parentType = commonInterfaceFqName) + } + + val k2JsDceArgumentsFqName = FqName(K2JSDceArguments::class.qualifiedName!!) + val jsDceImplFqName = FqName("org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptionsBase") + withPrinterToFile(File(srcDir, jsDceImplFqName)) { + generateImpl(jsDceImplFqName, + jsDceInterfaceFqName, + k2JsDceArgumentsFqName, + commonOptions + jsDceOptions) + } } fun main(args: Array) { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt index fe14b717494..33236281f09 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlin.gradle +import org.gradle.api.logging.LogLevel import org.jetbrains.kotlin.gradle.util.getFileByName import org.jetbrains.kotlin.gradle.util.modify import org.junit.Test @@ -214,4 +215,14 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { assertTrue("Source map should contain source of foo.kt") { map.contains("\"inline fun foo(): String {\\n") } } } + + @Test + fun testDce() { + val project = Project("kotlin2JsDceProject", "2.10", minLogLevel = LogLevel.INFO) + + project.build("runRhino") { + println(output) + assertSuccessful() + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/libraryProject/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/libraryProject/build.gradle new file mode 100644 index 00000000000..16a27601695 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/libraryProject/build.gradle @@ -0,0 +1,27 @@ +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'kotlin2js' + +repositories { + mavenLocal() +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" +} + +compileKotlin2Js.kotlinOptions.outputFile = "${buildDir}/examplelib.js" + +jar { + from buildDir + include "**/*.js" +} + +jar.dependsOn(compileKotlin2Js) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/libraryProject/src/main/kotlin/examplelib/lib.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/libraryProject/src/main/kotlin/examplelib/lib.kt new file mode 100644 index 00000000000..70f59d4e7bc --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/libraryProject/src/main/kotlin/examplelib/lib.kt @@ -0,0 +1,6 @@ +package examplelib + +fun foo() = "foo" + +fun bar() = "bar" + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/build.gradle new file mode 100644 index 00000000000..bf3771a600e --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/build.gradle @@ -0,0 +1,36 @@ +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: "kotlin2js" +apply plugin: "kotlin-dce-js" + +repositories { + mavenLocal() +} + +dependencies { + compile project(":libraryProject") + compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" + compile "org.mozilla:rhino:1.7.7.1" +} + +compileKotlin2Js.kotlinOptions.sourceMap = true +compileKotlin2Js.kotlinOptions.outputFile = "${buildDir}/exampleapp.js" +compileKotlin2Js.kotlinOptions.suppressWarnings = true +compileKotlin2Js.kotlinOptions.verbose = true +runDceKotlinJs.keep("exampleapp.exampleapp.status") + +task runRhino(type: JavaExec) { + classpath = sourceSets.main.runtimeClasspath + workingDir = "${buildDir}" + main = 'org.mozilla.javascript.tools.shell.Main' + args = ["-opt", "-1", "-f", "min/kotlin.js", "-f", "min/examplelib.js", "-f", "min/exampleapp.js", "-f", "../check.js"] +} + +runRhino.dependsOn(runDceKotlinJs) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/check.js b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/check.js new file mode 100644 index 00000000000..213b8394c17 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/check.js @@ -0,0 +1,6 @@ +(function() { + var status = exampleapp.exampleapp.status; + if (status !== "foo") { + throw new Error("Unexpected status: " + status); + } +})(); diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/src/main/kotlin/exampleapp/main.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/src/main/kotlin/exampleapp/main.kt new file mode 100644 index 00000000000..6c9550597d2 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/mainProject/src/main/kotlin/exampleapp/main.kt @@ -0,0 +1,9 @@ +package exampleapp + +import examplelib.* + +var status = "failure" + +fun main(args: Array) { + status = foo() +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/settings.gradle new file mode 100644 index 00000000000..9eeb29d9776 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin2JsDceProject/settings.gradle @@ -0,0 +1 @@ +include 'mainProject', 'libraryProject' \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonOptions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonOptions.kt index 146627ddf3d..c9dfd4407f3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonOptions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonOptions.kt @@ -2,7 +2,7 @@ // Generated by org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt package org.jetbrains.kotlin.gradle.dsl -interface KotlinCommonOptions { +interface KotlinCommonOptions : org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions { /** * Allow to use declarations only from the specified version of bundled libraries @@ -17,22 +17,4 @@ interface KotlinCommonOptions { * Default value: null */ var languageVersion: kotlin.String? - - /** - * Generate no warnings - * Default value: false - */ - var suppressWarnings: kotlin.Boolean - - /** - * Enable verbose logging output - * Default value: false - */ - var verbose: kotlin.Boolean - - /** - * A list of additional compiler arguments - * Default value: emptyList() - */ - var freeCompilerArgs: kotlin.collections.List } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonToolOptions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonToolOptions.kt new file mode 100644 index 00000000000..e52a0cfc2ba --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCommonToolOptions.kt @@ -0,0 +1,24 @@ +// DO NOT EDIT MANUALLY! +// Generated by org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt +package org.jetbrains.kotlin.gradle.dsl + +interface KotlinCommonToolOptions { + + /** + * Generate no warnings + * Default value: false + */ + var suppressWarnings: kotlin.Boolean + + /** + * Enable verbose logging output + * Default value: false + */ + var verbose: kotlin.Boolean + + /** + * A list of additional compiler arguments + * Default value: emptyList() + */ + var freeCompilerArgs: kotlin.collections.List +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCompile.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCompile.kt index 31b4d1f24d2..b5d17caa671 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCompile.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinCompile.kt @@ -39,4 +39,21 @@ interface KotlinCompile : Task, CompilerArgumentAware { interface KotlinJsCompile : KotlinCompile -interface KotlinJvmCompile : KotlinCompile \ No newline at end of file +interface KotlinJvmCompile : KotlinCompile + +interface KotlinJsDce : Task { + val dceOptions: KotlinJsDceOptions + + val keep: MutableList + + fun dceOptions(fn: KotlinJsDceOptions.() -> Unit) { + dceOptions.fn() + } + + fun dceOptions(fn: Closure<*>) { + fn.delegate = dceOptions + fn.call() + } + + fun keep(vararg fqn: String) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptions.kt new file mode 100644 index 00000000000..3ed746e94c7 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptions.kt @@ -0,0 +1,6 @@ +// DO NOT EDIT MANUALLY! +// Generated by org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt +package org.jetbrains.kotlin.gradle.dsl + +interface KotlinJsDceOptions : org.jetbrains.kotlin.gradle.dsl.KotlinCommonToolOptions { +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptionsBase.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptionsBase.kt new file mode 100644 index 00000000000..add9e81cb26 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptionsBase.kt @@ -0,0 +1,26 @@ +// DO NOT EDIT MANUALLY! +// Generated by org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt +package org.jetbrains.kotlin.gradle.dsl + +internal abstract class KotlinJsDceOptionsBase : org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptions { + + private var suppressWarningsField: kotlin.Boolean? = null + override var suppressWarnings: kotlin.Boolean + get() = suppressWarningsField ?: false + set(value) { suppressWarningsField = value } + + private var verboseField: kotlin.Boolean? = null + override var verbose: kotlin.Boolean + get() = verboseField ?: false + set(value) { verboseField = value } + + internal open fun updateArguments(args: org.jetbrains.kotlin.cli.common.arguments.K2JSDceArguments) { + suppressWarningsField?.let { args.suppressWarnings = it } + verboseField?.let { args.verbose = it } + } +} + +internal fun org.jetbrains.kotlin.cli.common.arguments.K2JSDceArguments.fillDefaultValues() { + suppressWarnings = false + verbose = false +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptionsImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptionsImpl.kt new file mode 100644 index 00000000000..d39cb463889 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsDceOptionsImpl.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.gradle.dsl + +import org.jetbrains.kotlin.cli.common.arguments.K2JSDceArguments +import org.jetbrains.kotlin.cli.js.dce.K2JSDce + +internal class KotlinJsDceOptionsImpl : KotlinJsDceOptionsBase() { + override var freeCompilerArgs: List = listOf() + + override fun updateArguments(args: K2JSDceArguments) { + super.updateArguments(args) + val freeArgsArray = (freeCompilerArgs as List).map(Any::toString).toTypedArray() + K2JSDce().parseArguments(freeArgsArray, args) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsBase.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsBase.kt index 65b990da07d..3eb529bb36c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsBase.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsBase.kt @@ -4,16 +4,6 @@ package org.jetbrains.kotlin.gradle.dsl internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.KotlinJsOptions { - private var apiVersionField: kotlin.String?? = null - override var apiVersion: kotlin.String? - get() = apiVersionField ?: null - set(value) { apiVersionField = value } - - private var languageVersionField: kotlin.String?? = null - override var languageVersion: kotlin.String? - get() = languageVersionField ?: null - set(value) { languageVersionField = value } - private var suppressWarningsField: kotlin.Boolean? = null override var suppressWarnings: kotlin.Boolean get() = suppressWarningsField ?: false @@ -24,6 +14,16 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko get() = verboseField ?: false set(value) { verboseField = value } + private var apiVersionField: kotlin.String?? = null + override var apiVersion: kotlin.String? + get() = apiVersionField ?: null + set(value) { apiVersionField = value } + + private var languageVersionField: kotlin.String?? = null + override var languageVersion: kotlin.String? + get() = languageVersionField ?: null + set(value) { languageVersionField = value } + private var friendModulesDisabledField: kotlin.Boolean? = null override var friendModulesDisabled: kotlin.Boolean get() = friendModulesDisabledField ?: false @@ -80,10 +80,10 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko set(value) { typedArraysField = value } internal open fun updateArguments(args: org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments) { - apiVersionField?.let { args.apiVersion = it } - languageVersionField?.let { args.languageVersion = it } suppressWarningsField?.let { args.suppressWarnings = it } verboseField?.let { args.verbose = it } + apiVersionField?.let { args.apiVersion = it } + languageVersionField?.let { args.languageVersion = it } friendModulesDisabledField?.let { args.friendModulesDisabled = it } mainField?.let { args.main = it } metaInfoField?.let { args.metaInfo = it } @@ -99,10 +99,10 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko } internal fun org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments.fillDefaultValues() { - apiVersion = null - languageVersion = null suppressWarnings = false verbose = false + apiVersion = null + languageVersion = null friendModulesDisabled = false main = "call" metaInfo = true diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsBase.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsBase.kt index a973dca7a9c..2d2c2143abd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsBase.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsBase.kt @@ -4,16 +4,6 @@ package org.jetbrains.kotlin.gradle.dsl internal abstract class KotlinJvmOptionsBase : org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions { - private var apiVersionField: kotlin.String?? = null - override var apiVersion: kotlin.String? - get() = apiVersionField ?: null - set(value) { apiVersionField = value } - - private var languageVersionField: kotlin.String?? = null - override var languageVersion: kotlin.String? - get() = languageVersionField ?: null - set(value) { languageVersionField = value } - private var suppressWarningsField: kotlin.Boolean? = null override var suppressWarnings: kotlin.Boolean get() = suppressWarningsField ?: false @@ -24,6 +14,16 @@ internal abstract class KotlinJvmOptionsBase : org.jetbrains.kotlin.gradle.dsl.K get() = verboseField ?: false set(value) { verboseField = value } + private var apiVersionField: kotlin.String?? = null + override var apiVersion: kotlin.String? + get() = apiVersionField ?: null + set(value) { apiVersionField = value } + + private var languageVersionField: kotlin.String?? = null + override var languageVersion: kotlin.String? + get() = languageVersionField ?: null + set(value) { languageVersionField = value } + private var includeRuntimeField: kotlin.Boolean? = null override var includeRuntime: kotlin.Boolean get() = includeRuntimeField ?: false @@ -60,10 +60,10 @@ internal abstract class KotlinJvmOptionsBase : org.jetbrains.kotlin.gradle.dsl.K set(value) { noStdlibField = value } internal open fun updateArguments(args: org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments) { - apiVersionField?.let { args.apiVersion = it } - languageVersionField?.let { args.languageVersion = it } suppressWarningsField?.let { args.suppressWarnings = it } verboseField?.let { args.verbose = it } + apiVersionField?.let { args.apiVersion = it } + languageVersionField?.let { args.languageVersion = it } includeRuntimeField?.let { args.includeRuntime = it } javaParametersField?.let { args.javaParameters = it } jdkHomeField?.let { args.jdkHome = it } @@ -75,10 +75,10 @@ internal abstract class KotlinJvmOptionsBase : org.jetbrains.kotlin.gradle.dsl.K } internal fun org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments.fillDefaultValues() { - apiVersion = null - languageVersion = null suppressWarnings = false verbose = false + apiVersion = null + languageVersion = null includeRuntime = false javaParameters = false jdkHome = null diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsDcePlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsDcePlugin.kt new file mode 100644 index 00000000000..7cde868efca --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsDcePlugin.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.gradle.plugin + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.internal.file.UnionFileCollection +import org.gradle.api.internal.file.UnionFileTree +import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.api.tasks.Copy +import org.gradle.api.tasks.SourceSet +import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile +import org.jetbrains.kotlin.gradle.tasks.KotlinJsDce +import java.io.File + +class KotlinJsDcePlugin : Plugin { + override fun apply(project: Project) { + project.pluginManager.apply(Kotlin2JsPluginWrapper::class.java) + + val javaPluginConvention = project.convention.getPlugin(JavaPluginConvention::class.java) + javaPluginConvention.sourceSets?.forEach { processSourceSet(project, it) } + } + + private fun processSourceSet(project: Project, sourceSet: SourceSet) { + val kotlinTaskName = sourceSet.getCompileTaskName("kotlin2Js") + val kotlinTask = project.tasks.findByName(kotlinTaskName) as? Kotlin2JsCompile ?: return + val dceTaskName = sourceSet.getTaskName(DCE_TASK_PREFIX, TASK_SUFFIX) + val dceTask = project.tasks.create(dceTaskName, KotlinJsDce::class.java).also { + it.dependsOn(kotlinTask) + project.tasks.findByName("build")?.dependsOn(it) + } + + project.afterEvaluate { + val outputDir = File(kotlinTask.outputFile).parentFile + + val dependenciesDir = File(outputDir, "dependencies") + copyDependencies(project, sourceSet, dependenciesDir, dceTask) + + val dceInputTrees = listOf(project.fileTree(kotlinTask.outputFile), project.fileTree(dependenciesDir)) + val dceInputFiles = UnionFileTree("dce-input", dceInputTrees) + + with (dceTask) { + classpath = sourceSet.compileClasspath + destinationDir = File(outputDir, "min") + source(dceInputFiles.filter { it.path.endsWith(".js") }) + } + } + } + + private fun copyDependencies(project: Project, sourceSet: SourceSet, outputDir: File, dceTask: Task) { + val configuration = project.configurations.findByName(sourceSet.compileConfigurationName) ?: return + + val files = UnionFileCollection(configuration.map { project.zipTree(it) }) + .filter { it.path.endsWith(".js") } + .filter { File(it.path.removeSuffix(".js") + ".meta.js").exists() } + + val name = sourceSet.getTaskName(DEPENDENCIES_TASK_PREFIX, TASK_SUFFIX) + with(project.tasks.create(name, Copy::class.java)) { + from(files) + into(outputDir) + includeEmptyDirs = true + include { + it.path.let { it.endsWith(".js") && !it.endsWith(".meta.js") } + } + + dceTask.dependsOn(this) + } + } + + companion object { + private const val TASK_SUFFIX = "kotlinJs" + private const val DEPENDENCIES_TASK_PREFIX = "copyDependencies" + private const val DCE_TASK_PREFIX = "runDce" + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt new file mode 100644 index 00000000000..00af2432d04 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinJsDce.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.gradle.tasks + +import org.gradle.api.Project +import org.gradle.api.tasks.TaskAction +import org.jetbrains.kotlin.cli.common.CLITool +import org.jetbrains.kotlin.cli.common.arguments.K2JSDceArguments +import org.jetbrains.kotlin.cli.js.dce.K2JSDce +import org.jetbrains.kotlin.compilerRunner.ArgumentUtils +import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce +import org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptions +import org.jetbrains.kotlin.gradle.dsl.KotlinJsDceOptionsImpl +import java.io.File + +open class KotlinJsDce : AbstractKotlinCompileTool(), KotlinJsDce { + private val dceOptionsImpl = KotlinJsDceOptionsImpl() + + override val dceOptions: KotlinJsDceOptions + get() = dceOptionsImpl + + override val keep: MutableList = mutableListOf() + + override fun findKotlinCompilerJar(project: Project): File? = findKotlinJsDceJar(project) + + override fun compile() {} + + override fun keep(vararg fqn: String) { + keep += fqn + } + + @TaskAction + fun performDce() { + val inputFiles = getSource().files.map { it.path } + + val outputDirArgs = arrayOf("-output-dir", destinationDir.path) + + val args = K2JSDceArguments() + dceOptionsImpl.updateArguments(args) + args.declarationsToKeep = keep.toTypedArray() + val argsArray = ArgumentUtils.convertArgumentsToStringList(args).toTypedArray() + val exitCode = CLITool.doMainNoExit(K2JSDce(), argsArray + outputDirArgs + inputFiles) + throwGradleExceptionIfError(exitCode) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 08905f98809..e3a2a05b5ad 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.annotation.AnnotationFileUpdater import org.jetbrains.kotlin.annotation.AnnotationFileUpdaterImpl import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments +import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation @@ -51,7 +52,16 @@ const val ANNOTATIONS_PLUGIN_NAME = "org.jetbrains.kotlin.kapt" const val KOTLIN_BUILD_DIR_NAME = "kotlin" const val USING_INCREMENTAL_COMPILATION_MESSAGE = "Using kotlin incremental compilation" -abstract class AbstractKotlinCompile() : AbstractCompile(), CompilerArgumentAware { +abstract class AbstractKotlinCompileTool() : AbstractCompile() { + var compilerJarFile: File? = null + internal val compilerJar: File + get() = compilerJarFile + ?: findKotlinCompilerJar(project) + ?: throw IllegalStateException("Could not find Kotlin Compiler jar. Please specify $name.compilerJarFile") + protected abstract fun findKotlinCompilerJar(project: Project): File? +} + +abstract class AbstractKotlinCompile() : AbstractKotlinCompileTool(), CompilerArgumentAware { abstract protected fun createCompilerArgs(): T protected val additionalClasspath = arrayListOf() @@ -102,13 +112,6 @@ abstract class AbstractKotlinCompile() : AbstractCo ?: coroutinesFromGradleProperties ?: Coroutines.DEFAULT - var compilerJarFile: File? = null - internal val compilerJar: File - get() = compilerJarFile - ?: findKotlinCompilerJar(project) - ?: throw IllegalStateException("Could not find Kotlin Compiler jar. Please specify $name.compilerJarFile") - protected abstract fun findKotlinCompilerJar(project: Project): File? - internal var compilerCalled: Boolean = false // TODO: consider more reliable approach (see usage) internal var anyClassesCompiled: Boolean = false diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt index 0b1f102cfb0..017f253a538 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/jarSearchingUtil.kt @@ -30,6 +30,7 @@ import java.util.zip.ZipFile private val K2JVM_COMPILER_CLASS = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler" private val K2JS_COMPILER_CLASS = "org.jetbrains.kotlin.cli.js.K2JSCompiler" +private val K2JS_DCE_CLASS = "org.jetbrains.kotlin.cli.js.dce.K2JSDce" private val K2METADATA_COMPILER_CLASS = "org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler" private val KOTLIN_MODULE_GROUP = "org.jetbrains.kotlin" private val KOTLIN_GRADLE_PLUGIN = "kotlin-gradle-plugin" @@ -44,6 +45,9 @@ internal fun findKotlinJsCompilerJar(project: Project): File? = internal fun findKotlinMetadataCompilerJar(project: Project): File? = findKotlinCompilerJar(project, K2METADATA_COMPILER_CLASS) +internal fun findKotlinJsDceJar(project: Project): File? = + findKotlinCompilerJar(project, K2JS_DCE_CLASS) + internal fun findToolsJar(): File? = Class.forName("com.sun.tools.javac.util.Context")?.let(::findJarByClass) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin-dce-js.properties b/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin-dce-js.properties new file mode 100644 index 00000000000..e006c858bd1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin-dce-js.properties @@ -0,0 +1 @@ +implementation-class=org.jetbrains.kotlin.gradle.plugin.KotlinJsDcePlugin \ No newline at end of file