diff --git a/errors.go b/errors.go index a00924b5..d9a6ee76 100644 --- a/errors.go +++ b/errors.go @@ -116,6 +116,7 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError { maxLine := errLine + len(after) - 1 lineColumnWidth := len(strconv.Itoa(maxLine)) + // Write the lines of context strictly before the error. for i := len(before) - 1; i > 0; i-- { line := errLine - i buf.WriteString(formatLineNumber(line, lineColumnWidth)) @@ -129,6 +130,8 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError { buf.WriteRune('\n') } + // Write the document line that contains the error. + buf.WriteString(formatLineNumber(errLine, lineColumnWidth)) buf.WriteString("| ") @@ -143,6 +146,10 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError { } buf.WriteRune('\n') + + // Write the line with the error message itself (so it does not have a line + // number). + buf.WriteString(strings.Repeat(" ", lineColumnWidth)) buf.WriteString("| ") @@ -157,6 +164,8 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError { buf.WriteString(errMessage) } + // Write the lines of context strictly after the error. + for i := 1; i < len(after); i++ { buf.WriteRune('\n') line := errLine + i @@ -230,7 +239,7 @@ forward: rest = rest[o+1:] o = 0 - case o == len(rest)-1 && o > 0: + case o == len(rest)-1: // add last line only if it's non-empty afterLines = append(afterLines, rest) diff --git a/errors_test.go b/errors_test.go index d0986478..1c02595f 100644 --- a/errors_test.go +++ b/errors_test.go @@ -148,6 +148,13 @@ line 5`, 6| 7| line 4`, }, + { + desc: "handle remainder of the error line when there is only one line", + doc: [3]string{`P=`, `[`, `#`}, + msg: "array is incomplete", + expected: `1| P=[# + | ~ array is incomplete`, + }, } for _, e := range examples { diff --git a/parser.go b/parser.go index 1781cc94..a53c2b7b 100644 --- a/parser.go +++ b/parser.go @@ -397,6 +397,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) { // array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ] // array-sep = %x2C ; , Comma // ws-comment-newline = *( wschar / [ comment ] newline ) + arrayStart := b b = b[1:] parent := p.builder.Push(ast.Node{ @@ -415,7 +416,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) { } if len(b) == 0 { - return parent, nil, newDecodeError(b, "array is incomplete") + return parent, nil, newDecodeError(arrayStart[:1], "array is incomplete") } if b[0] == ']' { diff --git a/unmarshaler_test.go b/unmarshaler_test.go index 008dfda3..25484c2c 100644 --- a/unmarshaler_test.go +++ b/unmarshaler_test.go @@ -1728,6 +1728,12 @@ func TestIssue579(t *testing.T) { require.Error(t, err) } +func TestIssue581(t *testing.T) { + var v interface{} + err := toml.Unmarshal([]byte(`P=[#`), &v) + require.Error(t, err) +} + //nolint:funlen func TestUnmarshalDecodeErrors(t *testing.T) { examples := []struct {