Fix negative caret width rendering multi-line expression errors (#1793)

The expression preamble length was subtracted from endColumn even
when endColumn came from the already-stripped sourceLine.length(),
so multi-line frames got a negative caret width and String.repeat
threw. Apply the offset only to the frame-derived columns.

---------

Co-authored-by: Dan Chao <dan.chao@apple.com>
This commit is contained in:
David Tesler
2026-07-24 20:57:05 +00:00
committed by GitHub
co-authored by Dan Chao
parent 2c9e3161d8
commit 175e2b6273
2 changed files with 37 additions and 7 deletions
@@ -128,17 +128,13 @@ public final class StackTraceRenderer {
sourceLine = sourceLine.substring(PREAMBLE_LENGTH);
hasPreamble = true;
}
var startColumn = frame.getStartColumn() - leadingWhitespace;
var preambleOffset = hasPreamble ? PREAMBLE_LENGTH : 0;
var startColumn = frame.getStartColumn() - leadingWhitespace - preambleOffset;
var endColumn =
frame.getStartLine() == frame.getEndLine()
? frame.getEndColumn() - leadingWhitespace
? frame.getEndColumn() - leadingWhitespace - preambleOffset
: sourceLine.length();
if (hasPreamble) {
startColumn -= PREAMBLE_LENGTH;
endColumn -= PREAMBLE_LENGTH;
}
var prefix = frame.getStartLine() + " | ";
out.append(AnsiTheme.STACK_TRACE_MARGIN, leftMargin)
.append(AnsiTheme.STACK_TRACE_LINE_NUMBER, prefix);
@@ -165,6 +165,40 @@ class EvaluateExpressionTest {
)
}
@Test
fun `evaluate throwing multi-line expression renders without crashing`() {
val error =
assertThrows<PklException> {
evaluate(
"x = 1",
"""
let (_a = 1)
let (_b = 2)
throw("boom")
"""
.trimIndent(),
)
}
assertThat(error.message)
.isEqualTo(
"""
–– Pkl Error ––
boom
3 | throw("boom")
^^^^^^^^^^^^^
at (repl:text)
1 | let (_a = 1)
^^^^^^^^^^^^
at repl:text.<let expr> (repl:text)
"""
.trimIndent()
)
}
@Test
fun `evaluate import`() {
val result = evaluate("import \"pkl:base\"", "base")