Add total reset to repl history and state interfaces

This commit is contained in:
Ilya Chernikov
2017-03-25 14:31:59 +01:00
parent c746cae72d
commit 8cc576d44f
10 changed files with 68 additions and 11 deletions
@@ -52,11 +52,19 @@ open class AggregatedReplStateHistory<T1, T2>(val history1: IReplStageHistory<T1
ReplHistoryRecord(r1.id, r1.item to r2.item)
}
override fun reset(): Iterable<ILineId> = 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<ILineId> = 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
}
@@ -49,6 +49,14 @@ open class BasicReplStageHistory<T>(override val lock: ReentrantReadWriteLock =
override fun pop(): ReplHistoryRecord<T>? = lock.write { if (isEmpty()) null else removeAt(lastIndex) }
override fun reset(): Iterable<ILineId> {
lock.write {
val removed = map { it.id }
clear()
return removed
}
}
override fun resetTo(id: ILineId): Iterable<ILineId> {
lock.write {
val idx = indexOfFirst { it.id == id }
@@ -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)
}
@@ -52,6 +52,13 @@ class ReplHistory<T>(startingHistory: CompiledHistoryList<T> = emptyList()) : Se
}
}
/* resets back complete history and returns the lines removed */
fun reset(): SourceHistoryList<T> {
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<T> {
val removed = arrayListOf<SourceHistoryItem<T>>()
@@ -41,6 +41,8 @@ interface IReplStageHistory<T> : List<ReplHistoryRecord<T>> {
else null
}
fun reset(): Iterable<ILineId>
fun resetTo(id: ILineId): Iterable<ILineId>
val lock: ReentrantReadWriteLock
@@ -26,16 +26,28 @@ import kotlin.script.dependencies.KotlinScriptExternalDependencies
class ReplCompilerStageHistory(private val state: GenericReplCompilerState) : BasicReplStageHistory<ScriptDescriptor>(state.lock) {
override fun reset(): Iterable<ILineId> {
val removedCompiledLines = super.reset()
val removedAnalyzedLines = state.analyzerEngine.reset()
checkConsistent(removedCompiledLines, removedAnalyzedLines)
return removedCompiledLines
}
override fun resetTo(id: ILineId): Iterable<ILineId> {
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<ILineId>, removedAnalyzedLines: List<ReplCodeLine>) {
removedCompiledLines.zip(removedAnalyzedLines).forEach {
if (it.first != LineId(it.second)) {
throw IllegalStateException("History mismatch when resetting lines: ${it.first.no} != ${it.second}")
}
}
return removedCompiledLines
}
}
@@ -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<ReplCodeLine> = replState.resetToLine(lineNumber)
fun resetToLine(lineId: ILineId): List<ReplCodeLine> = replState.resetToLine(lineId)
fun reset(): List<ReplCodeLine> = replState.reset()
fun analyzeReplLine(psiFile: KtFile, codeLine: ReplCodeLine): ReplLineAnalysisResult {
topDownAnalysisContext.scripts.clear()
@@ -172,12 +175,17 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
private val successfulLines = ReplHistory<LineInfo.SuccessfulLine>()
private val submittedLines = hashMapOf<KtFile, LineInfo>()
fun resetToLine(lineNumber: Int): List<ReplCodeLine> {
val removed = successfulLines.resetToLine(lineNumber)
fun resetToLine(lineId: ILineId): List<ReplCodeLine> {
val removed = successfulLines.resetToLine(lineId.no)
removed.forEach { submittedLines.remove(it.second.linePsi) }
return removed.map { it.first }
}
fun reset(): List<ReplCodeLine> {
submittedLines.clear()
return successfulLines.reset().map { it.first }
}
fun submitLine(ktFile: KtFile, codeLine: ReplCodeLine) {
val line = LineInfo.SubmittedLine(ktFile, successfulLines.lastValue())
submittedLines[ktFile] = line
@@ -37,10 +37,12 @@ class RemoteReplCompilerStateHistory(private val state: RemoteReplCompilerState)
throw NotImplementedError("pop from remote history is not supported")
}
override fun reset(): Iterable<ILineId> = state.replStateFacade.historyReset().apply {
currentGeneration.incrementAndGet()
}
override fun resetTo(id: ILineId): Iterable<ILineId> = state.replStateFacade.historyResetTo(id).apply {
if (isNotEmpty()) {
currentGeneration.incrementAndGet()
}
currentGeneration.incrementAndGet()
}
val currentGeneration = AtomicInteger(REPL_CODE_LINE_FIRST_GEN)
@@ -31,6 +31,9 @@ interface ReplStateFacade : Remote {
@Throws(RemoteException::class)
fun historyGet(index: Int): ILineId
@Throws(RemoteException::class)
fun historyReset(): List<ILineId>
@Throws(RemoteException::class)
fun historyResetTo(id: ILineId): List<ILineId>
}
@@ -35,5 +35,7 @@ class RemoteReplStateFacadeServer(val _id: Int,
override fun historyGet(index: Int): ILineId = state.history[index].id
override fun historyReset(): List<ILineId> = state.history.reset().toList()
override fun historyResetTo(id: ILineId): List<ILineId> = state.history.resetTo(id).toList()
}