[cli-repl] Error render and XML-interop with IDE console
This commit is contained in:
committed by
Pavel V. Talanov
parent
a11f411f7d
commit
cb1756f5fa
+14
-45
@@ -53,7 +53,7 @@ import static org.jetbrains.kotlin.diagnostics.DiagnosticUtils.sortedDiagnostics
|
||||
public final class AnalyzerWithCompilerReport {
|
||||
|
||||
@NotNull
|
||||
private static CompilerMessageSeverity convertSeverity(@NotNull Severity severity) {
|
||||
public static CompilerMessageSeverity convertSeverity(@NotNull Severity severity) {
|
||||
switch (severity) {
|
||||
case INFO:
|
||||
return CompilerMessageSeverity.INFO;
|
||||
@@ -76,7 +76,7 @@ public final class AnalyzerWithCompilerReport {
|
||||
|
||||
private static boolean reportDiagnostic(
|
||||
@NotNull Diagnostic diagnostic,
|
||||
@NotNull MessageCollector messageCollector,
|
||||
@NotNull DiagnosticMessageReporter reporter,
|
||||
boolean incompatibleFilesFound
|
||||
) {
|
||||
if (!diagnostic.isValid()) return false;
|
||||
@@ -96,11 +96,7 @@ public final class AnalyzerWithCompilerReport {
|
||||
}
|
||||
|
||||
PsiFile file = diagnostic.getPsiFile();
|
||||
messageCollector.report(
|
||||
convertSeverity(diagnostic.getSeverity()),
|
||||
render,
|
||||
MessageUtil.psiFileToMessageLocation(file, file.getName(), DiagnosticUtils.getLineAndColumn(diagnostic))
|
||||
);
|
||||
reporter.report(diagnostic, file, render);
|
||||
|
||||
return diagnostic.getSeverity() == Severity.ERROR;
|
||||
}
|
||||
@@ -175,20 +171,16 @@ public final class AnalyzerWithCompilerReport {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean reportDiagnostics(
|
||||
@NotNull Diagnostics diagnostics,
|
||||
@NotNull MessageCollector messageCollector,
|
||||
boolean incompatibleFilesFound
|
||||
) {
|
||||
public static boolean reportDiagnostics(@NotNull Diagnostics diagnostics, @NotNull DiagnosticMessageReporter reporter, boolean incompatibleFilesFound) {
|
||||
boolean hasErrors = false;
|
||||
for (Diagnostic diagnostic : sortedDiagnostics(diagnostics.all())) {
|
||||
hasErrors |= reportDiagnostic(diagnostic, messageCollector, incompatibleFilesFound);
|
||||
hasErrors |= reportDiagnostic(diagnostic, reporter, incompatibleFilesFound);
|
||||
}
|
||||
return hasErrors;
|
||||
}
|
||||
|
||||
public static boolean reportDiagnostics(@NotNull Diagnostics diagnostics, @NotNull MessageCollector collector) {
|
||||
return reportDiagnostics(diagnostics, collector, false);
|
||||
public static boolean reportDiagnostics(@NotNull Diagnostics diagnostics, @NotNull MessageCollector messageCollector, boolean incompatibleFilesFound) {
|
||||
return reportDiagnostics(diagnostics, new DefaultDiagnosticReporter(messageCollector), incompatibleFilesFound);
|
||||
}
|
||||
|
||||
private void reportSyntaxErrors(@NotNull Collection<JetFile> files) {
|
||||
@@ -215,14 +207,17 @@ public final class AnalyzerWithCompilerReport {
|
||||
}
|
||||
}
|
||||
|
||||
public static SyntaxErrorReport reportSyntaxErrors(@NotNull final PsiElement file, @NotNull final MessageCollector messageCollector) {
|
||||
public static SyntaxErrorReport reportSyntaxErrors(
|
||||
@NotNull final PsiElement file,
|
||||
@NotNull final DiagnosticMessageReporter reporter
|
||||
) {
|
||||
class ErrorReportingVisitor extends AnalyzingUtils.PsiErrorElementVisitor {
|
||||
boolean hasErrors = false;
|
||||
boolean allErrorsAtEof = true;
|
||||
|
||||
private <E extends PsiElement> void reportDiagnostic(E element, DiagnosticFactory0<E> factory, String message) {
|
||||
MyDiagnostic<?> diagnostic = new MyDiagnostic<E>(element, factory, message);
|
||||
AnalyzerWithCompilerReport.reportDiagnostic(diagnostic, messageCollector, false);
|
||||
AnalyzerWithCompilerReport.reportDiagnostic(diagnostic, reporter, false);
|
||||
if (element.getTextRange().getStartOffset() != file.getTextRange().getEndOffset()) {
|
||||
allErrorsAtEof = false;
|
||||
}
|
||||
@@ -242,34 +237,8 @@ public final class AnalyzerWithCompilerReport {
|
||||
return new SyntaxErrorReport(visitor.hasErrors, visitor.allErrorsAtEof);
|
||||
}
|
||||
|
||||
public static SyntaxErrorReport reportSyntaxErrorsWithDiagnostics(@NotNull final PsiElement file, @NotNull final MessageCollector messageCollector,
|
||||
@NotNull final List<Diagnostic> diagnostics) {
|
||||
class ErrorReportingVisitor extends AnalyzingUtils.PsiErrorElementVisitor {
|
||||
boolean hasErrors = false;
|
||||
boolean allErrorsAtEof = true;
|
||||
|
||||
private <E extends PsiElement> void reportDiagnostic(E element, DiagnosticFactory0<E> factory, String message) {
|
||||
MyDiagnostic<?> diagnostic = new MyDiagnostic<E>(element, factory, message);
|
||||
AnalyzerWithCompilerReport.reportDiagnostic(diagnostic, messageCollector);
|
||||
if (element.getTextRange().getStartOffset() != file.getTextRange().getEndOffset()) {
|
||||
allErrorsAtEof = false;
|
||||
}
|
||||
hasErrors = true;
|
||||
|
||||
diagnostics.add(diagnostic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitErrorElement(PsiErrorElement element) {
|
||||
String description = element.getErrorDescription();
|
||||
reportDiagnostic(element, SYNTAX_ERROR_FACTORY, StringUtil.isEmpty(description) ? "Syntax error" : description);
|
||||
}
|
||||
}
|
||||
ErrorReportingVisitor visitor = new ErrorReportingVisitor();
|
||||
|
||||
file.accept(visitor);
|
||||
|
||||
return new SyntaxErrorReport(visitor.hasErrors, visitor.allErrorsAtEof);
|
||||
public static SyntaxErrorReport reportSyntaxErrors(@NotNull PsiElement file, @NotNull MessageCollector messageCollector) {
|
||||
return reportSyntaxErrors(file, new DefaultDiagnosticReporter(messageCollector));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.common.messages
|
||||
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
|
||||
/**
|
||||
* This class behaviour is the same as [MessageCollector.report] in [AnalyzerWithCompilerReport.reportDiagnostic].
|
||||
*/
|
||||
public class DefaultDiagnosticReporter(override val messageCollector: MessageCollector) : MessageCollectorBasedReporter
|
||||
|
||||
public interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
||||
|
||||
val messageCollector: MessageCollector
|
||||
|
||||
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
|
||||
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
|
||||
render,
|
||||
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
|
||||
)
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.common.messages
|
||||
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
|
||||
public interface DiagnosticMessageReporter {
|
||||
fun report(diagnostic: Diagnostic, file: PsiFile, render: String)
|
||||
}
|
||||
@@ -26,6 +26,14 @@ public interface MessageRenderer {
|
||||
|
||||
MessageRenderer XML = new XmlMessageRenderer();
|
||||
|
||||
MessageRenderer WITHOUT_PATHS = new PlainTextMessageRenderer() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected String getPath(@NotNull CompilerMessageLocation location) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
MessageRenderer PLAIN_FULL_PATHS = new PlainTextMessageRenderer() {
|
||||
@Nullable
|
||||
@Override
|
||||
|
||||
@@ -23,13 +23,14 @@ import com.intellij.testFramework.LightVirtualFile;
|
||||
import jline.console.ConsoleReader;
|
||||
import jline.console.history.FileHistory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.cli.common.KotlinVersion;
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.FromIdeXmlMessagesParser;
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemOutWrapper;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.utils.UtilsPackage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -40,18 +41,22 @@ public class ReplFromTerminal {
|
||||
private final Object waitRepl = new Object();
|
||||
|
||||
private final boolean ideMode;
|
||||
private ReplSystemOutWrapper replWriter;
|
||||
private final ReplSystemOutWrapper replWriter;
|
||||
|
||||
private final ConsoleReader consoleReader;
|
||||
|
||||
public ReplFromTerminal(
|
||||
@NotNull final Disposable disposable,
|
||||
@NotNull final CompilerConfiguration compilerConfiguration) {
|
||||
@NotNull final CompilerConfiguration compilerConfiguration
|
||||
) {
|
||||
String replIdeMode = System.getProperty("repl.ideMode");
|
||||
ideMode = replIdeMode != null && replIdeMode.equals("true");
|
||||
|
||||
new Thread("initialize-repl") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
replInterpreter = new ReplInterpreter(disposable, compilerConfiguration);
|
||||
replInterpreter = new ReplInterpreter(disposable, compilerConfiguration, ideMode);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
replInitializationFailed = e;
|
||||
@@ -62,8 +67,11 @@ public class ReplFromTerminal {
|
||||
}
|
||||
}.start();
|
||||
|
||||
String replIdeMode = System.getProperty("repl.ideMode");
|
||||
ideMode = replIdeMode != null && replIdeMode.equals("true");
|
||||
// wrapper is required to escape every input in [ideMode];
|
||||
// if [ideMode == false] then just redirects all input to [System.out]
|
||||
// if user calls [System.setOut(...)] then undefined behaviour
|
||||
replWriter = new ReplSystemOutWrapper(System.out, ideMode);
|
||||
System.setOut(replWriter);
|
||||
|
||||
try {
|
||||
OutputStream outStream = System.out;
|
||||
@@ -72,11 +80,6 @@ public class ReplFromTerminal {
|
||||
// to prevent such behaviour we redirect his output to dummy output stream
|
||||
VirtualFile consoleOutputRedirect = new LightVirtualFile("kotlinConsoleReplRedirect");
|
||||
outStream = consoleOutputRedirect.getOutputStream(null);
|
||||
|
||||
// wrapper is required to escape every input;
|
||||
// if user calls [System.setOut(...)] then undefined behaviour
|
||||
replWriter = new ReplSystemOutWrapper(System.out);
|
||||
System.setOut(replWriter);
|
||||
}
|
||||
|
||||
consoleReader = new ConsoleReader("kotlin", System.in, outStream, null);
|
||||
@@ -87,8 +90,6 @@ public class ReplFromTerminal {
|
||||
catch (Exception e) {
|
||||
throw UtilsPackage.rethrow(e);
|
||||
}
|
||||
|
||||
getReplInterpreter().setIdeMode(ideMode);
|
||||
}
|
||||
|
||||
private ReplInterpreter getReplInterpreter() {
|
||||
@@ -113,9 +114,9 @@ public class ReplFromTerminal {
|
||||
|
||||
private void doRun() {
|
||||
try {
|
||||
System.out.println("Welcome to Kotlin version " + KotlinVersion.VERSION +
|
||||
replWriter.println("Welcome to Kotlin version " + KotlinVersion.VERSION +
|
||||
" (JRE " + System.getProperty("java.runtime.version") + ")");
|
||||
System.out.println("Type :help for help, :quit for quit");
|
||||
replWriter.println("Type :help for help, :quit for quit");
|
||||
WhatNextAfterOneLine next = WhatNextAfterOneLine.READ_LINE;
|
||||
while (true) {
|
||||
next = one(next);
|
||||
@@ -147,7 +148,7 @@ public class ReplFromTerminal {
|
||||
private WhatNextAfterOneLine one(@NotNull WhatNextAfterOneLine next) {
|
||||
try {
|
||||
String prompt = getPrompt(next);
|
||||
String line = consoleReader.readLine(prompt);
|
||||
String line = readLine(prompt);
|
||||
|
||||
if (line == null) {
|
||||
return WhatNextAfterOneLine.QUIT;
|
||||
@@ -171,6 +172,7 @@ public class ReplFromTerminal {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getPrompt(@NotNull WhatNextAfterOneLine next) {
|
||||
String prompt = null;
|
||||
// consoleReader always print prompt; in [ideMode] we don't allow it
|
||||
@@ -180,22 +182,28 @@ public class ReplFromTerminal {
|
||||
return prompt;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String readLine(@Nullable String prompt) throws IOException {
|
||||
String line = consoleReader.readLine(prompt);
|
||||
if (ideMode && line != null) {
|
||||
line = FromIdeXmlMessagesParser.parse(line);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ReplInterpreter.LineResultType eval(@NotNull String line) {
|
||||
ReplInterpreter.LineResult lineResult = getReplInterpreter().eval(line);
|
||||
if (lineResult.getType() == ReplInterpreter.LineResultType.SUCCESS) {
|
||||
if (!lineResult.isUnit()) {
|
||||
System.out.println(lineResult.getValue());
|
||||
replWriter.printlnResult(lineResult.getValue());
|
||||
}
|
||||
}
|
||||
else if (lineResult.getType() == ReplInterpreter.LineResultType.INCOMPLETE) {
|
||||
replWriter.printlnIncomplete();
|
||||
}
|
||||
else if (lineResult.getType() == ReplInterpreter.LineResultType.ERROR) {
|
||||
if (ideMode) {
|
||||
replWriter.printlnWithEscaping(lineResult.getErrorText(), EscapeType.REPORT);
|
||||
} else {
|
||||
System.out.print(lineResult.getErrorText());
|
||||
}
|
||||
replWriter.printlnError(lineResult.getErrorText());
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("unknown line result type: " + lineResult);
|
||||
@@ -206,15 +214,15 @@ public class ReplFromTerminal {
|
||||
private boolean oneCommand(@NotNull String command) throws Exception {
|
||||
List<String> split = splitCommand(command);
|
||||
if (split.size() >= 1 && command.equals("help")) {
|
||||
System.out.println("Available commands:");
|
||||
System.out.println(":help show this help");
|
||||
System.out.println(":quit exit the interpreter");
|
||||
System.out.println(":dump bytecode dump classes to terminal");
|
||||
System.out.println(":load <file> load script from specified file");
|
||||
replWriter.println("Available commands:");
|
||||
replWriter.println(":help show this help");
|
||||
replWriter.println(":quit exit the interpreter");
|
||||
replWriter.println(":dump bytecode dump classes to terminal");
|
||||
replWriter.println(":load <file> load script from specified file");
|
||||
return true;
|
||||
}
|
||||
else if (split.size() >= 2 && split.get(0).equals("dump") && split.get(1).equals("bytecode")) {
|
||||
getReplInterpreter().dumpClasses(new PrintWriter(System.out));
|
||||
getReplInterpreter().dumpClasses(new PrintWriter(replWriter));
|
||||
return true;
|
||||
}
|
||||
else if (split.size() >= 1 && split.get(0).equals("quit")) {
|
||||
@@ -227,8 +235,8 @@ public class ReplFromTerminal {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
System.out.println("Unknown command");
|
||||
System.out.println("Type :help for help");
|
||||
replWriter.println("Unknown command");
|
||||
replWriter.println("Type :help for help");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
@@ -35,11 +33,15 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport;
|
||||
import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.di.ContainerForReplWithJava;
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.di.DiPackage;
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.DiagnosticMessageHolder;
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplIdeDiagnosticMessageHolder;
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplTerminalDiagnosticMessageHolder;
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactories;
|
||||
import org.jetbrains.kotlin.codegen.CompilationErrorHandler;
|
||||
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade;
|
||||
@@ -49,7 +51,6 @@ import org.jetbrains.kotlin.context.MutableModuleContext;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.idea.JetLanguage;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.parsing.JetParserDefinition;
|
||||
@@ -68,24 +69,9 @@ import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
import org.jetbrains.kotlin.utils.UtilsPackage;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.ls.DOMImplementationLS;
|
||||
import org.w3c.dom.ls.LSSerializer;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
@@ -117,9 +103,9 @@ public class ReplInterpreter {
|
||||
private final ResolveSession resolveSession;
|
||||
private final ScriptMutableDeclarationProviderFactory scriptDeclarationFactory;
|
||||
|
||||
private boolean ideMode;
|
||||
private final boolean ideMode;
|
||||
|
||||
public ReplInterpreter(@NotNull Disposable disposable, @NotNull CompilerConfiguration configuration) {
|
||||
public ReplInterpreter(@NotNull Disposable disposable, @NotNull CompilerConfiguration configuration, boolean ideMode) {
|
||||
KotlinCoreEnvironment environment =
|
||||
KotlinCoreEnvironment.createForProduction(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||
Project project = environment.getProject();
|
||||
@@ -170,27 +156,20 @@ public class ReplInterpreter {
|
||||
}
|
||||
|
||||
this.classLoader = new ReplClassLoader(new URLClassLoader(classpath.toArray(new URL[classpath.size()]), null));
|
||||
|
||||
this.ideMode = ideMode;
|
||||
}
|
||||
|
||||
private static void prepareForTheNextReplLine(@NotNull TopDownAnalysisContext c) {
|
||||
c.getScripts().clear();
|
||||
}
|
||||
|
||||
public void setIdeMode(boolean ideMode) {
|
||||
this.ideMode = ideMode;
|
||||
}
|
||||
|
||||
public enum LineResultType {
|
||||
SUCCESS,
|
||||
ERROR,
|
||||
INCOMPLETE,
|
||||
}
|
||||
|
||||
private enum ErrorType {
|
||||
CODE_ERROR,
|
||||
THROWABLE
|
||||
}
|
||||
|
||||
public static class LineResult {
|
||||
private final Object value;
|
||||
private final boolean unit;
|
||||
@@ -234,82 +213,28 @@ public class ReplInterpreter {
|
||||
return new LineResult(value, unit, null, LineResultType.SUCCESS);
|
||||
}
|
||||
|
||||
public static LineResult error(@NotNull String errorText, boolean ideMode,
|
||||
@NotNull ErrorType errType, @Nullable Collection<Diagnostic> diagnostics
|
||||
) {
|
||||
public static LineResult error(@NotNull String errorText) {
|
||||
if (errorText.isEmpty()) {
|
||||
errorText = "<unknown error>";
|
||||
}
|
||||
|
||||
String[] lines = errorTextToLinesWithPreprocessing(errorText);
|
||||
|
||||
if (ideMode && errType == ErrorType.CODE_ERROR) {
|
||||
assert diagnostics != null : "diagnostics should not be null in not-throwable case";
|
||||
errorText = convertLinesToXML(lines, diagnostics);
|
||||
}
|
||||
else {
|
||||
errorText = StringUtil.join(lines, "\n");
|
||||
}
|
||||
|
||||
if (!errorText.endsWith("\n")) {
|
||||
else if (!errorText.endsWith("\n")) {
|
||||
errorText += "\n";
|
||||
}
|
||||
|
||||
return new LineResult(null, false, errorText, LineResultType.ERROR);
|
||||
}
|
||||
|
||||
private static String[] errorTextToLinesWithPreprocessing(@NotNull String errorText) {
|
||||
// cut "/line_i.kts:row:column" prefix and capitalize "error:" and "warning:"
|
||||
String[] lines = errorText.split("\\n");
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
if (lines[i].contains("error:")) {
|
||||
int pos = lines[i].indexOf("error:");
|
||||
lines[i] = "E" + lines[i].substring(pos + 1);
|
||||
}
|
||||
else if (lines[i].contains("warning:")) {
|
||||
int pos = lines[i].indexOf("warning:");
|
||||
lines[i] = "W" + lines[i].substring(pos + 1);
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
private static String convertLinesToXML(@NotNull String[] lines, @NotNull Collection<Diagnostic> diagnostics) {
|
||||
try {
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
|
||||
Document errorReport = docBuilder.newDocument();
|
||||
|
||||
Element rootElement = errorReport.createElement("report");
|
||||
errorReport.appendChild(rootElement);
|
||||
|
||||
Iterator<Diagnostic> di = diagnostics.iterator();
|
||||
for (String s : lines) {
|
||||
if (s.startsWith("Error:") || s.startsWith("Warning:")) {
|
||||
TextRange errorRange = di.hasNext() ? di.next().getTextRanges().get(0) : TextRange.EMPTY_RANGE;
|
||||
|
||||
Element reportEntry = errorReport.createElement("reportEntry");
|
||||
reportEntry.setAttribute("rangeStart", String.valueOf(errorRange.getStartOffset()));
|
||||
reportEntry.setAttribute("rangeEnd", String.valueOf(errorRange.getEndOffset()));
|
||||
reportEntry.appendChild(errorReport.createTextNode(StringUtil.escapeXml(s)));
|
||||
|
||||
rootElement.appendChild(reportEntry);
|
||||
}
|
||||
}
|
||||
|
||||
DOMImplementationLS domImplementation = (DOMImplementationLS) errorReport.getImplementation();
|
||||
LSSerializer lsSerializer = domImplementation.createLSSerializer();
|
||||
return lsSerializer.writeToString(errorReport);
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw UtilsPackage.rethrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static LineResult incomplete() {
|
||||
return new LineResult(null, false, null, LineResultType.INCOMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DiagnosticMessageHolder createDiagnosticHolder() {
|
||||
return ideMode ? new ReplIdeDiagnosticMessageHolder()
|
||||
: new ReplTerminalDiagnosticMessageHolder();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LineResult eval(@NotNull String line) {
|
||||
++lineNumber;
|
||||
@@ -328,11 +253,9 @@ public class ReplInterpreter {
|
||||
JetFile psiFile = (JetFile) psiFileFactory.trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false);
|
||||
assert psiFile != null : "Script file not analyzed at line " + lineNumber + ": " + fullText;
|
||||
|
||||
ReplMessageCollectorWrapper errorCollector = new ReplMessageCollectorWrapper();
|
||||
List<Diagnostic> syntaxDiagnostics = new ArrayList<Diagnostic>();
|
||||
DiagnosticMessageHolder errorHolder = createDiagnosticHolder();
|
||||
|
||||
AnalyzerWithCompilerReport.SyntaxErrorReport syntaxErrorReport =
|
||||
AnalyzerWithCompilerReport.reportSyntaxErrorsWithDiagnostics(psiFile, errorCollector.getMessageCollector(), syntaxDiagnostics);
|
||||
AnalyzerWithCompilerReport.SyntaxErrorReport syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors(psiFile, errorHolder);
|
||||
|
||||
if (syntaxErrorReport.isHasErrors() && syntaxErrorReport.isAllErrorsAtEof()) {
|
||||
previousIncompleteLines.add(line);
|
||||
@@ -342,7 +265,7 @@ public class ReplInterpreter {
|
||||
previousIncompleteLines.clear();
|
||||
|
||||
if (syntaxErrorReport.isHasErrors()) {
|
||||
return LineResult.error(errorCollector.getString(), ideMode, ErrorType.CODE_ERROR, syntaxDiagnostics);
|
||||
return LineResult.error(errorHolder.getRenderedDiagnostics());
|
||||
}
|
||||
|
||||
prepareForTheNextReplLine(topDownAnalysisContext);
|
||||
@@ -351,9 +274,9 @@ public class ReplInterpreter {
|
||||
//noinspection ConstantConditions
|
||||
psiFile.getScript().putUserData(ScriptPriorities.PRIORITY_KEY, lineNumber);
|
||||
|
||||
ScriptDescriptor scriptDescriptor = doAnalyze(psiFile, errorCollector);
|
||||
ScriptDescriptor scriptDescriptor = doAnalyze(psiFile, errorHolder);
|
||||
if (scriptDescriptor == null) {
|
||||
return LineResult.error(errorCollector.getString(), ideMode, ErrorType.CODE_ERROR, trace.getBindingContext().getDiagnostics().all());
|
||||
return LineResult.error(errorHolder.getRenderedDiagnostics());
|
||||
}
|
||||
|
||||
List<Pair<ScriptDescriptor, Type>> earlierScripts = Lists.newArrayList();
|
||||
@@ -391,7 +314,7 @@ public class ReplInterpreter {
|
||||
scriptInstance = scriptInstanceConstructor.newInstance(constructorArgs);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
return LineResult.error(renderStackTrace(e.getCause()), ideMode, ErrorType.THROWABLE, null);
|
||||
return LineResult.error(renderStackTrace(e.getCause()));
|
||||
}
|
||||
Field rvField = scriptClass.getDeclaredField("rv");
|
||||
rvField.setAccessible(true);
|
||||
@@ -433,7 +356,7 @@ public class ReplInterpreter {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ScriptDescriptor doAnalyze(@NotNull JetFile psiFile, @NotNull ReplMessageCollectorWrapper messageCollector) {
|
||||
private ScriptDescriptor doAnalyze(@NotNull JetFile psiFile, @NotNull DiagnosticMessageReporter errorReporter) {
|
||||
scriptDeclarationFactory.setDelegateFactory(
|
||||
new FileBasedDeclarationProviderFactory(resolveSession.getStorageManager(), Collections.singletonList(psiFile)));
|
||||
|
||||
@@ -446,9 +369,7 @@ public class ReplInterpreter {
|
||||
trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile, resolveSession.getPackageFragment(FqName.ROOT));
|
||||
}
|
||||
|
||||
boolean hasErrors = AnalyzerWithCompilerReport.reportDiagnostics(
|
||||
trace.getBindingContext().getDiagnostics(), messageCollector.getMessageCollector()
|
||||
);
|
||||
boolean hasErrors = AnalyzerWithCompilerReport.reportDiagnostics(trace.getBindingContext().getDiagnostics(), errorReporter);
|
||||
if (hasErrors) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.jvm.repl;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer;
|
||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class ReplMessageCollectorWrapper {
|
||||
private static final Charset UTF8 = Charset.forName("utf-8");
|
||||
|
||||
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
private final MessageCollector actualCollector =
|
||||
new PrintingMessageCollector(new PrintStream(outputStream), MessageRenderer.PLAIN_FULL_PATHS, false);
|
||||
|
||||
@NotNull
|
||||
public MessageCollector getMessageCollector() {
|
||||
return actualCollector;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getString() {
|
||||
return UTF8.decode(ByteBuffer.wrap(outputStream.toByteArray())).toString();
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.jvm.repl
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import java.io.PrintStream
|
||||
|
||||
enum class EscapeType {
|
||||
ORDINARY, REPORT
|
||||
}
|
||||
|
||||
public class ReplSystemOutWrapper(private val standardOut: PrintStream) : PrintStream(standardOut, true) {
|
||||
private val XML_PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
|
||||
|
||||
private fun xmlEscape(s: String, escapeType: EscapeType): String {
|
||||
val singleLine = StringUtil.escapeLineBreak(s)
|
||||
return "$XML_PREFIX<output type=\"$escapeType\">${StringUtil.escapeXml(singleLine)}</output>"
|
||||
}
|
||||
|
||||
override fun print(x: Any) = printWithEscaping(x.toString())
|
||||
private fun printWithEscaping(text: String, escapeType: EscapeType = EscapeType.ORDINARY) = super.print(xmlEscape(text, escapeType))
|
||||
|
||||
override fun println(x: String) = printlnWithEscaping(x)
|
||||
override fun println(x: Any) = printlnWithEscaping(x.toString())
|
||||
public fun printlnWithEscaping(text: String, escapeType: EscapeType = EscapeType.ORDINARY): Unit = super.println(xmlEscape(text, escapeType))
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.jvm.repl.messages
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter
|
||||
|
||||
public interface DiagnosticMessageHolder : DiagnosticMessageReporter {
|
||||
val renderedDiagnostics: String
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.jvm.repl.messages
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.w3c.dom.Element
|
||||
import org.xml.sax.InputSource
|
||||
import java.io.ByteArrayInputStream
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
import kotlin.platform.platformStatic
|
||||
|
||||
public object FromIdeXmlMessagesParser {
|
||||
private fun strToSource(s: String) = InputSource(ByteArrayInputStream(s.toByteArray()))
|
||||
|
||||
platformStatic fun parse(inputMessage: String): String {
|
||||
val docFactory = DocumentBuilderFactory.newInstance()
|
||||
val docBuilder = docFactory.newDocumentBuilder()
|
||||
val input = docBuilder.parse(strToSource(inputMessage))
|
||||
|
||||
val root = input.firstChild as Element
|
||||
val inputContent = StringUtil.unescapeStringCharacters(root.textContent).trim()
|
||||
|
||||
return inputContent
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.jvm.repl.messages
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.w3c.dom.ls.DOMImplementationLS
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
|
||||
public class ReplIdeDiagnosticMessageHolder : DiagnosticMessageHolder {
|
||||
private val diagnostics = arrayListOf<Pair<Diagnostic, String>>()
|
||||
|
||||
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) {
|
||||
diagnostics.add(diagnostic to render)
|
||||
}
|
||||
|
||||
override val renderedDiagnostics: String
|
||||
get() {
|
||||
val docFactory = DocumentBuilderFactory.newInstance()
|
||||
val docBuilder = docFactory.newDocumentBuilder()
|
||||
val errorReport = docBuilder.newDocument()
|
||||
|
||||
val rootElement = errorReport.createElement("report")
|
||||
errorReport.appendChild(rootElement)
|
||||
|
||||
for ((diagnostic, message) in diagnostics) {
|
||||
val errorRange = DiagnosticUtils.firstRange(diagnostic.textRanges)
|
||||
|
||||
val reportEntry = errorReport.createElement("reportEntry")
|
||||
reportEntry.setAttribute("severity", diagnostic.severity.toString())
|
||||
reportEntry.setAttribute("rangeStart", errorRange.startOffset.toString())
|
||||
reportEntry.setAttribute("rangeEnd", errorRange.endOffset.toString())
|
||||
reportEntry.appendChild(errorReport.createTextNode(StringUtil.escapeXml(message)))
|
||||
|
||||
rootElement.appendChild(reportEntry)
|
||||
}
|
||||
|
||||
val domImplementation = errorReport.implementation as DOMImplementationLS
|
||||
val lsSerializer = domImplementation.createLSSerializer()
|
||||
return lsSerializer.writeToString(errorReport)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.jvm.repl.messages
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.util.LineSeparator
|
||||
import java.io.PrintStream
|
||||
|
||||
public class ReplSystemOutWrapper(private val standardOut: PrintStream, private val ideMode: Boolean) : PrintStream(standardOut, true) {
|
||||
private val XML_PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
private val END_LINE = LineSeparator.getSystemLineSeparator().separatorString
|
||||
|
||||
private enum class EscapeType {
|
||||
INITIAL_PROMPT,
|
||||
USER_OUTPUT,
|
||||
REPL_RESULT,
|
||||
REPL_INCOMPLETE,
|
||||
ERROR
|
||||
}
|
||||
|
||||
override fun print(x: Boolean) = printWithEscaping(x.toString())
|
||||
override fun print(x: Char) = printWithEscaping(x.toString())
|
||||
override fun print(x: Int) = printWithEscaping(x.toString())
|
||||
override fun print(x: Long) = printWithEscaping(x.toString())
|
||||
override fun print(x: Float) = printWithEscaping(x.toString())
|
||||
override fun print(x: Double) = printWithEscaping(x.toString())
|
||||
override fun print(x: String) = printWithEscaping(x)
|
||||
override fun print(x: Any?) = printWithEscaping(x.toString())
|
||||
|
||||
private fun printlnWithEscaping(text: String, escapeType: EscapeType = EscapeType.USER_OUTPUT) = printWithEscaping("$text$END_LINE", escapeType)
|
||||
|
||||
private fun printWithEscaping(text: String, escapeType: EscapeType = EscapeType.USER_OUTPUT) {
|
||||
if (ideMode)
|
||||
super.print("${xmlEscape(text, escapeType)}$END_LINE")
|
||||
else
|
||||
super.print(text)
|
||||
}
|
||||
|
||||
private fun xmlEscape(s: String, escapeType: EscapeType): String {
|
||||
val singleLine = StringUtil.escapeLineBreak(s)
|
||||
return "$XML_PREFIX<output type=\"$escapeType\">${StringUtil.escapeXml(singleLine)}</output>"
|
||||
}
|
||||
|
||||
fun printlnResult(x: Any?) = printlnWithEscaping(x.toString(), EscapeType.REPL_RESULT)
|
||||
fun printlnError(x: String) = printlnWithEscaping(x, EscapeType.ERROR)
|
||||
fun printlnInit(x: String) = printlnWithEscaping(x, EscapeType.INITIAL_PROMPT)
|
||||
fun printlnIncomplete() = printlnWithEscaping("", EscapeType.REPL_INCOMPLETE)
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.cli.jvm.repl.messages
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.*
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
public class ReplTerminalDiagnosticMessageHolder() : MessageCollectorBasedReporter, DiagnosticMessageHolder {
|
||||
private val outputStream = ByteArrayOutputStream()
|
||||
override val messageCollector = PrintingMessageCollector(PrintStream(outputStream), MessageRenderer.WITHOUT_PATHS, false)
|
||||
|
||||
override val renderedDiagnostics: String
|
||||
get() = Charsets.UTF_8.decode(ByteBuffer.wrap(outputStream.toByteArray())).toString()
|
||||
}
|
||||
Reference in New Issue
Block a user