
org.jetbrains.jet.cli.common.CLICompiler Maven / Gradle / Ivy
/*
* Copyright 2010-2013 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.common;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.sampullara.cli.Args;
import com.sampullara.cli.ArgumentUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments;
import org.jetbrains.jet.cli.common.messages.*;
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentException;
import org.jetbrains.jet.config.CompilerConfiguration;
import java.io.PrintStream;
import java.util.List;
import static org.jetbrains.jet.cli.common.ExitCode.*;
public abstract class CLICompiler {
@NotNull
private List compilerPlugins = Lists.newArrayList();
@NotNull
public List getCompilerPlugins() {
return compilerPlugins;
}
public void setCompilerPlugins(@NotNull List compilerPlugins) {
this.compilerPlugins = compilerPlugins;
}
@NotNull
public ExitCode exec(@NotNull PrintStream errStream, @NotNull String... args) {
A arguments = createArguments();
if (!parseArguments(errStream, arguments, args)) {
return INTERNAL_ERROR;
}
return exec(errStream, arguments);
}
/**
* Returns true if the arguments can be parsed correctly
*/
protected boolean parseArguments(@NotNull PrintStream errStream, @NotNull A arguments, @NotNull String[] args) {
try {
arguments.freeArgs = Args.parse(arguments, args);
checkArguments(arguments);
return true;
}
catch (IllegalArgumentException e) {
errStream.println(e.getMessage());
usage(errStream);
}
catch (Throwable t) {
// Always use tags
errStream.println(MessageRenderer.TAGS.renderException(t));
}
return false;
}
protected void checkArguments(@NotNull A argument) {
}
/**
* Allow derived classes to add additional command line arguments
*/
protected void usage(@NotNull PrintStream target) {
// We should say something like
// Args.usage(target, K2JVMCompilerArguments.class);
// but currently cli-parser we are using does not support that
// a corresponding patch has been sent to the authors
// For now, we are using this:
PrintStream oldErr = System.err;
System.setErr(target);
try {
// TODO: use proper argv0
Args.usage(createArguments());
}
finally {
System.setErr(oldErr);
}
}
/**
* Strategy method to configure the environment, allowing compiler
* based tools to customise their own plugins
*/
protected void configureEnvironment(@NotNull CompilerConfiguration configuration, @NotNull A arguments) {
configuration.addAll(CLIConfigurationKeys.COMPILER_PLUGINS, compilerPlugins);
}
@NotNull
protected abstract A createArguments();
/**
* Executes the compiler on the parsed arguments
*/
@NotNull
public ExitCode exec(@NotNull PrintStream errStream, @NotNull A arguments) {
if (arguments.help) {
usage(errStream);
return OK;
}
MessageRenderer messageRenderer = getMessageRenderer(arguments);
errStream.print(messageRenderer.renderPreamble());
printArgumentsIfNeeded(errStream, arguments, messageRenderer);
printVersionIfNeeded(errStream, arguments, messageRenderer);
MessageCollector collector = new PrintingMessageCollector(errStream, messageRenderer, arguments.verbose);
if (arguments.suppressAllWarnings()) {
collector = new FilteringMessageCollector(collector, Predicates.equalTo(CompilerMessageSeverity.WARNING));
}
try {
return exec(collector, arguments);
}
finally {
errStream.print(messageRenderer.renderConclusion());
}
}
@NotNull
public ExitCode exec(@NotNull MessageCollector messageCollector, @NotNull A arguments) {
GroupingMessageCollector groupingCollector = new GroupingMessageCollector(messageCollector);
try {
Disposable rootDisposable = Disposer.newDisposable();
try {
MessageSeverityCollector severityCollector = new MessageSeverityCollector(groupingCollector);
ExitCode code = doExecute(arguments, severityCollector, rootDisposable);
return severityCollector.anyReported(CompilerMessageSeverity.ERROR) ? COMPILATION_ERROR : code;
}
finally {
Disposer.dispose(rootDisposable);
}
}
catch (Throwable t) {
groupingCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(t),
CompilerMessageLocation.NO_LOCATION);
return INTERNAL_ERROR;
}
finally {
groupingCollector.flush();
}
}
@NotNull
protected abstract ExitCode doExecute(@NotNull A arguments, @NotNull MessageCollector messageCollector, @NotNull Disposable rootDisposable);
//TODO: can we make it private?
@NotNull
protected MessageRenderer getMessageRenderer(@NotNull A arguments) {
return arguments.tags ? MessageRenderer.TAGS : MessageRenderer.PLAIN;
}
protected void printVersionIfNeeded(
@NotNull PrintStream errStream,
@NotNull A arguments,
@NotNull MessageRenderer messageRenderer
) {
if (arguments.version) {
String versionMessage = messageRenderer.render(CompilerMessageSeverity.INFO,
"Kotlin Compiler version " + KotlinVersion.VERSION,
CompilerMessageLocation.NO_LOCATION);
errStream.println(versionMessage);
}
}
private void printArgumentsIfNeeded(
@NotNull PrintStream errStream,
@NotNull A arguments,
@NotNull MessageRenderer messageRenderer
) {
if (arguments.printArgs) {
String freeArgs = !arguments.freeArgs.isEmpty() ? " " + StringUtil.join(arguments.freeArgs, " ") : "";
List argumentsAsList = ArgumentUtils.convertArgumentsToStringList(arguments, createArguments());
String argumentsAsString = StringUtil.join(argumentsAsList, " ");
String printArgsMessage = messageRenderer.render(CompilerMessageSeverity.INFO,
"Invoking compiler " + getClass().getName() +
" with arguments " + argumentsAsString + freeArgs,
CompilerMessageLocation.NO_LOCATION);
errStream.println(printArgsMessage);
}
}
/**
* Useful main for derived command line tools
*/
public static void doMain(@NotNull CLICompiler compiler, @NotNull String[] args) {
// We depend on swing (indirectly through PSI or something), so we want to declare headless mode,
// to avoid accidentally starting the UI thread
System.setProperty("java.awt.headless", "true");
ExitCode exitCode = doMainNoExit(compiler, args);
if (exitCode != OK) {
System.exit(exitCode.getCode());
}
}
@NotNull
public static ExitCode doMainNoExit(@NotNull CLICompiler compiler, @NotNull String[] args) {
try {
ExitCode rc = compiler.exec(System.out, args);
if (rc != OK) {
System.err.println("exec() finished with " + rc + " return code");
}
return rc;
}
catch (CompileEnvironmentException e) {
System.err.println(e.getMessage());
return INTERNAL_ERROR;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy