Implement proper script runtime exception rendering with tests

#KT-42335 fixed
This commit is contained in:
Ilya Chernikov
2020-10-01 13:15:05 +02:00
parent d5ad424e8f
commit db23460fd5
7 changed files with 165 additions and 20 deletions
@@ -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
}
}
}