From 8cc576d44f56f57fd821195acadd5ad6cd0317b4 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Sat, 25 Mar 2017 14:31:59 +0100 Subject: [PATCH] Add total reset to repl history and state interfaces --- .../cli/common/repl/AggregatedReplState.kt | 10 +++++++++- .../kotlin/cli/common/repl/BasicReplState.kt | 8 ++++++++ .../common/repl/GenericReplCompilingEvaluator.kt | 9 +++++++-- .../kotlin/cli/common/repl/ReplHistory.kt | 7 +++++++ .../kotlin/cli/common/repl/ReplState.kt | 2 ++ .../kotlin/cli/jvm/repl/GenericCompilerState.kt | 16 ++++++++++++++-- .../kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt | 14 +++++++++++--- .../daemon/client/RemoteReplCompilerState.kt | 8 +++++--- .../kotlin/daemon/common/ReplStateFacade.kt | 3 +++ .../kotlin/daemon/RemoteReplStateFacadeImpl.kt | 2 ++ 10 files changed, 68 insertions(+), 11 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/AggregatedReplState.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/AggregatedReplState.kt index 56c4a8cf440..dc7747dc686 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/AggregatedReplState.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/AggregatedReplState.kt @@ -52,11 +52,19 @@ open class AggregatedReplStateHistory(val history1: IReplStageHistory = lock.write { + assertSameSize() + val i1 = history1.reset().toList() + val i2 = history2.reset().toList() + if (i1 != i2) throw IllegalStateException("Aggregated history reset lines mismatch: $i1 != $i2") + i1 + } + override fun resetTo(id: ILineId): Iterable = lock.write { assertSameSize() val i1 = history1.resetTo(id).toList() val i2 = history2.resetTo(id).toList() - if (i1 != i2) throw IllegalStateException("Aggregated history resetted lines mismatch: $i1 != $i2") + if (i1 != i2) throw IllegalStateException("Aggregated history reset lines mismatch: $i1 != $i2") i1 } diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/BasicReplState.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/BasicReplState.kt index d0c5a13ad5f..16834b3c1c7 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/BasicReplState.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/BasicReplState.kt @@ -49,6 +49,14 @@ open class BasicReplStageHistory(override val lock: ReentrantReadWriteLock = override fun pop(): ReplHistoryRecord? = lock.write { if (isEmpty()) null else removeAt(lastIndex) } + override fun reset(): Iterable { + lock.write { + val removed = map { it.id } + clear() + return removed + } + } + override fun resetTo(id: ILineId): Iterable { lock.write { val idx = indexOfFirst { it.id == id } diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompilingEvaluator.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompilingEvaluator.kt index 9e731e8174b..6da1650ecb6 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompilingEvaluator.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/GenericReplCompilingEvaluator.kt @@ -46,8 +46,13 @@ class GenericReplCompilingEvaluator(val compiler: ReplCompiler, aggregatedState.apply { lock.write { if (state1.history.size > state2.history.size) { - state2.history.peek()?.let { - state1.history.resetTo(it.id) + if (state2.history.size == 0) { + state1.history.reset() + } + else { + state2.history.peek()?.let { + state1.history.resetTo(it.id) + } } assert(state1.history.size == state2.history.size) } diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/ReplHistory.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/ReplHistory.kt index c029a6896e6..61d4dcedea5 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/ReplHistory.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/ReplHistory.kt @@ -52,6 +52,13 @@ class ReplHistory(startingHistory: CompiledHistoryList = emptyList()) : Se } } + /* resets back complete history and returns the lines removed */ + fun reset(): SourceHistoryList { + val removed = history.map { Pair(it.first.source, it.second) } + history.clear() + return removed + } + /* resets back to a previous line number and returns the lines removed */ fun resetToLine(lineNumber: Int): SourceHistoryList { val removed = arrayListOf>() diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/ReplState.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/ReplState.kt index 3648c6bcca7..6e16717e561 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/ReplState.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/repl/ReplState.kt @@ -41,6 +41,8 @@ interface IReplStageHistory : List> { else null } + fun reset(): Iterable + fun resetTo(id: ILineId): Iterable val lock: ReentrantReadWriteLock diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericCompilerState.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericCompilerState.kt index a168a2191d7..4eb7d3a863f 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericCompilerState.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericCompilerState.kt @@ -26,16 +26,28 @@ import kotlin.script.dependencies.KotlinScriptExternalDependencies class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : BasicReplStageHistory(state.lock) { + override fun reset(): Iterable { + val removedCompiledLines = super.reset() + val removedAnalyzedLines = state.analyzerEngine.reset() + + checkConsistent(removedCompiledLines, removedAnalyzedLines) + return removedCompiledLines + } + override fun resetTo(id: ILineId): Iterable { val removedCompiledLines = super.resetTo(id) - val removedAnalyzedLines = state.analyzerEngine.resetToLine(id.no) + val removedAnalyzedLines = state.analyzerEngine.resetToLine(id) + checkConsistent(removedCompiledLines, removedAnalyzedLines) + return removedCompiledLines + } + + private fun checkConsistent(removedCompiledLines: Iterable, removedAnalyzedLines: List) { removedCompiledLines.zip(removedAnalyzedLines).forEach { if (it.first != LineId(it.second)) { throw IllegalStateException("History mismatch when resetting lines: ${it.first.no} != ${it.second}") } } - return removedCompiledLines } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt index 69593c28039..5484c14a8e3 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.cli.jvm.repl import org.jetbrains.kotlin.cli.common.repl.CompiledReplCodeLine +import org.jetbrains.kotlin.cli.common.repl.ILineId import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine import org.jetbrains.kotlin.cli.common.repl.ReplHistory import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport @@ -88,7 +89,9 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) { } } - fun resetToLine(lineNumber: Int): List = replState.resetToLine(lineNumber) + fun resetToLine(lineId: ILineId): List = replState.resetToLine(lineId) + + fun reset(): List = replState.reset() fun analyzeReplLine(psiFile: KtFile, codeLine: ReplCodeLine): ReplLineAnalysisResult { topDownAnalysisContext.scripts.clear() @@ -172,12 +175,17 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) { private val successfulLines = ReplHistory() private val submittedLines = hashMapOf() - fun resetToLine(lineNumber: Int): List { - val removed = successfulLines.resetToLine(lineNumber) + fun resetToLine(lineId: ILineId): List { + val removed = successfulLines.resetToLine(lineId.no) removed.forEach { submittedLines.remove(it.second.linePsi) } return removed.map { it.first } } + fun reset(): List { + submittedLines.clear() + return successfulLines.reset().map { it.first } + } + fun submitLine(ktFile: KtFile, codeLine: ReplCodeLine) { val line = LineInfo.SubmittedLine(ktFile, successfulLines.lastValue()) submittedLines[ktFile] = line diff --git a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/RemoteReplCompilerState.kt b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/RemoteReplCompilerState.kt index e16f050cfb2..3129b755dff 100644 --- a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/RemoteReplCompilerState.kt +++ b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/RemoteReplCompilerState.kt @@ -37,10 +37,12 @@ class RemoteReplCompilerStateHistory(private val state: RemoteReplCompilerState) throw NotImplementedError("pop from remote history is not supported") } + override fun reset(): Iterable = state.replStateFacade.historyReset().apply { + currentGeneration.incrementAndGet() + } + override fun resetTo(id: ILineId): Iterable = state.replStateFacade.historyResetTo(id).apply { - if (isNotEmpty()) { - currentGeneration.incrementAndGet() - } + currentGeneration.incrementAndGet() } val currentGeneration = AtomicInteger(REPL_CODE_LINE_FIRST_GEN) diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReplStateFacade.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReplStateFacade.kt index f9482a92fa4..0f507fb449f 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReplStateFacade.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReplStateFacade.kt @@ -31,6 +31,9 @@ interface ReplStateFacade : Remote { @Throws(RemoteException::class) fun historyGet(index: Int): ILineId + @Throws(RemoteException::class) + fun historyReset(): List + @Throws(RemoteException::class) fun historyResetTo(id: ILineId): List } \ No newline at end of file diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteReplStateFacadeImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteReplStateFacadeImpl.kt index 5692042ca6b..75ad0f3578e 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteReplStateFacadeImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteReplStateFacadeImpl.kt @@ -35,5 +35,7 @@ class RemoteReplStateFacadeServer(val _id: Int, override fun historyGet(index: Int): ILineId = state.history[index].id + override fun historyReset(): List = state.history.reset().toList() + override fun historyResetTo(id: ILineId): List = state.history.resetTo(id).toList() }