diff --git a/README.md b/README.md
index e8608712..e0e5e6a1 100644
--- a/README.md
+++ b/README.md
@@ -574,6 +574,7 @@ Flags:
# gosec: False positive is triggered by 'src, err := ioutil.ReadFile(filename)'
- Potential file inclusion via variable
(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-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.
diff --git a/docs/demo.svg b/docs/demo.svg
index d5dbb4a8..da93b49d 100644
--- a/docs/demo.svg
+++ b/docs/demo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+~/go/src/github.com/astaxie/beego(master)$golangci-lint~/go/src/github.com/astaxie/beego(master)$golangci-lintrunadmin.go:85:13:Errorreturnvalueof`r.ParseForm`isnotchecked(errcheck)r.ParseForm()^admin.go:88:11:Errorreturnvalueof`rw.Write`isnotchecked(errcheck)rw.Write([]byte("commandnotsupport"))^admin.go:105:15:Errorreturnvalueof`tmpl.Execute`isnotchecked(errcheck)tmpl.Execute(rw,data)^admin.go:160:11:Errorreturnvalueof`rw.Write`isnotchecked(errcheck)admin.go:246:13:Errorreturnvalueof`r.ParseForm`isnotchecked(errcheck)admin.go:268:11:Errorreturnvalueof`rw.Write`isnotchecked(errcheck)rw.Write(dataJSON)admin.go:321:15:Errorreturnvalueof`req.ParseForm`isnotchecked(errcheck)req.ParseForm()^admin.go:366:14:Errorreturnvalueof`tmpl.Execute`isnotchecked(errcheck)tmpl.Execute(rw,data)^app.go:477:30:Errorreturnvalueof`BeeApp.Handlers.InsertFilter`isnotchecked(errcheck)BeeApp.Handlers.InsertFilter(pattern,pos,filter,params...)^beego.go:106:10:Errorreturnvalueof`os.Chdir`isnotchecked(errcheck)os.Chdir(ap)^cache/file.go:69:16:Errorreturnvalueof`json.Unmarshal`isnotchecked(errcheck)json.Unmarshal([]byte(config),&cfg)^cache/file.go:101:16:Errorreturnvalueof`io.WriteString`isnotchecked(errcheck)io.WriteString(m,key)cache/file.go:126:11:Errorreturnvalueof`GobDecode`isnotchecked(errcheck)GobDecode(fileData,&to)^cache/file.go:182:8:Errorreturnvalueof`fc.Put`isnotchecked(errcheck)fc.Put(key,incr,FileCacheEmbedExpiry)^cache/file.go:195:8:Errorreturnvalueof`fc.Put`isnotchecked(errcheck)fc.Put(key,decr,FileCacheEmbedExpiry)cache/memcache/memcache.go:167:16:Errorreturnvalueof`json.Unmarshal`isnotchecked(errcheck)json.Unmarshal([]byte(config),&cf)cache/memory.go:198:16:Errorreturnvalueof`json.Unmarshal`isnotchecked(errcheck)config/ini.go:77:16:Errorreturnvalueof`buf.ReadByte`isnotchecked(errcheck)buf.ReadByte()context/context.go:86:26:Errorreturnvalueof`ctx.ResponseWriter.Write`isnotchecked(errcheck)ctx.ResponseWriter.Write([]byte(content))^context/input.go:321:34:Errorreturnvalueof`input.Context.Request.ParseForm`isnotchecked(errcheck)input.Context.Request.ParseForm()^context/input.go:444:34:Errorreturnvalueof`input.Context.Request.ParseForm`isnotchecked(errcheck)context/output.go:82:9:Errorreturnvalueof`io.Copy`isnotchecked(errcheck)io.Copy(output.Context.ResponseWriter,buf)^context/output.go:173:18:Errorreturnvalueof`ctx.Output.JSON`isnotchecked(errcheck)ctx.Output.JSON(value,false,false)^context/output.go:180:18:Errorreturnvalueof`ctx.Output.Body`isnotchecked(errcheck)ctx.Output.Body([]byte(err.Error()))context/output.go:361:37:Errorreturnvalueof`output.Context.Input.CruSession.Set`isnotchecked(errcheck)output.Context.Input.CruSession.Set(name,value)^controller.go:235:26:Errorreturnvalueof`ExecuteViewPathTemplate`isnotchecked(errcheck)ExecuteViewPathTemplate(&buf,c.Layout,c.viewPath(),c.Data)^controller.go:261:16:Errorreturnvalueof`BuildTemplate`isnotchecked(errcheck)BuildTemplate(c.viewPath(),buildFiles...)^controller.go:296:28:Errorreturnvalueof`c.Ctx.ResponseWriter.Write`isnotchecked(errcheck)c.Ctx.ResponseWriter.Write([]byte(body))^controller.go:329:19:Errorreturnvalueof`c.Ctx.Output.JSON`isnotchecked(errcheck)c.Ctx.Output.JSON(c.Data["json"],hasIndent,hasEncoding)^controller.go:338:20:Errorreturnvalueof`c.Ctx.Output.JSONP`isnotchecked(errcheck)c.Ctx.Output.JSONP(c.Data["jsonp"],hasIndent)^controller.go:347:18:Errorreturnvalueof`c.Ctx.Output.XML`isnotchecked(errcheck)c.Ctx.Output.XML(c.Data["xml"],hasIndent)controller.go:366:26:Errorreturnvalueof`c.Ctx.Request.ParseForm`isnotchecked(errcheck)c.Ctx.Request.ParseForm()controller.go:562:9:Errorreturnvalueof`io.Copy`isnotchecked(errcheck)io.Copy(f,file)controller.go:579:18:Errorreturnvalueof`c.CruSession.Set`isnotchecked(errcheck)c.CruSession.Set(name,value)controller.go:595:21:Errorreturnvalueof`c.CruSession.Delete`isnotchecked(errcheck)c.CruSession.Delete(name)^controller.go:610:30:Errorreturnvalueof`c.Ctx.Input.CruSession.Flush`isnotchecked(errcheck)c.Ctx.Input.CruSession.Flush()error.go:101:11:Errorreturnvalueof`t.Execute`isnotchecked(errcheck)t.Execute(ctx.ResponseWriter,data)error.go:374:11:Errorreturnvalueof`t.Execute`isnotchecked(errcheck)t.Execute(rw,data)grace/listener.go:37:17:Errorreturnvalueof`tc.SetKeepAlive`isnotchecked(errcheck)tc.SetKeepAlive(true)^grace/listener.go:38:23:Errorreturnvalueof`tc.SetKeepAlivePeriod`isnotchecked(errcheck)tc.SetKeepAlivePeriod(3*time.Minute)hooks.go:17:24:Errorreturnvalueof`mime.AddExtensionType`isnotchecked(errcheck)mime.AddExtensionType(k,v)^httplib/httplib.go:383:28:Errorreturnvalueof`bodyWriter.WriteField`isnotchecked(errcheck)bodyWriter.WriteField(k,vv)^logs/conn.go:94:23:Errorreturnvalueof`tcpConn.SetKeepAlive`isnotchecked(errcheck)tcpConn.SetKeepAlive(true)logs/file.go:167:11:Errorreturnvalueof`os.Chmod`isnotchecked(errcheck)os.Chmod(w.Filename,os.FileMode(perm))logs/file.go:300:15:Errorreturnvalueof`filepath.Walk`isnotchecked(errcheck)filepath.Walk(dir,func(pathstring,infoos.FileInfo,errerror)(returnErrerror){logs/file.go:330:19:Errorreturnvalueof`w.fileWriter.Sync`isnotchecked(errcheck)w.fileWriter.Sync()logs/log.go:153:14:Errorreturnvalueof`bl.setLogger`isnotchecked(errcheck)bl.setLogger(AdapterConsole)logs/log.go:263:15:Errorreturnvalueof`bl.setLogger`isnotchecked(errcheck)bl.setLogger(AdapterConsole)logs/log.go:355:13:Errorreturnvalueof`bl.writeMsg`isnotchecked(errcheck)bl.writeMsg(LevelEmergency,format,v...)logs/log.go:363:13:Errorreturnvalueof`bl.writeMsg`isnotchecked(errcheck)bl.writeMsg(LevelAlert,format,v...)logs/smtp.go:78:G402:TLSInsecureSkipVerifysettrue.(gas)InsecureSkipVerify:true,orm/db.go:283:G201:SQLstringformatting(gas)query:=fmt.Sprintf("INSERTINTO%s%s%s(%s%s%s)VALUES(%s)",Q,mi.table,Q,Q,columns,Q,qmarks)orm/db.go:350:G201:SQLstringformatting(gas)query:=fmt.Sprintf("SELECT%s%s%sFROM%s%s%sWHERE%s%s%s=?%s",Q,sels,Q,Q,mi.table,Q,Q,wheres,Q,forUpdate)orm/db.go:477:G201:SQLstringformatting(gas)orm/db.go:576:G202:SQLstringconcatenation(gas)query:=fmt.Sprintf("INSERTINTO%s%s%s(%s%s%s)VALUES(%s)%s"+qupdates,Q,mi.table,Q,Q,columns,Q,qmarks,iouStr)orm/db_mysql.go:157:G202:SQLstringconcatenation(gas)orm/db_tables.go:387:G202:SQLstringconcatenation(gas)where="WHERE"+wherelogs/alils/request.go:5:G501:Blacklistedimportcrypto/md5:weakcryptographicprimitive(gas)"crypto/md5"logs/alils/request.go:26:G401:Useofweakcryptographicprimitive(gas)bodyMD5:=fmt.Sprintf("%X",md5.Sum(body))cache/file.go:19:G501:Blacklistedimportcrypto/md5:weakcryptographicprimitive(gas)cache/file.go:100:G401:Useofweakcryptographicprimitive(gas)m:=md5.New()controller.go:230:G203:thismethodwillnotauto-escapeHTML.Verifydataiswellformed.(gas)c.Data[sectionName]=template.HTML(buf.String())error.go:372:G203:thismethodwillnotauto-escapeHTML.Verifydataiswellformed.(gas)"Content":template.HTML(errContent),templatefunc.go:272:G203:thismethodwillnotauto-escapeHTML.Verifydataiswellformed.(gas)returntemplate.HTML(text)logs/alils/log.pb.go:328:6:`encodeFixed64Log`isunused(deadcode)funcencodeFixed64Log(data[]byte,offsetint,vuint64)int{^logs/alils/log.pb.go:339:6:`encodeFixed32Log`isunused(deadcode)funcencodeFixed32Log(data[]byte,offsetint,vuint32)int{logs/alils/log.pb.go:447:6:`sozLog`isunused(deadcode)funcsozLog(xuint64)(nint){context/param/methodparams.go:19:2:`param`isunused(deadcode)paramparamType=iota^session/memcache/sess_memcache.go:109:2:`poolsize`isunused(structcheck)poolsizeintsession/memcache/sess_memcache.go:110:2:`password`isunused(structcheck)passwordstringorm/orm_log.go:110:2:`tx`isunused(structcheck)txtxerorm/orm_log.go:111:2:`txe`isunused(structcheck)txetxEnderorm/models_info_f.go:36:2:`rels`isunused(structcheck)rels[]*fieldInfocontroller.go:76:2:`gotofunc`isunused(structcheck)gotofuncstringparser.go:183:42:cutsetcontainsduplicatecharacters(megacheck)t:=strings.TrimSpace(strings.TrimLeft(c.Text,"//"))^parser.go:200:54:cutsetcontainsduplicatecharacters(megacheck)pv:=getparams(strings.TrimSpace(strings.TrimLeft(t,"@Param")))^session/sess_file.go:140:6:thisvalueoferrisneverused(megacheck)f,err=os.OpenFile(path.Join(fp.savePath,string(sid[0]),string(sid[1]),sid),os.O_RDWR,0777)session/sess_file.go:142:6:thisvalueoferrisneverused(megacheck)f,err=os.Create(path.Join(fp.savePath,string(sid[0]),string(sid[1]),sid))cache/memory.go:41:9:shouldusetime.Sinceinsteadoftime.Now().Sub(megacheck)returntime.Now().Sub(mi.createdTime)>mi.lifespanorm/orm_log.go:39:9:shouldusetime.Sinceinsteadoftime.Now().Sub(megacheck)sub:=time.Now().Sub(t)/1e5toolbox/profile.go:109:14:shouldusetime.Sinceinsteadoftime.Now().Sub(megacheck)elapsed:=time.Now().Sub(startTime)orm/db_tables.go:77:20:func(*dbTables).getisunused(megacheck)func(t*dbTables)get(namestring)(*dbTable,bool){~/go/src/github.com/astaxie/beego(master)$#~/go/src/github.com/astaxie/beego(master)$#too~/go/src/github.com/astaxie/beego(master)$#toomuch~/go/src/github.com/astaxie/beego(master)$#toomuchissues,~/go/src/github.com/astaxie/beego(master)$golangci-~/go/src/github.com/astaxie/beego(master)$golangci-l~/go/src/github.com/astaxie/beego(master)$golangci-li~/go/src/github.com/astaxie/beego(master)$golangci-lin~/go/src/github.com/astaxie/beego(master)$golangci-lintr~/go/src/github.com/astaxie/beego(master)$golangci-lintruorm/orm_log.go:39:9:s~/go/src/github.com/astaxie/beego(master)$~/go/src/github.com/astaxie/beego(master)$#t~/go/src/github.com/astaxie/beego(master)$#to~/go/src/github.com/astaxie/beego(master)$#toom~/go/src/github.com/astaxie/beego(master)$#toomu~/go/src/github.com/astaxie/beego(master)$#toomuc~/go/src/github.com/astaxie/beego(master)$#toomuchi~/go/src/github.com/astaxie/beego(master)$#toomuchis~/go/src/github.com/astaxie/beego(master)$#toomuchiss~/go/src/github.com/astaxie/beego(master)$#toomuchissu~/go/src/github.com/astaxie/beego(master)$#toomuchissue~/go/src/github.com/astaxie/beego(master)$#toomuchissues~/go/src/github.com/astaxie/beego(master)$#toomuchissues,l~/go/src/github.com/astaxie/beego(master)$#toomuchissues,le~/go/src/github.com/astaxie/beego(master)$#toomuchissues,let~/go/src/github.com/astaxie/beego(master)$#toomuchissues,let'
\ No newline at end of file
diff --git a/pkg/commands/run.go b/pkg/commands/run.go
index b805995e..17f0f3fb 100644
--- a/pkg/commands/run.go
+++ b/pkg/commands/run.go
@@ -189,6 +189,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, is
ic := &cfg.Issues
fs.StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", nil, wh("Exclude issue by regexp"))
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,
wh("Maximum issues count per one linter. Set to 0 to disable"))
diff --git a/pkg/config/config.go b/pkg/config/config.go
index f97ec591..2b3048cb 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -411,9 +411,10 @@ func (e ExcludeRule) Validate() error {
}
type Issues struct {
- ExcludePatterns []string `mapstructure:"exclude"`
- ExcludeRules []ExcludeRule `mapstructure:"exclude-rules"`
- UseDefaultExcludes bool `mapstructure:"exclude-use-default"`
+ ExcludeCaseSensitive bool `mapstructure:"exclude-case-sensitive"`
+ 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 4dc40f3f..dd9e6946 100644
--- a/pkg/lint/runner.go
+++ b/pkg/lint/runner.go
@@ -40,6 +40,13 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
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)
if err != nil {
return nil, err
@@ -63,6 +70,12 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
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{
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.
processors.NewIdentifierMarker(),
- processors.NewExclude(excludeTotalPattern),
- processors.NewExcludeRules(excludeRules, lineCache, log.Child("exclude_rules")),
+ excludeProcessor,
+ excludeRulesProcessor,
processors.NewNolint(log.Child("nolint"), dbManager),
processors.NewUniqByLine(cfg),
diff --git a/pkg/result/processors/exclude.go b/pkg/result/processors/exclude.go
index 80c4b894..92959a32 100644
--- a/pkg/result/processors/exclude.go
+++ b/pkg/result/processors/exclude.go
@@ -37,3 +37,23 @@ func (p Exclude) Process(issues []result.Issue) ([]result.Issue, error) {
}
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"
+}
diff --git a/pkg/result/processors/exclude_rules.go b/pkg/result/processors/exclude_rules.go
index 6b16fdc5..b926af5b 100644
--- a/pkg/result/processors/exclude_rules.go
+++ b/pkg/result/processors/exclude_rules.go
@@ -37,24 +37,29 @@ func NewExcludeRules(rules []ExcludeRule, lineCache *fsutils.LineCache, log logu
lineCache: lineCache,
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 {
parsedRule := excludeRule{
linters: rule.Linters,
}
if rule.Text != "" {
- parsedRule.text = regexp.MustCompile("(?i)" + rule.Text)
+ parsedRule.text = regexp.MustCompile(prefix + rule.Text)
}
if rule.Source != "" {
- parsedRule.source = regexp.MustCompile("(?i)" + rule.Source)
+ parsedRule.source = regexp.MustCompile(prefix + rule.Source)
}
if rule.Path != "" {
parsedRule.path = regexp.MustCompile(rule.Path)
}
- r.rules = append(r.rules, parsedRule)
+ parsedRules = append(parsedRules, parsedRule)
}
-
- return r
+ return parsedRules
}
func (p ExcludeRules) Process(issues []result.Issue) ([]result.Issue, error) {
@@ -118,3 +123,21 @@ func (ExcludeRules) Name() string { return "exclude-rules" }
func (ExcludeRules) Finish() {}
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{}
diff --git a/pkg/result/processors/exclude_rules_test.go b/pkg/result/processors/exclude_rules_test.go
index ee2f15e1..80759d4f 100644
--- a/pkg/result/processors/exclude_rules_test.go
+++ b/pkg/result/processors/exclude_rules_test.go
@@ -31,26 +31,12 @@ func TestExcludeRulesMultiple(t *testing.T) {
Linters: []string{"lll"},
},
}, 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{
{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: filepath.Join("testdata", "exclude_rules.go"), Line: 3, Linter: "lll"},
@@ -71,11 +57,30 @@ func TestExcludeRulesMultiple(t *testing.T) {
}
expectedCases := []issueCase{
{Path: "e.go", Text: "some", Linter: "linter"},
+ {Path: "e_Test.go", Text: "normal", Linter: "testlinter"},
{Path: "e_test.go", Text: "another", Linter: "linter"},
}
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) {
p := NewExcludeRules([]ExcludeRule{
{
@@ -103,6 +108,96 @@ func TestExcludeRulesText(t *testing.T) {
}
assert.Equal(t, texts[1:], processedTexts)
}
+
func TestExcludeRulesEmpty(t *testing.T) {
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"))
+}
diff --git a/pkg/result/processors/exclude_test.go b/pkg/result/processors/exclude_test.go
index 7f68d908..7965f2fd 100644
--- a/pkg/result/processors/exclude_test.go
+++ b/pkg/result/processors/exclude_test.go
@@ -51,3 +51,21 @@ func TestExclude(t *testing.T) {
func TestNoExclude(t *testing.T) {
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)
+}
diff --git a/pkg/result/processors/testdata/exclude_rules_case_sensitive.go b/pkg/result/processors/testdata/exclude_rules_case_sensitive.go
new file mode 100644
index 00000000..fe2cabdf
--- /dev/null
+++ b/pkg/result/processors/testdata/exclude_rules_case_sensitive.go
@@ -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