CommandLineProcessor infrastructure added
This commit is contained in:
committed by
Yan Zhulanow
parent
565ce5a781
commit
d961e2f5b4
+10
@@ -23,6 +23,8 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class CommonCompilerArguments {
|
public abstract class CommonCompilerArguments {
|
||||||
|
public static final String PLUGIN_OPTION_FORMAT = "<pluginId>:<optionName>=<value>";
|
||||||
|
|
||||||
@Argument(value = "nowarn", description = "Generate no warnings")
|
@Argument(value = "nowarn", description = "Generate no warnings")
|
||||||
public boolean suppressWarnings;
|
public boolean suppressWarnings;
|
||||||
|
|
||||||
@@ -41,6 +43,14 @@ public abstract class CommonCompilerArguments {
|
|||||||
@Argument(value = "Xno-inline", description = "Disable method inlining")
|
@Argument(value = "Xno-inline", description = "Disable method inlining")
|
||||||
public boolean noInline;
|
public boolean noInline;
|
||||||
|
|
||||||
|
@Argument(value = "Xplugin", description = "Load a plugin from the given classpath")
|
||||||
|
@ValueDescription("<path>")
|
||||||
|
public String[] pluginClasspaths;
|
||||||
|
|
||||||
|
@Argument(value = "P", description = "Pass an option to a plugin")
|
||||||
|
@ValueDescription(PLUGIN_OPTION_FORMAT)
|
||||||
|
public String[] pluginOptions;
|
||||||
|
|
||||||
public List<String> freeArgs = new SmartList<String>();
|
public List<String> freeArgs = new SmartList<String>();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.jet.cli.jvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor
|
||||||
|
import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments
|
||||||
|
import kotlin.platform.*
|
||||||
|
import java.util.jar.JarFile
|
||||||
|
import java.util.jar.Attributes
|
||||||
|
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
import org.jetbrains.jet.utils.valuesToMap
|
||||||
|
import org.jetbrains.jet.config.CompilerConfiguration
|
||||||
|
import com.intellij.util.containers.MultiMap
|
||||||
|
import org.jetbrains.kotlin.compiler.plugin.CliOption
|
||||||
|
|
||||||
|
public object PluginCliParser {
|
||||||
|
|
||||||
|
public val PLUGIN_ARGUMENT_PREFIX: String = "plugin:"
|
||||||
|
|
||||||
|
private fun getCommandLineProcessors(arguments: CommonCompilerArguments): Collection<CommandLineProcessor> {
|
||||||
|
return arguments.pluginClasspaths!!.map {
|
||||||
|
loadCommandLineProcessor(JarFile(it).getManifest()?.getAttributes("org.jetbrains.kotlin.compiler.plugin"))
|
||||||
|
}.filterNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadCommandLineProcessor(attributes: Attributes?): CommandLineProcessor? {
|
||||||
|
if (attributes == null) return null
|
||||||
|
|
||||||
|
val processorClassName = attributes.getValue("CommandLineProcessor")
|
||||||
|
if (processorClassName == null) return null
|
||||||
|
|
||||||
|
try {
|
||||||
|
val processorClass = Class.forName(processorClassName)
|
||||||
|
return processorClass.newInstance() as CommandLineProcessor
|
||||||
|
}
|
||||||
|
catch (e: Throwable) {
|
||||||
|
throw CliOptionProcessingException("Loading plugin component failed: $processorClassName", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[platformStatic]
|
||||||
|
fun processPluginOptions(arguments: CommonCompilerArguments, configuration: CompilerConfiguration) {
|
||||||
|
val optionValuesByPlugin = arguments.pluginOptions!!.map { parsePluginOption(it) }.groupBy {
|
||||||
|
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
|
||||||
|
it.optionName
|
||||||
|
}
|
||||||
|
|
||||||
|
val processors = getCommandLineProcessors(arguments)
|
||||||
|
for (processor in processors) {
|
||||||
|
val declaredOptions = processor.pluginOptions.valuesToMap { it.name }
|
||||||
|
val optionsToValues = MultiMap<CliOption, PluginOptionValue>()
|
||||||
|
|
||||||
|
for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) {
|
||||||
|
val option = declaredOptions[optionValue!!.optionName]
|
||||||
|
if (option == null) {
|
||||||
|
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 CliOptionProcessingException("Required plugin option not present: ${processor.pluginId}:${option.name}")
|
||||||
|
}
|
||||||
|
if (!option.allowMultipleOccurrences && values.size() > 1) {
|
||||||
|
throw CliOptionProcessingException("Multiple values not allowed for plugin option ${processor.pluginId}:${option.name}")
|
||||||
|
}
|
||||||
|
|
||||||
|
for (value in values) {
|
||||||
|
processor.processOption(option, value.value, configuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PluginOptionValue(
|
||||||
|
val pluginId: String,
|
||||||
|
val optionName: String,
|
||||||
|
val value: String
|
||||||
|
) {
|
||||||
|
override fun toString() = "$pluginId:$optionName=$value"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parsePluginOption(argumentValue: String): PluginOptionValue? {
|
||||||
|
val pattern = Pattern.compile("""^([^:]*):([^=]*)=(.*)$""")
|
||||||
|
val matcher = pattern.matcher(argumentValue)
|
||||||
|
if (matcher.matches()) {
|
||||||
|
return PluginOptionValue(matcher.group(1)!!, matcher.group(2)!!, matcher.group(3)!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import com.google.common.base.Splitter;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.Disposable;
|
import com.intellij.openapi.Disposable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.cli.jvm.PluginCliParser;
|
||||||
import org.jetbrains.kotlin.cli.common.CLICompiler;
|
import org.jetbrains.kotlin.cli.common.CLICompiler;
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
|
||||||
import org.jetbrains.kotlin.cli.common.ExitCode;
|
import org.jetbrains.kotlin.cli.common.ExitCode;
|
||||||
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.cli.common.modules.ModuleScriptData;
|
|||||||
import org.jetbrains.kotlin.cli.jvm.compiler.*;
|
import org.jetbrains.kotlin.cli.jvm.compiler.*;
|
||||||
import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal;
|
import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal;
|
||||||
import org.jetbrains.kotlin.codegen.CompilationException;
|
import org.jetbrains.kotlin.codegen.CompilationException;
|
||||||
|
import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException;
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys;
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||||
import org.jetbrains.kotlin.config.Services;
|
import org.jetbrains.kotlin.config.Services;
|
||||||
@@ -90,12 +92,13 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
|||||||
return INTERNAL_ERROR;
|
return INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.androidRes != null) {
|
try {
|
||||||
configuration.put(JVMConfigurationKeys.ANDROID_RES_PATH, arguments.androidRes);
|
PluginCliParser.processPluginOptions(arguments, configuration);
|
||||||
}
|
}
|
||||||
|
catch (CliOptionProcessingException e) {
|
||||||
if (arguments.androidManifest != null) {
|
// TODO Print usage?
|
||||||
configuration.put(JVMConfigurationKeys.ANDROID_MANIFEST, arguments.androidManifest);
|
messageCollector.report(CompilerMessageSeverity.ERROR, e.getMessage(), CompilerMessageLocation.NO_LOCATION);
|
||||||
|
return INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.script) {
|
if (arguments.script) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" exported="" name="intellij-core" level="project" />
|
<orderEntry type="library" exported="" name="intellij-core" level="project" />
|
||||||
|
<orderEntry type="library" name="kotlin-runtime" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 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.compiler.plugin
|
||||||
|
|
||||||
|
import org.jetbrains.jet.config.CompilerConfiguration
|
||||||
|
|
||||||
|
public class CliOption(
|
||||||
|
public val name: String,
|
||||||
|
public val valueDescription: String,
|
||||||
|
public val description: String,
|
||||||
|
public val required: Boolean = true,
|
||||||
|
public val allowMultipleOccurrences: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
public class CliOptionProcessingException(message: String, cause: Throwable? = null): RuntimeException(message, cause)
|
||||||
|
|
||||||
|
public trait CommandLineProcessor {
|
||||||
|
public val pluginId: String
|
||||||
|
public val pluginOptions: Collection<CliOption>
|
||||||
|
|
||||||
|
[throws(javaClass<CliOptionProcessingException>())]
|
||||||
|
public fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user