Implement proper script runtime exception rendering with tests
#KT-42335 fixed
This commit is contained in:
+17
@@ -87,6 +87,22 @@ class ReplTest : TestCase() {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEvalWithExceptionWithCause() {
|
||||
checkEvaluateInRepl(
|
||||
sequenceOf(
|
||||
"""
|
||||
try {
|
||||
throw Exception("Error!")
|
||||
} catch (e: Exception) {
|
||||
throw Exception("Oh no", e)
|
||||
}
|
||||
""".trimIndent()
|
||||
),
|
||||
sequenceOf(Exception("Oh no", Exception("Error!")))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEvalWithErrorWithLocation() {
|
||||
checkEvaluateInReplDiags(
|
||||
@@ -240,6 +256,7 @@ class ReplTest : TestCase() {
|
||||
is ResultValue.Error -> Assert.assertTrue(
|
||||
"#$index: Expected $expectedVal, got Error: ${actualVal.error}",
|
||||
expectedVal is Throwable && expectedVal.message == actualVal.error.message
|
||||
&& expectedVal.cause?.message == actualVal.error.cause?.message
|
||||
)
|
||||
is ResultValue.NotEvaluated -> Assert.assertEquals(
|
||||
"#$index: Expected $expectedVal, got NotEvaluated",
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.script.experimental.jvm.util
|
||||
|
||||
import java.io.PrintStream
|
||||
import kotlin.script.experimental.api.ResultValue
|
||||
|
||||
fun ResultValue.Error.renderError(stream: PrintStream) {
|
||||
var trace = error.stackTrace
|
||||
val wrappingTrace = wrappingException?.stackTrace
|
||||
if (wrappingException == null || trace.size < wrappingTrace!!.size) {
|
||||
error.printStackTrace(stream)
|
||||
} else {
|
||||
// subtracting wrapping message stacktrace from error stacktrace to show only user-specific part of it
|
||||
|
||||
fun PrintStream.printTrace(stackTrace: Array<StackTraceElement>, dropLastFrames: Int) {
|
||||
for (element in stackTrace.dropLast(dropLastFrames)) {
|
||||
println("\tat $element")
|
||||
}
|
||||
}
|
||||
|
||||
stream.println(error)
|
||||
stream.printTrace(trace, wrappingTrace.size)
|
||||
|
||||
var current: Throwable? = error.cause
|
||||
var wrapping = error
|
||||
val cyclesDetection = hashSetOf(wrapping)
|
||||
while (current != null && cyclesDetection.add(current)) {
|
||||
trace = current.stackTrace
|
||||
val sameFramesCount =
|
||||
trace.asList().asReversed().asSequence()
|
||||
.zip(wrapping.stackTrace.asList().asReversed().asSequence())
|
||||
.takeWhile { it.first == it.second }
|
||||
.count()
|
||||
stream.println("Caused by: $current")
|
||||
stream.printTrace(trace, sameFramesCount)
|
||||
wrapping = current
|
||||
current = current.cause
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user