feat: replace run.skip-xxx options by issues.exclude-xxx options (#4509)

This commit is contained in:
Ludovic Fernandez 2024-03-16 17:07:42 +01:00 committed by GitHub
parent 1466b36e50
commit 4b7a55a79d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 234 additions and 159 deletions

View File

@ -28,31 +28,6 @@ run:
build-tags: build-tags:
- mytag - mytag
# Which dirs to skip: issues from them won't be reported.
# Can use regexp here: `generated.*`, regexp is applied on full path,
# including the path prefix if one is set.
# Default dirs are skipped independently of this option's value (see skip-dirs-use-default).
# "/" will be replaced by current OS file path separator to properly work on Windows.
# Default: []
skip-dirs:
- src/external_libs
- autogenerated_by_my_lib
# Enables skipping of directories:
# - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
# Default: true
skip-dirs-use-default: false
# Which files to skip: they will be analyzed, but issues from them won't be reported.
# There is no need to include all autogenerated files,
# we confidently recognize autogenerated files.
# If it's not, please let us know.
# "/" will be replaced by current OS file path separator to properly work on Windows.
# Default: []
skip-files:
- ".*\\.my\\.go$"
- lib/bad.go
# If set, we pass it to "go list -mod={option}". From "go help modules": # If set, we pass it to "go list -mod={option}". From "go help modules":
# If invoked with -mod=readonly, the go command is disallowed from the implicit # If invoked with -mod=readonly, the go command is disallowed from the implicit
# automatic updating of go.mod described above. Instead, it fails when any changes # automatic updating of go.mod described above. Instead, it fails when any changes
@ -2810,10 +2785,35 @@ issues:
# Default: true # Default: true
exclude-use-default: false exclude-use-default: false
# If set to true exclude and exclude-rules regular expressions become case-sensitive. # If set to true, `exclude` and `exclude-rules` regular expressions become case-sensitive.
# Default: false # Default: false
exclude-case-sensitive: false exclude-case-sensitive: false
# Which dirs to exclude: issues from them won't be reported.
# Can use regexp here: `generated.*`, regexp is applied on full path,
# including the path prefix if one is set.
# Default dirs are skipped independently of this option's value (see exclude-dirs-use-default).
# "/" will be replaced by current OS file path separator to properly work on Windows.
# Default: []
exclude-dirs:
- src/external_libs
- autogenerated_by_my_lib
# Enables exclude of directories:
# - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
# Default: true
exclude-dirs-use-default: false
# Which files to exclude: they will be analyzed, but issues from them won't be reported.
# There is no need to include all autogenerated files,
# we confidently recognize autogenerated files.
# If it's not, please let us know.
# "/" will be replaced by current OS file path separator to properly work on Windows.
# Default: []
exclude-files:
- ".*\\.my\\.go$"
- lib/bad.go
# To follow strictly the Go generated file convention. # To follow strictly the Go generated file convention.
# #
# If set to true, source files that have lines matching only the following regular expression will be excluded: # If set to true, source files that have lines matching only the following regular expression will be excluded:

View File

@ -175,7 +175,7 @@ issues:
run: run:
timeout: 5m timeout: 5m
skip-dirs: skip-dirs: # TODO(ldez): should be replaced by `issues.exclude-dirs` after the next release.
- test/testdata_etc # test files - test/testdata_etc # test files
- internal/cache # extracted from Go code - internal/cache # extracted from Go code
- internal/renameio # extracted from Go code - internal/renameio # extracted from Go code

View File

@ -74,7 +74,7 @@ issues:
### Exclude Issues by Path ### Exclude Issues by Path
Exclude issues in path by `run.skip-dirs`, `run.skip-files` or `issues.exclude-rules` config options. Exclude issues in path by `issues.exclude-dirs`, `issues.exclude-files` or `issues.exclude-rules` config options.
Beware that the paths that get matched here are relative to the current working directory. Beware that the paths that get matched here are relative to the current working directory.
When the configuration contains path patterns that check for specific directories, When the configuration contains path patterns that check for specific directories,
@ -103,19 +103,19 @@ issues:
- goconst - goconst
``` ```
In the following example, all the reports related to the files (`skip-files`) are excluded: In the following example, all the reports related to the files (`exclude-files`) are excluded:
```yml ```yml
run: issues:
skip-files: exclude-files:
- path/to/a/file.go - path/to/a/file.go
``` ```
In the following example, all the reports related to the directories (`skip-dirs`) are excluded: In the following example, all the reports related to the directories (`exclude-dirs`) are excluded:
```yml ```yml
run: issues:
skip-dirs: exclude-dirs:
- path/to/a/dir/ - path/to/a/dir/
``` ```

View File

@ -422,33 +422,6 @@
"default": [], "default": [],
"examples": [["mytag"]] "examples": [["mytag"]]
}, },
"skip-dirs": {
"description": "Which directories to skip: issues from them won't be reported.",
"type": "array",
"items": {
"description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
"type": "string",
"examples": ["generated.*"]
},
"default": [],
"examples": [["src/external_libs", "autogenerated_by_my_lib"]]
},
"skip-dirs-use-default": {
"description": "Enable skipping of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
"type": "boolean",
"default": true
},
"skip-files": {
"description": "Which files to skip: they will be analyzed, but issues from them will not be reported.",
"type": "array",
"items": {
"description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
"type": "string",
"examples": [".*\\.my\\.go$"]
},
"default": [],
"examples": [[".*\\.my\\.go$", "lib/bad.go"]]
},
"modules-download-mode": { "modules-download-mode": {
"description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.", "description": "Option to pass to \"go list -mod={option}\".\nSee \"go help modules\" for more information.",
"enum": ["mod", "readonly", "vendor"] "enum": ["mod", "readonly", "vendor"]
@ -3347,6 +3320,33 @@
"type": "boolean", "type": "boolean",
"default": false "default": false
}, },
"exclude-dirs": {
"description": "Which directories to exclude: issues from them won't be reported.",
"type": "array",
"items": {
"description": "You can use regexp here. The regexp is applied on the full path.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
"type": "string",
"examples": ["generated.*"]
},
"default": [],
"examples": [["src/external_libs", "autogenerated_by_my_lib"]]
},
"exclude-dirs-use-default": {
"description": "Enable exclusion of directories \"vendor\", \"third_party\", \"testdata\", \"examples\", \"Godeps\", and \"builtin\".",
"type": "boolean",
"default": true
},
"exclude-files": {
"description": "Which files to exclude: they will be analyzed, but issues from them will not be reported.",
"type": "array",
"items": {
"description": "You can use regexp here. There is no need to include all autogenerated files, we confidently recognize them. If that is not the case, please let us know.\n\"/\" will be replaced by current OS file path separator to properly work on Windows.",
"type": "string",
"examples": [".*\\.my\\.go$"]
},
"default": [],
"examples": [[".*\\.my\\.go$", "lib/bad.go"]]
},
"include": { "include": {
"description": "The list of ids of default excludes to include or disable.", "description": "The list of ids of default excludes to include or disable.",
"type": "array", "type": "array",

View File

@ -12,22 +12,22 @@ import (
"github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/exitcodes" "github.com/golangci/golangci-lint/pkg/exitcodes"
"github.com/golangci/golangci-lint/pkg/lint/lintersdb" "github.com/golangci/golangci-lint/pkg/lint/lintersdb"
"github.com/golangci/golangci-lint/pkg/packages"
) )
func setupLintersFlagSet(v *viper.Viper, fs *pflag.FlagSet) { func setupLintersFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
fs.StringSliceP("disable", "D", nil, color.GreenString("Disable specific linter")) // Hack see Loader.applyStringSliceHack internal.AddHackedStringSliceP(fs, "disable", "D", color.GreenString("Disable specific linter"))
internal.AddFlagAndBind(v, fs, fs.Bool, "disable-all", "linters.disable-all", false, color.GreenString("Disable all linters")) internal.AddFlagAndBind(v, fs, fs.Bool, "disable-all", "linters.disable-all", false, color.GreenString("Disable all linters"))
fs.StringSliceP("enable", "E", nil, color.GreenString("Enable specific linter")) // Hack see Loader.applyStringSliceHack internal.AddHackedStringSliceP(fs, "enable", "E", color.GreenString("Enable specific linter"))
internal.AddFlagAndBind(v, fs, fs.Bool, "enable-all", "linters.enable-all", false, color.GreenString("Enable all linters")) internal.AddFlagAndBind(v, fs, fs.Bool, "enable-all", "linters.enable-all", false, color.GreenString("Enable all linters"))
internal.AddFlagAndBind(v, fs, fs.Bool, "fast", "linters.fast", false, internal.AddFlagAndBind(v, fs, fs.Bool, "fast", "linters.fast", false,
color.GreenString("Enable only fast linters from enabled linters set (first run won't be fast)")) color.GreenString("Enable only fast linters from enabled linters set (first run won't be fast)"))
// Hack see Loader.applyStringSliceHack internal.AddHackedStringSliceP(fs, "presets", "p",
fs.StringSliceP("presets", "p", nil, color.GreenString(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint help linters' to see them. "+
color.GreenString(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint help linters' to see "+ "This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|"))))
"them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|"))))
fs.StringSlice("enable-only", nil, fs.StringSlice("enable-only", nil,
color.GreenString("Override linters configuration section to only run the specific linter(s)")) // Flags only. color.GreenString("Override linters configuration section to only run the specific linter(s)")) // Flags only.
@ -42,14 +42,16 @@ func setupRunFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
internal.AddFlagAndBind(v, fs, fs.Int, "issues-exit-code", "run.issues-exit-code", exitcodes.IssuesFound, internal.AddFlagAndBind(v, fs, fs.Int, "issues-exit-code", "run.issues-exit-code", exitcodes.IssuesFound,
color.GreenString("Exit code when issues were found")) color.GreenString("Exit code when issues were found"))
internal.AddFlagAndBind(v, fs, fs.String, "go", "run.go", "", color.GreenString("Targeted Go version")) internal.AddFlagAndBind(v, fs, fs.String, "go", "run.go", "", color.GreenString("Targeted Go version"))
fs.StringSlice("build-tags", nil, color.GreenString("Build tags")) // Hack see Loader.applyStringSliceHack internal.AddHackedStringSlice(fs, "build-tags", color.GreenString("Build tags"))
internal.AddFlagAndBind(v, fs, fs.Duration, "timeout", "run.timeout", defaultTimeout, color.GreenString("Timeout for total work")) internal.AddFlagAndBind(v, fs, fs.Duration, "timeout", "run.timeout", defaultTimeout, color.GreenString("Timeout for total work"))
internal.AddFlagAndBind(v, fs, fs.Bool, "tests", "run.tests", true, color.GreenString("Analyze tests (*_test.go)")) internal.AddFlagAndBind(v, fs, fs.Bool, "tests", "run.tests", true, color.GreenString("Analyze tests (*_test.go)"))
fs.StringSlice("skip-dirs", nil, color.GreenString("Regexps of directories to skip")) // Hack see Loader.applyStringSliceHack
internal.AddFlagAndBind(v, fs, fs.Bool, "skip-dirs-use-default", "run.skip-dirs-use-default", true, getDefaultDirectoryExcludeHelp()) internal.AddDeprecatedHackedStringSlice(fs, "skip-files", color.GreenString("Regexps of files to skip"))
fs.StringSlice("skip-files", nil, color.GreenString("Regexps of files to skip")) // Hack see Loader.applyStringSliceHack internal.AddDeprecatedHackedStringSlice(fs, "skip-dirs", color.GreenString("Regexps of directories to skip"))
internal.AddDeprecatedFlagAndBind(v, fs, fs.Bool, "skip-dirs-use-default", "run.skip-dirs-use-default", true,
getDefaultDirectoryExcludeHelp())
const allowParallelDesc = "Allow multiple parallel golangci-lint instances running. " + const allowParallelDesc = "Allow multiple parallel golangci-lint instances running. " +
"If false (default) - golangci-lint acquires file lock on start." "If false (default) - golangci-lint acquires file lock on start."
@ -80,7 +82,7 @@ func setupOutputFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
//nolint:gomnd //nolint:gomnd
func setupIssuesFlagSet(v *viper.Viper, fs *pflag.FlagSet) { func setupIssuesFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
fs.StringSliceP("exclude", "e", nil, color.GreenString("Exclude issue by regexp")) // Hack see Loader.applyStringSliceHack internal.AddHackedStringSliceP(fs, "exclude", "e", color.GreenString("Exclude issue by regexp"))
internal.AddFlagAndBind(v, fs, fs.Bool, "exclude-use-default", "issues.exclude-use-default", true, internal.AddFlagAndBind(v, fs, fs.Bool, "exclude-use-default", "issues.exclude-use-default", true,
getDefaultIssueExcludeHelp()) getDefaultIssueExcludeHelp())
internal.AddFlagAndBind(v, fs, fs.Bool, "exclude-case-sensitive", "issues.exclude-case-sensitive", false, internal.AddFlagAndBind(v, fs, fs.Bool, "exclude-case-sensitive", "issues.exclude-case-sensitive", false,
@ -91,6 +93,11 @@ func setupIssuesFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
internal.AddFlagAndBind(v, fs, fs.Int, "max-same-issues", "issues.max-same-issues", 3, internal.AddFlagAndBind(v, fs, fs.Int, "max-same-issues", "issues.max-same-issues", 3,
color.GreenString("Maximum count of issues with the same text. Set to 0 to disable")) color.GreenString("Maximum count of issues with the same text. Set to 0 to disable"))
internal.AddHackedStringSlice(fs, "exclude-files", color.GreenString("Regexps of files to exclude"))
internal.AddHackedStringSlice(fs, "exclude-dirs", color.GreenString("Regexps of directories to exclude"))
internal.AddFlagAndBind(v, fs, fs.Bool, "exclude-dirs-use-default", "issues.exclude-dirs-use-default", true,
getDefaultDirectoryExcludeHelp())
const newDesc = "Show only new issues: if there are unstaged changes or untracked files, only those changes " + const newDesc = "Show only new issues: if there are unstaged changes or untracked files, only those changes " +
"are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration " + "are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration " +
"of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at " + "of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at " +
@ -107,3 +114,24 @@ func setupIssuesFlagSet(v *viper.Viper, fs *pflag.FlagSet) {
internal.AddFlagAndBind(v, fs, fs.Bool, "fix", "issues.fix", false, internal.AddFlagAndBind(v, fs, fs.Bool, "fix", "issues.fix", false,
color.GreenString("Fix found issues (if it's supported by the linter)")) color.GreenString("Fix found issues (if it's supported by the linter)"))
} }
func getDefaultIssueExcludeHelp() string {
parts := []string{color.GreenString("Use or not use default excludes:")}
for _, ep := range config.DefaultExcludePatterns {
parts = append(parts,
fmt.Sprintf(" # %s %s: %s", ep.ID, ep.Linter, ep.Why),
fmt.Sprintf(" - %s", color.YellowString(ep.Pattern)),
"",
)
}
return strings.Join(parts, "\n")
}
func getDefaultDirectoryExcludeHelp() string {
parts := []string{color.GreenString("Use or not use default excluded directories:")}
for _, dir := range packages.StdExcludeDirRegexps {
parts = append(parts, fmt.Sprintf(" - %s", color.YellowString(dir)))
}
parts = append(parts, "")
return strings.Join(parts, "\n")
}

View File

@ -30,3 +30,30 @@ func AddFlagAndBindP[T any](v *viper.Viper, fs *pflag.FlagSet, pfn FlagPFunc[T],
panic(fmt.Sprintf("failed to bind flag %s: %v", name, err)) panic(fmt.Sprintf("failed to bind flag %s: %v", name, err))
} }
} }
// AddDeprecatedFlagAndBind similar to AddFlagAndBind but deprecate the flag.
func AddDeprecatedFlagAndBind[T any](v *viper.Viper, fs *pflag.FlagSet, pfn FlagFunc[T], name, bind string, value T, usage string) {
AddFlagAndBind(v, fs, pfn, name, bind, value, usage)
deprecateFlag(fs, name)
}
// AddHackedStringSliceP Hack for slice, see Loader.applyStringSliceHack.
func AddHackedStringSliceP(fs *pflag.FlagSet, name, shorthand, usage string) {
fs.StringSliceP(name, shorthand, nil, usage)
}
// AddHackedStringSlice Hack for slice, see Loader.applyStringSliceHack.
func AddHackedStringSlice(fs *pflag.FlagSet, name, usage string) {
AddHackedStringSliceP(fs, name, "", usage)
}
// AddDeprecatedHackedStringSlice similar to AddHackedStringSlice but deprecate the flag.
func AddDeprecatedHackedStringSlice(fs *pflag.FlagSet, name, usage string) {
AddHackedStringSlice(fs, name, usage)
deprecateFlag(fs, name)
}
func deprecateFlag(fs *pflag.FlagSet, name string) {
_ = fs.MarkHidden(name)
_ = fs.MarkDeprecated(name, "check the documentation for more information.")
}

View File

@ -38,7 +38,6 @@ import (
"github.com/golangci/golangci-lint/pkg/lint/linter" "github.com/golangci/golangci-lint/pkg/lint/linter"
"github.com/golangci/golangci-lint/pkg/lint/lintersdb" "github.com/golangci/golangci-lint/pkg/lint/lintersdb"
"github.com/golangci/golangci-lint/pkg/logutils" "github.com/golangci/golangci-lint/pkg/logutils"
"github.com/golangci/golangci-lint/pkg/packages"
"github.com/golangci/golangci-lint/pkg/printers" "github.com/golangci/golangci-lint/pkg/printers"
"github.com/golangci/golangci-lint/pkg/report" "github.com/golangci/golangci-lint/pkg/report"
"github.com/golangci/golangci-lint/pkg/result" "github.com/golangci/golangci-lint/pkg/result"
@ -426,11 +425,7 @@ func (c *runCommand) printDeprecatedLinterMessages(enabledLinters map[string]*li
} }
func (c *runCommand) printStats(issues []result.Issue) { func (c *runCommand) printStats(issues []result.Issue) {
if c.cfg.Run.ShowStats { if !c.cfg.Output.ShowStats {
c.log.Warnf("The configuration option `run.show-stats` is deprecated, please use `output.show-stats`")
}
if !c.cfg.Run.ShowStats && !c.cfg.Output.ShowStats {
return return
} }
@ -465,7 +460,7 @@ func (c *runCommand) setupExitCode(ctx context.Context) {
return return
} }
needFailOnWarnings := os.Getenv(lintersdb.EnvTestRun) == "1" || os.Getenv(envFailOnWarnings) == "1" needFailOnWarnings := os.Getenv(logutils.EnvTestRun) == "1" || os.Getenv(envFailOnWarnings) == "1"
if needFailOnWarnings && len(c.reportData.Warnings) != 0 { if needFailOnWarnings && len(c.reportData.Warnings) != 0 {
c.exitCode = exitcodes.WarningInTest c.exitCode = exitcodes.WarningInTest
return return
@ -578,27 +573,6 @@ func setupConfigFileFlagSet(fs *pflag.FlagSet, cfg *config.LoaderOptions) {
fs.BoolVar(&cfg.NoConfig, "no-config", false, color.GreenString("Don't read config file")) fs.BoolVar(&cfg.NoConfig, "no-config", false, color.GreenString("Don't read config file"))
} }
func getDefaultIssueExcludeHelp() string {
parts := []string{color.GreenString("Use or not use default excludes:")}
for _, ep := range config.DefaultExcludePatterns {
parts = append(parts,
fmt.Sprintf(" # %s %s: %s", ep.ID, ep.Linter, ep.Why),
fmt.Sprintf(" - %s", color.YellowString(ep.Pattern)),
"",
)
}
return strings.Join(parts, "\n")
}
func getDefaultDirectoryExcludeHelp() string {
parts := []string{color.GreenString("Use or not use default excluded directories:")}
for _, dir := range packages.StdExcludeDirRegexps {
parts = append(parts, fmt.Sprintf(" - %s", color.YellowString(dir)))
}
parts = append(parts, "")
return strings.Join(parts, "\n")
}
func setupRunPersistentFlags(fs *pflag.FlagSet, opts *runOptions) { func setupRunPersistentFlags(fs *pflag.FlagSet, opts *runOptions) {
fs.BoolVar(&opts.PrintResourcesUsage, "print-resources-usage", false, fs.BoolVar(&opts.PrintResourcesUsage, "print-resources-usage", false,
color.GreenString("Print avg and max memory usage of golangci-lint and total time")) color.GreenString("Print avg and max memory usage of golangci-lint and total time"))

View File

@ -112,6 +112,10 @@ type Issues struct {
ExcludeGeneratedStrict bool `mapstructure:"exclude-generated-strict"` ExcludeGeneratedStrict bool `mapstructure:"exclude-generated-strict"`
UseDefaultExcludes bool `mapstructure:"exclude-use-default"` UseDefaultExcludes bool `mapstructure:"exclude-use-default"`
ExcludeFiles []string `mapstructure:"exclude-files"`
ExcludeDirs []string `mapstructure:"exclude-dirs"`
UseDefaultExcludeDirs bool `mapstructure:"exclude-dirs-use-default"`
MaxIssuesPerLinter int `mapstructure:"max-issues-per-linter"` MaxIssuesPerLinter int `mapstructure:"max-issues-per-linter"`
MaxSameIssues int `mapstructure:"max-same-issues"` MaxSameIssues int `mapstructure:"max-same-issues"`

View File

@ -61,6 +61,8 @@ func (l *Loader) Load() error {
l.handleGoVersion() l.handleGoVersion()
l.handleDeprecation()
err = l.handleEnableOnlyOption() err = l.handleEnableOnlyOption()
if err != nil { if err != nil {
return err return err
@ -69,51 +71,6 @@ func (l *Loader) Load() error {
return nil return nil
} }
func (l *Loader) handleEnableOnlyOption() error {
only, err := l.fs.GetStringSlice("enable-only")
if err != nil {
return err
}
if len(only) > 0 {
l.cfg.Linters = Linters{
Enable: only,
DisableAll: true,
}
}
return nil
}
func (l *Loader) handleGoVersion() {
if l.cfg.Run.Go == "" {
l.cfg.Run.Go = detectGoVersion()
}
l.cfg.LintersSettings.Govet.Go = l.cfg.Run.Go
l.cfg.LintersSettings.ParallelTest.Go = l.cfg.Run.Go
if l.cfg.LintersSettings.Gofumpt.LangVersion == "" {
l.cfg.LintersSettings.Gofumpt.LangVersion = l.cfg.Run.Go
}
trimmedGoVersion := trimGoVersion(l.cfg.Run.Go)
l.cfg.LintersSettings.Gocritic.Go = trimmedGoVersion
// staticcheck related linters.
if l.cfg.LintersSettings.Staticcheck.GoVersion == "" {
l.cfg.LintersSettings.Staticcheck.GoVersion = trimmedGoVersion
}
if l.cfg.LintersSettings.Gosimple.GoVersion == "" {
l.cfg.LintersSettings.Gosimple.GoVersion = trimmedGoVersion
}
if l.cfg.LintersSettings.Stylecheck.GoVersion != "" {
l.cfg.LintersSettings.Stylecheck.GoVersion = trimmedGoVersion
}
}
func (l *Loader) setConfigFile() error { func (l *Loader) setConfigFile() error {
configFile, err := l.evaluateOptions() configFile, err := l.evaluateOptions()
if err != nil { if err != nil {
@ -278,9 +235,12 @@ func (l *Loader) applyStringSliceHack() {
l.appendStringSlice("disable", &l.cfg.Linters.Disable) l.appendStringSlice("disable", &l.cfg.Linters.Disable)
l.appendStringSlice("presets", &l.cfg.Linters.Presets) l.appendStringSlice("presets", &l.cfg.Linters.Presets)
l.appendStringSlice("build-tags", &l.cfg.Run.BuildTags) l.appendStringSlice("build-tags", &l.cfg.Run.BuildTags)
l.appendStringSlice("exclude", &l.cfg.Issues.ExcludePatterns)
l.appendStringSlice("skip-dirs", &l.cfg.Run.SkipDirs) l.appendStringSlice("skip-dirs", &l.cfg.Run.SkipDirs)
l.appendStringSlice("skip-files", &l.cfg.Run.SkipFiles) l.appendStringSlice("skip-files", &l.cfg.Run.SkipFiles)
l.appendStringSlice("exclude", &l.cfg.Issues.ExcludePatterns) l.appendStringSlice("exclude-dirs", &l.cfg.Issues.ExcludeDirs)
l.appendStringSlice("exclude-files", &l.cfg.Issues.ExcludeFiles)
} }
func (l *Loader) appendStringSlice(name string, current *[]string) { func (l *Loader) appendStringSlice(name string, current *[]string) {
@ -290,6 +250,83 @@ func (l *Loader) appendStringSlice(name string, current *[]string) {
} }
} }
func (l *Loader) handleGoVersion() {
if l.cfg.Run.Go == "" {
l.cfg.Run.Go = detectGoVersion()
}
l.cfg.LintersSettings.Govet.Go = l.cfg.Run.Go
l.cfg.LintersSettings.ParallelTest.Go = l.cfg.Run.Go
if l.cfg.LintersSettings.Gofumpt.LangVersion == "" {
l.cfg.LintersSettings.Gofumpt.LangVersion = l.cfg.Run.Go
}
trimmedGoVersion := trimGoVersion(l.cfg.Run.Go)
l.cfg.LintersSettings.Gocritic.Go = trimmedGoVersion
// staticcheck related linters.
if l.cfg.LintersSettings.Staticcheck.GoVersion == "" {
l.cfg.LintersSettings.Staticcheck.GoVersion = trimmedGoVersion
}
if l.cfg.LintersSettings.Gosimple.GoVersion == "" {
l.cfg.LintersSettings.Gosimple.GoVersion = trimmedGoVersion
}
if l.cfg.LintersSettings.Stylecheck.GoVersion != "" {
l.cfg.LintersSettings.Stylecheck.GoVersion = trimmedGoVersion
}
}
func (l *Loader) handleDeprecation() {
if len(l.cfg.Run.SkipFiles) > 0 {
l.warn("The configuration option `run.skip-files` is deprecated, please use `issues.exclude-files`.")
l.cfg.Issues.ExcludeFiles = l.cfg.Run.SkipFiles
}
if len(l.cfg.Run.SkipDirs) > 0 {
l.warn("The configuration option `run.skip-dirs` is deprecated, please use `issues.exclude-dirs`.")
l.cfg.Issues.ExcludeDirs = l.cfg.Run.SkipDirs
}
// The 2 options are true by default.
if !l.cfg.Run.UseDefaultSkipDirs {
l.warn("The configuration option `run.skip-dirs-use-default` is deprecated, please use `issues.exclude-dirs-use-default`.")
}
l.cfg.Issues.UseDefaultExcludeDirs = l.cfg.Run.UseDefaultSkipDirs && l.cfg.Issues.UseDefaultExcludeDirs
// The 2 options are false by default.
if l.cfg.Run.ShowStats {
l.warn("The configuration option `run.show-stats` is deprecated, please use `output.show-stats`")
}
l.cfg.Output.ShowStats = l.cfg.Run.ShowStats || l.cfg.Output.ShowStats
}
func (l *Loader) handleEnableOnlyOption() error {
only, err := l.fs.GetStringSlice("enable-only")
if err != nil {
return err
}
if len(only) > 0 {
l.cfg.Linters = Linters{
Enable: only,
DisableAll: true,
}
}
return nil
}
func (l *Loader) warn(format string) {
if l.cfg.InternalTest || l.cfg.InternalCmdTest || os.Getenv(logutils.EnvTestRun) == "1" {
return
}
l.log.Warnf(format)
}
func fileDecoderHook() viper.DecoderConfigOption { func fileDecoderHook() viper.DecoderConfigOption {
return viper.DecodeHook(mapstructure.ComposeDecodeHookFunc( return viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
// Default hooks (https://github.com/spf13/viper/blob/518241257478c557633ab36e474dfcaeb9a3c623/viper.go#L135-L138). // Default hooks (https://github.com/spf13/viper/blob/518241257478c557633ab36e474dfcaeb9a3c623/viper.go#L135-L138).

View File

@ -16,9 +16,12 @@ type Run struct {
ExitCodeIfIssuesFound int `mapstructure:"issues-exit-code"` ExitCodeIfIssuesFound int `mapstructure:"issues-exit-code"`
AnalyzeTests bool `mapstructure:"tests"` AnalyzeTests bool `mapstructure:"tests"`
SkipFiles []string `mapstructure:"skip-files"` // Deprecated: use Issues.ExcludeFiles instead.
SkipDirs []string `mapstructure:"skip-dirs"` SkipFiles []string `mapstructure:"skip-files"`
UseDefaultSkipDirs bool `mapstructure:"skip-dirs-use-default"` // Deprecated: use Issues.ExcludeDirs instead.
SkipDirs []string `mapstructure:"skip-dirs"`
// Deprecated: use Issues.UseDefaultExcludeDirs instead.
UseDefaultSkipDirs bool `mapstructure:"skip-dirs-use-default"`
AllowParallelRunners bool `mapstructure:"allow-parallel-runners"` AllowParallelRunners bool `mapstructure:"allow-parallel-runners"`
AllowSerialRunners bool `mapstructure:"allow-serial-runners"` AllowSerialRunners bool `mapstructure:"allow-serial-runners"`

View File

@ -12,7 +12,7 @@ func NewGochecknoglobals() *goanalysis.Linter {
// gochecknoglobals only lints test files if the `-t` flag is passed, // gochecknoglobals only lints test files if the `-t` flag is passed,
// so we pass the `t` flag as true to the analyzer before running it. // so we pass the `t` flag as true to the analyzer before running it.
// This can be turned off by using the regular golangci-lint flags such as `--tests` or `--skip-files`. // This can be turned off by using the regular golangci-lint flags such as `--tests` or `--exclude-files`.
linterConfig := map[string]map[string]any{ linterConfig := map[string]map[string]any{
a.Name: {"t": true}, a.Name: {"t": true},
} }

View File

@ -14,9 +14,6 @@ import (
"github.com/golangci/golangci-lint/pkg/logutils" "github.com/golangci/golangci-lint/pkg/logutils"
) )
// EnvTestRun value: "1"
const EnvTestRun = "GL_TEST_RUN"
type Builder interface { type Builder interface {
Build(cfg *config.Config) ([]*linter.Config, error) Build(cfg *config.Config) ([]*linter.Config, error)
} }
@ -97,7 +94,7 @@ func (m *Manager) GetAllLinterConfigsForPreset(p string) []*linter.Config {
func (m *Manager) GetEnabledLintersMap() (map[string]*linter.Config, error) { func (m *Manager) GetEnabledLintersMap() (map[string]*linter.Config, error) {
enabledLinters := m.build(m.GetAllEnabledByDefaultLinters()) enabledLinters := m.build(m.GetAllEnabledByDefaultLinters())
if os.Getenv(EnvTestRun) == "1" { if os.Getenv(logutils.EnvTestRun) == "1" {
m.verbosePrintLintersStatus(enabledLinters) m.verbosePrintLintersStatus(enabledLinters)
} }

View File

@ -41,15 +41,16 @@ func NewRunner(log logutils.Log, cfg *config.Config, goenv *goutil.Env,
// or process other paths (skip files). // or process other paths (skip files).
files := fsutils.NewFiles(lineCache, cfg.Output.PathPrefix) files := fsutils.NewFiles(lineCache, cfg.Output.PathPrefix)
skipFilesProcessor, err := processors.NewSkipFiles(cfg.Run.SkipFiles, cfg.Output.PathPrefix) skipFilesProcessor, err := processors.NewSkipFiles(cfg.Issues.ExcludeFiles, cfg.Output.PathPrefix)
if err != nil { if err != nil {
return nil, err return nil, err
} }
skipDirs := cfg.Run.SkipDirs skipDirs := cfg.Issues.ExcludeDirs
if cfg.Run.UseDefaultSkipDirs { if cfg.Issues.UseDefaultExcludeDirs {
skipDirs = append(skipDirs, packages.StdExcludeDirRegexps...) skipDirs = append(skipDirs, packages.StdExcludeDirRegexps...)
} }
skipDirsProcessor, err := processors.NewSkipDirs(skipDirs, log.Child(logutils.DebugKeySkipDirs), cfg.Run.Args, cfg.Output.PathPrefix) skipDirsProcessor, err := processors.NewSkipDirs(skipDirs, log.Child(logutils.DebugKeySkipDirs), cfg.Run.Args, cfg.Output.PathPrefix)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -5,6 +5,9 @@ import (
"strings" "strings"
) )
// EnvTestRun value: "1"
const EnvTestRun = "GL_TEST_RUN"
// envDebug value: one or several debug keys. // envDebug value: one or several debug keys.
// examples: // examples:
// - Remove output to `/dev/null`: `GL_DEBUG=linters_output ./golangci-lint run` // - Remove output to `/dev/null`: `GL_DEBUG=linters_output ./golangci-lint run`

View File

@ -10,12 +10,13 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/golangci/golangci-lint/pkg/lint/lintersdb" "github.com/golangci/golangci-lint/pkg/lint/lintersdb"
"github.com/golangci/golangci-lint/pkg/logutils"
"github.com/golangci/golangci-lint/test/testshared" "github.com/golangci/golangci-lint/test/testshared"
) )
func TestEnabledLinters(t *testing.T) { func TestEnabledLinters(t *testing.T) {
// require to display the message "Active x linters: [x,y]" // require to display the message "Active x linters: [x,y]"
t.Setenv(lintersdb.EnvTestRun, "1") t.Setenv(logutils.EnvTestRun, "1")
cases := []struct { cases := []struct {
name string name string

View File

@ -370,7 +370,7 @@ func TestSkippedDirsNoMatchArg(t *testing.T) {
WithNoConfig(). WithNoConfig().
WithArgs( WithArgs(
"--print-issued-lines=false", "--print-issued-lines=false",
"--skip-dirs", dir, "--exclude-dirs", dir,
"-Erevive", "-Erevive",
). ).
WithTargetPath(dir). WithTargetPath(dir).