eval: Add a Cause function to safely extract the cause of exceptions.

This commit is contained in:
Qi Xiao 2018-10-09 21:21:26 +08:00
parent c10693df8d
commit 0b76987569
6 changed files with 29 additions and 6 deletions

View File

@ -56,7 +56,7 @@ func each(fm *Frame, f Callable, inputs Inputs) error {
newFm.Close()
if ex != nil {
switch ex.(*Exception).Cause {
switch Cause(ex) {
case nil, Continue:
// nop
case Break:
@ -87,7 +87,7 @@ func peach(fm *Frame, f Callable, inputs Inputs) error {
newFm.Close()
if ex != nil {
switch ex.(*Exception).Cause {
switch Cause(ex) {
case nil, Continue:
// nop
case Break:

View File

@ -159,7 +159,7 @@ func eawk(fm *Frame, f Callable, inputs Inputs) error {
newFm.Close()
if ex != nil {
switch ex.(*Exception).Cause {
switch Cause(ex) {
case nil, Continue:
// nop
case Break:

View File

@ -212,7 +212,7 @@ type fnWrap struct{ wrapped effectOp }
func (op fnWrap) invoke(fm *Frame) error {
err := fm.Eval(op.wrapped)
if err != nil && err.(*Exception).Cause != Return {
if err != nil && Cause(err) != Return {
// rethrow
return err
}

View File

@ -22,6 +22,15 @@ type Exception struct {
Traceback *stackTrace
}
// Cause returns the Cause field if err is an *Exception. Otherwise it returns
// err itself.
func Cause(err error) error {
if exc, ok := err.(*Exception); ok {
return exc.Cause
}
return err
}
// OK is a pointer to the zero value of Exception, representing the absence of
// exception.
var OK = &Exception{}

View File

@ -1,6 +1,20 @@
package eval
import "testing"
import (
"errors"
"testing"
"github.com/elves/elvish/tt"
)
func TestCause(t *testing.T) {
err := errors.New("ordinary error")
exc := &Exception{Cause: err}
tt.Test(t, tt.Fn("Cause", Cause), tt.Table{
tt.Args(err).Rets(err),
tt.Args(exc).Rets(err),
})
}
func TestException(t *testing.T) {
Test(t,

View File

@ -223,7 +223,7 @@ func matchErr(want, got error) bool {
if got == nil {
return want == nil
}
return want == errAny || reflect.DeepEqual(got.(*Exception).Cause, want)
return want == errAny || reflect.DeepEqual(Cause(got), want)
}
// MustMkdirAll calls os.MkdirAll and panics if an error is returned. It is