github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/staticcheck/sa1018/sa1018.go (about) 1 package sa1018 2 3 import ( 4 "fmt" 5 "go/constant" 6 7 "github.com/amarpal/go-tools/analysis/callcheck" 8 "github.com/amarpal/go-tools/analysis/lint" 9 "github.com/amarpal/go-tools/go/ir" 10 "github.com/amarpal/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: "SA1018", 18 Requires: []*analysis.Analyzer{buildir.Analyzer}, 19 Run: callcheck.Analyzer(rules), 20 }, 21 Doc: &lint.Documentation{ 22 Title: `\'strings.Replace\' called with \'n == 0\', which does nothing`, 23 Text: `With \'n == 0\', zero instances will be replaced. To replace all 24 instances, use a negative number, or use \'strings.ReplaceAll\'.`, 25 Since: "2017.1", 26 Severity: lint.SeverityWarning, 27 MergeIf: lint.MergeIfAny, // MergeIfAny if we only flag literals, not named constants 28 }, 29 }) 30 31 var Analyzer = SCAnalyzer.Analyzer 32 33 var rules = map[string]callcheck.Check{ 34 "strings.Replace": check("strings.Replace", 3), 35 "bytes.Replace": check("bytes.Replace", 3), 36 } 37 38 func check(name string, arg int) callcheck.Check { 39 return func(call *callcheck.Call) { 40 arg := call.Args[arg] 41 if k, ok := arg.Value.Value.(*ir.Const); ok && k.Value.Kind() == constant.Int { 42 if v, ok := constant.Int64Val(k.Value); ok && v == 0 { 43 arg.Invalid(fmt.Sprintf("calling %s with n == 0 will return no results, did you mean -1?", name)) 44 } 45 } 46 } 47 }