diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index d0489d307f7..8fd6605d801 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -126,6 +126,7 @@ public open class K2JVMCompiler : CLICompiler() { configuration.put(JVMConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME) if (arguments.module == null && arguments.freeArgs.isEmpty() && !arguments.version) { + configuration.put(JVMConfigurationKeys.MODULE_NAME, "replModule") ReplFromTerminal.run(rootDisposable, configuration) return ExitCode.OK } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.java index 6664eb5c466..72f09af9c9a 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplFromTerminal.java @@ -26,6 +26,7 @@ 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.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.ReplSystemOutWrapper; import org.jetbrains.kotlin.config.CompilerConfiguration; @@ -44,8 +45,9 @@ public class ReplFromTerminal { private final boolean ideMode; private ReplSystemInWrapper replReader; private final ReplSystemOutWrapper replWriter; + private final ReplErrorLogger replErrorLogger; - private final ConsoleReader consoleReader; + private ConsoleReader consoleReader; public ReplFromTerminal( @NotNull final Disposable disposable, @@ -67,6 +69,8 @@ public class ReplFromTerminal { System.setIn(replReader); } + replErrorLogger = new ReplErrorLogger(ideMode, replWriter); + new Thread("initialize-repl") { @Override public void run() { @@ -97,7 +101,7 @@ public class ReplFromTerminal { consoleReader.setHistory(new FileHistory(new File(new File(System.getProperty("user.home")), ".kotlin_history"))); } catch (Exception e) { - throw UtilsPackage.rethrow(e); + replErrorLogger.logException(e); } } @@ -135,14 +139,14 @@ public class ReplFromTerminal { } } catch (Exception e) { - throw UtilsPackage.rethrow(e); + replErrorLogger.logException(e); } finally { try { ((FileHistory) consoleReader.getHistory()).flush(); } catch (Exception e) { - replWriter.printlnInnerError("failed to flush history: " + e); + replErrorLogger.logException(e); } } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java index a8696c2ef6b..5fd304664a0 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplInterpreter.java @@ -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.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.ReplSystemInWrapper; -import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplTerminalDiagnosticMessageHolder; +import org.jetbrains.kotlin.cli.jvm.repl.messages.*; import org.jetbrains.kotlin.codegen.ClassBuilderFactories; import org.jetbrains.kotlin.codegen.CompilationErrorHandler; import org.jetbrains.kotlin.codegen.KotlinCodegenFacade; @@ -341,10 +338,10 @@ public class ReplInterpreter { scriptInstance = scriptInstanceConstructor.newInstance(constructorArgs); } catch (Throwable e) { - setReplScriptExecuting(false); return LineResult.runtimeError(renderStackTrace(e.getCause())); + } finally { + setReplScriptExecuting(false); } - setReplScriptExecuting(false); Field rvField = scriptClass.getDeclaredField("rv"); rvField.setAccessible(true); @@ -387,6 +384,8 @@ public class ReplInterpreter { } } Collections.reverse(newTrace); + + // throw away last element which contains Line1.kts(Unknown source) List resultingTrace = newTrace.subList(0, newTrace.size() - 1); cause.setStackTrace(resultingTrace.toArray(new StackTraceElement[resultingTrace.size()])); diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplErrorLogger.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplErrorLogger.kt new file mode 100644 index 00000000000..cea086a678b --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplErrorLogger.kt @@ -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)) + } +} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemInWrapper.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemInWrapper.kt index e3470a4f104..2b43f5592c0 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemInWrapper.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemInWrapper.kt @@ -42,7 +42,7 @@ public class ReplSystemInWrapper( $isReplScriptExecuting = value } - override synchronized fun read(): Int { + override fun read(): Int { if (isLastScriptByteProcessed && isReplScriptExecuting) { isLastScriptByteProcessed = false return -1 diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapper.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapper.kt index dd1b89c30c5..59a65838d72 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapper.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/ReplSystemOutWrapper.kt @@ -34,7 +34,7 @@ public class ReplSystemOutWrapper(private val ideMode: Boolean, standardOut: Pri REPL_INCOMPLETE, COMPILE_ERROR, RUNTIME_ERROR, - INNER_ERROR + INTERNAL_ERROR } 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 printlnCompileError(x: String) = printlnWithEscaping(x, EscapeType.COMPILE_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) } \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/UnescapeUtils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/UnescapeUtils.kt index 99156b240b0..f467808302a 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/UnescapeUtils.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/messages/UnescapeUtils.kt @@ -38,5 +38,5 @@ fun parseXml(inputMessage: String): String { } 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) } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/repl/AbstractReplInterpreterTest.kt b/compiler/tests/org/jetbrains/kotlin/repl/AbstractReplInterpreterTest.kt index 1a8bff8bb68..6df0844b9b8 100644 --- a/compiler/tests/org/jetbrains/kotlin/repl/AbstractReplInterpreterTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/repl/AbstractReplInterpreterTest.kt @@ -25,8 +25,7 @@ import org.jetbrains.kotlin.test.TestJdkKind import org.junit.Assert import java.io.File import java.io.PrintWriter -import java.util.ArrayDeque -import java.util.ArrayList +import java.util.* import java.util.regex.Pattern import kotlin.text.Regex diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinConsoleKeeper.kt b/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinConsoleKeeper.kt index aba6cfde4b8..9d07bc13c6b 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinConsoleKeeper.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinConsoleKeeper.kt @@ -112,6 +112,6 @@ public class KotlinConsoleKeeper(val project: Project) { } companion object { - jvmStatic fun getInstance(project: Project) = ServiceManager.getService(project, KotlinConsoleKeeper::class.java) + @JvmStatic fun getInstance(project: Project) = ServiceManager.getService(project, KotlinConsoleKeeper::class.java) } } \ No newline at end of file diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinReplOutputHandler.kt b/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinReplOutputHandler.kt index ca75aaf97b1..e0f9cda31d9 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinReplOutputHandler.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/console/KotlinReplOutputHandler.kt @@ -20,7 +20,6 @@ import com.intellij.execution.process.OSProcessHandler import com.intellij.openapi.util.Key import com.intellij.openapi.util.TextRange 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.KotlinReplOutputHighlighter import org.jetbrains.kotlin.diagnostics.Severity @@ -68,7 +67,7 @@ public class KotlinReplOutputHandler( "REPL_INCOMPLETE", "COMPILE_ERROR" -> outputHighlighter.highlightCompilerErrors(createCompilerMessages(content)) "RUNTIME_ERROR" -> outputHighlighter.printRuntimeError("${content.trim()}\n") - "INNER_ERROR" -> logError(this.javaClass, content) + "INTERNAL_ERROR" -> outputHighlighter.printInternalErrorMessage(content) } } diff --git a/idea/idea-repl/src/org/jetbrains/kotlin/console/highlight/KotlinReplOutputHighlighter.kt b/idea/idea-repl/src/org/jetbrains/kotlin/console/highlight/KotlinReplOutputHighlighter.kt index adc77027a7f..03084bf056a 100644 --- a/idea/idea-repl/src/org/jetbrains/kotlin/console/highlight/KotlinReplOutputHighlighter.kt +++ b/idea/idea-repl/src/org/jetbrains/kotlin/console/highlight/KotlinReplOutputHighlighter.kt @@ -31,6 +31,7 @@ import com.intellij.psi.PsiDocumentManager import org.jetbrains.kotlin.console.KotlinConsoleHistoryManager import org.jetbrains.kotlin.console.KotlinConsoleRunner 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.KotlinConsoleErrorRenderer import org.jetbrains.kotlin.console.gutter.KotlinConsoleIndicatorRenderer @@ -108,7 +109,7 @@ public class KotlinReplOutputHighlighter( } fun highlightCompilerErrors(compilerMessages: List) = WriteCommandAction.runWriteCommandAction(project) { - val lastCommandStartOffset = historyDocument.textLength - historyManager.lastCommandLength + val lastCommandStartOffset = historyDocument.textLength - historyManager.lastCommandLength - 1 val lastCommandStartLine = historyDocument.getLineNumber(lastCommandStartOffset) val historyCommandRunIndicator = historyMarkup.allHighlighters.filter { historyDocument.getLineNumber(it.startOffset) == lastCommandStartLine && it.gutterIconRenderer != null @@ -144,6 +145,12 @@ public class KotlinReplOutputHighlighter( 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 { val attributes = when (severity) { Severity.ERROR -> getAttributesForSeverity(HighlightInfoType.ERROR, HighlightSeverity.ERROR, CodeInsightColors.ERRORS_ATTRIBUTES, start, end)