Increment repl line generation on compilation error
fixes #KT-17921 and #KT-21141 Tests added to the JSR223 local eval example
This commit is contained in:
@@ -53,6 +53,7 @@ open class BasicReplStageHistory<T>(override val lock: ReentrantReadWriteLock =
|
|||||||
lock.write {
|
lock.write {
|
||||||
val removed = map { it.id }
|
val removed = map { it.id }
|
||||||
clear()
|
clear()
|
||||||
|
currentGeneration.incrementAndGet()
|
||||||
return removed
|
return removed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +68,10 @@ open class BasicReplStageHistory<T>(override val lock: ReentrantReadWriteLock =
|
|||||||
currentGeneration.incrementAndGet()
|
currentGeneration.incrementAndGet()
|
||||||
removed
|
removed
|
||||||
}
|
}
|
||||||
else emptyList()
|
else {
|
||||||
|
currentGeneration.incrementAndGet()
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-9
@@ -35,7 +35,15 @@ class GenericReplCompilingEvaluator(val compiler: ReplCompiler,
|
|||||||
val aggregatedState = state.asState(AggregatedReplStageState::class.java)
|
val aggregatedState = state.asState(AggregatedReplStageState::class.java)
|
||||||
val compiled = compiler.compile(state, codeLine)
|
val compiled = compiler.compile(state, codeLine)
|
||||||
when (compiled) {
|
when (compiled) {
|
||||||
is ReplCompileResult.Error -> ReplEvalResult.Error.CompileTime(compiled.message, compiled.location)
|
is ReplCompileResult.Error -> {
|
||||||
|
aggregatedState.apply {
|
||||||
|
lock.write {
|
||||||
|
assert(state1.history.size == state2.history.size)
|
||||||
|
adjustHistories() // needed due to statefulness of AnalyzerEngine - in case of compilation errors the line name reuse leads to #KT-17921
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReplEvalResult.Error.CompileTime(compiled.message, compiled.location)
|
||||||
|
}
|
||||||
is ReplCompileResult.Incomplete -> ReplEvalResult.Incomplete()
|
is ReplCompileResult.Incomplete -> ReplEvalResult.Incomplete()
|
||||||
is ReplCompileResult.CompiledClasses -> {
|
is ReplCompileResult.CompiledClasses -> {
|
||||||
val result = eval(state, compiled, scriptArgs, invokeWrapper)
|
val result = eval(state, compiled, scriptArgs, invokeWrapper)
|
||||||
@@ -46,14 +54,7 @@ class GenericReplCompilingEvaluator(val compiler: ReplCompiler,
|
|||||||
aggregatedState.apply {
|
aggregatedState.apply {
|
||||||
lock.write {
|
lock.write {
|
||||||
if (state1.history.size > state2.history.size) {
|
if (state1.history.size > state2.history.size) {
|
||||||
if (state2.history.size == 0) {
|
adjustHistories()
|
||||||
state1.history.reset()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
state2.history.peek()?.let {
|
|
||||||
state1.history.resetTo(it.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(state1.history.size == state2.history.size)
|
assert(state1.history.size == state2.history.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,3 +92,9 @@ class GenericReplCompilingEvaluator(val compiler: ReplCompiler,
|
|||||||
evaluator.eval(state, compiledCode, scriptArgs ?: defaultScriptArgs, invokeWrapper)
|
evaluator.eval(state, compiledCode, scriptArgs ?: defaultScriptArgs, invokeWrapper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun AggregatedReplStageState<*, *>.adjustHistories(): Iterable<ILineId>? =
|
||||||
|
state2.history.peek()?.let {
|
||||||
|
state1.history.resetTo(it.id)
|
||||||
|
}
|
||||||
|
?: state1.history.reset()
|
||||||
|
|||||||
+40
@@ -72,6 +72,46 @@ class KotlinJsr223LocalScriptEngineIT {
|
|||||||
Assert.assertEquals(5, res2)
|
Assert.assertEquals(5, res2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testEvalWithError() {
|
||||||
|
val engine = ScriptEngineManager().getEngineByExtension("kts")!!
|
||||||
|
|
||||||
|
try {
|
||||||
|
engine.eval("java.lang.fish")
|
||||||
|
Assert.fail("Script error expected")
|
||||||
|
}
|
||||||
|
catch (e: ScriptException) {}
|
||||||
|
|
||||||
|
val res1 = engine.eval("val x = 3")
|
||||||
|
Assert.assertNull(res1)
|
||||||
|
|
||||||
|
try {
|
||||||
|
engine.eval("y")
|
||||||
|
Assert.fail("Script error expected")
|
||||||
|
}
|
||||||
|
catch (e: ScriptException) {
|
||||||
|
Assert.assertTrue("Expected message to contain \"unresolved reference: y\", actual: \"${e.message}\"",
|
||||||
|
e.message?.contains("unresolved reference: y") ?: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val res3 = engine.eval("x + 2")
|
||||||
|
Assert.assertEquals(5, res3)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testEngineRepeatWithReset() {
|
||||||
|
val code = "open class A {}\n" +
|
||||||
|
"class B : A() {}"
|
||||||
|
val engine = ScriptEngineManager().getEngineByExtension("kts") as KotlinJsr223JvmLocalScriptEngine
|
||||||
|
|
||||||
|
val res1 = engine.eval(code)
|
||||||
|
Assert.assertNull(res1)
|
||||||
|
|
||||||
|
engine.state.history.reset()
|
||||||
|
|
||||||
|
engine.eval(code)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInvocable() {
|
fun testInvocable() {
|
||||||
val engine = ScriptEngineManager().getEngineByExtension("kts")!!
|
val engine = ScriptEngineManager().getEngineByExtension("kts")!!
|
||||||
|
|||||||
Reference in New Issue
Block a user