Skip to content

Commit 56f8b29

Browse files
authored
Refactor overflowError to be pretty-printable (#470)
When trying to yaml.Unmarshal a negative number into an uint, the resulting error indicates an overflow with type information, but without the position. For example: > cannot unmarshal -23 into Go value of type uint64 ( overflow ) From an end user's perspective reading an error for an invalid YAML, this is quite unintuitive. Especially compared to the error message when trying to unmarshal a string into an uint. > [1:4] cannot unmarshal string into Go struct field Foo.A of type uint64 > > 1 | a: 'foo' > ^ This change has moved overflowError to internal.errors.overflowError, implementing both the PrettyPrinter and Formatter. Its implementation is uniform with those of the syntaxError and TypeError. Thus, the error from above now looks like: > [1:4] cannot unmarshal -23 into Go value of type uint64 ( overflow ) > > 1 | a: -23 > ^
1 parent 248a29c commit 56f8b29

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

decode.go

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -515,19 +515,6 @@ func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node)
515515
return v.Convert(typ), nil
516516
}
517517

518-
type overflowError struct {
519-
dstType reflect.Type
520-
srcNum string
521-
}
522-
523-
func (e *overflowError) Error() string {
524-
return fmt.Sprintf("cannot unmarshal %s into Go value of type %s ( overflow )", e.srcNum, e.dstType)
525-
}
526-
527-
func errOverflow(dstType reflect.Type, num string) *overflowError {
528-
return &overflowError{dstType: dstType, srcNum: num}
529-
}
530-
531518
func errTypeMismatch(dstType, srcType reflect.Type, token *token.Token) *errors.TypeError {
532519
return &errors.TypeError{DstType: dstType, SrcType: srcType, Token: token}
533520
}
@@ -895,7 +882,7 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No
895882
default:
896883
return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken())
897884
}
898-
return errOverflow(valueType, fmt.Sprint(v))
885+
return errors.ErrOverflow(valueType, fmt.Sprint(v), src.GetToken())
899886
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
900887
v := d.nodeToValue(src)
901888
switch vv := v.(type) {
@@ -927,7 +914,7 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No
927914
default:
928915
return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken())
929916
}
930-
return errOverflow(valueType, fmt.Sprint(v))
917+
return errors.ErrOverflow(valueType, fmt.Sprint(v), src.GetToken())
931918
}
932919
v := reflect.ValueOf(d.nodeToValue(src))
933920
if v.IsValid() {

internal/errors/error.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ func ErrSyntax(msg string, tk *token.Token) *syntaxError {
4040
}
4141
}
4242

43+
// ErrOverflow creates an overflow error instance with message and a token.
44+
func ErrOverflow(dstType reflect.Type, num string, tk *token.Token) *overflowError {
45+
return &overflowError{dstType: dstType, srcNum: num, token: tk}
46+
}
47+
4348
type baseError struct {
4449
state fmt.State
4550
verb rune
@@ -166,6 +171,39 @@ func (e *wrapError) Error() string {
166171
return buf.String()
167172
}
168173

174+
type overflowError struct {
175+
dstType reflect.Type
176+
srcNum string
177+
token *token.Token
178+
}
179+
180+
func (e *overflowError) Error() string {
181+
return fmt.Sprintf("cannot unmarshal %s into Go value of type %s ( overflow )", e.srcNum, e.dstType)
182+
}
183+
184+
func (e *overflowError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
185+
return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource})
186+
}
187+
188+
func (e *overflowError) FormatError(p xerrors.Printer) error {
189+
var pp printer.Printer
190+
191+
var colored, inclSource bool
192+
if fep, ok := p.(*FormatErrorPrinter); ok {
193+
colored = fep.Colored
194+
inclSource = fep.InclSource
195+
}
196+
197+
pos := fmt.Sprintf("[%d:%d] ", e.token.Position.Line, e.token.Position.Column)
198+
msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, e.Error()), colored)
199+
if inclSource {
200+
msg += "\n" + pp.PrintErrorToken(e.token, colored)
201+
}
202+
p.Print(msg)
203+
204+
return nil
205+
}
206+
169207
type syntaxError struct {
170208
*baseError
171209
msg string

0 commit comments

Comments
 (0)