aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralandonovan <adonovan@google.com>2020-11-18 12:36:49 -0500
committerGitHub <noreply@github.com>2020-11-18 12:36:49 -0500
commita5c0cc49931aeca4ff5eedc21ba1c2d1b37ae780 (patch)
tree8f66f662d3eeca2683a46ad1fb7d114948dba57c
parente292e66a28cd2a152317d4cb315ae6f6643d38b6 (diff)
downloadstarlark-go-a5c0cc49931aeca4ff5eedc21ba1c2d1b37ae780.tar.gz
starlark: skip last frame of stack backtrace if built-in (#319)
Instead, the name of the built-in function is append to the error message ("Error in foo: ...").
-rw-r--r--starlark/eval.go14
-rw-r--r--starlark/eval_test.go7
2 files changed, 16 insertions, 5 deletions
diff --git a/starlark/eval.go b/starlark/eval.go
index 633fc30..c9bbb67 100644
--- a/starlark/eval.go
+++ b/starlark/eval.go
@@ -217,7 +217,9 @@ func (stack *CallStack) Pop() CallFrame {
// String returns a user-friendly description of the stack.
func (stack CallStack) String() string {
out := new(strings.Builder)
- fmt.Fprintf(out, "Traceback (most recent call last):\n")
+ if len(stack) > 0 {
+ fmt.Fprintf(out, "Traceback (most recent call last):\n")
+ }
for _, fr := range stack {
fmt.Fprintf(out, " %s: in %s\n", fr.Pos, fr.Name)
}
@@ -259,7 +261,15 @@ func (e *EvalError) Error() string { return e.Msg }
// Backtrace returns a user-friendly error message describing the stack
// of calls that led to this error.
func (e *EvalError) Backtrace() string {
- return fmt.Sprintf("%sError: %s", e.CallStack, e.Msg)
+ // If the topmost stack frame is a built-in function,
+ // remove it from the stack and add print "Error in fn:".
+ stack := e.CallStack
+ suffix := ""
+ if last := len(stack) - 1; last >= 0 && stack[last].Pos.Filename() == builtinFilename {
+ suffix = " in " + stack[last].Name
+ stack = stack[:last]
+ }
+ return fmt.Sprintf("%sError%s: %s", stack, suffix, e.Msg)
}
func (e *EvalError) Unwrap() error { return e.cause }
diff --git a/starlark/eval_test.go b/starlark/eval_test.go
index a2d61c5..703f09b 100644
--- a/starlark/eval_test.go
+++ b/starlark/eval_test.go
@@ -512,7 +512,6 @@ i()
`
thread := new(starlark.Thread)
_, err := starlark.ExecFile(thread, "crash.star", src, nil)
- // Compiled code currently has no column information.
const want = `Traceback (most recent call last):
crash.star:6:2: in <toplevel>
crash.star:5:18: in i
@@ -527,6 +526,9 @@ Error: floored division by zero`
// Additionally, ensure that errors originating in
// Starlark and/or Go each have an accurate frame.
+ // The topmost frame, if built-in, is not shown,
+ // but the name of the built-in function is shown
+ // as "Error in fn: ...".
//
// This program fails in Starlark (f) if x==0,
// or in Go (string.join) if x is non-zero.
@@ -542,8 +544,7 @@ Error: floored division by zero`,
1: `Traceback (most recent call last):
crash.star:3:2: in <toplevel>
crash.star:2:17: in f
- <builtin>: in join
-Error: join: in list, want string, got int`,
+Error in join: join: in list, want string, got int`,
} {
globals := starlark.StringDict{"i": starlark.MakeInt(i)}
_, err := starlark.ExecFile(thread, "crash.star", src2, globals)