github.com/haraldrudell/parl@v0.4.176/perrors/new-errorf.go (about) 1 /* 2 © 2020–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package perrors 7 8 import ( 9 "errors" 10 "fmt" 11 12 "github.com/haraldrudell/parl/perrors/errorglue" 13 "github.com/haraldrudell/parl/pruntime" 14 ) 15 16 const ( 17 e116StacknFramesToSkip = 1 18 e116StackFrames = 1 19 perrNewFrames = 1 20 ) 21 22 // error116.New is similar to errors.New but ensures that the returned error 23 // has at least one stack trace associated 24 func New(s string) error { 25 if s == "" { // ensure there is an error message 26 s = "StackNew from " + pruntime.NewCodeLocation(perrNewFrames).Short() 27 } 28 return Stackn(errors.New(s), e116StackFrames) 29 } 30 31 func NewPF(s string) error { 32 packFunc := pruntime.NewCodeLocation(perrNewFrames).PackFunc() 33 if s == "" { 34 s = packFunc 35 } else { 36 s = packFunc + "\x20" + s 37 } 38 return Stackn(errors.New(s), e116StackFrames) 39 } 40 41 // error116.Errorf is similar to fmt.Errorf but ensures that the returned err 42 // has at least one stack trace associated 43 func Errorf(format string, a ...interface{}) (err error) { 44 err = fmt.Errorf(format, a...) 45 if HasStack(err) { 46 return 47 } 48 return Stackn(err, e116StackFrames) 49 } 50 51 func ErrorfPF(format string, a ...interface{}) (err error) { 52 // format may include %w directives, meaning fmt.Errorf must be used 53 // format may include numeric indices like %[1]s, meaning values cannot be prepended to a 54 format = pruntime.NewCodeLocation(perrNewFrames).PackFunc() + "\x20" + format 55 err = fmt.Errorf(format, a...) 56 if HasStack(err) { 57 return 58 } 59 return Stackn(err, e116StackFrames) 60 } 61 62 // error116.Stack ensures the err has a stack trace 63 // associated. 64 // err can be nil in which nil is returned 65 func Stack(err error) (err2 error) { 66 if HasStack(err) { 67 return err 68 } 69 return Stackn(err, e116StackFrames) 70 } 71 72 // error116.Stackn always attaches a new stack trace to err and 73 // allows for skipping stack frames using framesToSkip. 74 // if err is nil, no action is taken 75 func Stackn(err error, framesToSkip int) (err2 error) { 76 if err == nil { 77 return 78 } 79 if framesToSkip < 0 { 80 framesToSkip = 0 81 } 82 err2 = errorglue.NewErrorStack(err, pruntime.NewStack(e116StacknFramesToSkip+framesToSkip)) 83 return 84 }