Repl: keep track of command entries which were already processed
Fixes race condition
This commit is contained in:
@@ -25,6 +25,8 @@ class CommandHistory {
|
||||
)
|
||||
|
||||
private val entries = arrayListOf<Entry>()
|
||||
private var processedEntriesCount: Int = 0
|
||||
|
||||
val listeners = arrayListOf<HistoryUpdateListener>()
|
||||
|
||||
operator fun get(i: Int) = entries[i]
|
||||
@@ -34,6 +36,19 @@ class CommandHistory {
|
||||
listeners.forEach { it.onNewEntry(entry) }
|
||||
}
|
||||
|
||||
fun lastUnprocessedEntry(): CommandHistory.Entry? {
|
||||
if (processedEntriesCount < size) {
|
||||
return get(processedEntriesCount)
|
||||
}
|
||||
else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
fun entryProcessed() {
|
||||
processedEntriesCount++
|
||||
}
|
||||
|
||||
val size: Int
|
||||
get() = entries.size
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ 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.diagnostics.Severity
|
||||
import org.w3c.dom.Element
|
||||
import org.xml.sax.InputSource
|
||||
@@ -69,6 +70,12 @@ class ReplOutputHandler(
|
||||
"COMPILE_ERROR" -> outputProcessor.highlightCompilerErrors(createCompilerMessages(content))
|
||||
"RUNTIME_ERROR" -> outputProcessor.printRuntimeError("${content.trim()}\n")
|
||||
"INTERNAL_ERROR" -> outputProcessor.printInternalErrorMessage(content)
|
||||
"SUCCESS" -> Unit
|
||||
else -> logError(ReplOutputHandler::class.java, "Unexpected output type:\n$outputType")
|
||||
}
|
||||
|
||||
if (outputType in setOf("SUCCESS", "COMPILE_ERROR", "INTERNAL_ERROR", "RUNTIME_ERROR")) {
|
||||
runner.commandHistory.entryProcessed()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,11 @@ public class ReplOutputProcessor(
|
||||
|
||||
fun highlightCompilerErrors(compilerMessages: List<SeverityDetails>) = WriteCommandAction.runWriteCommandAction(project) {
|
||||
val commandHistory = runner.commandHistory
|
||||
val lastCommandStartOffset = historyDocument.textLength - commandHistory[commandHistory.size - 1].entryText.length - 1
|
||||
val lastUnprocessedHistoryEntry = commandHistory.lastUnprocessedEntry() ?: return@runWriteCommandAction logError(
|
||||
ReplOutputProcessor::class.java,
|
||||
"Processed more commands than were sent. Sent commands: ${commandHistory.size}. Processed: ${commandHistory.processedEntriesCount}"
|
||||
)
|
||||
val lastCommandStartOffset = lastUnprocessedHistoryEntry.rangeInHistoryDocument.startOffset
|
||||
val lastCommandStartLine = historyDocument.getLineNumber(lastCommandStartOffset)
|
||||
val historyCommandRunIndicator = historyMarkup.allHighlighters.filter {
|
||||
historyDocument.getLineNumber(it.startOffset) == lastCommandStartLine && it.gutterIconRenderer != null
|
||||
|
||||
@@ -88,7 +88,7 @@ public class KotlinReplTest : PlatformTestCase() {
|
||||
}
|
||||
|
||||
@Test fun testOnePlusOne() = testSimpleCommand("1 + 1", "2")
|
||||
@Test fun testPrintlnText() = "Hello, console world!" let { testSimpleCommand("println(\"$it\")", it) }
|
||||
@Test fun testPrintlnText() = "Hello, console world!".let { testSimpleCommand("println(\"$it\")", it) }
|
||||
@Test fun testDivisionByZeroException() = testSimpleCommand("1 / 0", "java.lang.ArithmeticException: / by zero")
|
||||
|
||||
@Test fun testMultilineSupport() {
|
||||
@@ -125,4 +125,11 @@ public class KotlinReplTest : PlatformTestCase() {
|
||||
sendCommand("b")
|
||||
waitForExpectedOutput(readLineTextB)
|
||||
}
|
||||
|
||||
@Test fun testCorrectAfterError() {
|
||||
val message = "MyMessage"
|
||||
sendCommand("fun f() { println(x)\n println(y) ")
|
||||
sendCommand("println(\"$message\")")
|
||||
waitForExpectedOutput(message)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user