diff --git a/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/messages/MessageSeverityCollector.java b/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/messages/MessageSeverityCollector.java new file mode 100644 index 00000000000..0b8c3fc9703 --- /dev/null +++ b/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/messages/MessageSeverityCollector.java @@ -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 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)); + } +} diff --git a/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/messages/PrintingMessageCollector.java b/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/messages/PrintingMessageCollector.java index 67e6653a42f..ef16c579114 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/messages/PrintingMessageCollector.java +++ b/compiler/cli/cli-common/src/org/jetbrains/jet/cli/common/messages/PrintingMessageCollector.java @@ -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 groupedMessages = LinkedHashMultimap.create(); - private final Set 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)); - } } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java index 1c2e468a675..c2f17dcafc9 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java @@ -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 { * 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 { * 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()); diff --git a/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java index 54d353101fd..d3beab03a7a 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java @@ -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 { @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 { } 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 files = environmentForJS.getSourceFiles(); Iterable fileNames = Iterables.transform(files, new Function() { @@ -121,23 +121,22 @@ public class K2JSCompiler extends CLICompiler { } @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 sources, @NotNull final Config config) { AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(messageCollector); analyzerWithCompilerReport.analyzeAndReport(new Function0() { diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompiler.java index 2cf1c40ff46..d189c99b03d 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompiler.java @@ -58,7 +58,7 @@ public class K2JVMCompiler extends CLICompiler { @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 { File outputDir = arguments.outputDir != null ? new File(arguments.outputDir) : null; if (arguments.module != null) { - boolean oldVerbose = messageCollector.isVerbose(); - messageCollector.setVerbose(false); - List modules = CompileEnvironmentUtil.loadModuleScript(paths, arguments.module, messageCollector); - messageCollector.setVerbose(oldVerbose); + MessageCollector sanitizedCollector = new FilteringMessageCollector(messageCollector); + List 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 { 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 { // 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 { } 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); + } + } + } }