diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/plugins/PluginCliParser.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/plugins/PluginCliParser.kt index 1c72ee0877e..cab932d3f20 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/plugins/PluginCliParser.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/plugins/PluginCliParser.kt @@ -84,12 +84,14 @@ object PluginCliParser { it.pluginId } ?: mapOf() + // TODO issue a warning on using deprecated command line processors when all official plugin migrate to the newer convention + val commandLineProcessors = ServiceLoader.load(CommandLineProcessor::class.java, classLoader).toMutableList() commandLineProcessors.addAll(BundledCompilerPlugins.commandLineProcessors) for (processor in commandLineProcessors) { - val declaredOptions = processor.pluginOptions.associateBy { it.name } - val optionsToValues = MultiMap() + val declaredOptions = processor.pluginOptions.associateBy { it.optionName } + val optionsToValues = MultiMap() for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) { val option = declaredOptions[optionValue!!.optionName] @@ -103,14 +105,14 @@ object PluginCliParser { throw PluginCliOptionProcessingException( processor.pluginId, processor.pluginOptions, - "Required plugin option not present: ${processor.pluginId}:${option.name}" + "Required plugin option not present: ${processor.pluginId}:${option.optionName}" ) } if (!option.allowMultipleOccurrences && values.size > 1) { throw PluginCliOptionProcessingException( processor.pluginId, processor.pluginOptions, - "Multiple values are not allowed for plugin option ${processor.pluginId}:${option.name}" + "Multiple values are not allowed for plugin option ${processor.pluginId}:${option.optionName}" ) } diff --git a/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/CliOptions.kt b/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/CliOptions.kt index f36901d90bf..7d6bc774770 100644 --- a/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/CliOptions.kt +++ b/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/CliOptions.kt @@ -18,29 +18,41 @@ package org.jetbrains.kotlin.compiler.plugin import java.util.regex.Pattern +interface AbstractCliOption { + val optionName: String + val valueDescription: String + val description: String + val required: Boolean + val allowMultipleOccurrences: Boolean +} + class CliOption( - val name: String, - val valueDescription: String, - val description: String, - val required: Boolean = true, - val allowMultipleOccurrences: Boolean = false -) + override val optionName: String, + override val valueDescription: String, + override val description: String, + override val required: Boolean = true, + override val allowMultipleOccurrences: Boolean = false +) : AbstractCliOption { + @Deprecated("Use optionName instead.", ReplaceWith("optionName")) + val name: String + get() = optionName +} open class CliOptionProcessingException(message: String, cause: Throwable? = null): RuntimeException(message, cause) class PluginCliOptionProcessingException( val pluginId: String, - val options: Collection, + val options: Collection, message: String, cause: Throwable? = null ): CliOptionProcessingException(message, cause) -fun cliPluginUsageString(pluginId: String, options: Collection): String { +fun cliPluginUsageString(pluginId: String, options: Collection): String { val LEFT_INDENT = 2 val MAX_OPTION_WIDTH = 26 val renderedOptions = options.map { - val name = "${it.name} ${it.valueDescription}" + val name = "${it.optionName} ${it.valueDescription}" val margin = if (name.length > MAX_OPTION_WIDTH) { "\n" + " ".repeat(MAX_OPTION_WIDTH + LEFT_INDENT + 1) } else " ".repeat(1 + MAX_OPTION_WIDTH - name.length) diff --git a/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/CommandLineProcessor.kt b/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/CommandLineProcessor.kt index 96a963e012e..82bd2f02474 100644 --- a/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/CommandLineProcessor.kt +++ b/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/CommandLineProcessor.kt @@ -21,9 +21,18 @@ import org.jetbrains.kotlin.config.CompilerConfigurationKey interface CommandLineProcessor { val pluginId: String - val pluginOptions: Collection + val pluginOptions: Collection - @Throws(CliOptionProcessingException::class) fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) + @Throws(CliOptionProcessingException::class) + fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) { + @Suppress("DEPRECATION") + processOption(option as CliOption, value, configuration) + } + + // TODO remove processOption(AbstractCliOption, ...) implementation after removal of this. + @Deprecated("Implement processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) instead.") + @Throws(CliOptionProcessingException::class) + fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {} fun CompilerConfiguration.appendList(option: CompilerConfigurationKey>, value: T) { val paths = getList(option).toMutableList() @@ -37,9 +46,9 @@ interface CommandLineProcessor { put(option, paths) } - fun CompilerConfiguration.applyOptionsFrom(map: Map>, pluginOptions: Collection) { + fun CompilerConfiguration.applyOptionsFrom(map: Map>, pluginOptions: Collection) { for ((key, values) in map) { - val option = pluginOptions.firstOrNull { it.name == key } ?: continue + val option = pluginOptions.firstOrNull { it.optionName == key } ?: continue for (value in values) { processOption(option, value, this) diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/MavenPluginComponent.kt b/libraries/tools/kotlin-maven-plugin-test/src/it/test-plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/MavenPluginComponent.kt index 9a993b96c99..8417a4ed45a 100644 --- a/libraries/tools/kotlin-maven-plugin-test/src/it/test-plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/MavenPluginComponent.kt +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/MavenPluginComponent.kt @@ -25,7 +25,7 @@ class MavenPluginComponent : KotlinMavenPluginExtension { return listOf(PluginOption( "test-me", TestCommandLineProcessor.TestPluginId, - TestCommandLineProcessor.MyTestOption.name, + TestCommandLineProcessor.MyTestOption.optionName, "my-special-value")) } } \ No newline at end of file diff --git a/libraries/tools/kotlin-maven-plugin-test/src/it/test-plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/TestKotlinPluginRegistrar.kt b/libraries/tools/kotlin-maven-plugin-test/src/it/test-plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/TestKotlinPluginRegistrar.kt index 0dcf96b3352..9729f85280c 100644 --- a/libraries/tools/kotlin-maven-plugin-test/src/it/test-plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/TestKotlinPluginRegistrar.kt +++ b/libraries/tools/kotlin-maven-plugin-test/src/it/test-plugins/test-extension/src/main/kotlin/org/jetbrains/kotlin/test/TestKotlinPluginRegistrar.kt @@ -25,7 +25,7 @@ class TestCommandLineProcessor : CommandLineProcessor { MyTestOption -> { configuration.put(TestPluginKeys.TestOption, value) } - else -> throw CliOptionProcessingException("Unknown option: ${option.name}") + else -> throw CliOptionProcessingException("Unknown option: ${option.optionName}") } } } diff --git a/plugins/imports-dumper/src/org/jetbrains/kotlin/importsDumper/ImportsDumperCommandLineProcessor.kt b/plugins/imports-dumper/src/org/jetbrains/kotlin/importsDumper/ImportsDumperCommandLineProcessor.kt index bca3a7305ad..79698a799dd 100644 --- a/plugins/imports-dumper/src/org/jetbrains/kotlin/importsDumper/ImportsDumperCommandLineProcessor.kt +++ b/plugins/imports-dumper/src/org/jetbrains/kotlin/importsDumper/ImportsDumperCommandLineProcessor.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.config.CompilerConfigurationKey object ImportsDumperCliOptions { val DESTINATION = CliOption( - name = "output-imports", + optionName = "output-imports", valueDescription = "", description = "Output imports from all compiled files to the specified file in JSON format", required = false // non-required because importsDumper is a bundled plugin diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt index 42a3721328f..f1ec3a54960 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt @@ -24,10 +24,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot -import org.jetbrains.kotlin.compiler.plugin.CliOption -import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException -import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor -import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.jetbrains.kotlin.compiler.plugin.* import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfigurationKey @@ -38,25 +35,11 @@ import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.ANNOTATION_PROCESSORS_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.ANNOTATION_PROCESSOR_CLASSPATH_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.APT_MODE_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.APT_ONLY_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.APT_OPTIONS_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.CLASS_OUTPUT_DIR_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.CORRECT_ERROR_TYPES_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.INCREMENTAL_DATA_OUTPUT_DIR_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.INFO_AS_WARNINGS_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.JAVAC_CLI_OPTIONS_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.MAP_DIAGNOSTIC_LOCATIONS_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.SOURCE_OUTPUT_DIR_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.STUBS_OUTPUT_DIR_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.USE_LIGHT_ANALYSIS_OPTION -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.VERBOSE_MODE_OPTION +import org.jetbrains.kotlin.kapt3.KaptCliOptions.* import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.APT_OPTIONS import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.JAVAC_CLI_OPTIONS -import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.STRICT_MODE_OPTION +import org.jetbrains.kotlin.kapt3.KaptCliOptions.Companion.ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID import org.jetbrains.kotlin.kapt3.base.Kapt import org.jetbrains.kotlin.kapt3.base.KaptPaths import org.jetbrains.kotlin.kapt3.base.log @@ -123,100 +106,65 @@ object Kapt3ConfigurationKeys { CompilerConfigurationKey.create(STRICT_MODE_OPTION.description) } -class Kapt3CommandLineProcessor : CommandLineProcessor { +enum class KaptCliOptions( + override val optionName: String, + override val valueDescription: String, + override val description: String, + override val allowMultipleOccurrences: Boolean = false +) : AbstractCliOption { + CONFIGURATION("configuration", "", "Encoded configuration"), + SOURCE_OUTPUT_DIR_OPTION("sources", "", "Output path for the generated files"), + CLASS_OUTPUT_DIR_OPTION("classes", "", "Output path for the class files"), + STUBS_OUTPUT_DIR_OPTION("stubs", "", "Output path for the Java stubs"), + INCREMENTAL_DATA_OUTPUT_DIR_OPTION("incrementalData", "", "Output path for the incremental data"), + ANNOTATION_PROCESSOR_CLASSPATH_OPTION("apclasspath", "", "Annotation processor classpath", true), + APT_OPTIONS_OPTION("apoptions", "options map", "Encoded annotation processor options", false), + JAVAC_CLI_OPTIONS_OPTION("javacArguments", "javac CLI options map", "Encoded javac CLI options", false), + ANNOTATION_PROCESSORS_OPTION("processors", "", "Annotation processor qualified names", true), + VERBOSE_MODE_OPTION("verbose", "true | false", "Enable verbose output"), + INFO_AS_WARNINGS_OPTION("infoAsWarnings", "true | false", "Show information messages as warnings"), + STRICT_MODE_OPTION("strict", "true | false", "Show errors on incompatibilities during stub generation"), + APT_MODE_OPTION( + "aptMode", "apt | stubs | stubsAndApt | compile", + "Annotation processing mode: only apt, only stub generation, both, or with the subsequent compilation" + ), + USE_LIGHT_ANALYSIS_OPTION( + "useLightAnalysis", + "true | false", + "Do not analyze declaration bodies if can" + ), + CORRECT_ERROR_TYPES_OPTION( + "correctErrorTypes", + "true | false", + "Replace generated or error types with ones from the generated sources" + ), + MAP_DIAGNOSTIC_LOCATIONS_OPTION( + "mapDiagnosticLocations", + "true | false", + "Map diagnostic reported on kapt stubs to original locations in Kotlin sources" + ), + + @Deprecated("Use APT_MODE_OPTION instead.") + APT_ONLY_OPTION("aptOnly", "true | false", "Run only annotation processing, do not compile Kotlin files"); + + override val required: Boolean = false + companion object { const val ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID: String = "org.jetbrains.kotlin.kapt3" - - val CONFIGURATION = CliOption("configuration", "", "Encoded configuration", required = false) - - val SOURCE_OUTPUT_DIR_OPTION: CliOption = - CliOption("sources", "", "Output path for the generated files", required = false) - - val CLASS_OUTPUT_DIR_OPTION: CliOption = - CliOption("classes", "", "Output path for the class files", required = false) - - val STUBS_OUTPUT_DIR_OPTION: CliOption = - CliOption("stubs", "", "Output path for the Java stubs", required = false) - - val INCREMENTAL_DATA_OUTPUT_DIR_OPTION: CliOption = - CliOption("incrementalData", "", "Output path for the incremental data", required = false) - - val ANNOTATION_PROCESSOR_CLASSPATH_OPTION: CliOption = - CliOption( - "apclasspath", "", "Annotation processor classpath", - required = false, allowMultipleOccurrences = true - ) - - val APT_OPTIONS_OPTION: CliOption = - CliOption( - "apoptions", "options map", "Encoded annotation processor options", - required = false, allowMultipleOccurrences = false - ) - - val JAVAC_CLI_OPTIONS_OPTION: CliOption = - CliOption( - "javacArguments", "javac CLI options map", "Encoded javac CLI options", - required = false, allowMultipleOccurrences = false - ) - - val ANNOTATION_PROCESSORS_OPTION: CliOption = - CliOption( - "processors", "", "Annotation processor qualified names", - required = false, allowMultipleOccurrences = true - ) - - val VERBOSE_MODE_OPTION: CliOption = - CliOption("verbose", "true | false", "Enable verbose output", required = false) - - val INFO_AS_WARNINGS_OPTION: CliOption = - CliOption("infoAsWarnings", "true | false", "Show information messages as warnings", required = false) - - @Deprecated("Use APT_MODE_OPTION instead.") - val APT_ONLY_OPTION: CliOption = - CliOption("aptOnly", "true | false", "Run only annotation processing, do not compile Kotlin files", required = false) - - val APT_MODE_OPTION: CliOption = - CliOption( - "aptMode", "apt | stubs | stubsAndApt | compile", - "Annotation processing mode: only apt, only stub generation, both, or with the subsequent compilation", - required = false - ) - - val USE_LIGHT_ANALYSIS_OPTION: CliOption = - CliOption("useLightAnalysis", "true | false", "Do not analyze declaration bodies if can", required = false) - - val CORRECT_ERROR_TYPES_OPTION: CliOption = - CliOption( - "correctErrorTypes", - "true | false", - "Replace generated or error types with ones from the generated sources", - required = false - ) - - val MAP_DIAGNOSTIC_LOCATIONS_OPTION: CliOption = - CliOption( - "mapDiagnosticLocations", - "true | false", - "Map diagnostic reported on kapt stubs to original locations in Kotlin sources", - required = false - ) - - val STRICT_MODE_OPTION: CliOption = - CliOption("strict", "true | false", "Show errors on incompatibilities during stub generation", required = false) } +} +class Kapt3CommandLineProcessor : CommandLineProcessor { override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID - override val pluginOptions: Collection = - listOf( - SOURCE_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, APT_OPTIONS_OPTION, JAVAC_CLI_OPTIONS_OPTION, - CLASS_OUTPUT_DIR_OPTION, VERBOSE_MODE_OPTION, STUBS_OUTPUT_DIR_OPTION, APT_ONLY_OPTION, APT_MODE_OPTION, - USE_LIGHT_ANALYSIS_OPTION, CORRECT_ERROR_TYPES_OPTION, ANNOTATION_PROCESSORS_OPTION, INCREMENTAL_DATA_OUTPUT_DIR_OPTION, - CONFIGURATION, MAP_DIAGNOSTIC_LOCATIONS_OPTION, INFO_AS_WARNINGS_OPTION, STRICT_MODE_OPTION - ) + override val pluginOptions: Collection = KaptCliOptions.values().asList() - override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) { - when (option) { + override fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) { + if (option !is KaptCliOptions) { + throw CliOptionProcessingException("Unknown option: ${option.optionName}") + } + + return when (option) { ANNOTATION_PROCESSOR_CLASSPATH_OPTION -> configuration.appendList(ANNOTATION_PROCESSOR_CLASSPATH, value) ANNOTATION_PROCESSORS_OPTION -> configuration.appendList( Kapt3ConfigurationKeys.ANNOTATION_PROCESSORS, value.split(',').map { it.trim() }.filter { it.isNotEmpty() }) @@ -235,7 +183,6 @@ class Kapt3CommandLineProcessor : CommandLineProcessor { INFO_AS_WARNINGS_OPTION -> configuration.put(Kapt3ConfigurationKeys.INFO_AS_WARNINGS, value) STRICT_MODE_OPTION -> configuration.put(Kapt3ConfigurationKeys.STRICT_MODE, value) CONFIGURATION -> configuration.applyOptionsFrom(decodePluginOptions(value), pluginOptions) - else -> throw CliOptionProcessingException("Unknown option: ${option.name}") } } }