GoPLS Viewer

Home|gopls/go/analysis/passes/nilfunc/nilfunc.go
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.
7package nilfunc
8
9import (
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    "golang.org/x/tools/internal/typeparams"
18)
19
20const Doc = `check for useless comparisons between functions and nil
21
22A useless comparison is one like f == nil as opposed to f() == nil.`
23
24var Analyzer = &analysis.Analyzer{
25    Name:     "nilfunc",
26    Doc:      Doc,
27    Requires: []*analysis.Analyzer{inspect.Analyzer},
28    Run:      run,
29}
30
31func run(pass *analysis.Pass) (interface{}, error) {
32    inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
33
34    nodeFilter := []ast.Node{
35        (*ast.BinaryExpr)(nil),
36    }
37    inspect.Preorder(nodeFilter, func(n ast.Node) {
38        e := n.(*ast.BinaryExpr)
39
40        // Only want == or != comparisons.
41        if e.Op != token.EQL && e.Op != token.NEQ {
42            return
43        }
44
45        // Only want comparisons with a nil identifier on one side.
46        var e2 ast.Expr
47        switch {
48        case pass.TypesInfo.Types[e.X].IsNil():
49            e2 = e.Y
50        case pass.TypesInfo.Types[e.Y].IsNil():
51            e2 = e.X
52        default:
53            return
54        }
55
56        // Only want identifiers or selector expressions.
57        var obj types.Object
58        switch v := e2.(type) {
59        case *ast.Ident:
60            obj = pass.TypesInfo.Uses[v]
61        case *ast.SelectorExpr:
62            obj = pass.TypesInfo.Uses[v.Sel]
63        case *ast.IndexExpr, *typeparams.IndexListExpr:
64            // Check generic functions such as "f[T1,T2]".
65            x___ := typeparams.UnpackIndexExpr(v)
66            if idok := x.(*ast.Ident); ok {
67                obj = pass.TypesInfo.Uses[id]
68            }
69        default:
70            return
71        }
72
73        // Only want functions.
74        if _ok := obj.(*types.Func); !ok {
75            return
76        }
77
78        pass.ReportRangef(e"comparison of function %v %v nil is always %v"obj.Name(), e.Ope.Op == token.NEQ)
79    })
80    return nilnil
81}
82
MembersX
run.BlockStmt.e2
run.BlockStmt.obj
run.BlockStmt.BlockStmt.x
types
typeparams
inspector
Doc
run.BlockStmt.BlockStmt._
ast
inspect
run.pass
token
run
analysis
run.nodeFilter
Members
X