s1036.go (2154B)
1 package s1036 2 3 import ( 4 "go/ast" 5 6 "honnef.co/go/tools/analysis/code" 7 "honnef.co/go/tools/analysis/edit" 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: "S1036", 18 Run: run, 19 Requires: code.RequiredAnalyzers, 20 }, 21 Doc: &lint.RawDocumentation{ 22 Title: `Unnecessary guard around map access`, 23 24 Text: ` 25 When accessing a map key that doesn't exist yet, one receives a zero 26 value. Often, the zero value is a suitable value, for example when 27 using append or doing integer math. 28 29 The following 30 31 if _, ok := m["foo"]; ok { 32 m["foo"] = append(m["foo"], "bar") 33 } else { 34 m["foo"] = []string{"bar"} 35 } 36 37 can be simplified to 38 39 m["foo"] = append(m["foo"], "bar") 40 41 and 42 43 if _, ok := m2["k"]; ok { 44 m2["k"] += 4 45 } else { 46 m2["k"] = 4 47 } 48 49 can be simplified to 50 51 m["k"] += 4 52 `, 53 Since: "2020.1", 54 MergeIf: lint.MergeIfAny, 55 }, 56 }) 57 58 var Analyzer = SCAnalyzer.Analyzer 59 60 var checkUnnecessaryGuardQ = pattern.MustParse(` 61 (Or 62 (IfStmt 63 (AssignStmt [(Ident "_") ok@(Ident _)] ":=" indexexpr@(IndexExpr _ _)) 64 ok 65 set@(AssignStmt indexexpr "=" (CallExpr (Builtin "append") indexexpr:values)) 66 (AssignStmt indexexpr "=" (CompositeLit _ values))) 67 (IfStmt 68 (AssignStmt [(Ident "_") ok] ":=" indexexpr@(IndexExpr _ _)) 69 ok 70 set@(AssignStmt indexexpr "+=" value) 71 (AssignStmt indexexpr "=" value)) 72 (IfStmt 73 (AssignStmt [(Ident "_") ok] ":=" indexexpr@(IndexExpr _ _)) 74 ok 75 set@(IncDecStmt indexexpr "++") 76 (AssignStmt indexexpr "=" (IntegerLiteral "1"))))`) 77 78 func run(pass *analysis.Pass) (any, error) { 79 for node, m := range code.Matches(pass, checkUnnecessaryGuardQ) { 80 if code.MayHaveSideEffects(pass, m.State["indexexpr"].(ast.Expr), nil) { 81 continue 82 } 83 report.Report(pass, node, "unnecessary guard around map access", 84 report.ShortRange(), 85 report.Fixes(edit.Fix("Simplify map access", edit.ReplaceWithNode(pass.Fset, node, m.State["set"].(ast.Node))))) 86 } 87 return nil, nil 88 }