error.go raw

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