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  }