Compiler API refactored:
* exec(messageCollector, arguments) introduced * exception-catching logic moved closer to the entry point * PrintingMessageCollector localized
This commit is contained in:
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.messages;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
public class MessageSeverityCollector implements MessageCollector {
|
||||
|
||||
private final MessageCollector delegate;
|
||||
|
||||
private final Set<CompilerMessageSeverity> reportedSeverities = Sets.newHashSet();
|
||||
|
||||
public MessageSeverityCollector(@NotNull MessageCollector delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report(
|
||||
@NotNull CompilerMessageSeverity severity,
|
||||
@NotNull String message,
|
||||
@NotNull CompilerMessageLocation location
|
||||
) {
|
||||
delegate.report(severity, message, location);
|
||||
|
||||
reportedSeverities.add(severity);
|
||||
}
|
||||
|
||||
public boolean anyReported(@NotNull CompilerMessageSeverity... severities) {
|
||||
return reportedSeverities.containsAll(Arrays.asList(severities));
|
||||
}
|
||||
}
|
||||
+10
-24
@@ -18,38 +18,36 @@ package org.jetbrains.jet.cli.common.messages;
|
||||
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public class PrintingMessageCollector implements MessageCollector {
|
||||
|
||||
private boolean verbose;
|
||||
private final boolean verbose;
|
||||
private final PrintStream errStream;
|
||||
private final MessageRenderer messageRenderer;
|
||||
|
||||
// File path (nullable) -> error message
|
||||
private final Multimap<String, String> groupedMessages = LinkedHashMultimap.create();
|
||||
|
||||
private final Set<CompilerMessageSeverity> reportedSeverities = Sets.newHashSet();
|
||||
|
||||
public PrintingMessageCollector(PrintStream errStream,
|
||||
MessageRenderer messageRenderer,
|
||||
boolean verbose) {
|
||||
public PrintingMessageCollector(
|
||||
@NotNull PrintStream errStream,
|
||||
@NotNull MessageRenderer messageRenderer,
|
||||
boolean verbose
|
||||
) {
|
||||
this.verbose = verbose;
|
||||
this.errStream = errStream;
|
||||
this.messageRenderer = messageRenderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report(@NotNull CompilerMessageSeverity severity,
|
||||
public void report(
|
||||
@NotNull CompilerMessageSeverity severity,
|
||||
@NotNull String message,
|
||||
@NotNull CompilerMessageLocation location) {
|
||||
reportedSeverities.add(severity);
|
||||
@NotNull CompilerMessageLocation location
|
||||
) {
|
||||
|
||||
String text = messageRenderer.render(severity, message, location);
|
||||
if (severity == CompilerMessageSeverity.LOGGING || severity == CompilerMessageSeverity.OUTPUT) {
|
||||
@@ -73,16 +71,4 @@ public class PrintingMessageCollector implements MessageCollector {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isVerbose() {
|
||||
return verbose;
|
||||
}
|
||||
|
||||
public void setVerbose(boolean verbose) {
|
||||
this.verbose = verbose;
|
||||
}
|
||||
|
||||
public boolean anyReported(@NotNull CompilerMessageSeverity... severities) {
|
||||
return reportedSeverities.containsAll(Arrays.asList(severities));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,14 @@ import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.sampullara.cli.Args;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation;
|
||||
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
|
||||
import org.jetbrains.jet.cli.common.messages.MessageRenderer;
|
||||
import org.jetbrains.jet.cli.common.messages.PrintingMessageCollector;
|
||||
import org.jetbrains.jet.cli.common.messages.*;
|
||||
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentException;
|
||||
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil;
|
||||
import org.jetbrains.jet.config.CompilerConfiguration;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import static org.jetbrains.jet.cli.common.ExitCode.COMPILATION_ERROR;
|
||||
import static org.jetbrains.jet.cli.common.ExitCode.INTERNAL_ERROR;
|
||||
import static org.jetbrains.jet.cli.common.ExitCode.OK;
|
||||
|
||||
@@ -99,30 +97,50 @@ public abstract class CLICompiler<A extends CompilerArguments> {
|
||||
* Executes the compiler on the parsed arguments
|
||||
*/
|
||||
@NotNull
|
||||
public ExitCode exec(final PrintStream errStream, A arguments) {
|
||||
public ExitCode exec(@NotNull PrintStream errStream, @NotNull A arguments) {
|
||||
if (arguments.isHelp()) {
|
||||
usage(errStream);
|
||||
return OK;
|
||||
}
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
final MessageRenderer messageRenderer = getMessageRenderer(arguments);
|
||||
MessageRenderer messageRenderer = getMessageRenderer(arguments);
|
||||
errStream.print(messageRenderer.renderPreamble());
|
||||
|
||||
printVersionIfNeeded(errStream, arguments, messageRenderer);
|
||||
|
||||
PrintingMessageCollector messageCollector = new PrintingMessageCollector(errStream, messageRenderer, arguments.isVerbose());
|
||||
Disposable rootDisposable = CompileEnvironmentUtil.createMockDisposable();
|
||||
|
||||
try {
|
||||
return doExecute(arguments, messageCollector, rootDisposable);
|
||||
return exec(messageCollector, arguments);
|
||||
}
|
||||
finally {
|
||||
messageCollector.printToErrStream();
|
||||
errStream.print(messageRenderer.renderConclusion());
|
||||
Disposer.dispose(rootDisposable);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ExitCode exec(@NotNull MessageCollector messageCollector, @NotNull A arguments) {
|
||||
try {
|
||||
Disposable rootDisposable = CompileEnvironmentUtil.createMockDisposable();
|
||||
try {
|
||||
MessageSeverityCollector severityCollector = new MessageSeverityCollector(messageCollector);
|
||||
ExitCode code = doExecute(arguments, severityCollector, rootDisposable);
|
||||
return severityCollector.anyReported(CompilerMessageSeverity.ERROR) ? COMPILATION_ERROR : code;
|
||||
}
|
||||
finally {
|
||||
Disposer.dispose(rootDisposable);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(t),
|
||||
CompilerMessageLocation.NO_LOCATION);
|
||||
return INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: can't declare parameters as not null due to KT-1863
|
||||
@NotNull
|
||||
protected abstract ExitCode doExecute(A arguments, PrintingMessageCollector messageCollector, Disposable rootDisposable);
|
||||
protected abstract ExitCode doExecute(A arguments, MessageCollector messageCollector, Disposable rootDisposable);
|
||||
|
||||
//TODO: can we make it private?
|
||||
@NotNull
|
||||
@@ -145,6 +163,9 @@ public abstract class CLICompiler<A extends CompilerArguments> {
|
||||
* 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());
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.jetbrains.jet.cli.common.ExitCode;
|
||||
import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport;
|
||||
import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation;
|
||||
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
|
||||
import org.jetbrains.jet.cli.common.messages.PrintingMessageCollector;
|
||||
import org.jetbrains.jet.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.config.CommonConfigurationKeys;
|
||||
import org.jetbrains.jet.config.CompilerConfiguration;
|
||||
@@ -67,7 +67,7 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected ExitCode doExecute(K2JSCompilerArguments arguments, PrintingMessageCollector messageCollector, Disposable rootDisposable) {
|
||||
protected ExitCode doExecute(K2JSCompilerArguments arguments, MessageCollector messageCollector, Disposable rootDisposable) {
|
||||
if (arguments.sourceFiles == null) {
|
||||
messageCollector.report(CompilerMessageSeverity.ERROR, "Specify sources location via -sourceFiles", NO_LOCATION);
|
||||
return ExitCode.INTERNAL_ERROR;
|
||||
@@ -99,10 +99,10 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
}
|
||||
|
||||
MainCallParameters mainCallParameters = arguments.createMainCallParameters();
|
||||
return translateAndGenerateOutputFile(mainCallParameters, messageCollector, environmentForJS, config, outputFile);
|
||||
return translateAndGenerateOutputFile(mainCallParameters, environmentForJS, config, outputFile);
|
||||
}
|
||||
|
||||
private static void reportCompiledSourcesList(@NotNull PrintingMessageCollector messageCollector,
|
||||
private static void reportCompiledSourcesList(@NotNull MessageCollector messageCollector,
|
||||
@NotNull JetCoreEnvironment environmentForJS) {
|
||||
List<JetFile> files = environmentForJS.getSourceFiles();
|
||||
Iterable<String> fileNames = Iterables.transform(files, new Function<JetFile, String>() {
|
||||
@@ -121,23 +121,22 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ExitCode translateAndGenerateOutputFile(@NotNull MainCallParameters mainCall,
|
||||
@NotNull PrintingMessageCollector messageCollector,
|
||||
@NotNull JetCoreEnvironment environmentForJS, @NotNull Config config, @NotNull String outputFile) {
|
||||
private static ExitCode translateAndGenerateOutputFile(
|
||||
@NotNull MainCallParameters mainCall,
|
||||
@NotNull JetCoreEnvironment environmentForJS,
|
||||
@NotNull Config config,
|
||||
@NotNull String outputFile
|
||||
) {
|
||||
try {
|
||||
K2JSTranslator.translateWithMainCallParametersAndSaveToFile(mainCall, environmentForJS.getSourceFiles(), outputFile, config);
|
||||
}
|
||||
catch (Exception e) {
|
||||
messageCollector.report(CompilerMessageSeverity.ERROR, "Exception while translating:\n" + e.getMessage(),
|
||||
CompilerMessageLocation.NO_LOCATION);
|
||||
// TODO we should report the exception nicely to the collector so it can report
|
||||
// for example inside a mvn plugin we need to see the stack trace
|
||||
return ExitCode.INTERNAL_ERROR;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return messageCollector.anyReported(CompilerMessageSeverity.ERROR) ? COMPILATION_ERROR : OK;
|
||||
return OK;
|
||||
}
|
||||
|
||||
private static boolean analyzeAndReportErrors(@NotNull PrintingMessageCollector messageCollector,
|
||||
private static boolean analyzeAndReportErrors(@NotNull MessageCollector messageCollector,
|
||||
@NotNull final List<JetFile> sources, @NotNull final Config config) {
|
||||
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(messageCollector);
|
||||
analyzerWithCompilerReport.analyzeAndReport(new Function0<AnalyzeExhaust>() {
|
||||
|
||||
@@ -58,7 +58,7 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected ExitCode doExecute(K2JVMCompilerArguments arguments, PrintingMessageCollector messageCollector, Disposable rootDisposable) {
|
||||
protected ExitCode doExecute(K2JVMCompilerArguments arguments, MessageCollector messageCollector, Disposable rootDisposable) {
|
||||
KotlinPaths paths = arguments.kotlinHome != null
|
||||
? new KotlinPathsFromHomeDir(new File(arguments.kotlinHome))
|
||||
: PathUtil.getKotlinPathsForCompiler();
|
||||
@@ -127,10 +127,9 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
||||
File outputDir = arguments.outputDir != null ? new File(arguments.outputDir) : null;
|
||||
|
||||
if (arguments.module != null) {
|
||||
boolean oldVerbose = messageCollector.isVerbose();
|
||||
messageCollector.setVerbose(false);
|
||||
List<Module> modules = CompileEnvironmentUtil.loadModuleScript(paths, arguments.module, messageCollector);
|
||||
messageCollector.setVerbose(oldVerbose);
|
||||
MessageCollector sanitizedCollector = new FilteringMessageCollector(messageCollector);
|
||||
List<Module> modules = CompileEnvironmentUtil.loadModuleScript(paths, arguments.module, sanitizedCollector);
|
||||
|
||||
File directory = new File(arguments.module).getParentFile();
|
||||
KotlinToJVMBytecodeCompiler.compileModules(configuration, modules,
|
||||
directory, jar, outputDir,
|
||||
@@ -145,18 +144,13 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
||||
JetCoreEnvironment environment = new JetCoreEnvironment(rootDisposable, configuration);
|
||||
KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment, jar, outputDir, arguments.includeRuntime);
|
||||
}
|
||||
return messageCollector.anyReported(CompilerMessageSeverity.ERROR) ? COMPILATION_ERROR : OK;
|
||||
return OK;
|
||||
}
|
||||
catch (CompilationException e) {
|
||||
messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(e),
|
||||
MessageUtil.psiElementToMessageLocation(e.getElement()));
|
||||
return INTERNAL_ERROR;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(t),
|
||||
CompilerMessageLocation.NO_LOCATION);
|
||||
return INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +174,7 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
||||
// probably relates to KT-1863... well, may be not
|
||||
@NotNull
|
||||
@Override
|
||||
public ExitCode exec(PrintStream errStream, K2JVMCompilerArguments arguments) {
|
||||
public ExitCode exec(@NotNull PrintStream errStream, @NotNull K2JVMCompilerArguments arguments) {
|
||||
return super.exec(errStream, arguments);
|
||||
}
|
||||
|
||||
@@ -214,4 +208,21 @@ public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments> {
|
||||
}
|
||||
return annotationsPath;
|
||||
}
|
||||
|
||||
private static class FilteringMessageCollector implements MessageCollector {
|
||||
private final MessageCollector messageCollector;
|
||||
|
||||
public FilteringMessageCollector(@NotNull MessageCollector messageCollector) {
|
||||
this.messageCollector = messageCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report(
|
||||
@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location
|
||||
) {
|
||||
if (!(severity == CompilerMessageSeverity.LOGGING || severity == CompilerMessageSeverity.OUTPUT)) {
|
||||
messageCollector.report(severity, message, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user