diff --git a/error.go b/error.go index 3be8b302..3c24fea9 100644 --- a/error.go +++ b/error.go @@ -63,28 +63,40 @@ func IsInvalidAliasNameError(err error) bool { return xerrors.Is(err, ast.ErrInvalidAliasName) } -// SyntaxError represents an syntax error associated with a specific [token.Token]. -type SyntaxError struct { - Msg string +// TokenScopedError represents an error associated with a specific [token.Token]. +type TokenScopedError struct { + // Msg is the underlying error message. + Msg string + // Token is the [token.Token] associated with this error. Token *token.Token - - err *errors.SyntaxError + // err is the underlying, unwraped error. + err error } // Error implements the error interface. -func (s SyntaxError) Error() string { +// It returns the unwraped error returned by go-yaml. +func (s TokenScopedError) Error() string { return s.err.Error() } -// AsSyntaxError checks if error was a syntax error and returns it if so. +// AsTokenScopedError checks if the error is associated with a specific token. +// If so, it returns // Otherwise, it returns nil. -func AsSyntaxError(err error) *SyntaxError { +func AsTokenScopedError(err error) *TokenScopedError { var syntaxError *errors.SyntaxError if xerrors.As(err, &syntaxError) { - return &SyntaxError{ + return &TokenScopedError{ Msg: syntaxError.GetMessage(), Token: syntaxError.GetToken(), - err: syntaxError, + err: err, + } + } + var typeError *errors.TypeError + if xerrors.As(err, &typeError) { + return &TokenScopedError{ + Msg: typeError.Error(), + Token: typeError.Token, + err: err, } } return nil diff --git a/error_test.go b/error_test.go index d06dca7a..35abcb1e 100644 --- a/error_test.go +++ b/error_test.go @@ -1,6 +1,7 @@ package yaml import ( + "reflect" "testing" "github.com/goccy/go-yaml/internal/errors" @@ -11,7 +12,7 @@ import ( func TestAsSyntaxError(t *testing.T) { tests := []struct { input error - expected *SyntaxError + expected *TokenScopedError }{ { input: nil, @@ -23,7 +24,7 @@ func TestAsSyntaxError(t *testing.T) { }, { input: errors.ErrSyntax("some error", &token.Token{Value: "123"}), - expected: &SyntaxError{ + expected: &TokenScopedError{ Msg: "some error", Token: &token.Token{Value: "123"}, }, @@ -32,21 +33,35 @@ func TestAsSyntaxError(t *testing.T) { input: xerrors.Errorf( "something went wrong: %w", errors.ErrSyntax("some error", &token.Token{Value: "123"})), - expected: &SyntaxError{ + expected: &TokenScopedError{ Msg: "some error", Token: &token.Token{Value: "123"}, }, }, { input: errUnknownField("unknown field", &token.Token{Value: "123"}), - expected: &SyntaxError{ + expected: &TokenScopedError{ Msg: "unknown field", Token: &token.Token{Value: "123"}, }, }, + { + input: errDuplicateKey("duplicate key", &token.Token{Value: "123"}), + expected: &TokenScopedError{ + Msg: "duplicate key", + Token: &token.Token{Value: "123"}, + }, + }, + { + input: errTypeMismatch(reflect.TypeOf("string"), reflect.TypeOf(0), &token.Token{Value: "123"}), + expected: &TokenScopedError{ + Msg: "cannot unmarshal int into Go value of type string", + Token: &token.Token{Value: "123"}, + }, + }, } for _, test := range tests { - syntaxErr := AsSyntaxError(test.input) + syntaxErr := AsTokenScopedError(test.input) if test.expected == nil { if syntaxErr != nil { t.Fatalf("wanted nil, but go %v", syntaxErr) @@ -56,7 +71,7 @@ func TestAsSyntaxError(t *testing.T) { if syntaxErr == nil { t.Fatalf("must not be nil") } - if *test.expected.Token != *syntaxErr.Token && test.expected.Msg != syntaxErr.Msg { + if *test.expected.Token != *syntaxErr.Token || test.expected.Msg != syntaxErr.Msg { t.Fatalf("unexpected output.\nexpect:\n[%v]\nactual:\n[%v]", test.expected, syntaxErr) } }