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.

error-naming.go 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package rule
  2. import (
  3. "fmt"
  4. "go/ast"
  5. "go/token"
  6. "strings"
  7. "github.com/mgechev/revive/lint"
  8. )
  9. // ErrorNamingRule lints given else constructs.
  10. type ErrorNamingRule struct{}
  11. // Apply applies the rule to given file.
  12. func (r *ErrorNamingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
  13. var failures []lint.Failure
  14. fileAst := file.AST
  15. walker := lintErrors{
  16. file: file,
  17. fileAst: fileAst,
  18. onFailure: func(failure lint.Failure) {
  19. failures = append(failures, failure)
  20. },
  21. }
  22. ast.Walk(walker, fileAst)
  23. return failures
  24. }
  25. // Name returns the rule name.
  26. func (r *ErrorNamingRule) Name() string {
  27. return "error-naming"
  28. }
  29. type lintErrors struct {
  30. file *lint.File
  31. fileAst *ast.File
  32. onFailure func(lint.Failure)
  33. }
  34. func (w lintErrors) Visit(_ ast.Node) ast.Visitor {
  35. for _, decl := range w.fileAst.Decls {
  36. gd, ok := decl.(*ast.GenDecl)
  37. if !ok || gd.Tok != token.VAR {
  38. continue
  39. }
  40. for _, spec := range gd.Specs {
  41. spec := spec.(*ast.ValueSpec)
  42. if len(spec.Names) != 1 || len(spec.Values) != 1 {
  43. continue
  44. }
  45. ce, ok := spec.Values[0].(*ast.CallExpr)
  46. if !ok {
  47. continue
  48. }
  49. if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") {
  50. continue
  51. }
  52. id := spec.Names[0]
  53. prefix := "err"
  54. if id.IsExported() {
  55. prefix = "Err"
  56. }
  57. if !strings.HasPrefix(id.Name, prefix) {
  58. w.onFailure(lint.Failure{
  59. Node: id,
  60. Confidence: 0.9,
  61. Category: "naming",
  62. Failure: fmt.Sprintf("error var %s should have name of the form %sFoo", id.Name, prefix),
  63. })
  64. }
  65. }
  66. }
  67. return nil
  68. }