1
0
mirror of https://github.com/mgechev/revive.git synced 2025-12-19 23:42:11 +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. // Apply applies the rule to given file.
func (r *LintElseRule) Apply(file *file.File, arguments rule.Arguments) []rule.Failure { func (r *LintElseRule) Apply(file *file.File, arguments rule.Arguments) []rule.Failure {
var failures []rule.Failure var failures []rule.Failure
ast.Walk(lintElse(func(failure rule.Failure) {
onFailure := func(failure rule.Failure) {
failures = append(failures, failure) failures = append(failures, failure)
}), file.GetAST()) }
w := lintElse{make(map[*ast.IfStmt]bool), onFailure}
ast.Walk(w, file.GetAST())
return failures return failures
} }
@@ -25,36 +29,47 @@ func (r *LintElseRule) Name() string {
return "no-else-return" return "no-else-return"
} }
type lintElse func(rule.Failure) type lintElse struct {
ignore map[*ast.IfStmt]bool
func (f lintElse) Visit(n ast.Node) ast.Visitor { onFailure func(rule.Failure)
node, ok := n.(*ast.IfStmt) }
if ok {
if node.Else == nil { func (w lintElse) Visit(node ast.Node) ast.Visitor {
return f ifStmt, ok := node.(*ast.IfStmt)
} if !ok || ifStmt.Else == nil {
if _, ok := node.Else.(*ast.BlockStmt); !ok { return w
// only care about elses without conditions }
return f if w.ignore[ifStmt] {
} return w
if len(node.Body.List) == 0 { }
return f if elseif, ok := ifStmt.Else.(*ast.IfStmt); ok {
} w.ignore[elseif] = true
// shortDecl := false // does the if statement have a ":=" initialization statement? return w
if node.Init != nil { }
if as, ok := node.Init.(*ast.AssignStmt); ok && as.Tok == token.DEFINE { if _, ok := ifStmt.Else.(*ast.BlockStmt); !ok {
// shortDecl = true // only care about elses without conditions
} return w
} }
lastStmt := node.Body.List[len(node.Body.List)-1] if len(ifStmt.Body.List) == 0 {
if _, ok := lastStmt.(*ast.ReturnStmt); ok { return w
f(rule.Failure{ }
Failure: "if block ends with a return statement, so drop this else and outdent its block", shortDecl := false // does the if statement have a ":=" initialization statement?
Type: rule.FailureTypeWarning, if ifStmt.Init != nil {
Node: node.Else, 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]
return f 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
} }