Golangci-lint v2 part two (#498)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
+22
-10
@@ -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())
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user