Skip to content

Commit cd890db

Browse files
authoredMar 20, 2024··
fix: filter invalid issues before other processors (#4552)
1 parent 921d535 commit cd890db

7 files changed

+174
-59
lines changed
 

‎pkg/lint/runner.go

+3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ func NewRunner(log logutils.Log, cfg *config.Config, args []string, goenv *gouti
6868
// Must go after Cgo.
6969
processors.NewFilenameUnadjuster(lintCtx.Packages, log.Child(logutils.DebugKeyFilenameUnadjuster)),
7070

71+
// Must go after FilenameUnadjuster.
72+
processors.NewInvalidIssue(log.Child(logutils.DebugKeyInvalidIssue)),
73+
7174
// Must be before diff, nolint and exclude autogenerated processor at least.
7275
processors.NewPathPrettifier(),
7376
skipFilesProcessor,

‎pkg/logutils/logutils.go

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const (
2525
DebugKeyExcludeRules = "exclude_rules"
2626
DebugKeyExec = "exec"
2727
DebugKeyFilenameUnadjuster = "filename_unadjuster"
28+
DebugKeyInvalidIssue = "invalid_issue"
2829
DebugKeyForbidigo = "forbidigo"
2930
DebugKeyGoEnv = "goenv"
3031
DebugKeyLinter = "linter"

‎pkg/result/processors/autogenerated_exclude.go

-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package processors
22

33
import (
4-
"errors"
54
"fmt"
65
"go/parser"
76
"go/token"
@@ -59,18 +58,6 @@ func (p *AutogeneratedExclude) shouldPassIssue(issue *result.Issue) (bool, error
5958
return true, nil
6059
}
6160

62-
if filepath.Base(issue.FilePath()) == "go.mod" {
63-
return true, nil
64-
}
65-
66-
if issue.FilePath() == "" {
67-
return false, errors.New("no file path for issue")
68-
}
69-
70-
if !isGoFile(issue.FilePath()) {
71-
return false, nil
72-
}
73-
7461
// The file is already known.
7562
fs := p.fileSummaryCache[issue.FilePath()]
7663
if fs != nil {

‎pkg/result/processors/autogenerated_exclude_test.go

-33
Original file line numberDiff line numberDiff line change
@@ -166,28 +166,6 @@ func Test_shouldPassIssue(t *testing.T) {
166166
},
167167
assert: assert.True,
168168
},
169-
{
170-
desc: "go.mod",
171-
strict: false,
172-
issue: &result.Issue{
173-
FromLinter: "example",
174-
Pos: token.Position{
175-
Filename: filepath.FromSlash("/a/b/c/go.mod"),
176-
},
177-
},
178-
assert: assert.True,
179-
},
180-
{
181-
desc: "non Go file",
182-
strict: false,
183-
issue: &result.Issue{
184-
FromLinter: "example",
185-
Pos: token.Position{
186-
Filename: filepath.FromSlash("/a/b/c/test.txt"),
187-
},
188-
},
189-
assert: assert.False,
190-
},
191169
{
192170
desc: "lax ",
193171
strict: false,
@@ -239,17 +217,6 @@ func Test_shouldPassIssue_error(t *testing.T) {
239217
issue *result.Issue
240218
expected string
241219
}{
242-
{
243-
desc: "missing Filename",
244-
strict: false,
245-
issue: &result.Issue{
246-
FromLinter: "example",
247-
Pos: token.Position{
248-
Filename: "",
249-
},
250-
},
251-
expected: "no file path for issue",
252-
},
253220
{
254221
desc: "non-existing file (lax)",
255222
strict: false,
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package processors
2+
3+
import (
4+
"path/filepath"
5+
6+
"github.com/golangci/golangci-lint/pkg/logutils"
7+
"github.com/golangci/golangci-lint/pkg/result"
8+
)
9+
10+
var _ Processor = InvalidIssue{}
11+
12+
type InvalidIssue struct {
13+
log logutils.Log
14+
}
15+
16+
func NewInvalidIssue(log logutils.Log) *InvalidIssue {
17+
return &InvalidIssue{log: log}
18+
}
19+
20+
func (p InvalidIssue) Process(issues []result.Issue) ([]result.Issue, error) {
21+
return filterIssuesErr(issues, p.shouldPassIssue)
22+
}
23+
24+
func (p InvalidIssue) Name() string {
25+
return "invalid_issue"
26+
}
27+
28+
func (p InvalidIssue) Finish() {}
29+
30+
func (p InvalidIssue) shouldPassIssue(issue *result.Issue) (bool, error) {
31+
if issue.FromLinter == "typecheck" {
32+
return true, nil
33+
}
34+
35+
if issue.FilePath() == "" {
36+
// contextcheck has a known bug https://github.com/kkHAIKE/contextcheck/issues/21
37+
if issue.FromLinter != "contextcheck" {
38+
p.log.Warnf("no file path for the issue: probably a bug inside the linter %q: %#v", issue.FromLinter, issue)
39+
}
40+
41+
return false, nil
42+
}
43+
44+
if filepath.Base(issue.FilePath()) == "go.mod" {
45+
return true, nil
46+
}
47+
48+
if !isGoFile(issue.FilePath()) {
49+
p.log.Infof("issue related to file %s is skipped", issue.FilePath())
50+
return false, nil
51+
}
52+
53+
return true, nil
54+
}
+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package processors
2+
3+
import (
4+
"go/token"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/golangci/golangci-lint/pkg/logutils"
11+
"github.com/golangci/golangci-lint/pkg/result"
12+
)
13+
14+
func TestInvalidIssue_Process(t *testing.T) {
15+
logger := logutils.NewStderrLog(logutils.DebugKeyInvalidIssue)
16+
logger.SetLevel(logutils.LogLevelDebug)
17+
18+
p := NewInvalidIssue(logger)
19+
20+
testCases := []struct {
21+
desc string
22+
issues []result.Issue
23+
expected []result.Issue
24+
}{
25+
{
26+
desc: "typecheck",
27+
issues: []result.Issue{
28+
{FromLinter: "typecheck"},
29+
},
30+
expected: []result.Issue{
31+
{FromLinter: "typecheck"},
32+
},
33+
},
34+
{
35+
desc: "Go file",
36+
issues: []result.Issue{
37+
{
38+
FromLinter: "example",
39+
Pos: token.Position{
40+
Filename: "test.go",
41+
},
42+
},
43+
},
44+
expected: []result.Issue{
45+
{
46+
FromLinter: "example",
47+
Pos: token.Position{
48+
Filename: "test.go",
49+
},
50+
},
51+
},
52+
},
53+
{
54+
desc: "go.mod",
55+
issues: []result.Issue{
56+
{
57+
FromLinter: "example",
58+
Pos: token.Position{
59+
Filename: "go.mod",
60+
},
61+
},
62+
},
63+
expected: []result.Issue{
64+
{
65+
FromLinter: "example",
66+
Pos: token.Position{
67+
Filename: "go.mod",
68+
},
69+
},
70+
},
71+
},
72+
{
73+
desc: "non Go file",
74+
issues: []result.Issue{
75+
{
76+
FromLinter: "example",
77+
Pos: token.Position{
78+
Filename: "test.txt",
79+
},
80+
},
81+
},
82+
expected: []result.Issue{},
83+
},
84+
{
85+
desc: "no filename",
86+
issues: []result.Issue{
87+
{
88+
FromLinter: "example",
89+
Pos: token.Position{
90+
Filename: "",
91+
},
92+
},
93+
},
94+
expected: []result.Issue{},
95+
},
96+
}
97+
98+
for _, test := range testCases {
99+
test := test
100+
t.Run(test.desc, func(t *testing.T) {
101+
t.Parallel()
102+
103+
after, err := p.Process(test.issues)
104+
require.NoError(t, err)
105+
106+
assert.Equal(t, test.expected, after)
107+
})
108+
}
109+
}

‎pkg/result/processors/nolint.go

+7-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package processors
22

33
import (
4-
"errors"
54
"go/ast"
65
"go/parser"
76
"go/token"
@@ -99,19 +98,15 @@ func (p *Nolint) Process(issues []result.Issue) ([]result.Issue, error) {
9998
return filterIssuesErr(issues, p.shouldPassIssue)
10099
}
101100

102-
func (p *Nolint) getOrCreateFileData(issue *result.Issue) (*fileData, error) {
101+
func (p *Nolint) getOrCreateFileData(issue *result.Issue) *fileData {
103102
fd := p.cache[issue.FilePath()]
104103
if fd != nil {
105-
return fd, nil
104+
return fd
106105
}
107106

108107
fd = &fileData{}
109108
p.cache[issue.FilePath()] = fd
110109

111-
if issue.FilePath() == "" {
112-
return nil, errors.New("no file path for issue")
113-
}
114-
115110
// TODO: migrate this parsing to go/analysis facts
116111
// or cache them somehow per file.
117112

@@ -120,12 +115,14 @@ func (p *Nolint) getOrCreateFileData(issue *result.Issue) (*fileData, error) {
120115
f, err := parser.ParseFile(fset, issue.FilePath(), nil, parser.ParseComments)
121116
if err != nil {
122117
// Don't report error because it's already must be reporter by typecheck or go/analysis.
123-
return fd, nil
118+
return fd
124119
}
125120

126121
fd.ignoredRanges = p.buildIgnoredRangesForFile(f, fset, issue.FilePath())
122+
127123
nolintDebugf("file %s: built nolint ranges are %+v", issue.FilePath(), fd.ignoredRanges)
128-
return fd, nil
124+
125+
return fd
129126
}
130127

131128
func (p *Nolint) buildIgnoredRangesForFile(f *ast.File, fset *token.FileSet, filePath string) []ignoredRange {
@@ -161,10 +158,7 @@ func (p *Nolint) shouldPassIssue(issue *result.Issue) (bool, error) {
161158
nolintDebugf("checking that lint issue was used for %s: %v", issue.ExpectedNoLintLinter, issue)
162159
}
163160

164-
fd, err := p.getOrCreateFileData(issue)
165-
if err != nil {
166-
return false, err
167-
}
161+
fd := p.getOrCreateFileData(issue)
168162

169163
for _, ir := range fd.ignoredRanges {
170164
if ir.doesMatch(issue) {

0 commit comments

Comments
 (0)
Please sign in to comment.