| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | package errors | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/goccy/go-yaml/printer" | 
					
						
							|  |  |  | 	"github.com/goccy/go-yaml/token" | 
					
						
							|  |  |  | 	"golang.org/x/xerrors" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2019-10-23 13:32:30 +09:00
										 |  |  | 	// ColoredErr error with syntax highlight | 
					
						
							|  |  |  | 	ColoredErr = true | 
					
						
							|  |  |  | 	// WithSourceCode error with source code | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 	WithSourceCode = true | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:32:30 +09:00
										 |  |  | // Wrapf wrap error for stack trace | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func Wrapf(err error, msg string, args ...interface{}) error { | 
					
						
							|  |  |  | 	return &wrapError{ | 
					
						
							|  |  |  | 		baseError: &baseError{}, | 
					
						
							|  |  |  | 		err:       xerrors.Errorf(msg, args...), | 
					
						
							|  |  |  | 		nextErr:   err, | 
					
						
							|  |  |  | 		frame:     xerrors.Caller(1), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:32:30 +09:00
										 |  |  | // ErrSyntax create syntax error instance with message and token | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func ErrSyntax(msg string, tk *token.Token) *syntaxError { | 
					
						
							|  |  |  | 	return &syntaxError{ | 
					
						
							|  |  |  | 		baseError: &baseError{}, | 
					
						
							|  |  |  | 		Msg:       msg, | 
					
						
							|  |  |  | 		Token:     tk, | 
					
						
							|  |  |  | 		frame:     xerrors.Caller(1), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type baseError struct { | 
					
						
							|  |  |  | 	state fmt.State | 
					
						
							|  |  |  | 	verb  rune | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *baseError) Error() string { | 
					
						
							|  |  |  | 	return "" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *baseError) chainStateAndVerb(err error) { | 
					
						
							|  |  |  | 	wrapErr, ok := err.(*wrapError) | 
					
						
							|  |  |  | 	if ok { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 		wrapErr.state = e.state | 
					
						
							|  |  |  | 		wrapErr.verb = e.verb | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	syntaxErr, ok := err.(*syntaxError) | 
					
						
							|  |  |  | 	if ok { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 		syntaxErr.state = e.state | 
					
						
							|  |  |  | 		syntaxErr.verb = e.verb | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | type wrapError struct { | 
					
						
							|  |  |  | 	*baseError | 
					
						
							|  |  |  | 	err     error | 
					
						
							|  |  |  | 	nextErr error | 
					
						
							|  |  |  | 	frame   xerrors.Frame | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *wrapError) FormatError(p xerrors.Printer) error { | 
					
						
							|  |  |  | 	if e.verb == 'v' && e.state.Flag('+') { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 		// print stack trace for debugging | 
					
						
							|  |  |  | 		p.Print(e.err, "\n") | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 		e.frame.Format(p) | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 		e.chainStateAndVerb(e.nextErr) | 
					
						
							|  |  |  | 		return e.nextErr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err := e.nextErr | 
					
						
							|  |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 		if wrapErr, ok := err.(*wrapError); ok { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 			err = wrapErr.nextErr | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		break | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 	if ColoredErr { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 		var yp printer.Printer | 
					
						
							|  |  |  | 		p.Print(yp.PrintErrorMessage("syntax error: ", ColoredErr)) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		p.Print("syntax error: ") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	e.chainStateAndVerb(err) | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 	err.(xerrors.Formatter).FormatError(p) | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | type wrapState struct { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	org fmt.State | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func (s *wrapState) Write(b []byte) (n int, err error) { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	return s.org.Write(b) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func (s *wrapState) Width() (wid int, ok bool) { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	return s.org.Width() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func (s *wrapState) Precision() (prec int, ok bool) { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	return s.org.Precision() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func (s *wrapState) Flag(c int) bool { | 
					
						
							|  |  |  | 	// set true to 'printDetail' forced because when p.Detail() is false, xerrors.Printer no output any text | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	if c == '#' { | 
					
						
							|  |  |  | 		// ignore '#' keyword because xerrors.FormatError doesn't set true to printDetail. | 
					
						
							|  |  |  | 		// ( see https://github.com/golang/xerrors/blob/master/adaptor.go#L39-L43 ) | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 	return true | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func (e *wrapError) Format(state fmt.State, verb rune) { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	e.state = state | 
					
						
							|  |  |  | 	e.verb = verb | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 	xerrors.FormatError(e, &wrapState{org: state}, verb) | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func (e *wrapError) Error() string { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	return e.err.Error() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | type syntaxError struct { | 
					
						
							|  |  |  | 	*baseError | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	Msg   string | 
					
						
							|  |  |  | 	Token *token.Token | 
					
						
							|  |  |  | 	frame xerrors.Frame | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func (e *syntaxError) FormatError(p xerrors.Printer) error { | 
					
						
							|  |  |  | 	if e.verb == 'v' && e.state.Flag('+') { | 
					
						
							|  |  |  | 		// %+v | 
					
						
							|  |  |  | 		// print stack trace for debugging | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 		p.Print(e.Error()) | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 		e.frame.Format(p) | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 		p.Print(e.Error()) | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | func (e *syntaxError) Error() string { | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | 	var p printer.Printer | 
					
						
							| 
									
										
										
										
											2019-10-23 13:30:22 +09:00
										 |  |  | 	pos := fmt.Sprintf("[%d:%d] ", e.Token.Position.Line, e.Token.Position.Column) | 
					
						
							|  |  |  | 	msg := p.PrintErrorMessage(fmt.Sprintf("%s%s", pos, e.Msg), ColoredErr) | 
					
						
							|  |  |  | 	if WithSourceCode { | 
					
						
							|  |  |  | 		err := p.PrintErrorToken(e.Token, ColoredErr) | 
					
						
							|  |  |  | 		return fmt.Sprintf("%s\n%s", msg, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return msg | 
					
						
							| 
									
										
										
										
											2019-10-23 03:21:42 +09:00
										 |  |  | } |