Skip to content

Commit

Permalink
Add gomoddirectives linter. (#1817)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez committed Mar 9, 2021
1 parent c11228b commit 94d2d80
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 1 deletion.
10 changes: 10 additions & 0 deletions .golangci.example.yml
Expand Up @@ -449,6 +449,16 @@ linters-settings:
servingv1: knative.dev/serving/pkg/apis/serving/v1
# using `autoscalingv1alpha1` alias for `knative.dev/serving/pkg/apis/autoscaling/v1alpha1` package
autoscalingv1alpha1: knative.dev/serving/pkg/apis/autoscaling/v1alpha1
gomoddirectives:
# Allow local `replace` directives. Default is false.
replace-local: false
# List of allowed `replace` directives. Default is empty.
replace-allow-list:
- launchpad.net/gocheck
# Allow to not explain why the version has been retracted in the `retract` directives. Default is false.
retract-allow-no-explanation: false
# Forbid the use of the `exclude` directives. Default is false.
exclude-forbidden: false

# The custom section can be used to define linter plugins to be loaded at runtime. See README doc
# for more info.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -41,6 +41,7 @@ require (
github.com/kulti/thelper v0.4.0
github.com/kunwardeep/paralleltest v1.0.2
github.com/kyoh86/exportloopref v0.1.8
github.com/ldez/gomoddirectives v0.2.1
github.com/maratori/testpackage v1.0.1
github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // v1.0
github.com/mattn/go-colorable v0.1.8
Expand Down
5 changes: 4 additions & 1 deletion go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions pkg/config/config.go
Expand Up @@ -276,6 +276,7 @@ type LintersSettings struct {
Predeclared PredeclaredSettings
Cyclop Cyclop
ImportAs ImportAsSettings
GoModDirectives GoModDirectivesSettings

Custom map[string]CustomLinterSettings
}
Expand Down Expand Up @@ -464,6 +465,13 @@ type Cyclop struct {

type ImportAsSettings map[string]string

type GoModDirectivesSettings struct {
ReplaceAllowList []string `mapstructure:"replace-allow-list"`
ReplaceLocal bool `mapstructure:"replace-local"`
ExcludeForbidden bool `mapstructure:"exclude-forbidden"`
RetractAllowNoExplanation bool `mapstructure:"retract-allow-no-explanation"`
}

var defaultLintersSettings = LintersSettings{
Lll: LllSettings{
LineLength: 120,
Expand Down
64 changes: 64 additions & 0 deletions pkg/golinters/gomoddirectives.go
@@ -0,0 +1,64 @@
package golinters

import (
"sync"

"github.com/ldez/gomoddirectives"
"golang.org/x/tools/go/analysis"

"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/result"
)

const goModDirectivesName = "gomoddirectives"

// NewGoModDirectives returns a new gomoddirectives linter.
func NewGoModDirectives(settings *config.GoModDirectivesSettings) *goanalysis.Linter {
var issues []goanalysis.Issue
var once sync.Once

var opts gomoddirectives.Options
if settings != nil {
opts.ReplaceAllowLocal = settings.ReplaceLocal
opts.ReplaceAllowList = settings.ReplaceAllowList
opts.RetractAllowNoExplanation = settings.RetractAllowNoExplanation
opts.ExcludeForbidden = settings.ExcludeForbidden
}

analyzer := &analysis.Analyzer{
Name: goanalysis.TheOnlyAnalyzerName,
Doc: goanalysis.TheOnlyanalyzerDoc,
}

return goanalysis.NewLinter(
goModDirectivesName,
"Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod.",
[]*analysis.Analyzer{analyzer},
nil,
).WithContextSetter(func(lintCtx *linter.Context) {
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
once.Do(func() {
results, err := gomoddirectives.Analyze(opts)
if err != nil {
lintCtx.Log.Warnf("running %s failed: %s: "+
"if you are not using go modules it is suggested to disable this linter", goModDirectivesName, err)
return
}

for _, p := range results {
issues = append(issues, goanalysis.NewIssue(&result.Issue{
FromLinter: goModDirectivesName,
Pos: p.Start,
Text: p.Reason,
}, pass))
}
})

return nil, nil
}
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
return issues
}).WithLoadMode(goanalysis.LoadModeSyntax)
}
6 changes: 6 additions & 0 deletions pkg/lint/lintersdb/manager.go
Expand Up @@ -100,6 +100,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
var reviveCfg *config.ReviveSettings
var cyclopCfg *config.Cyclop
var importAsCfg *config.ImportAsSettings
var goModDirectivesCfg *config.GoModDirectivesSettings
if m.cfg != nil {
govetCfg = &m.cfg.LintersSettings.Govet
testpackageCfg = &m.cfg.LintersSettings.Testpackage
Expand All @@ -112,6 +113,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
reviveCfg = &m.cfg.LintersSettings.Revive
cyclopCfg = &m.cfg.LintersSettings.Cyclop
importAsCfg = &m.cfg.LintersSettings.ImportAs
goModDirectivesCfg = &m.cfg.LintersSettings.GoModDirectives
}
const megacheckName = "megacheck"
lcs := []*linter.Config{
Expand Down Expand Up @@ -394,6 +396,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetStyle).
WithLoadForGoAnalysis().
WithURL("https://github.com/gostaticanalysis/forcetypeassert"),
linter.NewConfig(golinters.NewGoModDirectives(goModDirectivesCfg)).
WithPresets(linter.PresetStyle).
WithLoadForGoAnalysis().
WithURL("https://github.com/ldez/gomoddirectives"),

// nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives
linter.NewConfig(golinters.NewNoLintLint()).
Expand Down
4 changes: 4 additions & 0 deletions pkg/result/processors/autogenerated_exclude.go
Expand Up @@ -53,6 +53,10 @@ func (p *AutogeneratedExclude) shouldPassIssue(i *result.Issue) (bool, error) {
return true, nil
}

if filepath.Base(i.FilePath()) == "go.mod" {
return true, nil
}

if isSpecialAutogeneratedFile(i.FilePath()) {
return false, nil
}
Expand Down

0 comments on commit 94d2d80

Please sign in to comment.