src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

sa6000.go (1382B)


      1 package sa6000
      2 
      3 import (
      4 	"fmt"
      5 
      6 	"honnef.co/go/tools/analysis/callcheck"
      7 	"honnef.co/go/tools/analysis/lint"
      8 	"honnef.co/go/tools/go/ir"
      9 	"honnef.co/go/tools/go/ir/irutil"
     10 	"honnef.co/go/tools/internal/passes/buildir"
     11 
     12 	"golang.org/x/tools/go/analysis"
     13 )
     14 
     15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
     16 	Analyzer: &analysis.Analyzer{
     17 		Name:     "SA6000",
     18 		Requires: []*analysis.Analyzer{buildir.Analyzer},
     19 		Run:      callcheck.Analyzer(rules),
     20 	},
     21 	Doc: &lint.RawDocumentation{
     22 		Title:    `Using \'regexp.Match\' or related in a loop, should use \'regexp.Compile\'`,
     23 		Since:    "2017.1",
     24 		Severity: lint.SeverityWarning,
     25 		MergeIf:  lint.MergeIfAny,
     26 	},
     27 })
     28 
     29 var Analyzer = SCAnalyzer.Analyzer
     30 
     31 var rules = map[string]callcheck.Check{
     32 	"regexp.Match":       check("regexp.Match"),
     33 	"regexp.MatchReader": check("regexp.MatchReader"),
     34 	"regexp.MatchString": check("regexp.MatchString"),
     35 }
     36 
     37 func check(name string) callcheck.Check {
     38 	return func(call *callcheck.Call) {
     39 		if callcheck.ExtractConst(call.Args[0].Value) == nil {
     40 			return
     41 		}
     42 		if !isInLoop(call.Instr.Block()) {
     43 			return
     44 		}
     45 		call.Invalid(fmt.Sprintf("calling %s in a loop has poor performance, consider using regexp.Compile", name))
     46 	}
     47 }
     48 
     49 func isInLoop(b *ir.BasicBlock) bool {
     50 	sets := irutil.FindLoops(b.Parent())
     51 	for _, set := range sets {
     52 		if set.Has(b) {
     53 			return true
     54 		}
     55 	}
     56 	return false
     57 }