From a3a04552bb298da41d85dc6c7c0f19e3f5f1b1cc Mon Sep 17 00:00:00 2001 From: Aleksandr Razumov Date: Sat, 9 Feb 2019 03:24:30 +0300 Subject: [PATCH] add support for exclude rules --- pkg/config/config.go | 11 ++- pkg/lint/runner.go | 10 +++ pkg/result/processors/exclude_rules.go | 86 +++++++++++++++++++++ pkg/result/processors/exclude_rules_test.go | 34 ++++++++ 4 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 pkg/result/processors/exclude_rules.go create mode 100644 pkg/result/processors/exclude_rules_test.go diff --git a/pkg/config/config.go b/pkg/config/config.go index cb5b4dd8..58a8c2d9 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -227,9 +227,16 @@ type Linters struct { Presets []string } +type ExcludeRule struct { + Linters []string + Path string + Text string +} + type Issues struct { - ExcludePatterns []string `mapstructure:"exclude"` - UseDefaultExcludes bool `mapstructure:"exclude-use-default"` + ExcludePatterns []string `mapstructure:"exclude"` + ExcludeRules []ExcludeRule `mapstructure:"exclude-rules"` + UseDefaultExcludes bool `mapstructure:"exclude-use-default"` MaxIssuesPerLinter int `mapstructure:"max-issues-per-linter"` MaxSameIssues int `mapstructure:"max-same-issues"` diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go index cd6c9a4e..0ebdfd18 100644 --- a/pkg/lint/runner.go +++ b/pkg/lint/runner.go @@ -49,6 +49,15 @@ func NewRunner(astCache *astcache.Cache, cfg *config.Config, log logutils.Log, g return nil, err } + var excludeRules []processors.ExcludeRule + for _, r := range icfg.ExcludeRules { + excludeRules = append(excludeRules, processors.ExcludeRule{ + Text: r.Text, + Path: r.Path, + Linters: r.Linters, + }) + } + return &Runner{ Processors: []processors.Processor{ processors.NewPathPrettifier(), // must be before diff, nolint and exclude autogenerated processor at least @@ -58,6 +67,7 @@ func NewRunner(astCache *astcache.Cache, cfg *config.Config, log logutils.Log, g processors.NewAutogeneratedExclude(astCache), processors.NewExclude(excludeTotalPattern), + processors.NewExcludeRules(excludeRules), processors.NewNolint(astCache, log.Child("nolint")), processors.NewUniqByLine(), diff --git a/pkg/result/processors/exclude_rules.go b/pkg/result/processors/exclude_rules.go new file mode 100644 index 00000000..dec3a57e --- /dev/null +++ b/pkg/result/processors/exclude_rules.go @@ -0,0 +1,86 @@ +package processors + +import ( + "regexp" + + "github.com/golangci/golangci-lint/pkg/result" +) + +type excludeRule struct { + text *regexp.Regexp + path *regexp.Regexp + linters []string +} + +func (r *excludeRule) isEmpty() bool { + return r.text == nil && r.path == nil && len(r.linters) == 0 +} + +func (r excludeRule) Match(i *result.Issue) bool { + if r.isEmpty() { + return false + } + if r.text != nil && !r.text.MatchString(i.Text) { + return false + } + if r.path != nil && !r.path.MatchString(i.FilePath()) { + return false + } + if len(r.linters) == 0 { + return true + } + for _, l := range r.linters { + if l == i.FromLinter { + return true + } + } + return false +} + +type ExcludeRule struct { + Text string + Path string + Linters []string +} + +func NewExcludeRules(rules []ExcludeRule) *ExcludeRules { + r := new(ExcludeRules) + for _, rule := range rules { + parsedRule := excludeRule{ + linters: rule.Linters, + } + if rule.Text != "" { + parsedRule.text = regexp.MustCompile("(?i)" + rule.Text) + } + if rule.Path != "" { + parsedRule.path = regexp.MustCompile(rule.Path) + } + // TODO: Forbid text-only, linter-only or path-only exclude rule. + r.rules = append(r.rules, parsedRule) + } + return r +} + +type ExcludeRules struct { + rules []excludeRule +} + +func (r ExcludeRules) Process(issues []result.Issue) ([]result.Issue, error) { + if len(r.rules) == 0 { + return issues, nil + } + // TODO: Concurrency? + return filterIssues(issues, func(i *result.Issue) bool { + for _, rule := range r.rules { + if rule.Match(i) { + return false + } + } + return true + }), nil +} + +func (ExcludeRules) Name() string { return "exclude-rules" } +func (ExcludeRules) Finish() {} + +var _ Processor = ExcludeRules{} diff --git a/pkg/result/processors/exclude_rules_test.go b/pkg/result/processors/exclude_rules_test.go new file mode 100644 index 00000000..94074be0 --- /dev/null +++ b/pkg/result/processors/exclude_rules_test.go @@ -0,0 +1,34 @@ +package processors + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/golangci/golangci-lint/pkg/result" +) + +func TestExcludeRules(t *testing.T) { + p := NewExcludeRules([]ExcludeRule{ + { + Text: "^exclude$", + }, + }) + texts := []string{"excLude", "1", "", "exclud", "notexclude"} + var issues []result.Issue + for _, t := range texts { + issues = append(issues, newTextIssue(t)) + } + + processedIssues := process(t, p, issues...) + assert.Len(t, processedIssues, len(issues)-1) + + var processedTexts []string + for _, i := range processedIssues { + processedTexts = append(processedTexts, i.Text) + } + assert.Equal(t, texts[1:], processedTexts) + t.Run("Empty", func(t *testing.T) { + processAssertSame(t, NewExcludeRules(nil), newTextIssue("test")) + }) +}