From 8d660c2f6e4deb84972012b4d20fec94507f3098 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 7 Oct 2016 16:46:04 +0300 Subject: [PATCH] Refactor gradle option generation mechanism Ensure there's a statically checked dependency on LanguageVersion and JvmTarget, so that this information is updated automatically once a new language version or a JVM target is added --- .../arguments/CommonCompilerArguments.java | 7 +-- .../cli/common/arguments/DefaultValues.kt | 55 +++++++++++++++++++ .../cli/common/arguments/GradleOption.kt | 5 +- .../arguments/K2JSCompilerArguments.java | 18 +++--- .../arguments/K2JVMCompilerArguments.java | 12 ++-- compiler/testData/cli/js/jsHelp.out | 2 +- .../org/jetbrains/kotlin/config/JvmTarget.kt | 3 + .../arguments/GenerateGradleOptions.kt | 22 +++++--- .../kotlin/gradle/dsl/KotlinJsOptions.kt | 2 +- 9 files changed, 95 insertions(+), 31 deletions(-) create mode 100644 compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/DefaultValues.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.java index 6fe761d0981..906a7412cbe 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.java @@ -25,17 +25,16 @@ import java.util.List; public abstract class CommonCompilerArguments { public static final String PLUGIN_OPTION_FORMAT = "plugin::="; - // todo: reuse LanguageVersion from frontend - @GradleOption(defaultValue = "\"1.1\"", possibleValues = { "\"1.0\", \"1.1\"" }) + @GradleOption(DefaultValues.LanguageVersions.class) @Argument(value = "language-version", description = "Provide source compatibility with specified language version") @ValueDescription("") public String languageVersion; - @GradleOption(defaultValue = "false") + @GradleOption(DefaultValues.BooleanFalseDefault.class) @Argument(value = "nowarn", description = "Generate no warnings") public boolean suppressWarnings; - @GradleOption(defaultValue = "false") + @GradleOption(DefaultValues.BooleanFalseDefault.class) @Argument(value = "verbose", description = "Enable verbose logging output") public boolean verbose; 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 new file mode 100644 index 00000000000..24ac74659fe --- /dev/null +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/DefaultValues.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2016 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.cli.common.arguments + +import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.CALL +import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.NO_CALL +import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.config.LanguageVersion + +open class DefaultValues(val defaultValue: String, val possibleValues: List? = null) { + object BooleanFalseDefault : DefaultValues("false") + + object BooleanTrueDefault : DefaultValues("true") + + object StringNullDefault : DefaultValues("null") + + object LanguageVersions : DefaultValues( + "\"" + LanguageVersion.LATEST.versionString + "\"", + LanguageVersion.values().map { "\"${it.versionString}\"" } + ) + + object JvmTargetVersions : DefaultValues( + "\"" + JvmTarget.DEFAULT.string + "\"", + JvmTarget.values().map { "\"${it.string}\"" } + ) + + object JsEcmaVersions : DefaultValues( + "\"v5\"", + listOf("\"v5\"") + ) + + object JsModuleKinds : DefaultValues( + "\"plain\"", + listOf("\"plain\"", "\"amd\"", "\"commonjs\"", "\"umd\"") + ) + + object JsMain : DefaultValues( + "\"" + NO_CALL + "\"", + listOf("\"" + CALL + "\"", "\"" + NO_CALL + "\"") + ) +} diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/GradleOption.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/GradleOption.kt index bf991e10f33..53e0dffdaa3 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/GradleOption.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/GradleOption.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.cli.common.arguments +import kotlin.reflect.KClass + @Retention(AnnotationRetention.RUNTIME) -annotation class GradleOption(val defaultValue: String, - val possibleValues: Array = arrayOf()) \ No newline at end of file +annotation class GradleOption(val value: KClass = DefaultValues::class) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.java index 8277c6858b5..23041665bca 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.java @@ -24,12 +24,12 @@ import static org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.CA import static org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.NO_CALL; public class K2JSCompilerArguments extends CommonCompilerArguments { - @GradleOption(defaultValue = "null") + @GradleOption(DefaultValues.StringNullDefault.class) @Argument(value = "output", description = "Output file path") @ValueDescription("") public String outputFile; - @GradleOption(defaultValue = "true") + @GradleOption(DefaultValues.BooleanTrueDefault.class) @Argument(value = "no-stdlib", description = "Don't use bundled Kotlin stdlib") public boolean noStdlib; @@ -37,29 +37,29 @@ public class K2JSCompilerArguments extends CommonCompilerArguments { @ValueDescription("") public String[] libraryFiles; - @GradleOption(defaultValue = "false") + @GradleOption(DefaultValues.BooleanFalseDefault.class) @Argument(value = "source-map", description = "Generate source map") public boolean sourceMap; - @GradleOption(defaultValue = "true") + @GradleOption(DefaultValues.BooleanTrueDefault.class) @Argument(value = "meta-info", description = "Generate metadata") public boolean metaInfo; - @GradleOption(defaultValue = "true") + @GradleOption(DefaultValues.BooleanTrueDefault.class) @Argument(value = "kjsm", description = "Generate kjsm-files (for creating libraries)") public boolean kjsm; - @GradleOption(defaultValue = "\"v5\"", possibleValues = { "\"v5\"" }) - @Argument(value = "target", description = "Generate JS files for specific ECMA version)") + @GradleOption(DefaultValues.JsEcmaVersions.class) + @Argument(value = "target", description = "Generate JS files for specific ECMA version") @ValueDescription("{ v5 }") public String target; - @GradleOption(defaultValue = "\"plain\"", possibleValues = { "\"plain\"", "\"amd\"", "\"commonjs\"", "\"umd\"" }) + @GradleOption(DefaultValues.JsModuleKinds.class) @Argument(value = "module-kind", description = "Kind of a module generated by compiler") @ValueDescription("{ plain, amd, commonjs, umd }") public String moduleKind; - @GradleOption(defaultValue = "\"" + NO_CALL + "\"", possibleValues = { "\"" + CALL + "\"", "\"" + NO_CALL + "\"" }) + @GradleOption(DefaultValues.JsMain.class) @Nullable @Argument(value = "main", description = "Whether a main function should be called") @ValueDescription("{" + CALL + "," + NO_CALL + "}") diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java index 314944b3c4c..c699106f03c 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.java @@ -28,24 +28,24 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments { @ValueDescription("") public String classpath; - @GradleOption(defaultValue = "false") + @GradleOption(DefaultValues.BooleanFalseDefault.class) @Argument(value = "include-runtime", description = "Include Kotlin runtime in to resulting .jar") public boolean includeRuntime; - @GradleOption(defaultValue = "null") + @GradleOption(DefaultValues.StringNullDefault.class) @Argument(value = "jdk-home", description = "Path to JDK home directory to include into classpath, if differs from default JAVA_HOME") @ValueDescription("") public String jdkHome; - @GradleOption(defaultValue = "false") + @GradleOption(DefaultValues.BooleanFalseDefault.class) @Argument(value = "no-jdk", description = "Don't include Java runtime into classpath") public boolean noJdk; - @GradleOption(defaultValue = "true") + @GradleOption(DefaultValues.BooleanTrueDefault.class) @Argument(value = "no-stdlib", description = "Don't include Kotlin runtime into classpath") public boolean noStdlib; - @GradleOption(defaultValue = "true") + @GradleOption(DefaultValues.BooleanTrueDefault.class) @Argument(value = "no-reflect", description = "Don't include Kotlin reflection implementation into classpath") public boolean noReflect; @@ -67,7 +67,7 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments { @Argument(value = "module-name", description = "Module name") public String moduleName; - @GradleOption(defaultValue = "\"1.6\"", possibleValues = { "\"1.6\"", "\"1.8\"" }) + @GradleOption(DefaultValues.JvmTargetVersions.class) @Argument(value = "jvm-target", description = "Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6") @ValueDescription("") public String jvmTarget; diff --git a/compiler/testData/cli/js/jsHelp.out b/compiler/testData/cli/js/jsHelp.out index ec0a1c1b394..101a52bfe90 100644 --- a/compiler/testData/cli/js/jsHelp.out +++ b/compiler/testData/cli/js/jsHelp.out @@ -6,7 +6,7 @@ where possible options include: -source-map Generate source map -meta-info Generate metadata -kjsm Generate kjsm-files (for creating libraries) - -target { v5 } Generate JS files for specific ECMA version) + -target { v5 } Generate JS files for specific ECMA version -module-kind { plain, amd, commonjs, umd } Kind of a module generated by compiler -main {call,noCall} Whether a main function should be called diff --git a/compiler/util/src/org/jetbrains/kotlin/config/JvmTarget.kt b/compiler/util/src/org/jetbrains/kotlin/config/JvmTarget.kt index 50965422035..64f538c92ad 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/JvmTarget.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/JvmTarget.kt @@ -22,6 +22,9 @@ enum class JvmTarget(val string: String) { ; companion object { + @JvmField + val DEFAULT = JVM_1_6 + @JvmStatic fun fromString(string: String) = values().find { it.string == string } } diff --git a/generators/src/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt b/generators/src/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt index ed0712ceca5..59fe34b692f 100644 --- a/generators/src/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt +++ b/generators/src/org/jetbrains/kotlin/generators/arguments/GenerateGradleOptions.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.generators.arguments import com.sampullara.cli.Argument +import org.jetbrains.kotlin.cli.common.arguments.DefaultValues import org.jetbrains.kotlin.cli.common.arguments.GradleOption import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments @@ -24,13 +25,18 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.utils.Printer import java.io.File import java.io.PrintStream -import kotlin.reflect.* +import kotlin.reflect.KAnnotatedElement +import kotlin.reflect.KProperty1 +import kotlin.reflect.memberProperties // Additional properties that should be included in interface +@Suppress("unused") interface AdditionalGradleProperties { - @GradleOption(defaultValue = "emptyList()") + @GradleOption(EmptyList::class) @Argument(description = "A list of additional compiler arguments") var freeCompilerArgs: List + + object EmptyList : DefaultValues("emptyList()") } fun main(args: Array) { @@ -173,12 +179,12 @@ private fun Printer.generatePropertyDeclaration(property: KProperty1<*, *>, modi private fun Printer.generateDoc(property: KProperty1<*, *>) { val description = property.findAnnotation()!!.description - val possibleValues = property.gradlePossibleValues + val possibleValues = property.gradleValues.possibleValues val defaultValue = property.gradleDefaultValue println("/**") println(" * $description") - if (possibleValues.isNotEmpty()) { + if (possibleValues != null) { println(" * Possible values: ${possibleValues.joinToString()}") } println(" * Default value: $defaultValue") @@ -191,11 +197,11 @@ private inline fun Printer.withIndent(fn: Printer.()->Unit) { popIndent() } -private val KProperty1<*, *>.gradlePossibleValues: Array - get() = findAnnotation()!!.possibleValues +private val KProperty1<*, *>.gradleValues: DefaultValues + get() = findAnnotation()!!.value.objectInstance!! private val KProperty1<*, *>.gradleDefaultValue: String - get() = findAnnotation()!!.defaultValue + get() = gradleValues.defaultValue private val KProperty1<*, *>.gradleReturnType: String get() { @@ -207,4 +213,4 @@ private val KProperty1<*, *>.gradleReturnType: String } private inline fun KAnnotatedElement.findAnnotation(): T? = - annotations.filterIsInstance().firstOrNull() \ No newline at end of file + annotations.filterIsInstance().firstOrNull() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptions.kt index acedfa6be48..7b7a6859731 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptions.kt @@ -62,7 +62,7 @@ interface KotlinJsOptions { var suppressWarnings: kotlin.Boolean /** - * Generate JS files for specific ECMA version) + * Generate JS files for specific ECMA version * Possible values: "v5" * Default value: "v5" */