This repository has been archived by the owner on Dec 30, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
flagDeref_checker.go
65 lines (57 loc) · 1.6 KB
/
flagDeref_checker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package checkers
import (
"go/ast"
"github.com/go-lintpack/lintpack"
"github.com/go-lintpack/lintpack/astwalk"
)
func init() {
var info lintpack.CheckerInfo
info.Name = "flagDeref"
info.Tags = []string{"diagnostic"}
info.Summary = "Detects immediate dereferencing of `flag` package pointers"
info.Details = "Suggests to use pointer to array to avoid the copy using `&` on range expression."
info.Before = `b := *flag.Bool("b", false, "b docs")`
info.After = `
var b bool
flag.BoolVar(&b, "b", false, "b docs")`
info.Note = `
Dereferencing returned pointers will lead to hard to find errors
where flag values are not updated after flag.Parse().`
collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
c := &flagDerefChecker{
ctx: ctx,
flagPtrFuncs: map[string]bool{
"flag.Bool": true,
"flag.Duration": true,
"flag.Float64": true,
"flag.Int": true,
"flag.Int64": true,
"flag.String": true,
"flag.Uint": true,
"flag.Uint64": true,
},
}
return astwalk.WalkerForExpr(c)
})
}
type flagDerefChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
flagPtrFuncs map[string]bool
}
func (c *flagDerefChecker) VisitExpr(expr ast.Expr) {
if expr, ok := expr.(*ast.StarExpr); ok {
call, ok := expr.X.(*ast.CallExpr)
if !ok {
return
}
called := qualifiedName(call.Fun)
if c.flagPtrFuncs[called] {
c.warn(expr, called+"Var")
}
}
}
func (c *flagDerefChecker) warn(x ast.Node, suggestion string) {
c.ctx.Warn(x, "immediate deref in %s is most likely an error; consider using %s",
x, suggestion)
}