66 lines
1.6 KiB
Go
66 lines
1.6 KiB
Go
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().`
|
|
|
|
lintpack.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)
|
|
}
|