]>
Commit | Line | Data |
---|---|---|
4f4a855d ILT |
1 | // Copyright 2013 The Go Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style | |
3 | // license that can be found in the LICENSE file. | |
4 | ||
5 | // Package nilfunc defines an Analyzer that checks for useless | |
6 | // comparisons against nil. | |
7 | package nilfunc | |
8 | ||
9 | import ( | |
10 | "go/ast" | |
11 | "go/token" | |
12 | "go/types" | |
13 | ||
14 | "golang.org/x/tools/go/analysis" | |
15 | "golang.org/x/tools/go/analysis/passes/inspect" | |
16 | "golang.org/x/tools/go/ast/inspector" | |
17 | ) | |
18 | ||
19 | const Doc = `check for useless comparisons between functions and nil | |
20 | ||
21 | A useless comparison is one like f == nil as opposed to f() == nil.` | |
22 | ||
23 | var Analyzer = &analysis.Analyzer{ | |
24 | Name: "nilfunc", | |
25 | Doc: Doc, | |
26 | Requires: []*analysis.Analyzer{inspect.Analyzer}, | |
27 | Run: run, | |
28 | } | |
29 | ||
30 | func run(pass *analysis.Pass) (interface{}, error) { | |
31 | inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) | |
32 | ||
33 | nodeFilter := []ast.Node{ | |
34 | (*ast.BinaryExpr)(nil), | |
35 | } | |
36 | inspect.Preorder(nodeFilter, func(n ast.Node) { | |
37 | e := n.(*ast.BinaryExpr) | |
38 | ||
39 | // Only want == or != comparisons. | |
40 | if e.Op != token.EQL && e.Op != token.NEQ { | |
41 | return | |
42 | } | |
43 | ||
44 | // Only want comparisons with a nil identifier on one side. | |
45 | var e2 ast.Expr | |
46 | switch { | |
47 | case pass.TypesInfo.Types[e.X].IsNil(): | |
48 | e2 = e.Y | |
49 | case pass.TypesInfo.Types[e.Y].IsNil(): | |
50 | e2 = e.X | |
51 | default: | |
52 | return | |
53 | } | |
54 | ||
55 | // Only want identifiers or selector expressions. | |
56 | var obj types.Object | |
57 | switch v := e2.(type) { | |
58 | case *ast.Ident: | |
59 | obj = pass.TypesInfo.Uses[v] | |
60 | case *ast.SelectorExpr: | |
61 | obj = pass.TypesInfo.Uses[v.Sel] | |
62 | default: | |
63 | return | |
64 | } | |
65 | ||
66 | // Only want functions. | |
67 | if _, ok := obj.(*types.Func); !ok { | |
68 | return | |
69 | } | |
70 | ||
5a8ea165 | 71 | pass.ReportRangef(e, "comparison of function %v %v nil is always %v", obj.Name(), e.Op, e.Op == token.NEQ) |
4f4a855d ILT |
72 | }) |
73 | return nil, nil | |
74 | } |