Merge pull request #1036 from iwankgb/exclude-case-sensitive
Adding case-sensitive exclude processor
This commit is contained in:
commit
e2b927f029
@ -574,6 +574,7 @@ Flags:
|
|||||||
# gosec: False positive is triggered by 'src, err := ioutil.ReadFile(filename)'
|
# gosec: False positive is triggered by 'src, err := ioutil.ReadFile(filename)'
|
||||||
- Potential file inclusion via variable
|
- Potential file inclusion via variable
|
||||||
(default true)
|
(default true)
|
||||||
|
--exclude-case-sensitive If set to true exclude and exclude rules regular expressions are case sensitive
|
||||||
--max-issues-per-linter int Maximum issues count per one linter. Set to 0 to disable (default 50)
|
--max-issues-per-linter int Maximum issues count per one linter. Set to 0 to disable (default 50)
|
||||||
--max-same-issues int Maximum count of issues with the same text. Set to 0 to disable (default 3)
|
--max-same-issues int Maximum count of issues with the same text. Set to 0 to disable (default 3)
|
||||||
-n, --new Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.
|
-n, --new Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.
|
||||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
@ -189,6 +189,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, is
|
|||||||
ic := &cfg.Issues
|
ic := &cfg.Issues
|
||||||
fs.StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", nil, wh("Exclude issue by regexp"))
|
fs.StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", nil, wh("Exclude issue by regexp"))
|
||||||
fs.BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, getDefaultIssueExcludeHelp())
|
fs.BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, getDefaultIssueExcludeHelp())
|
||||||
|
fs.BoolVar(&ic.ExcludeCaseSensitive, "exclude-case-sensitive", false, wh("If set to true exclude "+
|
||||||
|
"and exclude rules regular expressions are case sensitive"))
|
||||||
|
|
||||||
fs.IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50,
|
fs.IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50,
|
||||||
wh("Maximum issues count per one linter. Set to 0 to disable"))
|
wh("Maximum issues count per one linter. Set to 0 to disable"))
|
||||||
|
@ -411,9 +411,10 @@ func (e ExcludeRule) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Issues struct {
|
type Issues struct {
|
||||||
ExcludePatterns []string `mapstructure:"exclude"`
|
ExcludeCaseSensitive bool `mapstructure:"exclude-case-sensitive"`
|
||||||
ExcludeRules []ExcludeRule `mapstructure:"exclude-rules"`
|
ExcludePatterns []string `mapstructure:"exclude"`
|
||||||
UseDefaultExcludes bool `mapstructure:"exclude-use-default"`
|
ExcludeRules []ExcludeRule `mapstructure:"exclude-rules"`
|
||||||
|
UseDefaultExcludes bool `mapstructure:"exclude-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"`
|
||||||
|
@ -40,6 +40,13 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
|
|||||||
excludeTotalPattern = fmt.Sprintf("(%s)", strings.Join(excludePatterns, "|"))
|
excludeTotalPattern = fmt.Sprintf("(%s)", strings.Join(excludePatterns, "|"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var excludeProcessor processors.Processor
|
||||||
|
if cfg.Issues.ExcludeCaseSensitive {
|
||||||
|
excludeProcessor = processors.NewExcludeCaseSensitive(excludeTotalPattern)
|
||||||
|
} else {
|
||||||
|
excludeProcessor = processors.NewExclude(excludeTotalPattern)
|
||||||
|
}
|
||||||
|
|
||||||
skipFilesProcessor, err := processors.NewSkipFiles(cfg.Run.SkipFiles)
|
skipFilesProcessor, err := processors.NewSkipFiles(cfg.Run.SkipFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -63,6 +70,12 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
|
|||||||
Linters: r.Linters,
|
Linters: r.Linters,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
var excludeRulesProcessor processors.Processor
|
||||||
|
if cfg.Issues.ExcludeCaseSensitive {
|
||||||
|
excludeRulesProcessor = processors.NewExcludeRulesCaseSensitive(excludeRules, lineCache, log.Child("exclude_rules"))
|
||||||
|
} else {
|
||||||
|
excludeRulesProcessor = processors.NewExcludeRules(excludeRules, lineCache, log.Child("exclude_rules"))
|
||||||
|
}
|
||||||
|
|
||||||
return &Runner{
|
return &Runner{
|
||||||
Processors: []processors.Processor{
|
Processors: []processors.Processor{
|
||||||
@ -81,8 +94,8 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
|
|||||||
// Must be before exclude because users see already marked output and configure excluding by it.
|
// Must be before exclude because users see already marked output and configure excluding by it.
|
||||||
processors.NewIdentifierMarker(),
|
processors.NewIdentifierMarker(),
|
||||||
|
|
||||||
processors.NewExclude(excludeTotalPattern),
|
excludeProcessor,
|
||||||
processors.NewExcludeRules(excludeRules, lineCache, log.Child("exclude_rules")),
|
excludeRulesProcessor,
|
||||||
processors.NewNolint(log.Child("nolint"), dbManager),
|
processors.NewNolint(log.Child("nolint"), dbManager),
|
||||||
|
|
||||||
processors.NewUniqByLine(cfg),
|
processors.NewUniqByLine(cfg),
|
||||||
|
@ -37,3 +37,23 @@ func (p Exclude) Process(issues []result.Issue) ([]result.Issue, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p Exclude) Finish() {}
|
func (p Exclude) Finish() {}
|
||||||
|
|
||||||
|
type ExcludeCaseSensitive struct {
|
||||||
|
*Exclude
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Processor = ExcludeCaseSensitive{}
|
||||||
|
|
||||||
|
func NewExcludeCaseSensitive(pattern string) *ExcludeCaseSensitive {
|
||||||
|
var patternRe *regexp.Regexp
|
||||||
|
if pattern != "" {
|
||||||
|
patternRe = regexp.MustCompile(pattern)
|
||||||
|
}
|
||||||
|
return &ExcludeCaseSensitive{
|
||||||
|
&Exclude{pattern: patternRe},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ExcludeCaseSensitive) Name() string {
|
||||||
|
return "exclude-case-sensitive"
|
||||||
|
}
|
||||||
|
@ -37,24 +37,29 @@ func NewExcludeRules(rules []ExcludeRule, lineCache *fsutils.LineCache, log logu
|
|||||||
lineCache: lineCache,
|
lineCache: lineCache,
|
||||||
log: log,
|
log: log,
|
||||||
}
|
}
|
||||||
|
r.rules = createRules(rules, "(?i)")
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func createRules(rules []ExcludeRule, prefix string) []excludeRule {
|
||||||
|
parsedRules := make([]excludeRule, 0, len(rules))
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
parsedRule := excludeRule{
|
parsedRule := excludeRule{
|
||||||
linters: rule.Linters,
|
linters: rule.Linters,
|
||||||
}
|
}
|
||||||
if rule.Text != "" {
|
if rule.Text != "" {
|
||||||
parsedRule.text = regexp.MustCompile("(?i)" + rule.Text)
|
parsedRule.text = regexp.MustCompile(prefix + rule.Text)
|
||||||
}
|
}
|
||||||
if rule.Source != "" {
|
if rule.Source != "" {
|
||||||
parsedRule.source = regexp.MustCompile("(?i)" + rule.Source)
|
parsedRule.source = regexp.MustCompile(prefix + rule.Source)
|
||||||
}
|
}
|
||||||
if rule.Path != "" {
|
if rule.Path != "" {
|
||||||
parsedRule.path = regexp.MustCompile(rule.Path)
|
parsedRule.path = regexp.MustCompile(rule.Path)
|
||||||
}
|
}
|
||||||
r.rules = append(r.rules, parsedRule)
|
parsedRules = append(parsedRules, parsedRule)
|
||||||
}
|
}
|
||||||
|
return parsedRules
|
||||||
return r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ExcludeRules) Process(issues []result.Issue) ([]result.Issue, error) {
|
func (p ExcludeRules) Process(issues []result.Issue) ([]result.Issue, error) {
|
||||||
@ -118,3 +123,21 @@ func (ExcludeRules) Name() string { return "exclude-rules" }
|
|||||||
func (ExcludeRules) Finish() {}
|
func (ExcludeRules) Finish() {}
|
||||||
|
|
||||||
var _ Processor = ExcludeRules{}
|
var _ Processor = ExcludeRules{}
|
||||||
|
|
||||||
|
type ExcludeRulesCaseSensitive struct {
|
||||||
|
*ExcludeRules
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewExcludeRulesCaseSensitive(rules []ExcludeRule, lineCache *fsutils.LineCache, log logutils.Log) *ExcludeRulesCaseSensitive {
|
||||||
|
r := &ExcludeRules{
|
||||||
|
lineCache: lineCache,
|
||||||
|
log: log,
|
||||||
|
}
|
||||||
|
r.rules = createRules(rules, "")
|
||||||
|
|
||||||
|
return &ExcludeRulesCaseSensitive{r}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ExcludeRulesCaseSensitive) Name() string { return "exclude-rules-case-sensitive" }
|
||||||
|
|
||||||
|
var _ Processor = ExcludeCaseSensitive{}
|
||||||
|
@ -31,26 +31,12 @@ func TestExcludeRulesMultiple(t *testing.T) {
|
|||||||
Linters: []string{"lll"},
|
Linters: []string{"lll"},
|
||||||
},
|
},
|
||||||
}, lineCache, nil)
|
}, lineCache, nil)
|
||||||
type issueCase struct {
|
|
||||||
Path string
|
|
||||||
Line int
|
|
||||||
Text string
|
|
||||||
Linter string
|
|
||||||
}
|
|
||||||
var newIssueCase = func(c issueCase) result.Issue {
|
|
||||||
return result.Issue{
|
|
||||||
Text: c.Text,
|
|
||||||
FromLinter: c.Linter,
|
|
||||||
Pos: token.Position{
|
|
||||||
Filename: c.Path,
|
|
||||||
Line: c.Line,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cases := []issueCase{
|
cases := []issueCase{
|
||||||
{Path: "e.go", Text: "exclude", Linter: "linter"},
|
{Path: "e.go", Text: "exclude", Linter: "linter"},
|
||||||
{Path: "e.go", Text: "some", Linter: "linter"},
|
{Path: "e.go", Text: "some", Linter: "linter"},
|
||||||
{Path: "e_test.go", Text: "normal", Linter: "testlinter"},
|
{Path: "e_test.go", Text: "normal", Linter: "testlinter"},
|
||||||
|
{Path: "e_Test.go", Text: "normal", Linter: "testlinter"},
|
||||||
{Path: "e_test.go", Text: "another", Linter: "linter"},
|
{Path: "e_test.go", Text: "another", Linter: "linter"},
|
||||||
{Path: "e_test.go", Text: "testonly", Linter: "linter"},
|
{Path: "e_test.go", Text: "testonly", Linter: "linter"},
|
||||||
{Path: filepath.Join("testdata", "exclude_rules.go"), Line: 3, Linter: "lll"},
|
{Path: filepath.Join("testdata", "exclude_rules.go"), Line: 3, Linter: "lll"},
|
||||||
@ -71,11 +57,30 @@ func TestExcludeRulesMultiple(t *testing.T) {
|
|||||||
}
|
}
|
||||||
expectedCases := []issueCase{
|
expectedCases := []issueCase{
|
||||||
{Path: "e.go", Text: "some", Linter: "linter"},
|
{Path: "e.go", Text: "some", Linter: "linter"},
|
||||||
|
{Path: "e_Test.go", Text: "normal", Linter: "testlinter"},
|
||||||
{Path: "e_test.go", Text: "another", Linter: "linter"},
|
{Path: "e_test.go", Text: "another", Linter: "linter"},
|
||||||
}
|
}
|
||||||
assert.Equal(t, expectedCases, resultingCases)
|
assert.Equal(t, expectedCases, resultingCases)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type issueCase struct {
|
||||||
|
Path string
|
||||||
|
Line int
|
||||||
|
Text string
|
||||||
|
Linter string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newIssueCase(c issueCase) result.Issue {
|
||||||
|
return result.Issue{
|
||||||
|
Text: c.Text,
|
||||||
|
FromLinter: c.Linter,
|
||||||
|
Pos: token.Position{
|
||||||
|
Filename: c.Path,
|
||||||
|
Line: c.Line,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExcludeRulesText(t *testing.T) {
|
func TestExcludeRulesText(t *testing.T) {
|
||||||
p := NewExcludeRules([]ExcludeRule{
|
p := NewExcludeRules([]ExcludeRule{
|
||||||
{
|
{
|
||||||
@ -103,6 +108,96 @@ func TestExcludeRulesText(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.Equal(t, texts[1:], processedTexts)
|
assert.Equal(t, texts[1:], processedTexts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcludeRulesEmpty(t *testing.T) {
|
func TestExcludeRulesEmpty(t *testing.T) {
|
||||||
processAssertSame(t, NewExcludeRules(nil, nil, nil), newTextIssue("test"))
|
processAssertSame(t, NewExcludeRules(nil, nil, nil), newTextIssue("test"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExcludeRulesCaseSensitiveMultiple(t *testing.T) {
|
||||||
|
lineCache := fsutils.NewLineCache(fsutils.NewFileCache())
|
||||||
|
p := NewExcludeRulesCaseSensitive([]ExcludeRule{
|
||||||
|
{
|
||||||
|
Text: "^exclude$",
|
||||||
|
Linters: []string{"linter"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Linters: []string{"testlinter"},
|
||||||
|
Path: `_test\.go`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Text: "^testonly$",
|
||||||
|
Path: `_test\.go`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Source: "^//go:generate ",
|
||||||
|
Linters: []string{"lll"},
|
||||||
|
},
|
||||||
|
}, lineCache, nil)
|
||||||
|
|
||||||
|
cases := []issueCase{
|
||||||
|
{Path: "e.go", Text: "exclude", Linter: "linter"},
|
||||||
|
{Path: "e.go", Text: "excLude", Linter: "linter"},
|
||||||
|
{Path: "e.go", Text: "some", Linter: "linter"},
|
||||||
|
{Path: "e_test.go", Text: "normal", Linter: "testlinter"},
|
||||||
|
{Path: "e_Test.go", Text: "normal", Linter: "testlinter"},
|
||||||
|
{Path: "e_test.go", Text: "another", Linter: "linter"},
|
||||||
|
{Path: "e_test.go", Text: "testonly", Linter: "linter"},
|
||||||
|
{Path: "e_test.go", Text: "testOnly", Linter: "linter"},
|
||||||
|
{Path: filepath.Join("testdata", "exclude_rules_case_sensitive.go"), Line: 3, Linter: "lll"},
|
||||||
|
}
|
||||||
|
var issues []result.Issue
|
||||||
|
for _, c := range cases {
|
||||||
|
issues = append(issues, newIssueCase(c))
|
||||||
|
}
|
||||||
|
processedIssues := process(t, p, issues...)
|
||||||
|
var resultingCases []issueCase
|
||||||
|
for _, i := range processedIssues {
|
||||||
|
resultingCases = append(resultingCases, issueCase{
|
||||||
|
Path: i.FilePath(),
|
||||||
|
Linter: i.FromLinter,
|
||||||
|
Text: i.Text,
|
||||||
|
Line: i.Line(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
expectedCases := []issueCase{
|
||||||
|
{Path: "e.go", Text: "excLude", Linter: "linter"},
|
||||||
|
{Path: "e.go", Text: "some", Linter: "linter"},
|
||||||
|
{Path: "e_Test.go", Text: "normal", Linter: "testlinter"},
|
||||||
|
{Path: "e_test.go", Text: "another", Linter: "linter"},
|
||||||
|
{Path: "e_test.go", Text: "testOnly", Linter: "linter"},
|
||||||
|
{Path: filepath.Join("testdata", "exclude_rules_case_sensitive.go"), Line: 3, Linter: "lll"},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expectedCases, resultingCases)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExcludeRulesCaseSensitiveText(t *testing.T) {
|
||||||
|
p := NewExcludeRulesCaseSensitive([]ExcludeRule{
|
||||||
|
{
|
||||||
|
Text: "^exclude$",
|
||||||
|
Linters: []string{
|
||||||
|
"linter",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil, nil)
|
||||||
|
texts := []string{"exclude", "excLude", "1", "", "exclud", "notexclude"}
|
||||||
|
var issues []result.Issue
|
||||||
|
for _, t := range texts {
|
||||||
|
issues = append(issues, result.Issue{
|
||||||
|
Text: t,
|
||||||
|
FromLinter: "linter",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExcludeRulesCaseSensitiveEmpty(t *testing.T) {
|
||||||
|
processAssertSame(t, NewExcludeRulesCaseSensitive(nil, nil, nil), newTextIssue("test"))
|
||||||
|
}
|
||||||
|
@ -51,3 +51,21 @@ func TestExclude(t *testing.T) {
|
|||||||
func TestNoExclude(t *testing.T) {
|
func TestNoExclude(t *testing.T) {
|
||||||
processAssertSame(t, NewExclude(""), newTextIssue("test"))
|
processAssertSame(t, NewExclude(""), newTextIssue("test"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExcludeCaseSensitive(t *testing.T) {
|
||||||
|
p := NewExcludeCaseSensitive("^exclude$")
|
||||||
|
texts := []string{"excLude", "1", "", "exclud", "exclude"}
|
||||||
|
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[:len(texts)-1], processedTexts)
|
||||||
|
}
|
||||||
|
3
pkg/result/processors/testdata/exclude_rules_case_sensitive.go
vendored
Normal file
3
pkg/result/processors/testdata/exclude_rules_case_sensitive.go
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package testdata
|
||||||
|
|
||||||
|
//GO:generate long line that will be excluded by default processor but will not be affected by case-sensitive one because of capital GO
|
Loading…
x
Reference in New Issue
Block a user