Compare commits

...

2 commits
v0.3.0 ... main

Author SHA1 Message Date
34a01c6279 Pass through try-compatible errors
All checks were successful
continuous-integration/drone/push Build is passing
2021-10-17 10:59:33 +02:00
b6ff49baee add ReturnStd
All checks were successful
continuous-integration/drone/push Build is passing
2021-10-16 23:32:06 +02:00
2 changed files with 51 additions and 20 deletions

View file

@ -47,7 +47,14 @@ type call struct {
} }
// FromErr wraps a standard error into a try-compatible one with extended stack info. // FromErr wraps a standard error into a try-compatible one with extended stack info.
func FromErr(err error) *tryErr { func FromErr(err error) Err {
// If the error is already try-compatible, return
//nolint:errorlint
cterr, ok := err.(Err)
if ok {
return cterr
}
terr := &tryErr{err: err, callStack: []call{}} terr := &tryErr{err: err, callStack: []call{}}
pc, _, _, ok := runtime.Caller(0) pc, _, _, ok := runtime.Caller(0)
@ -82,7 +89,7 @@ func FromErr(err error) *tryErr {
} }
// NewErr creates a new try-compatible error with extended stack info. // NewErr creates a new try-compatible error with extended stack info.
func NewErr(msg string) *tryErr { func NewErr(msg string) Err {
return FromErr(errors.New(msg)) return FromErr(errors.New(msg))
} }
@ -179,9 +186,6 @@ func check(args []interface{}) {
// return errors there is a Catch function. Note! The handler function f is // return errors there is a Catch function. Note! The handler function f is
// called only when err != nil. // called only when err != nil.
func Handle(err *Err, f func()) { func Handle(err *Err, f func()) {
// This and Catch are similar but we need to call recover() here because
// how it works with defer. We cannot refactor these to use same function.
// We put real panic objects back and keep only those which are // We put real panic objects back and keep only those which are
// carrying our errors. We must also call all of the handlers in defer // carrying our errors. We must also call all of the handlers in defer
// stack. // stack.
@ -208,9 +212,6 @@ func Handle(err *Err, f func()) {
// Catch function per non error returning function. See Handle for more // Catch function per non error returning function. See Handle for more
// information. // information.
func Catch(f func(err Err)) { func Catch(f func(err Err)) {
// This and Handle are similar but we need to call recover here because how
// it works with defer. We cannot refactor these 2 to use same function.
if r := recover(); r != nil { if r := recover(); r != nil {
e, ok := r.(Err) e, ok := r.(Err)
if !ok { if !ok {
@ -223,9 +224,6 @@ func Catch(f func(err Err)) {
// CatchAll is a helper function to catch and write handlers for all errors and // CatchAll is a helper function to catch and write handlers for all errors and
// all panics thrown in the current go routine. // all panics thrown in the current go routine.
func CatchAll(errorHandler func(err Err), panicHandler func(v interface{})) { func CatchAll(errorHandler func(err Err), panicHandler func(v interface{})) {
// This and Handle are similar but we need to call recover here because how
// it works with defer. We cannot refactor these 2 to use same function.
if r := recover(); r != nil { if r := recover(); r != nil {
e, ok := r.(Err) e, ok := r.(Err)
if ok { if ok {
@ -256,9 +254,6 @@ func CatchTrace(exit int) {
// their errors. If you want to annotate errors see Annotate for more // their errors. If you want to annotate errors see Annotate for more
// information. // information.
func Return(err *Err) { func Return(err *Err) {
// This and Handle are similar but we need to call recover here because how
// it works with defer. We cannot refactor these two to use same function.
if r := recover(); r != nil { if r := recover(); r != nil {
e, ok := r.(Err) e, ok := r.(Err)
if !ok { if !ok {
@ -268,13 +263,19 @@ func Return(err *Err) {
} }
} }
// Annotate is for annotating an error. It's similar to Returnf but it takes only // ReturnStd is like Return, but it returns the Go standard error type.
// two arguments: a prefix string and a pointer to error. It adds ": " between func ReturnStd(err *error) {
// the prefix and the error text automatically. if r := recover(); r != nil {
func Annotate(err *Err, msg string) { e, ok := r.(Err)
// This and Handle are similar but we need to call recover here because how if !ok {
// it works with defer. We cannot refactor these two to use same function. panic(r) // Not ours, carry on panicking
}
*err = e.Unwrap()
}
}
// Annotate adds additional messages to the error.
func Annotate(err *Err, msg string) {
if r := recover(); r != nil { if r := recover(); r != nil {
e, ok := r.(Err) e, ok := r.(Err)
if !ok { if !ok {

View file

@ -206,6 +206,36 @@ func TestErrCompare(t *testing.T) {
} }
} }
func TestReturnStd(t *testing.T) {
tf := func() (err error) {
defer ReturnStd(&err)
String(throw())
return
}
err := tf()
if err.Error() != "this is an ERROR" {
t.Fail()
}
}
func TestCheckTryErr(t *testing.T) {
testErr := NewErr("TestErr")
tf := func() (err Err) {
defer Return(&err)
Check(testErr)
return
}
err := tf()
if err != testErr {
t.Fail()
}
}
func ExampleReturn() { func ExampleReturn() {
var err Err var err Err
defer Return(&err) defer Return(&err)