github.com/ladydascalie/elvish@v0.0.0-20170703214355-2964dd3ece7f/util/throw.go (about) 1 package util 2 3 // Thrown wraps an error that was raised by Throw, so that it can be recognized 4 // by Catch. 5 type Thrown struct { 6 Error error 7 } 8 9 // Throw panics with err wrapped properly so that it can be catched by Catch. 10 func Throw(err error) { 11 panic(Thrown{err}) 12 } 13 14 // Catch tries to catch an error thrown by Throw and stop the panic. If the 15 // panic is not caused by Throw, the panic is not stopped. It should be called 16 // directly from defer. 17 func Catch(perr *error) { 18 r := recover() 19 if r == nil { 20 return 21 } 22 if exc, ok := r.(Thrown); ok { 23 *perr = exc.Error 24 } else { 25 panic(r) 26 } 27 } 28 29 // PCall calls a function and catches anything Thrown'n and returns it. It does 30 // not protect against panics not using Throw, nor can it distinguish between 31 // nothing thrown and Throw(nil). 32 func PCall(f func()) (e error) { 33 defer Catch(&e) 34 f() 35 // If we reach here, f didn't throw anything. 36 return nil 37 } 38 39 // Throws returns whether calling f throws out a certain error (using Throw). It 40 // is useful for testing. 41 func Throws(f func(), e error) bool { 42 return PCall(f) == e 43 } 44 45 // DoesntThrow returns whether calling f does not throw anything. It is useful 46 // for testing. 47 func DoesntThrow(f func()) bool { 48 return PCall(f) == nil 49 }