Skip to content

Commit 98c110b

Browse files
authored
feat: new linter exclusions system (#5339)
1 parent e84aa52 commit 98c110b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1556
-697
lines changed

.golangci.next.reference.yml

+11-1
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,7 @@ linters-settings:
12541254
failOn: dsl,import
12551255
# Comma-separated list of file paths containing ruleguard rules.
12561256
# If a path is relative, it is relative to the directory where the golangci-lint command is executed.
1257-
# The special '${configDir}' variable is substituted with the absolute directory containing the golangci config file.
1257+
# The special '${configDir}' variable is substituted with the absolute directory containing the golangci-lint config file.
12581258
# Glob patterns such as 'rules-*.go' may be specified.
12591259
# Default: ""
12601260
rules: '${configDir}/ruleguard/rules-*.go,${configDir}/myrule1.go'
@@ -4141,6 +4141,16 @@ run:
41414141
# Default: 1m
41424142
timeout: 5m
41434143

4144+
# The mode used to evaluate relative paths.
4145+
# It's used by exclusions, Go plugins, and some linters.
4146+
# The value can be:
4147+
# - `gomod`: the paths will be relative to the directory of the `go.mod` file.
4148+
# - `gitroot`: the paths will be relative to the git root (the parent directory of `.git`).
4149+
# - `cfg`: the paths will be relative to the configuration file.
4150+
# - `wd` (NOT recommended): the paths will be relative to the place where golangci-lint is run.
4151+
# Default: wd
4152+
relative-path-mode: gomod
4153+
41444154
# Exit code when at least one issue was found.
41454155
# Default: 1
41464156
issues-exit-code: 2

.golangci.reference.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@ linters-settings:
12481248
failOn: dsl,import
12491249
# Comma-separated list of file paths containing ruleguard rules.
12501250
# If a path is relative, it is relative to the directory where the golangci-lint command is executed.
1251-
# The special '${configDir}' variable is substituted with the absolute directory containing the golangci config file.
1251+
# The special '${configDir}' variable is substituted with the absolute directory containing the golangci-lint config file.
12521252
# Glob patterns such as 'rules-*.go' may be specified.
12531253
# Default: ""
12541254
rules: '${configDir}/ruleguard/rules-*.go,${configDir}/myrule1.go'

.golangci.yml

-32
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,6 @@ issues:
154154
- mnd
155155
- lll
156156

157-
# The logic of creating a linter is similar between linters, it's not duplication.
158-
- path: pkg/golinters
159-
linters:
160-
- dupl
161-
162-
# Deprecated configuration options.
163-
- path: pkg/commands/run.go
164-
linters: [staticcheck]
165-
text: "SA1019: c.cfg.Run.ShowStats is deprecated: use Output.ShowStats instead."
166-
167157
# Deprecated linter options.
168158
- path: pkg/golinters/errcheck/errcheck.go
169159
linters: [staticcheck]
@@ -180,39 +170,17 @@ issues:
180170
- path: pkg/goformatters/gci/gci.go
181171
linters: [staticcheck]
182172
text: "SA1019: settings.LocalPrefixes is deprecated: use Sections instead."
183-
- path: pkg/golinters/mnd/mnd.go
184-
linters: [staticcheck]
185-
text: "SA1019: settings.Settings is deprecated: use root level settings instead."
186-
- path: pkg/golinters/mnd/mnd.go
187-
linters: [staticcheck]
188-
text: "SA1019: config.GoMndSettings is deprecated: use MndSettings."
189173

190174
# Related to `run.go`, it cannot be removed.
191175
- path: pkg/golinters/gofumpt/gofumpt.go
192176
linters: [staticcheck]
193177
text: "SA1019: settings.LangVersion is deprecated: use the global `run.go` instead."
194-
- path: pkg/golinters/internal/staticcheck_common.go
195-
linters: [staticcheck]
196-
text: "SA1019: settings.GoVersion is deprecated: use the global `run.go` instead."
197-
- path: pkg/lint/lintersdb/manager.go
198-
linters: [staticcheck]
199-
text: "SA1019: (.+).(GoVersion|LangVersion) is deprecated: use the global `run.go` instead."
200178

201179
# Based on existing code, the modifications should be limited to make maintenance easier.
202180
- path: pkg/golinters/unused/unused.go
203181
linters: [gocritic]
204182
text: "rangeValCopy: each iteration copies 160 bytes \\(consider pointers or indexing\\)"
205183

206-
# Related to file sizes.
207-
- path: pkg/goanalysis/runner_loadingpackage.go
208-
linters: [gosec]
209-
text: "G115: integer overflow conversion uintptr -> int"
210-
211-
# Related to PID.
212-
- path: test/bench/bench_test.go
213-
linters: [gosec]
214-
text: "G115: integer overflow conversion int -> int32"
215-
216184
# Related to the result of computation but divided multiple times by 1024.
217185
- path: test/bench/bench_test.go
218186
linters: [gosec]

jsonschema/golangci.next.jsonschema.json

+84
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,14 @@
446446
"type": "string"
447447
}
448448
]
449+
},
450+
"relative-path-modes": {
451+
"enum": [
452+
"gomod",
453+
"gitroot",
454+
"cfg",
455+
"wd"
456+
]
449457
}
450458
},
451459
"type": "object",
@@ -506,6 +514,12 @@
506514
"description": "Targeted Go version.",
507515
"type": "string",
508516
"default": "1.17"
517+
},
518+
"relative-path-mode": {
519+
"description": "The mode used to evaluate relative paths.",
520+
"type": "string",
521+
"$ref": "#/definitions/relative-path-modes",
522+
"default": "wd"
509523
}
510524
}
511525
},
@@ -3872,6 +3886,76 @@
38723886
"description": "Enable run of fast linters.",
38733887
"type": "boolean",
38743888
"default": false
3889+
},
3890+
"exclusions":{
3891+
"type": "object",
3892+
"additionalProperties": false,
3893+
"properties": {
3894+
"generated": {
3895+
"enum": ["strict", "lax", "disable"],
3896+
"default": "lax"
3897+
},
3898+
"warn-unused": {
3899+
"type": "boolean",
3900+
"default": false
3901+
},
3902+
"default": {
3903+
"type": "array",
3904+
"items": {
3905+
"enum": [
3906+
"comments",
3907+
"stdErrorHandling",
3908+
"commonFalsePositives",
3909+
"legacy"
3910+
]
3911+
}
3912+
},
3913+
"rules": {
3914+
"type": "array",
3915+
"items": {
3916+
"type": "object",
3917+
"properties": {
3918+
"path": {
3919+
"type": "string"
3920+
},
3921+
"path-except": {
3922+
"type": "string"
3923+
},
3924+
"linters": {
3925+
"type": "array",
3926+
"items": {
3927+
"$ref": "#/definitions/linters"
3928+
}
3929+
},
3930+
"text": {
3931+
"type": "string"
3932+
},
3933+
"source": {
3934+
"type": "string"
3935+
}
3936+
},
3937+
"anyOf": [
3938+
{ "required": ["path"] },
3939+
{ "required": ["path-except"] },
3940+
{ "required": ["linters"] },
3941+
{ "required": ["text"] },
3942+
{ "required": ["source"] }
3943+
]
3944+
}
3945+
},
3946+
"paths": {
3947+
"type": "array",
3948+
"items": {
3949+
"type": "string"
3950+
}
3951+
},
3952+
"paths-except": {
3953+
"type": "array",
3954+
"items": {
3955+
"type": "string"
3956+
}
3957+
}
3958+
}
38753959
}
38763960
}
38773961
},

pkg/config/base_rule.go

+75
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/config.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import (
1717

1818
// Config encapsulates the config data specified in the golangci-lint YAML config file.
1919
type Config struct {
20-
cfgDir string // The directory containing the golangci-lint config file.
20+
cfgDir string // Path to the directory containing golangci-lint config file.
21+
basePath string // Path the root directory related to [Run.RelativePathMode].
2122

2223
Run Run `mapstructure:"run"`
2324

@@ -32,11 +33,15 @@ type Config struct {
3233
InternalTest bool // Option is used only for testing golangci-lint code, don't use it
3334
}
3435

35-
// GetConfigDir returns the directory that contains golangci config file.
36+
// GetConfigDir returns the directory that contains golangci-lint config file.
3637
func (c *Config) GetConfigDir() string {
3738
return c.cfgDir
3839
}
3940

41+
func (c *Config) GetBasePath() string {
42+
return c.basePath
43+
}
44+
4045
func (c *Config) Validate() error {
4146
validators := []func() error{
4247
c.Run.Validate,

0 commit comments

Comments
 (0)