You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

early-return.go 1.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package rule
  2. import (
  3. "go/ast"
  4. "github.com/mgechev/revive/lint"
  5. )
  6. // EarlyReturnRule lints given else constructs.
  7. type EarlyReturnRule struct{}
  8. // Apply applies the rule to given file.
  9. func (r *EarlyReturnRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
  10. var failures []lint.Failure
  11. onFailure := func(failure lint.Failure) {
  12. failures = append(failures, failure)
  13. }
  14. w := lintEarlyReturnRule{onFailure: onFailure}
  15. ast.Walk(w, file.AST)
  16. return failures
  17. }
  18. // Name returns the rule name.
  19. func (r *EarlyReturnRule) Name() string {
  20. return "early-return"
  21. }
  22. type lintEarlyReturnRule struct {
  23. onFailure func(lint.Failure)
  24. }
  25. func (w lintEarlyReturnRule) Visit(node ast.Node) ast.Visitor {
  26. switch n := node.(type) {
  27. case *ast.IfStmt:
  28. if n.Else == nil {
  29. // no else branch
  30. return w
  31. }
  32. elseBlock, ok := n.Else.(*ast.BlockStmt)
  33. if !ok {
  34. // is if-else-if
  35. return w
  36. }
  37. lenElseBlock := len(elseBlock.List)
  38. if lenElseBlock < 1 {
  39. // empty else block, continue (there is another rule that warns on empty blocks)
  40. return w
  41. }
  42. lenThenBlock := len(n.Body.List)
  43. if lenThenBlock < 1 {
  44. // then block is empty thus the stmt can be simplified
  45. w.onFailure(lint.Failure{
  46. Confidence: 1,
  47. Node: n,
  48. Failure: "if c { } else {... return} can be simplified to if !c { ... return }",
  49. })
  50. return w
  51. }
  52. _, lastThenStmtIsReturn := n.Body.List[lenThenBlock-1].(*ast.ReturnStmt)
  53. _, lastElseStmtIsReturn := elseBlock.List[lenElseBlock-1].(*ast.ReturnStmt)
  54. if lastElseStmtIsReturn && !lastThenStmtIsReturn {
  55. w.onFailure(lint.Failure{
  56. Confidence: 1,
  57. Node: n,
  58. Failure: "if c {...} else {... return } can be simplified to if !c { ... return } ...",
  59. })
  60. }
  61. }
  62. return w
  63. }