2018-11-07 09:11:08 +03:00

51 lines
1.3 KiB
Go

package checkers
import (
"go/ast"
"github.com/go-lintpack/lintpack"
"github.com/go-lintpack/lintpack/astwalk"
"github.com/go-toolsmith/astcast"
"github.com/go-toolsmith/typep"
)
func init() {
var info lintpack.CheckerInfo
info.Name = "indexAlloc"
info.Tags = []string{"performance"}
info.Summary = "Detects strings.Index calls that may cause unwanted allocs"
info.Before = `strings.Index(string(x), y)`
info.After = `bytes.Index(x, []byte(y))`
info.Note = `See Go issue for details: https://github.com/golang/go/issues/25864`
lintpack.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
return astwalk.WalkerForExpr(&indexAllocChecker{ctx: ctx})
})
}
type indexAllocChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
}
func (c *indexAllocChecker) VisitExpr(e ast.Expr) {
call := astcast.ToCallExpr(e)
if qualifiedName(call.Fun) != "strings.Index" {
return
}
stringConv := astcast.ToCallExpr(call.Args[0])
if qualifiedName(stringConv.Fun) != "string" {
return
}
x := stringConv.Args[0]
y := call.Args[1]
if typep.SideEffectFree(c.ctx.TypesInfo, x) && typep.SideEffectFree(c.ctx.TypesInfo, y) {
c.warn(e, x, y)
}
}
func (c *indexAllocChecker) warn(cause ast.Node, x, y ast.Expr) {
c.ctx.Warn(cause, "consider replacing %s with bytes.Index(%s, []byte(%s))",
cause, x, y)
}