github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/yaml/internal/errors/error.go (about)

     1  package errors
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/bingoohuang/gg/pkg/yaml/printer"
     8  	"github.com/bingoohuang/gg/pkg/yaml/token"
     9  	"golang.org/x/xerrors"
    10  )
    11  
    12  const (
    13  	defaultColorize      = false
    14  	defaultIncludeSource = true
    15  )
    16  
    17  var ErrDecodeRequiredPointerType = xerrors.New("required pointer type value")
    18  
    19  // Wrapf wrap error for stack trace
    20  func Wrapf(err error, msg string, args ...interface{}) error {
    21  	return &wrapError{
    22  		baseError: &baseError{},
    23  		err:       xerrors.Errorf(msg, args...),
    24  		nextErr:   err,
    25  		frame:     xerrors.Caller(1),
    26  	}
    27  }
    28  
    29  // ErrSyntax create syntax error instance with message and token
    30  func ErrSyntax(msg string, tk *token.Token) *syntaxError {
    31  	return &syntaxError{
    32  		baseError: &baseError{},
    33  		msg:       msg,
    34  		token:     tk,
    35  		frame:     xerrors.Caller(1),
    36  	}
    37  }
    38  
    39  type baseError struct {
    40  	state fmt.State
    41  	verb  rune
    42  }
    43  
    44  func (e *baseError) Error() string {
    45  	return ""
    46  }
    47  
    48  func (e *baseError) chainStateAndVerb(err error) {
    49  	wrapErr, ok := err.(*wrapError)
    50  	if ok {
    51  		wrapErr.state = e.state
    52  		wrapErr.verb = e.verb
    53  	}
    54  	syntaxErr, ok := err.(*syntaxError)
    55  	if ok {
    56  		syntaxErr.state = e.state
    57  		syntaxErr.verb = e.verb
    58  	}
    59  }
    60  
    61  type wrapError struct {
    62  	*baseError
    63  	err     error
    64  	nextErr error
    65  	frame   xerrors.Frame
    66  }
    67  
    68  type myprinter struct {
    69  	xerrors.Printer
    70  	colored    bool
    71  	inclSource bool
    72  }
    73  
    74  func (e *wrapError) As(target interface{}) bool {
    75  	err := e.nextErr
    76  	for {
    77  		if wrapErr, ok := err.(*wrapError); ok {
    78  			err = wrapErr.nextErr
    79  			continue
    80  		}
    81  		break
    82  	}
    83  	return xerrors.As(err, target)
    84  }
    85  
    86  func (e *wrapError) Unwrap() error {
    87  	return e.nextErr
    88  }
    89  
    90  func (e *wrapError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
    91  	return e.FormatError(&myprinter{Printer: p, colored: colored, inclSource: inclSource})
    92  }
    93  
    94  func (e *wrapError) FormatError(p xerrors.Printer) error {
    95  	if _, ok := p.(*myprinter); !ok {
    96  		p = &myprinter{
    97  			Printer:    p,
    98  			colored:    defaultColorize,
    99  			inclSource: defaultIncludeSource,
   100  		}
   101  	}
   102  	if e.verb == 'v' && e.state.Flag('+') {
   103  		// print stack trace for debugging
   104  		p.Print(e.err, "\n")
   105  		e.frame.Format(p)
   106  		e.chainStateAndVerb(e.nextErr)
   107  		return e.nextErr
   108  	}
   109  	err := e.nextErr
   110  	for {
   111  		if wrapErr, ok := err.(*wrapError); ok {
   112  			err = wrapErr.nextErr
   113  			continue
   114  		}
   115  		break
   116  	}
   117  	e.chainStateAndVerb(err)
   118  	if fmtErr, ok := err.(xerrors.Formatter); ok {
   119  		fmtErr.FormatError(p)
   120  	} else {
   121  		p.Print(err)
   122  	}
   123  	return nil
   124  }
   125  
   126  type wrapState struct {
   127  	org fmt.State
   128  }
   129  
   130  func (s *wrapState) Write(b []byte) (n int, err error) {
   131  	return s.org.Write(b)
   132  }
   133  
   134  func (s *wrapState) Width() (wid int, ok bool) {
   135  	return s.org.Width()
   136  }
   137  
   138  func (s *wrapState) Precision() (prec int, ok bool) {
   139  	return s.org.Precision()
   140  }
   141  
   142  func (s *wrapState) Flag(c int) bool {
   143  	// set true to 'printDetail' forced because when p.Detail() is false, xerrors.Printer no output any text
   144  	if c == '#' {
   145  		// ignore '#' keyword because xerrors.FormatError doesn't set true to printDetail.
   146  		// ( see https://github.com/golang/xerrors/blob/master/adaptor.go#L39-L43 )
   147  		return false
   148  	}
   149  	return true
   150  }
   151  
   152  func (e *wrapError) Format(state fmt.State, verb rune) {
   153  	e.state = state
   154  	e.verb = verb
   155  	xerrors.FormatError(e, &wrapState{org: state}, verb)
   156  }
   157  
   158  func (e *wrapError) Error() string {
   159  	var buf bytes.Buffer
   160  	e.PrettyPrint(&Sink{&buf}, defaultColorize, defaultIncludeSource)
   161  	return buf.String()
   162  }
   163  
   164  type syntaxError struct {
   165  	*baseError
   166  	msg   string
   167  	token *token.Token
   168  	frame xerrors.Frame
   169  }
   170  
   171  func (e *syntaxError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
   172  	return e.FormatError(&myprinter{Printer: p, colored: colored, inclSource: inclSource})
   173  }
   174  
   175  func (e *syntaxError) FormatError(p xerrors.Printer) error {
   176  	var pp printer.Printer
   177  
   178  	var colored, inclSource bool
   179  	if mp, ok := p.(*myprinter); ok {
   180  		colored = mp.colored
   181  		inclSource = mp.inclSource
   182  	}
   183  
   184  	pos := fmt.Sprintf("[%d:%d] ", e.token.Position.Line, e.token.Position.Column)
   185  	msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, e.msg), colored)
   186  	if inclSource {
   187  		msg += "\n" + pp.PrintErrorToken(e.token, colored)
   188  	}
   189  	p.Print(msg)
   190  
   191  	if e.verb == 'v' && e.state.Flag('+') {
   192  		// %+v
   193  		// print stack trace for debugging
   194  		e.frame.Format(p)
   195  	}
   196  	return nil
   197  }
   198  
   199  type PrettyPrinter interface {
   200  	PrettyPrint(xerrors.Printer, bool, bool) error
   201  }
   202  type Sink struct{ *bytes.Buffer }
   203  
   204  func (es *Sink) Print(args ...interface{}) {
   205  	fmt.Fprint(es.Buffer, args...)
   206  }
   207  
   208  func (es *Sink) Printf(f string, args ...interface{}) {
   209  	fmt.Fprintf(es.Buffer, f, args...)
   210  }
   211  
   212  func (es *Sink) Detail() bool {
   213  	return false
   214  }
   215  
   216  func (e *syntaxError) Error() string {
   217  	var buf bytes.Buffer
   218  	e.PrettyPrint(&Sink{&buf}, defaultColorize, defaultIncludeSource)
   219  	return buf.String()
   220  }