[cli-repl][ide-console] Add logging of internal errors

Rename `jvmStatic` to `@JvmStatic`
This commit is contained in:
Dmitry Kovanikov
2015-09-09 19:00:13 +03:00
committed by Pavel V. Talanov
parent 38285496cb
commit 9bf0c8453d
11 changed files with 67 additions and 20 deletions
@@ -126,6 +126,7 @@ public open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
configuration.put(JVMConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME) configuration.put(JVMConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME)
if (arguments.module == null && arguments.freeArgs.isEmpty() && !arguments.version) { if (arguments.module == null && arguments.freeArgs.isEmpty() && !arguments.version) {
configuration.put(JVMConfigurationKeys.MODULE_NAME, "replModule")
ReplFromTerminal.run(rootDisposable, configuration) ReplFromTerminal.run(rootDisposable, configuration)
return ExitCode.OK return ExitCode.OK
} }
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.common.KotlinVersion; import org.jetbrains.kotlin.cli.common.KotlinVersion;
import org.jetbrains.kotlin.cli.jvm.repl.messages.IdeLinebreaksUnescaper; import org.jetbrains.kotlin.cli.jvm.repl.messages.IdeLinebreaksUnescaper;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplErrorLogger;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemInWrapper; import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemInWrapper;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemOutWrapper; import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemOutWrapper;
import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.CompilerConfiguration;
@@ -44,8 +45,9 @@ public class ReplFromTerminal {
private final boolean ideMode; private final boolean ideMode;
private ReplSystemInWrapper replReader; private ReplSystemInWrapper replReader;
private final ReplSystemOutWrapper replWriter; private final ReplSystemOutWrapper replWriter;
private final ReplErrorLogger replErrorLogger;
private final ConsoleReader consoleReader; private ConsoleReader consoleReader;
public ReplFromTerminal( public ReplFromTerminal(
@NotNull final Disposable disposable, @NotNull final Disposable disposable,
@@ -67,6 +69,8 @@ public class ReplFromTerminal {
System.setIn(replReader); System.setIn(replReader);
} }
replErrorLogger = new ReplErrorLogger(ideMode, replWriter);
new Thread("initialize-repl") { new Thread("initialize-repl") {
@Override @Override
public void run() { public void run() {
@@ -97,7 +101,7 @@ public class ReplFromTerminal {
consoleReader.setHistory(new FileHistory(new File(new File(System.getProperty("user.home")), ".kotlin_history"))); consoleReader.setHistory(new FileHistory(new File(new File(System.getProperty("user.home")), ".kotlin_history")));
} }
catch (Exception e) { catch (Exception e) {
throw UtilsPackage.rethrow(e); replErrorLogger.logException(e);
} }
} }
@@ -135,14 +139,14 @@ public class ReplFromTerminal {
} }
} }
catch (Exception e) { catch (Exception e) {
throw UtilsPackage.rethrow(e); replErrorLogger.logException(e);
} }
finally { finally {
try { try {
((FileHistory) consoleReader.getHistory()).flush(); ((FileHistory) consoleReader.getHistory()).flush();
} }
catch (Exception e) { catch (Exception e) {
replWriter.printlnInnerError("failed to flush history: " + e); replErrorLogger.logException(e);
} }
} }
} }
@@ -39,10 +39,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; 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.ContainerForReplWithJava;
import org.jetbrains.kotlin.cli.jvm.repl.di.DiPackage; 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.*;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplIdeDiagnosticMessageHolder;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemInWrapper;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplTerminalDiagnosticMessageHolder;
import org.jetbrains.kotlin.codegen.ClassBuilderFactories; import org.jetbrains.kotlin.codegen.ClassBuilderFactories;
import org.jetbrains.kotlin.codegen.CompilationErrorHandler; import org.jetbrains.kotlin.codegen.CompilationErrorHandler;
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade; import org.jetbrains.kotlin.codegen.KotlinCodegenFacade;
@@ -341,10 +338,10 @@ public class ReplInterpreter {
scriptInstance = scriptInstanceConstructor.newInstance(constructorArgs); scriptInstance = scriptInstanceConstructor.newInstance(constructorArgs);
} }
catch (Throwable e) { catch (Throwable e) {
setReplScriptExecuting(false);
return LineResult.runtimeError(renderStackTrace(e.getCause())); return LineResult.runtimeError(renderStackTrace(e.getCause()));
} finally {
setReplScriptExecuting(false);
} }
setReplScriptExecuting(false);
Field rvField = scriptClass.getDeclaredField("rv"); Field rvField = scriptClass.getDeclaredField("rv");
rvField.setAccessible(true); rvField.setAccessible(true);
@@ -387,6 +384,8 @@ public class ReplInterpreter {
} }
} }
Collections.reverse(newTrace); Collections.reverse(newTrace);
// throw away last element which contains Line1.kts<init>(Unknown source)
List<StackTraceElement> resultingTrace = newTrace.subList(0, newTrace.size() - 1); List<StackTraceElement> resultingTrace = newTrace.subList(0, newTrace.size() - 1);
cause.setStackTrace(resultingTrace.toArray(new StackTraceElement[resultingTrace.size()])); cause.setStackTrace(resultingTrace.toArray(new StackTraceElement[resultingTrace.size()]));
@@ -0,0 +1,38 @@
/*
* 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 java.io.PrintWriter
import java.io.StringWriter
import kotlin.reflect.jvm.internal.impl.utils.UtilsPackage
public class ReplErrorLogger(private val ideMode: Boolean, private val replWriter: ReplSystemOutWrapper) {
fun logException(e: Throwable?) {
if (ideMode) {
val errorStringWriter = StringWriter()
val errorPrintWriter = PrintWriter(errorStringWriter)
e?.printStackTrace(errorPrintWriter)
val writerString = errorStringWriter.toString()
val internalErrorText = if (writerString.isEmpty()) "Unknown error" else writerString
replWriter.sendInternalErrorReport(internalErrorText)
}
throw UtilsPackage.rethrow(e ?: Throwable("null exception", e))
}
}
@@ -42,7 +42,7 @@ public class ReplSystemInWrapper(
$isReplScriptExecuting = value $isReplScriptExecuting = value
} }
override synchronized fun read(): Int { override fun read(): Int {
if (isLastScriptByteProcessed && isReplScriptExecuting) { if (isLastScriptByteProcessed && isReplScriptExecuting) {
isLastScriptByteProcessed = false isLastScriptByteProcessed = false
return -1 return -1
@@ -34,7 +34,7 @@ public class ReplSystemOutWrapper(private val ideMode: Boolean, standardOut: Pri
REPL_INCOMPLETE, REPL_INCOMPLETE,
COMPILE_ERROR, COMPILE_ERROR,
RUNTIME_ERROR, RUNTIME_ERROR,
INNER_ERROR INTERNAL_ERROR
} }
override fun print(x: Boolean) = printWithEscaping(x.toString()) override fun print(x: Boolean) = printWithEscaping(x.toString())
@@ -68,5 +68,5 @@ public class ReplSystemOutWrapper(private val ideMode: Boolean, standardOut: Pri
fun printlnIncomplete() = printlnWithEscaping("", EscapeType.REPL_INCOMPLETE) fun printlnIncomplete() = printlnWithEscaping("", EscapeType.REPL_INCOMPLETE)
fun printlnCompileError(x: String) = printlnWithEscaping(x, EscapeType.COMPILE_ERROR) fun printlnCompileError(x: String) = printlnWithEscaping(x, EscapeType.COMPILE_ERROR)
fun printlnRuntimeError(x: String) = printlnWithEscaping(x, EscapeType.RUNTIME_ERROR) fun printlnRuntimeError(x: String) = printlnWithEscaping(x, EscapeType.RUNTIME_ERROR)
fun printlnInnerError(x: String) = printlnWithEscaping(x, EscapeType.INNER_ERROR) fun sendInternalErrorReport(x: String) = printlnWithEscaping(x, EscapeType.INTERNAL_ERROR)
} }
@@ -38,5 +38,5 @@ fun parseXml(inputMessage: String): String {
} }
public object IdeLinebreaksUnescaper { public object IdeLinebreaksUnescaper {
jvmStatic fun unescapeFromDiez(inputMessage: String) = StringUtil.replace(inputMessage, XML_REPLACEMENTS, SOURCE_CHARS) @JvmStatic fun unescapeFromDiez(inputMessage: String) = StringUtil.replace(inputMessage, XML_REPLACEMENTS, SOURCE_CHARS)
} }
@@ -25,8 +25,7 @@ import org.jetbrains.kotlin.test.TestJdkKind
import org.junit.Assert import org.junit.Assert
import java.io.File import java.io.File
import java.io.PrintWriter import java.io.PrintWriter
import java.util.ArrayDeque import java.util.*
import java.util.ArrayList
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.text.Regex import kotlin.text.Regex
@@ -112,6 +112,6 @@ public class KotlinConsoleKeeper(val project: Project) {
} }
companion object { companion object {
jvmStatic fun getInstance(project: Project) = ServiceManager.getService(project, KotlinConsoleKeeper::class.java) @JvmStatic fun getInstance(project: Project) = ServiceManager.getService(project, KotlinConsoleKeeper::class.java)
} }
} }
@@ -20,7 +20,6 @@ import com.intellij.execution.process.OSProcessHandler
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.console.actions.logError
import org.jetbrains.kotlin.console.highlight.KotlinHistoryHighlighter import org.jetbrains.kotlin.console.highlight.KotlinHistoryHighlighter
import org.jetbrains.kotlin.console.highlight.KotlinReplOutputHighlighter import org.jetbrains.kotlin.console.highlight.KotlinReplOutputHighlighter
import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.diagnostics.Severity
@@ -68,7 +67,7 @@ public class KotlinReplOutputHandler(
"REPL_INCOMPLETE", "REPL_INCOMPLETE",
"COMPILE_ERROR" -> outputHighlighter.highlightCompilerErrors(createCompilerMessages(content)) "COMPILE_ERROR" -> outputHighlighter.highlightCompilerErrors(createCompilerMessages(content))
"RUNTIME_ERROR" -> outputHighlighter.printRuntimeError("${content.trim()}\n") "RUNTIME_ERROR" -> outputHighlighter.printRuntimeError("${content.trim()}\n")
"INNER_ERROR" -> logError(this.javaClass, content) "INTERNAL_ERROR" -> outputHighlighter.printInternalErrorMessage(content)
} }
} }
@@ -31,6 +31,7 @@ import com.intellij.psi.PsiDocumentManager
import org.jetbrains.kotlin.console.KotlinConsoleHistoryManager import org.jetbrains.kotlin.console.KotlinConsoleHistoryManager
import org.jetbrains.kotlin.console.KotlinConsoleRunner import org.jetbrains.kotlin.console.KotlinConsoleRunner
import org.jetbrains.kotlin.console.SeverityDetails import org.jetbrains.kotlin.console.SeverityDetails
import org.jetbrains.kotlin.console.actions.logError
import org.jetbrains.kotlin.console.gutter.IconWithTooltip import org.jetbrains.kotlin.console.gutter.IconWithTooltip
import org.jetbrains.kotlin.console.gutter.KotlinConsoleErrorRenderer import org.jetbrains.kotlin.console.gutter.KotlinConsoleErrorRenderer
import org.jetbrains.kotlin.console.gutter.KotlinConsoleIndicatorRenderer import org.jetbrains.kotlin.console.gutter.KotlinConsoleIndicatorRenderer
@@ -108,7 +109,7 @@ public class KotlinReplOutputHighlighter(
} }
fun highlightCompilerErrors(compilerMessages: List<SeverityDetails>) = WriteCommandAction.runWriteCommandAction(project) { fun highlightCompilerErrors(compilerMessages: List<SeverityDetails>) = WriteCommandAction.runWriteCommandAction(project) {
val lastCommandStartOffset = historyDocument.textLength - historyManager.lastCommandLength val lastCommandStartOffset = historyDocument.textLength - historyManager.lastCommandLength - 1
val lastCommandStartLine = historyDocument.getLineNumber(lastCommandStartOffset) val lastCommandStartLine = historyDocument.getLineNumber(lastCommandStartOffset)
val historyCommandRunIndicator = historyMarkup.allHighlighters.filter { val historyCommandRunIndicator = historyMarkup.allHighlighters.filter {
historyDocument.getLineNumber(it.startOffset) == lastCommandStartLine && it.gutterIconRenderer != null historyDocument.getLineNumber(it.startOffset) == lastCommandStartLine && it.gutterIconRenderer != null
@@ -144,6 +145,12 @@ public class KotlinReplOutputHighlighter(
printOutput(errorText, ConsoleViewContentType.ERROR_OUTPUT, ReplIcons.RUNTIME_EXCEPTION) printOutput(errorText, ConsoleViewContentType.ERROR_OUTPUT, ReplIcons.RUNTIME_EXCEPTION)
} }
fun printInternalErrorMessage(internalErrorText: String) = WriteCommandAction.runWriteCommandAction(project) {
val promptText = "Internal error occurred. Please, send report to developers.\n"
printOutput(promptText, ConsoleViewContentType.ERROR_OUTPUT, ReplIcons.RUNTIME_EXCEPTION)
logError(this.javaClass, internalErrorText)
}
private fun getAttributesForSeverity(start: Int, end: Int, severity: Severity): TextAttributes { private fun getAttributesForSeverity(start: Int, end: Int, severity: Severity): TextAttributes {
val attributes = when (severity) { val attributes = when (severity) {
Severity.ERROR -> getAttributesForSeverity(HighlightInfoType.ERROR, HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES, start, end) Severity.ERROR -> getAttributesForSeverity(HighlightInfoType.ERROR, HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES, start, end)