1
0
mirror of https://github.com/mgechev/revive.git synced 2025-02-15 13:53:15 +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
onFailure func(rule.Failure)
}
func (f lintElse) Visit(n ast.Node) ast.Visitor { func (w lintElse) Visit(node ast.Node) ast.Visitor {
node, ok := n.(*ast.IfStmt) ifStmt, ok := node.(*ast.IfStmt)
if ok { if !ok || ifStmt.Else == nil {
if node.Else == nil { return w
return f }
} if w.ignore[ifStmt] {
if _, ok := node.Else.(*ast.BlockStmt); !ok { return w
// only care about elses without conditions }
return f if elseif, ok := ifStmt.Else.(*ast.IfStmt); ok {
} w.ignore[elseif] = true
if len(node.Body.List) == 0 { return w
return f }
} if _, ok := ifStmt.Else.(*ast.BlockStmt); !ok {
// shortDecl := false // does the if statement have a ":=" initialization statement? // only care about elses without conditions
if node.Init != nil { return w
if as, ok := node.Init.(*ast.AssignStmt); ok && as.Tok == token.DEFINE { }
// shortDecl = true if len(ifStmt.Body.List) == 0 {
} return w
} }
lastStmt := node.Body.List[len(node.Body.List)-1] shortDecl := false // does the if statement have a ":=" initialization statement?
if _, ok := lastStmt.(*ast.ReturnStmt); ok { if ifStmt.Init != nil {
f(rule.Failure{ if as, ok := ifStmt.Init.(*ast.AssignStmt); ok && as.Tok == token.DEFINE {
Failure: "if block ends with a return statement, so drop this else and outdent its block", shortDecl = true
Type: rule.FailureTypeWarning,
Node: node.Else,
})
return f
} }
} }
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
} }