Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new linter exclusions system #5339

Merged
merged 34 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f206cfc
chore: fix typos
ldez Jan 18, 2025
aa5b944
feat: relative path mode
ldez Jan 18, 2025
155eded
feat: relative path processor
ldez Jan 18, 2025
f240662
feat: go plugins path
ldez Jan 18, 2025
f7a4448
feat: linter placeholder
ldez Jan 18, 2025
5b89dd4
docs: configuration and JSONSchema
ldez Jan 18, 2025
547e6d2
chore: cleanup SkipFiles and SkipDirs
ldez Jan 18, 2025
11e33d2
chore: merge PathPrefixer into PathPrettifier
ldez Jan 18, 2025
4eaaf86
chore: rename AutogeneratedExclude to GeneratedFileFilter
ldez Jan 19, 2025
815fa1f
chore: rename Nolint to NolintFilter
ldez Jan 19, 2025
243307a
tests: isolate exclusions_generated_file_filter files
ldez Jan 19, 2025
494b94f
tests: isolate nolint_filter files
ldez Jan 19, 2025
1b10ce8
tests: isolate severity files
ldez Jan 19, 2025
22a6282
tests: isolate exclude_rules files
ldez Jan 19, 2025
effb675
chore: fix typo
ldez Jan 19, 2025
4d8ac35
refactor: restrict config scope
ldez Jan 19, 2025
becbabd
feat: new exclusion configuration
ldez Jan 20, 2025
6f68b64
refactor: new exclusion rules
ldez Jan 20, 2025
c31d2e7
refactor: use new option Generated
ldez Jan 20, 2025
3f5b0a3
chore: add v2 TODO
ldez Jan 20, 2025
99da68e
feat: new exclusion paths processor
ldez Jan 20, 2025
9420026
chore: remove unused exclusions
ldez Jan 20, 2025
2236d3d
refactor: replace Exclude processor by ExclusionRules processor
ldez Jan 20, 2025
fb63541
tests: neutral file paths for Windows
ldez Jan 20, 2025
5e65d35
refactor: use constants for default exclusions
ldez Jan 21, 2025
5bd5b9b
chore: validate LinterExclusions configuration
ldez Jan 21, 2025
612cbfb
review: fix typo
ldez Jan 21, 2025
e375825
feat: add inters.exclusions.paths-except
ldez Jan 23, 2025
bd4774b
chore: move comment
ldez Jan 23, 2025
a6d1ed7
feat: warning on unused path-except
ldez Jan 23, 2025
28bfdb4
refactor: improve GetBasePath to be more v2 ready
ldez Jan 23, 2025
c2f23d6
review
ldez Jan 24, 2025
f85fdaf
review
ldez Jan 28, 2025
3faf3af
review
ldez Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .golangci.next.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1254,7 +1254,7 @@ linters-settings:
failOn: dsl,import
# Comma-separated list of file paths containing ruleguard rules.
# If a path is relative, it is relative to the directory where the golangci-lint command is executed.
# The special '${configDir}' variable is substituted with the absolute directory containing the golangci config file.
# The special '${configDir}' variable is substituted with the absolute directory containing the golangci-lint config file.
# Glob patterns such as 'rules-*.go' may be specified.
# Default: ""
rules: '${configDir}/ruleguard/rules-*.go,${configDir}/myrule1.go'
Expand Down Expand Up @@ -4141,6 +4141,16 @@ run:
# Default: 1m
timeout: 5m

# The mode used to evaluate relative paths.
# It's used by exclusions, Go plugins, and some linters.
# The value can be:
# - `gomod`: the paths will be relative to the directory of the `go.mod` file.
# - `gitroot`: the paths will be relative to the git root (the parent directory of `.git`).
# - `cfg`: the paths will be relative to the configuration file.
# - `wd` (NOT recommended): the paths will be relative to the place where golangci-lint is run.
# Default: wd
relative-path-mode: gomod

# Exit code when at least one issue was found.
# Default: 1
issues-exit-code: 2
Expand Down
2 changes: 1 addition & 1 deletion .golangci.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1248,7 +1248,7 @@ linters-settings:
failOn: dsl,import
# Comma-separated list of file paths containing ruleguard rules.
# If a path is relative, it is relative to the directory where the golangci-lint command is executed.
# The special '${configDir}' variable is substituted with the absolute directory containing the golangci config file.
# The special '${configDir}' variable is substituted with the absolute directory containing the golangci-lint config file.
# Glob patterns such as 'rules-*.go' may be specified.
# Default: ""
rules: '${configDir}/ruleguard/rules-*.go,${configDir}/myrule1.go'
Expand Down
32 changes: 0 additions & 32 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,6 @@ issues:
- mnd
- lll

# The logic of creating a linter is similar between linters, it's not duplication.
- path: pkg/golinters
linters:
- dupl

# Deprecated configuration options.
- path: pkg/commands/run.go
linters: [staticcheck]
text: "SA1019: c.cfg.Run.ShowStats is deprecated: use Output.ShowStats instead."

# Deprecated linter options.
- path: pkg/golinters/errcheck/errcheck.go
linters: [staticcheck]
Expand All @@ -180,39 +170,17 @@ issues:
- path: pkg/goformatters/gci/gci.go
linters: [staticcheck]
text: "SA1019: settings.LocalPrefixes is deprecated: use Sections instead."
- path: pkg/golinters/mnd/mnd.go
linters: [staticcheck]
text: "SA1019: settings.Settings is deprecated: use root level settings instead."
- path: pkg/golinters/mnd/mnd.go
linters: [staticcheck]
text: "SA1019: config.GoMndSettings is deprecated: use MndSettings."

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

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

# Related to file sizes.
- path: pkg/goanalysis/runner_loadingpackage.go
linters: [gosec]
text: "G115: integer overflow conversion uintptr -> int"

# Related to PID.
- path: test/bench/bench_test.go
linters: [gosec]
text: "G115: integer overflow conversion int -> int32"

# Related to the result of computation but divided multiple times by 1024.
- path: test/bench/bench_test.go
linters: [gosec]
Expand Down
84 changes: 84 additions & 0 deletions jsonschema/golangci.next.jsonschema.json
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,14 @@
"type": "string"
}
]
},
"relative-path-modes": {
"enum": [
"gomod",
"gitroot",
"cfg",
"wd"
]
}
},
"type": "object",
Expand Down Expand Up @@ -506,6 +514,12 @@
"description": "Targeted Go version.",
"type": "string",
"default": "1.17"
},
"relative-path-mode": {
"description": "The mode used to evaluate relative paths.",
"type": "string",
"$ref": "#/definitions/relative-path-modes",
"default": "wd"
}
}
},
Expand Down Expand Up @@ -3872,6 +3886,76 @@
"description": "Enable run of fast linters.",
"type": "boolean",
"default": false
},
"exclusions":{
"type": "object",
"additionalProperties": false,
"properties": {
"generated": {
"enum": ["strict", "lax", "disable"],
"default": "lax"
},
"warn-unused": {
"type": "boolean",
"default": false
},
"default": {
"type": "array",
"items": {
"enum": [
"comments",
"stdErrorHandling",
"commonFalsePositives",
"legacy"
]
}
},
"rules": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"path-except": {
"type": "string"
},
"linters": {
"type": "array",
"items": {
"$ref": "#/definitions/linters"
}
},
"text": {
"type": "string"
},
"source": {
"type": "string"
}
},
"anyOf": [
{ "required": ["path"] },
{ "required": ["path-except"] },
{ "required": ["linters"] },
{ "required": ["text"] },
{ "required": ["source"] }
]
}
},
"paths": {
"type": "array",
"items": {
"type": "string"
}
},
"paths-except": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
Expand Down
75 changes: 75 additions & 0 deletions pkg/config/base_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package config

import (
"errors"
"fmt"
"regexp"
)

type BaseRule struct {
Linters []string
Path string
PathExcept string `mapstructure:"path-except"`
Text string
Source string

// For compatibility with exclude-use-default/include.
InternalReference string `mapstructure:"-"`
}

func (b *BaseRule) Validate(minConditionsCount int) error {
if err := validateOptionalRegex(b.Path); err != nil {
return fmt.Errorf("invalid path regex: %w", err)
}

if err := validateOptionalRegex(b.PathExcept); err != nil {
return fmt.Errorf("invalid path-except regex: %w", err)
}

if err := validateOptionalRegex(b.Text); err != nil {
return fmt.Errorf("invalid text regex: %w", err)
}

if err := validateOptionalRegex(b.Source); err != nil {
return fmt.Errorf("invalid source regex: %w", err)
}

if b.Path != "" && b.PathExcept != "" {
return errors.New("path and path-except should not be set at the same time")
}

nonBlank := 0
if len(b.Linters) > 0 {
nonBlank++
}

// Filtering by path counts as one condition, regardless how it is done (one or both).
// Otherwise, a rule with Path and PathExcept set would pass validation
// whereas before the introduction of path-except that wouldn't have been precise enough.
if b.Path != "" || b.PathExcept != "" {
nonBlank++
}

if b.Text != "" {
nonBlank++
}

if b.Source != "" {
nonBlank++
}

if nonBlank < minConditionsCount {
return fmt.Errorf("at least %d of (text, source, path[-except], linters) should be set", minConditionsCount)
}

return nil
}

func validateOptionalRegex(value string) error {
if value == "" {
return nil
}

_, err := regexp.Compile(value)
return err
}
9 changes: 7 additions & 2 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import (

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

Run Run `mapstructure:"run"`

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

// GetConfigDir returns the directory that contains golangci config file.
// GetConfigDir returns the directory that contains golangci-lint config file.
func (c *Config) GetConfigDir() string {
return c.cfgDir
}

func (c *Config) GetBasePath() string {
return c.basePath
}

func (c *Config) Validate() error {
validators := []func() error{
c.Run.Validate,
Expand Down
Loading
Loading