Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions internal/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ func NilNoop(err error) error { return err }

// func ErrorNoop(err error) {}

// initErrors initializes both i.Err and i.werr with a new error pointer.
// Used by PreProcess for setting up error handling with a local error variable.
func (i *Info) initErrors(errPtr *error) {
i.Err = errPtr
i.werr = *errPtr
}

// setErrors updates both *i.Err and i.werr to keep them in sync.
// Assumes i.Err is already initialized (non-nil pointer).
// Used by error handlers to update the error value.
func (i *Info) setErrors(err error) {
*i.Err = err
i.werr = err
}

func (i *Info) callNilHandler() {
if i.CheckHandler != nil && i.safeErr() == nil {
i.CheckHandler(true)
Expand All @@ -86,8 +101,8 @@ func (i *Info) callNilHandler() {
i.checkErrorTracer()
}
if i.NilFn != nil {
*i.Err = i.NilFn(i.werr)
i.werr = *i.Err // remember change both our errors!
result := i.NilFn(i.werr)
i.setErrors(result)
} else {
i.defaultNilHandler()
}
Expand Down Expand Up @@ -120,14 +135,16 @@ func (i *Info) callErrorHandler() {
if i.ErrorFn != nil {
// we want to auto-annotate error first and exec ErrorFn then
i.werr = i.workError()
var result error

if i.needErrorAnnotation && i.werr != nil {
i.buildFmtErr()
*i.Err = i.ErrorFn(*i.Err)
result = i.ErrorFn(*i.Err)
} else {
*i.Err = i.ErrorFn(i.Any.(error))
result = i.ErrorFn(i.Any.(error))
}

i.werr = *i.Err // remember change both our errors!
i.setErrors(result)
} else {
i.defaultErrorHandler()
}
Expand Down Expand Up @@ -165,8 +182,8 @@ func (i *Info) workError() (err error) {
}

func (i *Info) fmtErr() {
*i.Err = fmt.Errorf(i.Format+i.wrapStr(), append(i.Args, i.werr)...)
i.werr = *i.Err // remember change both our errors!
result := fmt.Errorf(i.Format+i.wrapStr(), append(i.Args, i.werr)...)
i.setErrors(result)
}

func (i *Info) buildFmtErr() {
Expand Down Expand Up @@ -279,11 +296,10 @@ func Process(info *Info) {
func PreProcess(errPtr *error, info *Info, a []any) error {
// Bug in Go?
// start to use local error ptr only for optimization reasons.
// We get 3x faster defer handlers without unsing ptr to original err
// We get 3x faster defer handlers without using ptr to original err
// named return val. Reason is unknown.
err := x.Whom(errPtr != nil, *errPtr, nil)
info.Err = &err
info.werr = *info.Err // remember change both our errors!
info.initErrors(&err)

// We want the function who sets the handler, i.e. calls the
// err2.Handle function via defer. Because call stack is in reverse
Expand Down Expand Up @@ -312,9 +328,12 @@ func PreProcess(errPtr *error, info *Info, a []any) error {
const framesToSkip = 6
frame = x.Whom(ok, frame, framesToSkip)
if LogOutput(frame, curErr.Error()) == nil {
*info.Err = nil // prevent dublicate "logging"
*info.Err = nil // prevent duplicate "logging"
}
}

// Note: Since info.Err points to &err, any updates to *info.Err will also update err.
// Therefore, we can return the local err variable which reflects the final processed state.
return err
}

Expand Down
Loading