Skip to content

Commit b03312b

Browse files
committed
chore: validate LinterExclusions configuration
1 parent 0e0d6ad commit b03312b

File tree

4 files changed

+107
-92
lines changed

4 files changed

+107
-92
lines changed

pkg/config/base_rule.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package config
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"regexp"
7+
)
8+
9+
type BaseRule struct {
10+
Linters []string
11+
Path string
12+
PathExcept string `mapstructure:"path-except"`
13+
Text string
14+
Source string
15+
16+
// For compatibility with exclude-use-default/include.
17+
InternalReference string `mapstructure:"-"`
18+
}
19+
20+
func (b *BaseRule) Validate(minConditionsCount int) error {
21+
if err := validateOptionalRegex(b.Path); err != nil {
22+
return fmt.Errorf("invalid path regex: %w", err)
23+
}
24+
25+
if err := validateOptionalRegex(b.PathExcept); err != nil {
26+
return fmt.Errorf("invalid path-except regex: %w", err)
27+
}
28+
29+
if err := validateOptionalRegex(b.Text); err != nil {
30+
return fmt.Errorf("invalid text regex: %w", err)
31+
}
32+
33+
if err := validateOptionalRegex(b.Source); err != nil {
34+
return fmt.Errorf("invalid source regex: %w", err)
35+
}
36+
37+
if b.Path != "" && b.PathExcept != "" {
38+
return errors.New("path and path-except should not be set at the same time")
39+
}
40+
41+
nonBlank := 0
42+
if len(b.Linters) > 0 {
43+
nonBlank++
44+
}
45+
46+
// Filtering by path counts as one condition, regardless how it is done (one or both).
47+
// Otherwise, a rule with Path and PathExcept set would pass validation
48+
// whereas before the introduction of path-except that wouldn't have been precise enough.
49+
if b.Path != "" || b.PathExcept != "" {
50+
nonBlank++
51+
}
52+
53+
if b.Text != "" {
54+
nonBlank++
55+
}
56+
57+
if b.Source != "" {
58+
nonBlank++
59+
}
60+
61+
if nonBlank < minConditionsCount {
62+
return fmt.Errorf("at least %d of (text, source, path[-except], linters) should be set", minConditionsCount)
63+
}
64+
65+
return nil
66+
}
67+
68+
func validateOptionalRegex(value string) error {
69+
if value == "" {
70+
return nil
71+
}
72+
73+
_, err := regexp.Compile(value)
74+
return err
75+
}

pkg/config/issues.go

Lines changed: 0 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
package config
22

33
import (
4-
"errors"
54
"fmt"
6-
"regexp"
75
)
86

9-
const excludeRuleMinConditionsCount = 2
10-
117
var DefaultExcludePatterns = []ExcludePattern{
128
{
139
ID: "EXC0001",
@@ -141,97 +137,13 @@ func (i *Issues) Validate() error {
141137
return nil
142138
}
143139

144-
type ExcludeRule struct {
145-
BaseRule `mapstructure:",squash"`
146-
}
147-
148-
func (e *ExcludeRule) Validate() error {
149-
return e.BaseRule.Validate(excludeRuleMinConditionsCount)
150-
}
151-
152-
type BaseRule struct {
153-
Linters []string
154-
Path string
155-
PathExcept string `mapstructure:"path-except"`
156-
Text string
157-
Source string
158-
159-
// For compatibility with exclude-use-default/include.
160-
InternalReference string `mapstructure:"-"`
161-
}
162-
163-
func (b *BaseRule) Validate(minConditionsCount int) error {
164-
if err := validateOptionalRegex(b.Path); err != nil {
165-
return fmt.Errorf("invalid path regex: %w", err)
166-
}
167-
168-
if err := validateOptionalRegex(b.PathExcept); err != nil {
169-
return fmt.Errorf("invalid path-except regex: %w", err)
170-
}
171-
172-
if err := validateOptionalRegex(b.Text); err != nil {
173-
return fmt.Errorf("invalid text regex: %w", err)
174-
}
175-
176-
if err := validateOptionalRegex(b.Source); err != nil {
177-
return fmt.Errorf("invalid source regex: %w", err)
178-
}
179-
180-
if b.Path != "" && b.PathExcept != "" {
181-
return errors.New("path and path-except should not be set at the same time")
182-
}
183-
184-
nonBlank := 0
185-
if len(b.Linters) > 0 {
186-
nonBlank++
187-
}
188-
189-
// Filtering by path counts as one condition, regardless how it is done (one or both).
190-
// Otherwise, a rule with Path and PathExcept set would pass validation
191-
// whereas before the introduction of path-except that wouldn't have been precise enough.
192-
if b.Path != "" || b.PathExcept != "" {
193-
nonBlank++
194-
}
195-
196-
if b.Text != "" {
197-
nonBlank++
198-
}
199-
200-
if b.Source != "" {
201-
nonBlank++
202-
}
203-
204-
if nonBlank < minConditionsCount {
205-
return fmt.Errorf("at least %d of (text, source, path[-except], linters) should be set", minConditionsCount)
206-
}
207-
208-
return nil
209-
}
210-
211-
func validateOptionalRegex(value string) error {
212-
if value == "" {
213-
return nil
214-
}
215-
216-
_, err := regexp.Compile(value)
217-
return err
218-
}
219-
220140
type ExcludePattern struct {
221141
ID string
222142
Pattern string
223143
Linter string
224144
Why string
225145
}
226146

227-
func GetDefaultExcludePatternsStrings() []string {
228-
ret := make([]string, len(DefaultExcludePatterns))
229-
for i, p := range DefaultExcludePatterns {
230-
ret[i] = p.Pattern
231-
}
232-
return ret
233-
}
234-
235147
// TODO(ldez): this behavior must be changed in v2, because this is confusing.
236148
func GetExcludePatterns(include []string) []ExcludePattern {
237149
includeMap := make(map[string]struct{}, len(include))

pkg/config/linters.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@ type Linters struct {
1818
}
1919

2020
func (l *Linters) Validate() error {
21-
if err := l.validateAllDisableEnableOptions(); err != nil {
22-
return err
21+
validators := []func() error{
22+
l.validateAllDisableEnableOptions,
23+
l.validateDisabledAndEnabledAtOneMoment,
24+
l.LinterExclusions.Validate,
2325
}
2426

25-
if err := l.validateDisabledAndEnabledAtOneMoment(); err != nil {
26-
return err
27+
for _, v := range validators {
28+
if err := v(); err != nil {
29+
return err
30+
}
2731
}
2832

2933
return nil

pkg/config/linters_exclusions.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,40 @@
11
package config
22

3+
import (
4+
"fmt"
5+
)
6+
37
const (
48
DefaultExclusionComments = "comments"
59
DefaultExclusionStdErrorHandling = "stdErrorHandling"
610
DefaultExclusionCommonFalsePositives = "commonFalsePositives"
711
DefaultExclusionLegacy = "legacy"
812
)
913

14+
const excludeRuleMinConditionsCount = 2
15+
1016
type LinterExclusions struct {
1117
Generated string `mapstructure:"generated"`
1218
WarnUnused bool `mapstructure:"warn-unused"`
1319
Default []string `mapstructure:"default"`
1420
Rules []ExcludeRule `mapstructure:"rules"`
1521
Paths []string `mapstructure:"paths"`
1622
}
23+
24+
func (e *LinterExclusions) Validate() error {
25+
for i, rule := range e.Rules {
26+
if err := rule.Validate(); err != nil {
27+
return fmt.Errorf("error in exclude rule #%d: %w", i, err)
28+
}
29+
}
30+
31+
return nil
32+
}
33+
34+
type ExcludeRule struct {
35+
BaseRule `mapstructure:",squash"`
36+
}
37+
38+
func (e *ExcludeRule) Validate() error {
39+
return e.BaseRule.Validate(excludeRuleMinConditionsCount)
40+
}

0 commit comments

Comments
 (0)