forked from Shiloh/githaven
75 lines
1.4 KiB
Go
75 lines
1.4 KiB
Go
|
package rule
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"go/ast"
|
||
|
"go/token"
|
||
|
|
||
|
"github.com/mgechev/revive/lint"
|
||
|
)
|
||
|
|
||
|
// IncrementDecrementRule lints given else constructs.
|
||
|
type IncrementDecrementRule struct{}
|
||
|
|
||
|
// Apply applies the rule to given file.
|
||
|
func (r *IncrementDecrementRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
|
||
|
var failures []lint.Failure
|
||
|
|
||
|
fileAst := file.AST
|
||
|
walker := lintIncrementDecrement{
|
||
|
file: file,
|
||
|
onFailure: func(failure lint.Failure) {
|
||
|
failures = append(failures, failure)
|
||
|
},
|
||
|
}
|
||
|
|
||
|
ast.Walk(walker, fileAst)
|
||
|
|
||
|
return failures
|
||
|
}
|
||
|
|
||
|
// Name returns the rule name.
|
||
|
func (r *IncrementDecrementRule) Name() string {
|
||
|
return "increment-decrement"
|
||
|
}
|
||
|
|
||
|
type lintIncrementDecrement struct {
|
||
|
file *lint.File
|
||
|
fileAst *ast.File
|
||
|
onFailure func(lint.Failure)
|
||
|
}
|
||
|
|
||
|
func (w lintIncrementDecrement) Visit(n ast.Node) ast.Visitor {
|
||
|
as, ok := n.(*ast.AssignStmt)
|
||
|
if !ok {
|
||
|
return w
|
||
|
}
|
||
|
if len(as.Lhs) != 1 {
|
||
|
return w
|
||
|
}
|
||
|
if !isOne(as.Rhs[0]) {
|
||
|
return w
|
||
|
}
|
||
|
var suffix string
|
||
|
switch as.Tok {
|
||
|
case token.ADD_ASSIGN:
|
||
|
suffix = "++"
|
||
|
case token.SUB_ASSIGN:
|
||
|
suffix = "--"
|
||
|
default:
|
||
|
return w
|
||
|
}
|
||
|
w.onFailure(lint.Failure{
|
||
|
Confidence: 0.8,
|
||
|
Node: as,
|
||
|
Category: "unary-op",
|
||
|
Failure: fmt.Sprintf("should replace %s with %s%s", w.file.Render(as), w.file.Render(as.Lhs[0]), suffix),
|
||
|
})
|
||
|
return w
|
||
|
}
|
||
|
|
||
|
func isOne(expr ast.Expr) bool {
|
||
|
lit, ok := expr.(*ast.BasicLit)
|
||
|
return ok && lit.Kind == token.INT && lit.Value == "1"
|
||
|
}
|