From 59cddbc57398aa61ae6a53a086628468b4b7c10e Mon Sep 17 00:00:00 2001 From: Vincent Serpoul Date: Thu, 15 Apr 2021 22:29:46 +0800 Subject: [PATCH] Golangci-lint v2 part two (#498) --- errors.go | 94 +++++++++++++++++++++++++++++++++++--------------- errors_test.go | 32 +++++++++++------ 2 files changed, 88 insertions(+), 38 deletions(-) diff --git a/errors.go b/errors.go index 79b59bb..35ecc05 100644 --- a/errors.go +++ b/errors.go @@ -50,7 +50,7 @@ func (e *DecodeError) String() string { return e.human } -/// Position returns the (line, column) pair indicating where the error +// Position returns the (line, column) pair indicating where the error // occurred in the document. Positions are 1-indexed. func (e *DecodeError) Position() (row int, column int) { return e.line, e.column @@ -63,110 +63,147 @@ func (e *DecodeError) Position() (row int, column int) { // // The function copies all bytes used in DecodeError, so that document and // highlight can be freely deallocated. +//nolint:funlen func wrapDecodeError(document []byte, de *decodeError) error { if de == nil { return nil } - err := &DecodeError{ - message: de.message, - } offset := unsafe.SubsliceOffset(document, de.highlight) - err.line, err.column = positionAtEnd(document[:offset]) + errMessage := de.message + errLine, errColumn := positionAtEnd(document[:offset]) before, after := linesOfContext(document, de.highlight, offset, 3) var buf strings.Builder - maxLine := err.line + len(after) - 1 + maxLine := errLine + len(after) - 1 lineColumnWidth := len(strconv.Itoa(maxLine)) for i := len(before) - 1; i > 0; i-- { - line := err.line - i + line := errLine - i buf.WriteString(formatLineNumber(line, lineColumnWidth)) - buf.WriteString("| ") - buf.Write(before[i]) + buf.WriteString("|") + + if len(before[i]) > 0 { + buf.WriteString(" ") + buf.Write(before[i]) + } + buf.WriteRune('\n') } - buf.WriteString(formatLineNumber(err.line, lineColumnWidth)) + buf.WriteString(formatLineNumber(errLine, lineColumnWidth)) buf.WriteString("| ") if len(before) > 0 { buf.Write(before[0]) } + buf.Write(de.highlight) + if len(after) > 0 { buf.Write(after[0]) } + buf.WriteRune('\n') buf.WriteString(strings.Repeat(" ", lineColumnWidth)) buf.WriteString("| ") + if len(before) > 0 { buf.WriteString(strings.Repeat(" ", len(before[0]))) } + buf.WriteString(strings.Repeat("~", len(de.highlight))) - buf.WriteString(" ") - buf.WriteString(err.message) + + if len(errMessage) > 0 { + buf.WriteString(" ") + buf.WriteString(errMessage) + } for i := 1; i < len(after); i++ { buf.WriteRune('\n') - line := err.line + i + line := errLine + i buf.WriteString(formatLineNumber(line, lineColumnWidth)) - buf.WriteString("| ") - buf.Write(after[i]) + buf.WriteString("|") + + if len(after[i]) > 0 { + buf.WriteString(" ") + buf.Write(after[i]) + } } - err.human = buf.String() - return err + return &DecodeError{ + message: errMessage, + line: errLine, + column: errColumn, + human: buf.String(), + } } func formatLineNumber(line int, width int) string { format := "%" + strconv.Itoa(width) + "d" + return fmt.Sprintf(format, line) } func linesOfContext(document []byte, highlight []byte, offset int, linesAround int) ([][]byte, [][]byte) { + return beforeLines(document, offset, linesAround), afterLines(document, highlight, offset, linesAround) +} + +func beforeLines(document []byte, offset int, linesAround int) [][]byte { var beforeLines [][]byte - // Walk the document in reverse from the highlight to find previous lines + // Walk the document backward from the highlight to find previous lines // of context. rest := document[:offset] +backward: for o := len(rest) - 1; o >= 0 && len(beforeLines) <= linesAround && len(rest) > 0; { - if rest[o] == '\n' { + switch { + case rest[o] == '\n': // handle individual lines beforeLines = append(beforeLines, rest[o+1:]) rest = rest[:o] o = len(rest) - 1 - } else if o == 0 { + case o == 0: // add the first line only if it's non-empty beforeLines = append(beforeLines, rest) - break - } else { + + break backward + default: o-- } } + return beforeLines +} + +func afterLines(document []byte, highlight []byte, offset int, linesAround int) [][]byte { var afterLines [][]byte // Walk the document forward from the highlight to find the following // lines of context. - rest = document[offset+len(highlight):] + rest := document[offset+len(highlight):] +forward: for o := 0; o < len(rest) && len(afterLines) <= linesAround; { - if rest[o] == '\n' { + switch { + case rest[o] == '\n': // handle individual lines afterLines = append(afterLines, rest[:o]) rest = rest[o+1:] o = 0 - } else if o == len(rest)-1 && o > 0 { + + case o == len(rest)-1 && o > 0: // add last line only if it's non-empty afterLines = append(afterLines, rest) - break - } else { + + break forward + default: o++ } } - return beforeLines, afterLines + + return afterLines } func positionAtEnd(b []byte) (row int, column int) { @@ -181,5 +218,6 @@ func positionAtEnd(b []byte) (row int, column int) { column++ } } + return } diff --git a/errors_test.go b/errors_test.go index 6f49d56..efbb59a 100644 --- a/errors_test.go +++ b/errors_test.go @@ -2,13 +2,17 @@ package toml import ( "bytes" + "errors" "strings" "testing" "github.com/stretchr/testify/assert" ) +//nolint:funlen func TestDecodeError(t *testing.T) { + t.Parallel() + examples := []struct { desc string doc [3]string @@ -103,7 +107,7 @@ should not be seen4`}, }, { desc: "last line of more than 10", - doc: [3]string{`should not be seen + doc: [3]string{`should not be seen should not be seen should not be seen should not be seen @@ -125,7 +129,8 @@ before `, "highlighted", ``}, }, { desc: "handle empty lines in the before/after blocks", - doc: [3]string{`line1 + doc: [3]string{ + `line1 line 2 before `, "highlighted", ` after @@ -134,21 +139,21 @@ line 3 line 4 line 5`, }, - expected: ` -1| line1 -2| + expected: `1| line1 +2| 3| line 2 4| before highlighted after - | ~~~~~~~~~~~ + | ~~~~~~~~~~~ 5| line 3 -6| -7| line 4 -`, +6| +7| line 4`, }, } for _, e := range examples { + e := e t.Run(e.desc, func(t *testing.T) { + t.Parallel() b := bytes.Buffer{} b.Write([]byte(e.doc[0])) start := b.Len() @@ -162,7 +167,14 @@ line 5`, highlight: hl, message: e.msg, }) - derr := err.(*DecodeError) + + var derr *DecodeError + if !errors.As(err, &derr) { + t.Errorf("error not in expected format") + + return + } + assert.Equal(t, strings.Trim(e.expected, "\n"), derr.String()) }) }