github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/staticcheck/sa1028/sa1028.go (about) 1 package sa1028 2 3 import ( 4 "fmt" 5 "go/types" 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: "SA1028", 18 Requires: []*analysis.Analyzer{buildir.Analyzer}, 19 Run: callcheck.Analyzer(rules), 20 }, 21 Doc: &lint.Documentation{ 22 Title: `\'sort.Slice\' can only be used on slices`, 23 Text: `The first argument of \'sort.Slice\' must be a slice.`, 24 Since: "2020.1", 25 Severity: lint.SeverityError, 26 MergeIf: lint.MergeIfAny, 27 }, 28 }) 29 30 var Analyzer = SCAnalyzer.Analyzer 31 32 var rules = map[string]callcheck.Check{ 33 "sort.Slice": check, 34 "sort.SliceIsSorted": check, 35 "sort.SliceStable": check, 36 } 37 38 func check(call *callcheck.Call) { 39 c := call.Instr.Common().StaticCallee() 40 arg := call.Args[0] 41 42 T := arg.Value.Value.Type().Underlying() 43 switch T.(type) { 44 case *types.Interface: 45 // we don't know. 46 // TODO(dh): if the value is a phi node we can look at its edges 47 if k, ok := arg.Value.Value.(*ir.Const); ok && k.Value == nil { 48 // literal nil, e.g. sort.Sort(nil, ...) 49 arg.Invalid(fmt.Sprintf("cannot call %s on nil literal", c)) 50 } 51 case *types.Slice: 52 // this is fine 53 default: 54 // this is not fine 55 arg.Invalid(fmt.Sprintf("%s must only be called on slices, was called on %s", c, T)) 56 } 57 }