[CLI] Introduce new compiler arguments for registering compiler plugins
With new syntax each plugin should be registered in separate argument with syntax `-Xcompiler-plugin=classpath1,classpath2[=argument1=value1,argument2=value2]`
This commit is contained in:
committed by
teamcity
parent
8919703448
commit
928416c9c5
+7
-3
@@ -20,6 +20,7 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
private val serialVersionUID = 0L
|
||||
|
||||
const val PLUGIN_OPTION_FORMAT = "plugin:<pluginId>:<optionName>=<value>"
|
||||
const val PLUGIN_DECLARATION_FORMAT = "<path>[=<optionName>=<value>]"
|
||||
|
||||
const val WARN = "warn"
|
||||
const val ERROR = "error"
|
||||
@@ -70,9 +71,6 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
@Argument(value = "-script", description = "Evaluate the given Kotlin script (*.kts) file")
|
||||
var script: Boolean by FreezableVar(false)
|
||||
|
||||
@Argument(value = "-P", valueDescription = PLUGIN_OPTION_FORMAT, description = "Pass an option to a plugin")
|
||||
var pluginOptions: Array<String>? by FreezableVar(null)
|
||||
|
||||
@Argument(
|
||||
value = "-opt-in",
|
||||
deprecatedName = "-Xopt-in",
|
||||
@@ -107,6 +105,12 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
@Argument(value = "-Xplugin", valueDescription = "<path>", description = "Load plugins from the given classpath")
|
||||
var pluginClasspaths: Array<String>? by FreezableVar(null)
|
||||
|
||||
@Argument(value = "-P", valueDescription = PLUGIN_OPTION_FORMAT, description = "Pass an option to a plugin")
|
||||
var pluginOptions: Array<String>? by FreezableVar(null)
|
||||
|
||||
@Argument(value = "-Xcompiler-plugin", valueDescription = "<path1>,<path2>:<optionName>=<value>,<optionName>=<value>", description = "Register compiler plugin", delimiter = "")
|
||||
var pluginConfigurations: Array<String>? by FreezableVar(null)
|
||||
|
||||
@Argument(value = "-Xmulti-platform", description = "Enable experimental language support for multi-platform projects")
|
||||
var multiPlatform: Boolean by FreezableVar(false)
|
||||
|
||||
|
||||
+60
-27
@@ -10,46 +10,79 @@ import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.compiler.plugin.*
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
|
||||
data class PluginClasspathAndOptions(
|
||||
val rawArgument: String,
|
||||
val classpath: List<String>,
|
||||
val options: List<CliOptionValue>
|
||||
)
|
||||
|
||||
private const val regularDelimiter = ","
|
||||
private const val classpathOptionsDelimiter = "="
|
||||
|
||||
fun extractPluginClasspathAndOptions(pluginConfigurations: Iterable<String>): List<PluginClasspathAndOptions> {
|
||||
return pluginConfigurations.map { extractPluginClasspathAndOptions(it)}
|
||||
}
|
||||
|
||||
fun extractPluginClasspathAndOptions(pluginConfiguration: String): PluginClasspathAndOptions {
|
||||
val rawClasspath = pluginConfiguration.substringBefore(classpathOptionsDelimiter)
|
||||
val rawOptions = pluginConfiguration.substringAfter(classpathOptionsDelimiter, missingDelimiterValue = "")
|
||||
val classPath = rawClasspath.split(regularDelimiter)
|
||||
val options = rawOptions.takeIf { it.isNotBlank() }
|
||||
?.split(regularDelimiter)
|
||||
?.mapNotNull { parseModernPluginOption(it) }
|
||||
?: emptyList()
|
||||
return PluginClasspathAndOptions(pluginConfiguration, classPath, options)
|
||||
}
|
||||
|
||||
fun processCompilerPluginsOptions(
|
||||
configuration: CompilerConfiguration,
|
||||
pluginOptions: Iterable<String>?,
|
||||
commandLineProcessors: List<CommandLineProcessor>
|
||||
) {
|
||||
val optionValuesByPlugin = pluginOptions?.map(::parsePluginOption)?.groupBy {
|
||||
val optionValuesByPlugin = pluginOptions?.map(::parseLegacyPluginOption)?.groupBy {
|
||||
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
|
||||
it.pluginId
|
||||
} ?: mapOf()
|
||||
|
||||
for (processor in commandLineProcessors) {
|
||||
val declaredOptions = processor.pluginOptions.associateBy { it.optionName }
|
||||
val optionsToValues = MultiMap<AbstractCliOption, CliOptionValue>()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
processCompilerPluginOptions(processor, optionValuesByPlugin[processor.pluginId].orEmpty() as List<CliOptionValue>, configuration)
|
||||
}
|
||||
}
|
||||
|
||||
for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) {
|
||||
val option = declaredOptions[optionValue!!.optionName]
|
||||
?: throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
|
||||
optionsToValues.putValue(option, optionValue)
|
||||
fun processCompilerPluginOptions(
|
||||
processor: CommandLineProcessor,
|
||||
pluginOptions: List<CliOptionValue>,
|
||||
configuration: CompilerConfiguration
|
||||
) {
|
||||
val declaredOptions = processor.pluginOptions.associateBy { it.optionName }
|
||||
val optionsToValues = MultiMap<AbstractCliOption, CliOptionValue>()
|
||||
|
||||
for (optionValue in pluginOptions) {
|
||||
val option = declaredOptions[optionValue.optionName]
|
||||
?: throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
|
||||
optionsToValues.putValue(option, optionValue)
|
||||
}
|
||||
|
||||
for (option in processor.pluginOptions) {
|
||||
val values = optionsToValues[option]
|
||||
if (option.required && values.isEmpty()) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"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.optionName}"
|
||||
)
|
||||
}
|
||||
|
||||
for (option in processor.pluginOptions) {
|
||||
val values = optionsToValues[option]
|
||||
if (option.required && values.isEmpty()) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"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.optionName}"
|
||||
)
|
||||
}
|
||||
|
||||
for (value in values) {
|
||||
processor.processOption(option, value.value, configuration)
|
||||
}
|
||||
for (value in values) {
|
||||
processor.processOption(option, value.value, configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user