Skip to content

Commit 07ddc54

Browse files
committed
another group of fixes after running on golang source code
1 parent d993d3a commit 07ddc54

File tree

8 files changed

+152
-13
lines changed

8 files changed

+152
-13
lines changed

internal/commands/run.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ func (e *Executor) initRun() {
8686
fmt.Sprintf("Use or not use default excludes: (%s)", strings.Join(config.DefaultExcludePatterns, "|")))
8787

8888
runCmd.Flags().IntVar(&rc.MaxIssuesPerLinter, "max-issues-per-linter", 50, "Maximum issues count per one linter. Set to 0 to disable")
89+
runCmd.Flags().IntVar(&rc.MaxSameIssues, "max-same-issues", 3, "Maximum count of issues with the same text. Set to 0 to disable")
8990

9091
runCmd.Flags().BoolVarP(&rc.Diff, "new", "n", false, "Show only new issues: if there are unstaged changes or untracked files, only those changes are shown, else only changes in HEAD~ are shown")
9192
runCmd.Flags().StringVar(&rc.DiffFromRevision, "new-from-rev", "", "Show only new issues created after git revision `REV`")
@@ -225,6 +226,7 @@ func (e *Executor) runAnalysis(ctx context.Context, args []string) (chan result.
225226
processors.NewDiff(e.cfg.Run.Diff, e.cfg.Run.DiffFromRevision, e.cfg.Run.DiffPatchFilePath),
226227
processors.NewMaxPerFileFromLinter(),
227228
processors.NewMaxFromLinter(e.cfg.Run.MaxIssuesPerLinter),
229+
processors.NewMaxSameIssues(e.cfg.Run.MaxSameIssues),
228230
processors.NewPathPrettifier(),
229231
},
230232
}

pkg/config/config.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,21 @@ const (
1515
var OutFormats = []string{OutFormatColoredLineNumber, OutFormatLineNumber, OutFormatJSON}
1616

1717
var DefaultExcludePatterns = []string{
18-
"Error return value of `(os\\.Std(out|err)\\.Write|.*\\.Close)` is not checked",
18+
// errcheck
19+
"Error return value of .(os\\.Std(out|err)\\.*|.*\\.Close|std(out|err)\\..*|os\\.Remove(All)?|.*[pP]rintf?). is not checked",
20+
21+
// golint
1922
"should have comment",
2023
"comment on exported method",
21-
"G104", // disable what errcheck does: it reports on Close etc
22-
"G204", // Subprocess launching should be audited: too lot false positives
23-
"G304", // Potential file inclusion via variable: `src, err := ioutil.ReadFile(filename)`
24+
25+
// gas
26+
"G103:", // Use of unsafe calls should be audited
27+
"G104:", // disable what errcheck does: it reports on Close etc
28+
"G204:", // Subprocess launching should be audited: too lot false positives
29+
"G304:", // Potential file inclusion via variable: `src, err := ioutil.ReadFile(filename)`
30+
31+
// govet
32+
"possible misuse of unsafe.Pointer",
2433
}
2534

2635
type Common struct {
@@ -92,6 +101,7 @@ type Run struct { // nolint:maligned
92101
Deadline time.Duration
93102

94103
MaxIssuesPerLinter int
104+
MaxSameIssues int
95105

96106
DiffFromRevision string
97107
DiffPatchFilePath string

pkg/printers/text.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ func (p Text) Print(issues chan result.Issue) (bool, error) {
7575

7676
lineRange := i.GetLineRange()
7777
for line := lineRange.From; line <= lineRange.To; line++ {
78+
if line == 0 { // some linters, e.g. gas can do it: it really means first line
79+
line = 1
80+
}
81+
7882
zeroIndexedLine := line - 1
7983
if zeroIndexedLine >= len(fc) {
8084
logrus.Warnf("No line %d in file %s", line, i.FilePath())
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package processors
2+
3+
import (
4+
"github.com/golangci/golangci-lint/pkg/result"
5+
"github.com/sirupsen/logrus"
6+
)
7+
8+
type textToCountMap map[string]int
9+
10+
type MaxSameIssues struct {
11+
tc textToCountMap
12+
limit int
13+
}
14+
15+
var _ Processor = &MaxSameIssues{}
16+
17+
func NewMaxSameIssues(limit int) *MaxSameIssues {
18+
return &MaxSameIssues{
19+
tc: textToCountMap{},
20+
limit: limit,
21+
}
22+
}
23+
24+
func (MaxSameIssues) Name() string {
25+
return "max_same_issues"
26+
}
27+
28+
func (p *MaxSameIssues) Process(issues []result.Issue) ([]result.Issue, error) {
29+
if p.limit <= 0 { // no limit
30+
return issues, nil
31+
}
32+
33+
return filterIssues(issues, func(i *result.Issue) bool {
34+
p.tc[i.Text]++ // always inc for stat
35+
return p.tc[i.Text] <= p.limit
36+
}), nil
37+
}
38+
39+
func (p MaxSameIssues) Finish() {
40+
for text, count := range p.tc {
41+
if count > p.limit {
42+
logrus.Infof("%d/%d issues with text %q were hidden, use --max-same-issues",
43+
count-p.limit, count, text)
44+
}
45+
}
46+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package processors
2+
3+
import (
4+
"testing"
5+
6+
"github.com/golangci/golangci-lint/pkg/result"
7+
)
8+
9+
func TestMaxSameIssues(t *testing.T) {
10+
p := NewMaxSameIssues(1)
11+
i1 := result.Issue{
12+
Text: "1",
13+
}
14+
i2 := result.Issue{
15+
Text: "2",
16+
}
17+
18+
processAssertSame(t, p, i1) // ok
19+
processAssertSame(t, p, i2) // ok: another
20+
processAssertEmpty(t, p, i1) // skip
21+
}

pkg/result/processors/nolint.go

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package processors
22

33
import (
4+
"bufio"
5+
"bytes"
46
"fmt"
57
"go/ast"
68
"go/parser"
79
"go/token"
10+
"io/ioutil"
811
"strings"
912

1013
"github.com/golangci/golangci-lint/pkg/result"
@@ -15,17 +18,21 @@ type comment struct {
1518
line int
1619
}
1720
type fileComments []comment
18-
type commentsCache map[string]fileComments
21+
type fileData struct {
22+
comments fileComments
23+
isGenerated bool
24+
}
25+
type filesCache map[string]*fileData
1926

2027
type Nolint struct {
2128
fset *token.FileSet
22-
cache commentsCache
29+
cache filesCache
2330
}
2431

2532
func NewNolint(fset *token.FileSet) *Nolint {
2633
return &Nolint{
2734
fset: fset,
28-
cache: commentsCache{},
35+
cache: filesCache{},
2936
}
3037
}
3138

@@ -39,19 +46,53 @@ func (p *Nolint) Process(issues []result.Issue) ([]result.Issue, error) {
3946
return filterIssuesErr(issues, p.shouldPassIssue)
4047
}
4148

49+
var (
50+
genHdr = []byte("// Code generated ")
51+
genFtr = []byte(" DO NOT EDIT.")
52+
)
53+
54+
// isGenerated reports whether the source file is generated code
55+
// according the rules from https://golang.org/s/generatedcode.
56+
func isGenerated(src []byte) bool {
57+
sc := bufio.NewScanner(bytes.NewReader(src))
58+
for sc.Scan() {
59+
b := sc.Bytes()
60+
if bytes.HasPrefix(b, genHdr) && bytes.HasSuffix(b, genFtr) && len(b) >= len(genHdr)+len(genFtr) {
61+
return true
62+
}
63+
}
64+
return false
65+
}
66+
4267
func (p *Nolint) shouldPassIssue(i *result.Issue) (bool, error) {
43-
comments := p.cache[i.FilePath()]
44-
if comments == nil {
45-
file, err := parser.ParseFile(p.fset, i.FilePath(), nil, parser.ParseComments)
68+
fd := p.cache[i.FilePath()]
69+
if fd == nil {
70+
fd = &fileData{}
71+
p.cache[i.FilePath()] = fd
72+
73+
src, err := ioutil.ReadFile(i.FilePath())
74+
if err != nil {
75+
return false, fmt.Errorf("can't read file %s: %s", i.FilePath(), err)
76+
}
77+
78+
fd.isGenerated = isGenerated(src)
79+
if fd.isGenerated { // don't report issues for autogenerated files
80+
return false, nil
81+
}
82+
83+
file, err := parser.ParseFile(p.fset, i.FilePath(), src, parser.ParseComments)
4684
if err != nil {
4785
return false, fmt.Errorf("can't parse file %s", i.FilePath())
4886
}
4987

50-
comments = extractFileComments(p.fset, file.Comments...)
51-
p.cache[i.FilePath()] = comments
88+
fd.comments = extractFileComments(p.fset, file.Comments...)
89+
}
90+
91+
if fd.isGenerated { // don't report issues for autogenerated files
92+
return false, nil
5293
}
5394

54-
for _, comment := range comments {
95+
for _, comment := range fd.comments {
5596
if comment.line != i.Line() {
5697
continue
5798
}

pkg/result/processors/nolint_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,14 @@ func TestNolint(t *testing.T) {
2929

3030
processAssertSame(t, p, newNolintFileIssue(1, "golint"))
3131
}
32+
33+
func TestNoIssuesInAutogeneratedFile(t *testing.T) {
34+
i := result.Issue{
35+
Pos: token.Position{
36+
Filename: filepath.Join("testdata", "nolint_autogenerated.go"),
37+
Line: 4,
38+
},
39+
}
40+
p := NewNolint(token.NewFileSet())
41+
processAssertEmpty(t, p, i)
42+
}

pkg/result/processors/testdata/nolint_autogenerated.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)