diff --git a/docs/src/docs/contributing/new-linters.mdx b/docs/src/docs/contributing/new-linters.mdx index b5a9900b..ec82ec88 100644 --- a/docs/src/docs/contributing/new-linters.mdx +++ b/docs/src/docs/contributing/new-linters.mdx @@ -83,8 +83,11 @@ If you're looking for instructions on how to configure your own custom linter, t That is all the configuration that is required to run a custom linter in your project. -Custom linters are disabled by default, and are not enabled when `linters.enable-all` is specified. -They can be enabled by adding them the `linters.enable` list, or providing the enabled option on the command line (`golangci-lint run -Eexample`). +Custom linters are enabled by default, but abide by the same rules as other linters. + +If the disable all option is specified either on command line or in `.golang.yml` files `linters.disable-all: true`, custom linters will be disabled; +they can be re-enabled by adding them to the `linters:enable` list, +or providing the enabled option on the command line, `golangci-lint run -Eexample`. The configuration inside the `settings` field of linter have some limitations (there are NOT related to the plugin system itself): we use Viper to handle the configuration but Viper put all the keys in lowercase, and `.` cannot be used inside a key. diff --git a/pkg/commands/executor.go b/pkg/commands/executor.go index 109edcb9..61e221cb 100644 --- a/pkg/commands/executor.go +++ b/pkg/commands/executor.go @@ -120,7 +120,7 @@ func NewExecutor(buildInfo BuildInfo) *Executor { } // recreate after getting config - e.DBManager = lintersdb.NewManager(e.cfg, e.log).WithCustomLinters() + e.DBManager = lintersdb.NewManager(e.cfg, e.log) // Slice options must be explicitly set for proper merging of config and command-line options. fixSlicesFlags(e.runCmd.Flags()) diff --git a/pkg/lint/lintersdb/custom_linters.go b/pkg/lint/lintersdb/custom_linters.go index 69989abd..bb1c61c0 100644 --- a/pkg/lint/lintersdb/custom_linters.go +++ b/pkg/lint/lintersdb/custom_linters.go @@ -12,35 +12,30 @@ import ( "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/logutils" - "github.com/golangci/golangci-lint/pkg/report" ) type AnalyzerPlugin interface { GetAnalyzers() []*analysis.Analyzer } -// WithCustomLinters loads private linters that are specified in the golangci config file. -func (m *Manager) WithCustomLinters() *Manager { - if m.log == nil { - m.log = report.NewLogWrapper(logutils.NewStderrLog(logutils.DebugKeyEmpty), &report.Data{}) +// getCustomLinterConfigs loads private linters that are specified in the golangci config file. +func (m *Manager) getCustomLinterConfigs() []*linter.Config { + if m.cfg == nil || m.log == nil { + return nil } - if m.cfg == nil { - return m - } + var linters []*linter.Config for name, settings := range m.cfg.LintersSettings.Custom { lc, err := m.loadCustomLinterConfig(name, settings) - if err != nil { m.log.Errorf("Unable to load custom analyzer %s:%s, %v", name, settings.Path, err) } else { - m.nameToLCs[name] = append(m.nameToLCs[name], lc) + linters = append(linters, lc) } } - return m + return linters } // loadCustomLinterConfig loads the configuration of private linters. diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index b01d6116..ca227c9a 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -8,13 +8,16 @@ import ( ) type Manager struct { - nameToLCs map[string][]*linter.Config - cfg *config.Config - log logutils.Log + cfg *config.Config + log logutils.Log + + nameToLCs map[string][]*linter.Config + customLinters []*linter.Config } func NewManager(cfg *config.Config, log logutils.Log) *Manager { m := &Manager{cfg: cfg, log: log} + m.customLinters = m.getCustomLinterConfigs() nameToLCs := make(map[string][]*linter.Config) for _, lc := range m.GetAllSupportedLinterConfigs() { @@ -247,9 +250,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { const megacheckName = "megacheck" + var linters []*linter.Config + linters = append(linters, m.customLinters...) + // The linters are sorted in the alphabetical order (case-insensitive). // When a new linter is added the version in `WithSince(...)` must be the next minor version of golangci-lint. - return []*linter.Config{ + linters = append(linters, linter.NewConfig(golinters.NewAsasalint(asasalintCfg)). WithSince("1.47.0"). WithPresets(linter.PresetBugs). @@ -867,18 +873,20 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetStyle). WithURL("https://github.com/bombsimon/wsl"), - // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives - linter.NewConfig(golinters.NewNoLintLint(noLintLintCfg)). - WithSince("v1.26.0"). - WithPresets(linter.PresetStyle). - WithURL("https://github.com/golangci/golangci-lint/blob/master/pkg/golinters/nolintlint/README.md"), - linter.NewConfig(golinters.NewZerologLint()). WithSince("v1.53.0"). WithPresets(linter.PresetBugs). WithLoadForGoAnalysis(). WithURL("https://github.com/ykadowak/zerologlint"), - } + + // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives + linter.NewConfig(golinters.NewNoLintLint(noLintLintCfg)). + WithSince("v1.26.0"). + WithPresets(linter.PresetStyle). + WithURL("https://github.com/golangci/golangci-lint/blob/master/pkg/golinters/nolintlint/README.md"), + ) + + return linters } func (m Manager) GetAllEnabledByDefaultLinters() []*linter.Config {