s1033.go raw
1 package s1033
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/facts/generated"
9 "honnef.co/go/tools/analysis/lint"
10 "honnef.co/go/tools/analysis/report"
11 "honnef.co/go/tools/pattern"
12
13 "golang.org/x/tools/go/analysis"
14 "golang.org/x/tools/go/analysis/passes/inspect"
15 )
16
17 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
18 Analyzer: &analysis.Analyzer{
19 Name: "S1033",
20 Run: run,
21 Requires: []*analysis.Analyzer{inspect.Analyzer, generated.Analyzer},
22 },
23 Doc: &lint.RawDocumentation{
24 Title: `Unnecessary guard around call to \"delete\"`,
25 Text: `Calling \'delete\' on a nil map is a no-op.`,
26 Since: "2019.2",
27 MergeIf: lint.MergeIfAny,
28 },
29 })
30
31 var Analyzer = SCAnalyzer.Analyzer
32
33 var checkGuardedDeleteQ = pattern.MustParse(`
34 (IfStmt
35 (AssignStmt
36 [(Ident "_") ok@(Ident _)]
37 ":="
38 (IndexExpr m key))
39 ok
40 [call@(CallExpr (Builtin "delete") [m key])]
41 nil)`)
42
43 func run(pass *analysis.Pass) (interface{}, error) {
44 fn := func(node ast.Node) {
45 if m, ok := code.Match(pass, checkGuardedDeleteQ, node); ok {
46 report.Report(pass, node, "unnecessary guard around call to delete",
47 report.ShortRange(),
48 report.FilterGenerated(),
49 report.Fixes(edit.Fix("remove guard", edit.ReplaceWithNode(pass.Fset, node, m.State["call"].(ast.Node)))))
50 }
51 }
52
53 code.Preorder(pass, fn, (*ast.IfStmt)(nil))
54 return nil, nil
55 }
56