1
0
mirror of https://github.com/mgechev/revive.git synced 2024-11-24 08:32:22 +02:00

Update the no-else-return rule

This commit is contained in:
mgechev 2017-11-19 19:38:28 -08:00
parent 57a87dda1a
commit 0cb70da5fc

View File

@ -14,9 +14,13 @@ type LintElseRule struct{}
// Apply applies the rule to given file.
func (r *LintElseRule) Apply(file *file.File, arguments rule.Arguments) []rule.Failure {
var failures []rule.Failure
ast.Walk(lintElse(func(failure rule.Failure) {
onFailure := func(failure rule.Failure) {
failures = append(failures, failure)
}), file.GetAST())
}
w := lintElse{make(map[*ast.IfStmt]bool), onFailure}
ast.Walk(w, file.GetAST())
return failures
}
@ -25,36 +29,47 @@ func (r *LintElseRule) Name() string {
return "no-else-return"
}
type lintElse func(rule.Failure)
type lintElse struct {
ignore map[*ast.IfStmt]bool
onFailure func(rule.Failure)
}
func (f lintElse) Visit(n ast.Node) ast.Visitor {
node, ok := n.(*ast.IfStmt)
if ok {
if node.Else == nil {
return f
}
if _, ok := node.Else.(*ast.BlockStmt); !ok {
// only care about elses without conditions
return f
}
if len(node.Body.List) == 0 {
return f
}
// shortDecl := false // does the if statement have a ":=" initialization statement?
if node.Init != nil {
if as, ok := node.Init.(*ast.AssignStmt); ok && as.Tok == token.DEFINE {
// shortDecl = true
}
}
lastStmt := node.Body.List[len(node.Body.List)-1]
if _, ok := lastStmt.(*ast.ReturnStmt); ok {
f(rule.Failure{
Failure: "if block ends with a return statement, so drop this else and outdent its block",
Type: rule.FailureTypeWarning,
Node: node.Else,
})
return f
func (w lintElse) Visit(node ast.Node) ast.Visitor {
ifStmt, ok := node.(*ast.IfStmt)
if !ok || ifStmt.Else == nil {
return w
}
if w.ignore[ifStmt] {
return w
}
if elseif, ok := ifStmt.Else.(*ast.IfStmt); ok {
w.ignore[elseif] = true
return w
}
if _, ok := ifStmt.Else.(*ast.BlockStmt); !ok {
// only care about elses without conditions
return w
}
if len(ifStmt.Body.List) == 0 {
return w
}
shortDecl := false // does the if statement have a ":=" initialization statement?
if ifStmt.Init != nil {
if as, ok := ifStmt.Init.(*ast.AssignStmt); ok && as.Tok == token.DEFINE {
shortDecl = true
}
}
return f
lastStmt := ifStmt.Body.List[len(ifStmt.Body.List)-1]
if _, ok := lastStmt.(*ast.ReturnStmt); ok {
extra := ""
if shortDecl {
extra = " (move short variable declaration to its own line if necessary)"
}
w.onFailure(rule.Failure{
Failure: "if block ends with a return statement, so drop this else and outdent its block" + extra,
Type: rule.FailureTypeWarning,
Node: ifStmt.Else,
})
}
return w
}