sa4024.go (1414B)
1 package sa4024 2 3 import ( 4 "fmt" 5 "go/ast" 6 7 "honnef.co/go/tools/analysis/code" 8 "honnef.co/go/tools/analysis/lint" 9 "honnef.co/go/tools/analysis/report" 10 "honnef.co/go/tools/pattern" 11 12 "golang.org/x/tools/go/analysis" 13 ) 14 15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ 16 Analyzer: &analysis.Analyzer{ 17 Name: "SA4024", 18 Run: run, 19 Requires: code.RequiredAnalyzers, 20 }, 21 Doc: &lint.RawDocumentation{ 22 Title: `Checking for impossible return value from a builtin function`, 23 Text: `Return values of the \'len\' and \'cap\' builtins cannot be negative. 24 25 See https://golang.org/pkg/builtin/#len and https://golang.org/pkg/builtin/#cap. 26 27 Example: 28 29 if len(slice) < 0 { 30 fmt.Println("unreachable code") 31 }`, 32 Since: "2021.1", 33 Severity: lint.SeverityWarning, 34 MergeIf: lint.MergeIfAny, 35 }, 36 }) 37 38 var Analyzer = SCAnalyzer.Analyzer 39 40 var builtinLessThanZeroQ = pattern.MustParse(` 41 (Or 42 (BinaryExpr 43 (IntegerLiteral "0") 44 ">" 45 (CallExpr builtin@(Builtin (Or "len" "cap")) _)) 46 (BinaryExpr 47 (CallExpr builtin@(Builtin (Or "len" "cap")) _) 48 "<" 49 (IntegerLiteral "0"))) 50 `) 51 52 func run(pass *analysis.Pass) (any, error) { 53 for node, matcher := range code.Matches(pass, builtinLessThanZeroQ) { 54 builtin := matcher.State["builtin"].(*ast.Ident) 55 report.Report(pass, node, fmt.Sprintf("builtin function %s does not return negative values", builtin.Name)) 56 } 57 return nil, nil 58 }