Skip to content

Commit 50b37c1

Browse files
authored
support FormatErrorWithToken function for custom error message (#677)
1 parent 53701cc commit 50b37c1

File tree

4 files changed

+113
-11
lines changed

4 files changed

+113
-11
lines changed

error.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var (
1616
ErrInvalidCommentMapValue = errors.New("invalid comment map value. it must be not nil value")
1717
ErrDecodeRequiredPointerType = errors.New("required pointer type value")
1818
ErrExceededMaxDepth = errors.New("exceeded max depth")
19+
FormatErrorWithToken = errors.FormatError
1920
)
2021

2122
type (
@@ -25,6 +26,7 @@ type (
2526
DuplicateKeyError = errors.DuplicateKeyError
2627
UnknownFieldError = errors.UnknownFieldError
2728
UnexpectedNodeTypeError = errors.UnexpectedNodeTypeError
29+
Error = errors.Error
2830
)
2931

3032
func ErrUnsupportedHeadPositionType(node ast.Node) error {

internal/errors/error.go

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,22 @@ const (
2121
defaultIncludeSource = true
2222
)
2323

24-
type PrettyFormatError interface {
24+
type Error interface {
25+
error
26+
GetToken() *token.Token
27+
GetMessage() string
2528
FormatError(bool, bool) string
2629
}
2730

31+
var (
32+
_ Error = new(SyntaxError)
33+
_ Error = new(TypeError)
34+
_ Error = new(OverflowError)
35+
_ Error = new(DuplicateKeyError)
36+
_ Error = new(UnknownFieldError)
37+
_ Error = new(UnexpectedNodeTypeError)
38+
)
39+
2840
type SyntaxError struct {
2941
Message string
3042
Token *token.Token
@@ -109,20 +121,40 @@ func ErrUnexpectedNodeType(actual, expected ast.NodeType, tk *token.Token) *Unex
109121
}
110122
}
111123

124+
func (e *SyntaxError) GetMessage() string {
125+
return e.Message
126+
}
127+
128+
func (e *SyntaxError) GetToken() *token.Token {
129+
return e.Token
130+
}
131+
112132
func (e *SyntaxError) Error() string {
113133
return e.FormatError(defaultFormatColor, defaultIncludeSource)
114134
}
115135

116136
func (e *SyntaxError) FormatError(colored, inclSource bool) string {
117-
return formatError(e.Message, e.Token, colored, inclSource)
137+
return FormatError(e.Message, e.Token, colored, inclSource)
138+
}
139+
140+
func (e *OverflowError) GetMessage() string {
141+
return e.msg()
142+
}
143+
144+
func (e *OverflowError) GetToken() *token.Token {
145+
return e.Token
118146
}
119147

120148
func (e *OverflowError) Error() string {
121149
return e.FormatError(defaultFormatColor, defaultIncludeSource)
122150
}
123151

124152
func (e *OverflowError) FormatError(colored, inclSource bool) string {
125-
return formatError(fmt.Sprintf("cannot unmarshal %s into Go value of type %s ( overflow )", e.SrcNum, e.DstType), e.Token, colored, inclSource)
153+
return FormatError(e.msg(), e.Token, colored, inclSource)
154+
}
155+
156+
func (e *OverflowError) msg() string {
157+
return fmt.Sprintf("cannot unmarshal %s into Go value of type %s ( overflow )", e.SrcNum, e.DstType)
126158
}
127159

128160
func (e *TypeError) msg() string {
@@ -132,39 +164,75 @@ func (e *TypeError) msg() string {
132164
return fmt.Sprintf("cannot unmarshal %s into Go value of type %s", e.SrcType, e.DstType)
133165
}
134166

167+
func (e *TypeError) GetMessage() string {
168+
return e.msg()
169+
}
170+
171+
func (e *TypeError) GetToken() *token.Token {
172+
return e.Token
173+
}
174+
135175
func (e *TypeError) Error() string {
136176
return e.FormatError(defaultFormatColor, defaultIncludeSource)
137177
}
138178

139179
func (e *TypeError) FormatError(colored, inclSource bool) string {
140-
return formatError(e.msg(), e.Token, colored, inclSource)
180+
return FormatError(e.msg(), e.Token, colored, inclSource)
181+
}
182+
183+
func (e *DuplicateKeyError) GetMessage() string {
184+
return e.Message
185+
}
186+
187+
func (e *DuplicateKeyError) GetToken() *token.Token {
188+
return e.Token
141189
}
142190

143191
func (e *DuplicateKeyError) Error() string {
144192
return e.FormatError(defaultFormatColor, defaultIncludeSource)
145193
}
146194

147195
func (e *DuplicateKeyError) FormatError(colored, inclSource bool) string {
148-
return formatError(e.Message, e.Token, colored, inclSource)
196+
return FormatError(e.Message, e.Token, colored, inclSource)
197+
}
198+
199+
func (e *UnknownFieldError) GetMessage() string {
200+
return e.Message
201+
}
202+
203+
func (e *UnknownFieldError) GetToken() *token.Token {
204+
return e.Token
149205
}
150206

151207
func (e *UnknownFieldError) Error() string {
152208
return e.FormatError(defaultFormatColor, defaultIncludeSource)
153209
}
154210

155211
func (e *UnknownFieldError) FormatError(colored, inclSource bool) string {
156-
return formatError(e.Message, e.Token, colored, inclSource)
212+
return FormatError(e.Message, e.Token, colored, inclSource)
213+
}
214+
215+
func (e *UnexpectedNodeTypeError) GetMessage() string {
216+
return e.msg()
217+
}
218+
219+
func (e *UnexpectedNodeTypeError) GetToken() *token.Token {
220+
return e.Token
157221
}
158222

159223
func (e *UnexpectedNodeTypeError) Error() string {
160224
return e.FormatError(defaultFormatColor, defaultIncludeSource)
161225
}
162226

163227
func (e *UnexpectedNodeTypeError) FormatError(colored, inclSource bool) string {
164-
return formatError(fmt.Sprintf("%s was used where %s is expected", e.Actual.YAMLName(), e.Expected.YAMLName()), e.Token, colored, inclSource)
228+
return FormatError(e.msg(), e.Token, colored, inclSource)
229+
}
230+
231+
func (e *UnexpectedNodeTypeError) msg() string {
232+
return fmt.Sprintf("%s was used where %s is expected", e.Actual.YAMLName(), e.Expected.YAMLName())
165233
}
166234

167-
func formatError(errMsg string, token *token.Token, colored, inclSource bool) string {
235+
func FormatError(errMsg string, token *token.Token, colored, inclSource bool) string {
168236
var pp printer.Printer
169237
pos := fmt.Sprintf("[%d:%d] ", token.Position.Line, token.Position.Column)
170238
msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, errMsg), colored)

yaml.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,9 @@ func NodeToValue(node ast.Node, v interface{}, opts ...DecodeOption) error {
222222
// If the third argument `inclSource` is true, the error message will
223223
// contain snippets of the YAML source that was used.
224224
func FormatError(e error, colored, inclSource bool) string {
225-
var pe errors.PrettyFormatError
226-
if errors.As(e, &pe) {
227-
return pe.FormatError(colored, inclSource)
225+
var yamlErr Error
226+
if errors.As(e, &yamlErr) {
227+
return yamlErr.FormatError(colored, inclSource)
228228
}
229229

230230
return e.Error()

yaml_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99

1010
"github.com/goccy/go-yaml"
11+
"github.com/goccy/go-yaml/parser"
1112
)
1213

1314
func TestRoundTripWithComment(t *testing.T) {
@@ -229,3 +230,34 @@ i:
229230
t.Fatalf("failed to encode: %s", string(got))
230231
}
231232
}
233+
234+
func TestCustomErrorMessage(t *testing.T) {
235+
data := `
236+
foo:
237+
bar:
238+
foo: 2
239+
baz:
240+
foo: 3
241+
foo: 2
242+
`
243+
if _, err := parser.ParseBytes([]byte(data), 0); err == nil {
244+
t.Fatalf("expected error")
245+
} else {
246+
yamlErr, ok := err.(yaml.Error)
247+
if !ok {
248+
t.Fatalf("failed to get yaml.Error from error: %T", err)
249+
}
250+
expected := `
251+
[7:1] custom message
252+
4 | foo: 2
253+
5 | baz:
254+
6 | foo: 3
255+
> 7 | foo: 2
256+
^
257+
`
258+
got := "\n" + yaml.FormatErrorWithToken("custom message", yamlErr.GetToken(), false, true)
259+
if expected != got {
260+
t.Fatalf("unexpected error message:\nexpected:\n%s\nbut got:\n%s", expected, got)
261+
}
262+
}
263+
}

0 commit comments

Comments
 (0)