sa4022.go raw
1 package sa4022
2
3 import (
4 "go/ast"
5
6 "honnef.co/go/tools/analysis/code"
7 "honnef.co/go/tools/analysis/lint"
8 "honnef.co/go/tools/analysis/report"
9 "honnef.co/go/tools/pattern"
10
11 "golang.org/x/tools/go/analysis"
12 "golang.org/x/tools/go/analysis/passes/inspect"
13 )
14
15 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
16 Analyzer: &analysis.Analyzer{
17 Name: "SA4022",
18 Run: run,
19 Requires: []*analysis.Analyzer{inspect.Analyzer},
20 },
21 Doc: &lint.RawDocumentation{
22 Title: `Comparing the address of a variable against nil`,
23 Text: `Code such as \"if &x == nil\" is meaningless, because taking the address of a variable always yields a non-nil pointer.`,
24 Since: "2020.1",
25 Severity: lint.SeverityWarning,
26 MergeIf: lint.MergeIfAny,
27 },
28 })
29
30 var Analyzer = SCAnalyzer.Analyzer
31
32 var CheckAddressIsNilQ = pattern.MustParse(
33 `(BinaryExpr
34 (UnaryExpr "&" _)
35 (Or "==" "!=")
36 (Builtin "nil"))`)
37
38 func run(pass *analysis.Pass) (interface{}, error) {
39 fn := func(node ast.Node) {
40 _, ok := code.Match(pass, CheckAddressIsNilQ, node)
41 if !ok {
42 return
43 }
44 report.Report(pass, node, "the address of a variable cannot be nil")
45 }
46 code.Preorder(pass, fn, (*ast.BinaryExpr)(nil))
47 return nil, nil
48 }
49