60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
package checkers
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/types"
|
|
|
|
"github.com/go-lintpack/lintpack"
|
|
"github.com/go-lintpack/lintpack/astwalk"
|
|
"github.com/go-toolsmith/astequal"
|
|
)
|
|
|
|
func init() {
|
|
var info lintpack.CheckerInfo
|
|
info.Name = "unslice"
|
|
info.Tags = []string{"style"}
|
|
info.Summary = "Detects slice expressions that can be simplified to sliced expression itself"
|
|
info.Before = `
|
|
f(s[:]) // s is string
|
|
copy(b[:], values...) // b is []byte`
|
|
info.After = `
|
|
f(s)
|
|
copy(b, values...)`
|
|
|
|
collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
|
|
return astwalk.WalkerForExpr(&unsliceChecker{ctx: ctx})
|
|
})
|
|
}
|
|
|
|
type unsliceChecker struct {
|
|
astwalk.WalkHandler
|
|
ctx *lintpack.CheckerContext
|
|
}
|
|
|
|
func (c *unsliceChecker) VisitExpr(expr ast.Expr) {
|
|
unsliced := c.unslice(expr)
|
|
if !astequal.Expr(expr, unsliced) {
|
|
c.warn(expr, unsliced)
|
|
c.SkipChilds = true
|
|
}
|
|
}
|
|
|
|
func (c *unsliceChecker) unslice(expr ast.Expr) ast.Expr {
|
|
slice, ok := expr.(*ast.SliceExpr)
|
|
if !ok || slice.Low != nil || slice.High != nil {
|
|
// No need to worry about 3-index slicing,
|
|
// because it's only permitted if expr.High is not nil.
|
|
return expr
|
|
}
|
|
switch c.ctx.TypesInfo.TypeOf(slice.X).(type) {
|
|
case *types.Slice, *types.Basic:
|
|
// Basic kind catches strings, Slice cathes everything else.
|
|
return c.unslice(slice.X)
|
|
}
|
|
return expr
|
|
}
|
|
|
|
func (c *unsliceChecker) warn(cause ast.Expr, unsliced ast.Expr) {
|
|
c.ctx.Warn(cause, "could simplify %s to %s", cause, unsliced)
|
|
}
|