
lll is using scanner.Scan() to read the file line by line. scanner.Scan() might fail if the line is longer than bufio.MaxScanTokenSize In the case where the specified maxLineLen is smaller than bufio.MaxScanTokenSize we can return this line as a long line instead of returning an error. The reason for this change is that this case might happen with autogenerated files The go-bindata tool for instance might generate a file with a very long line. In this case, as it's a auto generated file, the warning returned by lll will be ignored. But if we return a linter error here, and this error happens for an autogenerated file the error will be discarded (fine), but all the subsequent errors for lll will be discarded for other files and we'll miss legit error.
97 lines
2.7 KiB
Go
97 lines
2.7 KiB
Go
package golinters
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"fmt"
|
|
"go/token"
|
|
"os"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
|
"github.com/golangci/golangci-lint/pkg/result"
|
|
)
|
|
|
|
type Lll struct{}
|
|
|
|
func (Lll) Name() string {
|
|
return "lll"
|
|
}
|
|
|
|
func (Lll) Desc() string {
|
|
return "Reports long lines"
|
|
}
|
|
|
|
func (lint Lll) getIssuesForFile(filename string, maxLineLen int, tabSpaces string) ([]result.Issue, error) {
|
|
var res []result.Issue
|
|
|
|
f, err := os.Open(filename)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("can't open file %s: %s", filename, err)
|
|
}
|
|
defer f.Close()
|
|
|
|
lineNumber := 1
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
line = strings.Replace(line, "\t", tabSpaces, -1)
|
|
lineLen := utf8.RuneCountInString(line)
|
|
if lineLen > maxLineLen {
|
|
res = append(res, result.Issue{
|
|
Pos: token.Position{
|
|
Filename: filename,
|
|
Line: lineNumber,
|
|
Column: 1,
|
|
},
|
|
Text: fmt.Sprintf("line is %d characters", lineLen),
|
|
FromLinter: lint.Name(),
|
|
})
|
|
}
|
|
lineNumber++
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
if err == bufio.ErrTooLong && maxLineLen < bufio.MaxScanTokenSize {
|
|
// scanner.Scan() might fail if the line is longer than bufio.MaxScanTokenSize
|
|
// In the case where the specified maxLineLen is smaller than bufio.MaxScanTokenSize
|
|
// we can return this line as a long line instead of returning an error.
|
|
// The reason for this change is that this case might happen with autogenerated files
|
|
// The go-bindata tool for instance might generate a file with a very long line.
|
|
// In this case, as it's a auto generated file, the warning returned by lll will
|
|
// be ignored.
|
|
// But if we return a linter error here, and this error happens for an autogenerated
|
|
// file the error will be discarded (fine), but all the subsequent errors for lll will
|
|
// be discarded for other files and we'll miss legit error.
|
|
res = append(res, result.Issue{
|
|
Pos: token.Position{
|
|
Filename: filename,
|
|
Line: lineNumber,
|
|
Column: 1,
|
|
},
|
|
Text: fmt.Sprintf("line is more than %d characters", bufio.MaxScanTokenSize),
|
|
FromLinter: lint.Name(),
|
|
})
|
|
} else {
|
|
return nil, fmt.Errorf("can't scan file %s: %s", filename, err)
|
|
}
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func (lint Lll) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) {
|
|
var res []result.Issue
|
|
spaces := strings.Repeat(" ", lintCtx.Settings().Lll.TabWidth)
|
|
for _, f := range lintCtx.PkgProgram.Files(lintCtx.Cfg.Run.AnalyzeTests) {
|
|
issues, err := lint.getIssuesForFile(f, lintCtx.Settings().Lll.LineLength, spaces)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res = append(res, issues...)
|
|
}
|
|
|
|
return res, nil
|
|
}
|