David López 37e6995b45 lintpack/gocritic: update lintpack & gocritic versions
update lintpack & gocritic versions to support all the new gocritic checks
2018-12-22 15:34:16 +03:00

82 lines
2.1 KiB
Go

package checkers
import (
"go/ast"
"go/token"
"github.com/go-lintpack/lintpack"
"github.com/go-lintpack/lintpack/astwalk"
"github.com/go-toolsmith/astcopy"
"github.com/go-toolsmith/astequal"
"github.com/go-toolsmith/typep"
)
func init() {
var info lintpack.CheckerInfo
info.Name = "assignOp"
info.Tags = []string{"style"}
info.Summary = "Detects assignments that can be simplified by using assignment operators"
info.Before = `x = x * 2`
info.After = `x *= 2`
collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker {
return astwalk.WalkerForStmt(&assignOpChecker{ctx: ctx})
})
}
type assignOpChecker struct {
astwalk.WalkHandler
ctx *lintpack.CheckerContext
}
func (c *assignOpChecker) VisitStmt(stmt ast.Stmt) {
assign, ok := stmt.(*ast.AssignStmt)
cond := ok &&
assign.Tok == token.ASSIGN &&
len(assign.Lhs) == 1 &&
len(assign.Rhs) == 1 &&
typep.SideEffectFree(c.ctx.TypesInfo, assign.Lhs[0])
if !cond {
return
}
// TODO(quasilyte): can take commutativity into account.
expr, ok := assign.Rhs[0].(*ast.BinaryExpr)
if !ok || !astequal.Expr(assign.Lhs[0], expr.X) {
return
}
// TODO(quasilyte): perform unparen?
switch expr.Op {
case token.MUL:
c.warn(assign, token.MUL_ASSIGN, expr.Y)
case token.QUO:
c.warn(assign, token.QUO_ASSIGN, expr.Y)
case token.REM:
c.warn(assign, token.REM_ASSIGN, expr.Y)
case token.ADD:
c.warn(assign, token.ADD_ASSIGN, expr.Y)
case token.SUB:
c.warn(assign, token.SUB_ASSIGN, expr.Y)
case token.AND:
c.warn(assign, token.AND_ASSIGN, expr.Y)
case token.OR:
c.warn(assign, token.OR_ASSIGN, expr.Y)
case token.XOR:
c.warn(assign, token.XOR_ASSIGN, expr.Y)
case token.SHL:
c.warn(assign, token.SHL_ASSIGN, expr.Y)
case token.SHR:
c.warn(assign, token.SHR_ASSIGN, expr.Y)
case token.AND_NOT:
c.warn(assign, token.AND_NOT_ASSIGN, expr.Y)
}
}
func (c *assignOpChecker) warn(cause *ast.AssignStmt, op token.Token, rhs ast.Expr) {
suggestion := astcopy.AssignStmt(cause)
suggestion.Tok = op
suggestion.Rhs[0] = rhs
c.ctx.Warn(cause, "replace `%s` with `%s`", cause, suggestion)
}