diff options
author | alandonovan <adonovan@google.com> | 2020-11-18 12:36:49 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-18 12:36:49 -0500 |
commit | a5c0cc49931aeca4ff5eedc21ba1c2d1b37ae780 (patch) | |
tree | 8f66f662d3eeca2683a46ad1fb7d114948dba57c | |
parent | e292e66a28cd2a152317d4cb315ae6f6643d38b6 (diff) | |
download | starlark-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.go | 14 | ||||
-rw-r--r-- | starlark/eval_test.go | 7 |
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) |