...

Source file src/oss.terrastruct.com/util-go/xdefer/xdefer.go

Documentation: oss.terrastruct.com/util-go/xdefer

     1  // Package xdefer implements an extremely useful function, Errorf, to annotate all errors returned from a function transparently.
     2  package xdefer
     3  
     4  import (
     5  	"fmt"
     6  	"strings"
     7  
     8  	"golang.org/x/xerrors"
     9  )
    10  
    11  type deferError struct {
    12  	s     string
    13  	err   error
    14  	frame xerrors.Frame
    15  }
    16  
    17  var _ interface {
    18  	xerrors.Wrapper
    19  	xerrors.Formatter
    20  	Is(error) bool
    21  } = deferError{}
    22  
    23  func (e deferError) Unwrap() error {
    24  	return e.err
    25  }
    26  
    27  func (e deferError) Format(f fmt.State, c rune) {
    28  	xerrors.FormatError(e, f, c)
    29  }
    30  
    31  // Used to detect if there is a duplicate frame as a result
    32  // of using xdefer and if so to ignore it.
    33  type fakeXerrorsPrinter struct {
    34  	s []string
    35  }
    36  
    37  func (fp *fakeXerrorsPrinter) Print(v ...interface{}) {
    38  	fp.s = append(fp.s, fmt.Sprint(v...))
    39  }
    40  
    41  func (fp *fakeXerrorsPrinter) Printf(f string, v ...interface{}) {
    42  	fp.s = append(fp.s, fmt.Sprintf(f, v...))
    43  }
    44  
    45  func (fp *fakeXerrorsPrinter) Detail() bool {
    46  	return true
    47  }
    48  
    49  func (e deferError) shouldPrintFrame(p xerrors.Printer) bool {
    50  	fm, ok := e.err.(xerrors.Formatter)
    51  	if !ok {
    52  		return true
    53  	}
    54  
    55  	fp := &fakeXerrorsPrinter{}
    56  	e.frame.Format(fp)
    57  	fp2 := &fakeXerrorsPrinter{}
    58  	_ = fm.FormatError(fp2)
    59  	if len(fp.s) >= 2 && len(fp2.s) >= 3 {
    60  		if fp.s[1] == fp2.s[2] {
    61  			// We don't need to print our frame into the real
    62  			// xerrors printer as the next error will have it.
    63  			return false
    64  		}
    65  	}
    66  	return true
    67  }
    68  
    69  func (e deferError) FormatError(p xerrors.Printer) error {
    70  	if e.s == "" {
    71  		if e.shouldPrintFrame(p) {
    72  			e.frame.Format(p)
    73  		}
    74  		return e.err
    75  	}
    76  
    77  	p.Print(e.s)
    78  	if p.Detail() && e.shouldPrintFrame(p) {
    79  		e.frame.Format(p)
    80  	}
    81  	return e.err
    82  }
    83  
    84  func (e deferError) Is(err error) bool {
    85  	return xerrors.Is(e.err, err)
    86  }
    87  
    88  func (e deferError) Error() string {
    89  	if e.s == "" {
    90  		fp := &fakeXerrorsPrinter{}
    91  		e.frame.Format(fp)
    92  		if len(fp.s) < 1 {
    93  			return e.err.Error()
    94  		}
    95  		return fmt.Sprintf("%v: %v", strings.TrimSpace(fp.s[0]), e.err)
    96  	}
    97  	return fmt.Sprintf("%v: %v", e.s, e.err)
    98  }
    99  
   100  // Errorf makes it easy to defer annotate an error for all return paths in a function.
   101  // See the tests for how it's used.
   102  //
   103  // Pass s == "" to only annotate the location of the return.
   104  func Errorf(err *error, s string, v ...interface{}) {
   105  	if *err != nil {
   106  		*err = deferError{
   107  			s:     fmt.Sprintf(s, v...),
   108  			err:   *err,
   109  			frame: xerrors.Caller(1),
   110  		}
   111  	}
   112  }
   113  

View as plain text