123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- package rule
-
- import (
- "go/ast"
-
- "github.com/mgechev/revive/lint"
- )
-
- // EarlyReturnRule lints given else constructs.
- type EarlyReturnRule struct{}
-
- // Apply applies the rule to given file.
- func (r *EarlyReturnRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
- var failures []lint.Failure
-
- onFailure := func(failure lint.Failure) {
- failures = append(failures, failure)
- }
-
- w := lintEarlyReturnRule{onFailure: onFailure}
- ast.Walk(w, file.AST)
- return failures
- }
-
- // Name returns the rule name.
- func (r *EarlyReturnRule) Name() string {
- return "early-return"
- }
-
- type lintEarlyReturnRule struct {
- onFailure func(lint.Failure)
- }
-
- func (w lintEarlyReturnRule) Visit(node ast.Node) ast.Visitor {
- switch n := node.(type) {
- case *ast.IfStmt:
- if n.Else == nil {
- // no else branch
- return w
- }
-
- elseBlock, ok := n.Else.(*ast.BlockStmt)
- if !ok {
- // is if-else-if
- return w
- }
-
- lenElseBlock := len(elseBlock.List)
- if lenElseBlock < 1 {
- // empty else block, continue (there is another rule that warns on empty blocks)
- return w
- }
-
- lenThenBlock := len(n.Body.List)
- if lenThenBlock < 1 {
- // then block is empty thus the stmt can be simplified
- w.onFailure(lint.Failure{
- Confidence: 1,
- Node: n,
- Failure: "if c { } else {... return} can be simplified to if !c { ... return }",
- })
-
- return w
- }
-
- _, lastThenStmtIsReturn := n.Body.List[lenThenBlock-1].(*ast.ReturnStmt)
- _, lastElseStmtIsReturn := elseBlock.List[lenElseBlock-1].(*ast.ReturnStmt)
- if lastElseStmtIsReturn && !lastThenStmtIsReturn {
- w.onFailure(lint.Failure{
- Confidence: 1,
- Node: n,
- Failure: "if c {...} else {... return } can be simplified to if !c { ... return } ...",
- })
- }
- }
-
- return w
- }
|