Skip to content

Commit 627bb4f

Browse files
committed
feat: add inters.exclusions.paths-except
1 parent 499997d commit 627bb4f

File tree

4 files changed

+106
-24
lines changed

4 files changed

+106
-24
lines changed

Diff for: jsonschema/golangci.next.jsonschema.json

+6
Original file line numberDiff line numberDiff line change
@@ -3946,6 +3946,12 @@
39463946
"items": {
39473947
"type": "string"
39483948
}
3949+
},
3950+
"paths-except": {
3951+
"type": "array",
3952+
"items": {
3953+
"type": "string"
3954+
}
39493955
}
39503956
}
39513957
}

Diff for: pkg/config/linters_exclusions.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ const (
1414
const excludeRuleMinConditionsCount = 2
1515

1616
type LinterExclusions struct {
17-
Generated string `mapstructure:"generated"`
18-
WarnUnused bool `mapstructure:"warn-unused"`
19-
Default []string `mapstructure:"default"`
20-
Rules []ExcludeRule `mapstructure:"rules"`
21-
Paths []string `mapstructure:"paths"`
17+
Generated string `mapstructure:"generated"`
18+
WarnUnused bool `mapstructure:"warn-unused"`
19+
Default []string `mapstructure:"default"`
20+
Rules []ExcludeRule `mapstructure:"rules"`
21+
Paths []string `mapstructure:"paths"`
22+
PathsExcept []string `mapstructure:"paths-except"`
2223
}
2324

2425
func (e *LinterExclusions) Validate() error {

Diff for: pkg/result/processors/exclusion_paths.go

+34-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import (
1313
var _ Processor = (*ExclusionPaths)(nil)
1414

1515
type ExclusionPaths struct {
16-
patterns []*regexp.Regexp
16+
pathPatterns []*regexp.Regexp
17+
pathExceptPatterns []*regexp.Regexp
1718

1819
warnUnused bool
1920
skippedPathCounter map[*regexp.Regexp]int
@@ -24,7 +25,7 @@ type ExclusionPaths struct {
2425
func NewExclusionPaths(log logutils.Log, cfg *config.LinterExclusions) (*ExclusionPaths, error) {
2526
var counter = make(map[*regexp.Regexp]int)
2627

27-
var patternsRe []*regexp.Regexp
28+
var pathPatterns []*regexp.Regexp
2829
for _, p := range cfg.Paths {
2930
p = fsutils.NormalizePathInRegex(p)
3031

@@ -33,12 +34,26 @@ func NewExclusionPaths(log logutils.Log, cfg *config.LinterExclusions) (*Exclusi
3334
return nil, fmt.Errorf("can't compile regexp %q: %w", p, err)
3435
}
3536

36-
patternsRe = append(patternsRe, patternRe)
37+
pathPatterns = append(pathPatterns, patternRe)
38+
counter[patternRe] = 0
39+
}
40+
41+
var pathExceptPatterns []*regexp.Regexp
42+
for _, p := range cfg.PathsExcept {
43+
p = fsutils.NormalizePathInRegex(p)
44+
45+
patternRe, err := regexp.Compile(p)
46+
if err != nil {
47+
return nil, fmt.Errorf("can't compile regexp %q: %w", p, err)
48+
}
49+
50+
pathExceptPatterns = append(pathExceptPatterns, patternRe)
3751
counter[patternRe] = 0
3852
}
3953

4054
return &ExclusionPaths{
41-
patterns: patternsRe,
55+
pathPatterns: pathPatterns,
56+
pathExceptPatterns: pathExceptPatterns,
4257
warnUnused: cfg.WarnUnused,
4358
skippedPathCounter: counter,
4459
log: log.Child(logutils.DebugKeyExclusionPaths),
@@ -50,7 +65,7 @@ func (*ExclusionPaths) Name() string {
5065
}
5166

5267
func (p *ExclusionPaths) Process(issues []result.Issue) ([]result.Issue, error) {
53-
if len(p.patterns) == 0 {
68+
if len(p.pathPatterns) == 0 && len(p.pathExceptPatterns) == 0 {
5469
return issues, nil
5570
}
5671

@@ -68,12 +83,24 @@ func (p *ExclusionPaths) Finish() {
6883
}
6984

7085
func (p *ExclusionPaths) shouldPassIssue(issue *result.Issue) bool {
71-
for _, pattern := range p.patterns {
86+
for _, pattern := range p.pathPatterns {
7287
if pattern.MatchString(issue.RelativePath) {
7388
p.skippedPathCounter[pattern] += 1
7489
return false
7590
}
7691
}
7792

78-
return true
93+
if len(p.pathExceptPatterns) == 0 {
94+
return true
95+
}
96+
97+
for _, pattern := range p.pathExceptPatterns {
98+
if !pattern.MatchString(issue.RelativePath) {
99+
return true
100+
}
101+
102+
p.skippedPathCounter[pattern] += 1
103+
}
104+
105+
return false
79106
}

Diff for: pkg/result/processors/exclusion_paths_test.go

+60-12
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ func TestExclusionPaths_Process(t *testing.T) {
1818

1919
testCases := []struct {
2020
desc string
21-
patterns []string
21+
cfg *config.LinterExclusions
2222
issues []result.Issue
2323
expected []result.Issue
2424
}{
2525
{
26-
desc: "word",
27-
patterns: []string{"foo"},
26+
desc: "paths: word",
27+
cfg: &config.LinterExclusions{
28+
Paths: []string{"foo"},
29+
},
2830
issues: []result.Issue{
2931
{RelativePath: "foo.go"},
3032
{RelativePath: "foo/foo.go"},
@@ -37,8 +39,10 @@ func TestExclusionPaths_Process(t *testing.T) {
3739
},
3840
},
3941
{
40-
desc: "begin with word",
41-
patterns: []string{"^foo"},
42+
desc: "paths: begin with word",
43+
cfg: &config.LinterExclusions{
44+
Paths: []string{"^foo"},
45+
},
4246
issues: []result.Issue{
4347
{RelativePath: filepath.FromSlash("foo.go")},
4448
{RelativePath: filepath.FromSlash("foo/foo.go")},
@@ -52,8 +56,10 @@ func TestExclusionPaths_Process(t *testing.T) {
5256
},
5357
},
5458
{
55-
desc: "directory begin with word",
56-
patterns: []string{"^foo/"},
59+
desc: "paths: directory begin with word",
60+
cfg: &config.LinterExclusions{
61+
Paths: []string{"^foo/"},
62+
},
5763
issues: []result.Issue{
5864
{RelativePath: filepath.FromSlash("foo.go")},
5965
{RelativePath: filepath.FromSlash("foo/foo.go")},
@@ -68,17 +74,21 @@ func TestExclusionPaths_Process(t *testing.T) {
6874
},
6975
},
7076
{
71-
desc: "same suffix with unconstrained expression",
72-
patterns: []string{"c/d.go"},
77+
desc: "paths: same suffix with unconstrained expression",
78+
cfg: &config.LinterExclusions{
79+
Paths: []string{"c/d.go"},
80+
},
7381
issues: []result.Issue{
7482
{RelativePath: filepath.FromSlash("a/b/c/d.go")},
7583
{RelativePath: filepath.FromSlash("c/d.go")},
7684
},
7785
expected: []result.Issue{},
7886
},
7987
{
80-
desc: "same suffix with constrained expression",
81-
patterns: []string{"^c/d.go"},
88+
desc: "paths: same suffix with constrained expression",
89+
cfg: &config.LinterExclusions{
90+
Paths: []string{"^c/d.go"},
91+
},
8292
issues: []result.Issue{
8393
{RelativePath: filepath.FromSlash("a/b/c/d.go")},
8494
{RelativePath: filepath.FromSlash("c/d.go")},
@@ -87,13 +97,51 @@ func TestExclusionPaths_Process(t *testing.T) {
8797
{RelativePath: filepath.FromSlash("a/b/c/d.go")},
8898
},
8999
},
100+
{
101+
desc: "pathsExcept",
102+
cfg: &config.LinterExclusions{
103+
PathsExcept: []string{`^base/c/.*$`},
104+
},
105+
issues: []result.Issue{
106+
{RelativePath: filepath.FromSlash("base/a/file.go")},
107+
{RelativePath: filepath.FromSlash("base/b/file.go")},
108+
{RelativePath: filepath.FromSlash("base/c/file.go")},
109+
{RelativePath: filepath.FromSlash("base/c/a/file.go")},
110+
{RelativePath: filepath.FromSlash("base/c/b/file.go")},
111+
{RelativePath: filepath.FromSlash("base/d/file.go")},
112+
},
113+
expected: []result.Issue{
114+
{RelativePath: filepath.FromSlash("base/a/file.go")},
115+
{RelativePath: filepath.FromSlash("base/b/file.go")},
116+
{RelativePath: filepath.FromSlash("base/d/file.go")},
117+
},
118+
},
119+
{
120+
desc: "pathsExcept and paths",
121+
cfg: &config.LinterExclusions{
122+
Paths: []string{"^base/b/"},
123+
PathsExcept: []string{`^base/c/.*$`},
124+
},
125+
issues: []result.Issue{
126+
{RelativePath: filepath.FromSlash("base/a/file.go")},
127+
{RelativePath: filepath.FromSlash("base/b/file.go")},
128+
{RelativePath: filepath.FromSlash("base/c/file.go")},
129+
{RelativePath: filepath.FromSlash("base/c/a/file.go")},
130+
{RelativePath: filepath.FromSlash("base/c/b/file.go")},
131+
{RelativePath: filepath.FromSlash("base/d/file.go")},
132+
},
133+
expected: []result.Issue{
134+
{RelativePath: filepath.FromSlash("base/a/file.go")},
135+
{RelativePath: filepath.FromSlash("base/d/file.go")},
136+
},
137+
},
90138
}
91139

92140
for _, test := range testCases {
93141
t.Run(test.desc, func(t *testing.T) {
94142
t.Parallel()
95143

96-
p, err := NewExclusionPaths(logger, &config.LinterExclusions{Paths: test.patterns})
144+
p, err := NewExclusionPaths(logger, test.cfg)
97145
require.NoError(t, err)
98146

99147
processedIssues := process(t, p, test.issues...)

0 commit comments

Comments
 (0)