Skip to content

Commit 7dfb9cf

Browse files
committed
rework skip dir algorithm
1 parent 441bdb3 commit 7dfb9cf

File tree

4 files changed

+59
-55
lines changed

4 files changed

+59
-55
lines changed

pkg/lint/runner.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func NewRunner(astCache *astcache.Cache, cfg *config.Config, log logutils.Log, g
5454
processors.NewPathPrettifier(), // must be before diff, nolint and exclude autogenerated processor at least
5555
processors.NewCgo(goenv),
5656
skipFilesProcessor,
57-
skipDirsProcessor,
57+
skipDirsProcessor, // must be after path prettifier
5858

5959
processors.NewAutogeneratedExclude(astCache),
6060
processors.NewExclude(excludeTotalPattern),
@@ -205,6 +205,7 @@ func (r Runner) processLintResults(inCh <-chan lintRes) <-chan lintRes {
205205
go func() {
206206
sw := timeutils.NewStopwatch("processing", r.Log)
207207

208+
var issuesBefore, issuesAfter int
208209
defer close(outCh)
209210

210211
for res := range inCh {
@@ -214,7 +215,9 @@ func (r Runner) processLintResults(inCh <-chan lintRes) <-chan lintRes {
214215
}
215216

216217
if len(res.issues) != 0 {
218+
issuesBefore += len(res.issues)
217219
res.issues = r.processIssues(res.issues, sw)
220+
issuesAfter += len(res.issues)
218221
outCh <- res
219222
}
220223
}
@@ -228,6 +231,9 @@ func (r Runner) processLintResults(inCh <-chan lintRes) <-chan lintRes {
228231
})
229232
}
230233

234+
if issuesBefore != issuesAfter {
235+
r.Log.Infof("Issues before processing: %d, after processing: %d", issuesBefore, issuesAfter)
236+
}
231237
sw.PrintStages()
232238
}()
233239

pkg/result/processors/skip_dirs.go

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package processors
33
import (
44
"path/filepath"
55
"regexp"
6-
"sort"
76
"strings"
87

98
"github.com/pkg/errors"
@@ -13,19 +12,15 @@ import (
1312
)
1413

1514
type SkipDirs struct {
16-
patterns []*regexp.Regexp
17-
log logutils.Log
18-
skippedDirs map[string]bool
19-
sortedAbsArgs []string
15+
patterns []*regexp.Regexp
16+
log logutils.Log
17+
skippedDirs map[string][]string // regexp to dir mapping
18+
absArgsDirs []string
2019
}
2120

2221
var _ Processor = SkipFiles{}
2322

24-
type sortedByLenStrings []string
25-
26-
func (s sortedByLenStrings) Len() int { return len(s) }
27-
func (s sortedByLenStrings) Less(i, j int) bool { return len(s[i]) > len(s[j]) }
28-
func (s sortedByLenStrings) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
23+
const goFileSuffix = ".go"
2924

3025
func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string) (*SkipDirs, error) {
3126
var patternsRe []*regexp.Regexp
@@ -40,24 +35,25 @@ func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string) (*SkipDi
4035
if len(runArgs) == 0 {
4136
runArgs = append(runArgs, "./...")
4237
}
43-
var sortedAbsArgs []string
38+
var absArgsDirs []string
4439
for _, arg := range runArgs {
45-
if filepath.Base(arg) == "..." {
40+
base := filepath.Base(arg)
41+
if base == "..." || strings.HasSuffix(base, goFileSuffix) {
4642
arg = filepath.Dir(arg)
4743
}
44+
4845
absArg, err := filepath.Abs(arg)
4946
if err != nil {
5047
return nil, errors.Wrapf(err, "failed to abs-ify arg %q", arg)
5148
}
52-
sortedAbsArgs = append(sortedAbsArgs, absArg)
49+
absArgsDirs = append(absArgsDirs, absArg)
5350
}
54-
sort.Sort(sortedByLenStrings(sortedAbsArgs))
5551

5652
return &SkipDirs{
57-
patterns: patternsRe,
58-
log: log,
59-
skippedDirs: map[string]bool{},
60-
sortedAbsArgs: sortedAbsArgs,
53+
patterns: patternsRe,
54+
log: log,
55+
skippedDirs: map[string][]string{},
56+
absArgsDirs: absArgsDirs,
6157
}, nil
6258
}
6359

@@ -73,38 +69,38 @@ func (p *SkipDirs) Process(issues []result.Issue) ([]result.Issue, error) {
7369
return filterIssues(issues, p.shouldPassIssue), nil
7470
}
7571

76-
func (p *SkipDirs) getLongestArgRelativeIssuePath(i *result.Issue) string {
77-
issueAbsPath, err := filepath.Abs(i.FilePath())
78-
if err != nil {
79-
p.log.Warnf("Can't abs-ify path %q: %s", i.FilePath(), err)
80-
return ""
81-
}
82-
83-
for _, arg := range p.sortedAbsArgs {
84-
if !strings.HasPrefix(issueAbsPath, arg) {
85-
continue
86-
}
87-
88-
return i.FilePath()
72+
func (p *SkipDirs) shouldPassIssue(i *result.Issue) bool {
73+
if filepath.IsAbs(i.FilePath()) {
74+
p.log.Warnf("Got abs path in skip dirs processor, it should be relative")
75+
return true
8976
}
9077

91-
p.log.Infof("Issue path %q isn't relative to any of run args", i.FilePath())
92-
return ""
93-
}
94-
95-
func (p *SkipDirs) shouldPassIssue(i *result.Issue) bool {
96-
relIssuePath := p.getLongestArgRelativeIssuePath(i)
97-
if relIssuePath == "" {
78+
issueRelDir := filepath.Dir(i.FilePath())
79+
issueAbsDir, err := filepath.Abs(issueRelDir)
80+
if err != nil {
81+
p.log.Warnf("Can't abs-ify path %q: %s", issueRelDir, err)
9882
return true
9983
}
10084

101-
if strings.HasSuffix(filepath.Base(relIssuePath), ".go") {
102-
relIssuePath = filepath.Dir(relIssuePath)
85+
for _, absArgDir := range p.absArgsDirs {
86+
if absArgDir == issueAbsDir {
87+
p.log.Infof("Pass issue in file %s because it's dir was explicitly set in arg %s", i.FilePath(), absArgDir)
88+
// we must not skip issues if they are from explicitly set dirs
89+
// even if they match skip patterns
90+
return true
91+
}
10392
}
10493

94+
// We use issueRelDir for matching: it's the relative to the current
95+
// work dir path of directory of source file with the issue. It can lead
96+
// to unexpected behavior if we're analyzing files out of current work dir.
97+
// The alternative solution is to find relative to args path, but it has
98+
// disadvantages (https://github.com/golangci/golangci-lint/pull/313).
99+
105100
for _, pattern := range p.patterns {
106-
if pattern.MatchString(relIssuePath) {
107-
p.skippedDirs[relIssuePath] = true
101+
if pattern.MatchString(issueRelDir) {
102+
ps := pattern.String()
103+
p.skippedDirs[ps] = append(p.skippedDirs[ps], issueRelDir)
108104
return false
109105
}
110106
}
@@ -113,11 +109,7 @@ func (p *SkipDirs) shouldPassIssue(i *result.Issue) bool {
113109
}
114110

115111
func (p SkipDirs) Finish() {
116-
if len(p.skippedDirs) != 0 {
117-
var skippedDirs []string
118-
for dir := range p.skippedDirs {
119-
skippedDirs = append(skippedDirs, dir)
120-
}
121-
p.log.Infof("Skipped dirs: %s", skippedDirs)
112+
for pattern, dirs := range p.skippedDirs {
113+
p.log.Infof("Skipped by pattern %s dirs: %s", pattern, dirs)
122114
}
123115
}

test/run_test.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,21 @@ func TestUnsafeOk(t *testing.T) {
5656
testshared.NewLintRunner(t).Run("--enable-all", getTestDataDir("unsafe")).ExpectNoIssues()
5757
}
5858

59-
func TestSkippedDirs(t *testing.T) {
60-
r := testshared.NewLintRunner(t).Run("--print-issued-lines=false", "--no-config", "--skip-dirs", "skip_me", "-Egolint",
61-
getTestDataDir("skipdirs", "..."))
59+
func TestSkippedDirsNoMatchArg(t *testing.T) {
60+
dir := getTestDataDir("skipdirs", "skip_me", "nested")
61+
r := testshared.NewLintRunner(t).Run("--print-issued-lines=false", "--no-config", "--skip-dirs", dir, "-Egolint", dir)
6262

6363
r.ExpectExitCode(exitcodes.IssuesFound).
64-
ExpectOutputEq("testdata/skipdirs/examples_no_skip/with_issue.go:8:9: if block ends with " +
64+
ExpectOutputEq("testdata/skipdirs/skip_me/nested/with_issue.go:8:9: if block ends with " +
6565
"a return statement, so drop this else and outdent its block (golint)\n")
6666
}
6767

68+
func TestSkippedDirsTestdata(t *testing.T) {
69+
r := testshared.NewLintRunner(t).Run("--print-issued-lines=false", "--no-config", "-Egolint", getTestDataDir("skipdirs", "..."))
70+
71+
r.ExpectNoIssues() // all was skipped because in testdata
72+
}
73+
6874
func TestDeadcodeNoFalsePositivesInMainPkg(t *testing.T) {
6975
testshared.NewLintRunner(t).Run("--no-config", "--disable-all", "-Edeadcode", getTestDataDir("deadcode_main_pkg")).ExpectNoIssues()
7076
}

test/testshared/testshared.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ type RunResult struct {
4646
}
4747

4848
func (r *RunResult) ExpectNoIssues() {
49-
assert.Equal(r.t, "", r.output, r.exitCode)
50-
assert.Equal(r.t, exitcodes.Success, r.exitCode, r.output)
49+
assert.Equal(r.t, "", r.output, "exit code is %d", r.exitCode)
50+
assert.Equal(r.t, exitcodes.Success, r.exitCode, "output is %s", r.output)
5151
}
5252

5353
func (r *RunResult) ExpectExitCode(possibleCodes ...int) *RunResult {

0 commit comments

Comments
 (0)