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:
parent
57a87dda1a
commit
0cb70da5fc
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user