github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/error-return.go (about) 1 package rule 2 3 import ( 4 "go/ast" 5 6 "github.com/mgechev/revive/lint" 7 ) 8 9 // ErrorReturnRule lints given else constructs. 10 type ErrorReturnRule struct{} 11 12 // Apply applies the rule to given file. 13 func (r *ErrorReturnRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 14 var failures []lint.Failure 15 16 fileAst := file.AST 17 walker := lintErrorReturn{ 18 file: file, 19 fileAst: fileAst, 20 onFailure: func(failure lint.Failure) { 21 failures = append(failures, failure) 22 }, 23 } 24 25 ast.Walk(walker, fileAst) 26 27 return failures 28 } 29 30 // Name returns the rule name. 31 func (r *ErrorReturnRule) Name() string { 32 return "error-return" 33 } 34 35 type lintErrorReturn struct { 36 file *lint.File 37 fileAst *ast.File 38 onFailure func(lint.Failure) 39 } 40 41 func (w lintErrorReturn) Visit(n ast.Node) ast.Visitor { 42 fn, ok := n.(*ast.FuncDecl) 43 if !ok || fn.Type.Results == nil { 44 return w 45 } 46 ret := fn.Type.Results.List 47 if len(ret) <= 1 { 48 return w 49 } 50 if isIdent(ret[len(ret)-1].Type, "error") { 51 return nil 52 } 53 // An error return parameter should be the last parameter. 54 // Flag any error parameters found before the last. 55 for _, r := range ret[:len(ret)-1] { 56 if isIdent(r.Type, "error") { 57 w.onFailure(lint.Failure{ 58 Category: "arg-order", 59 Confidence: 0.9, 60 Node: fn, 61 Failure: "error should be the last type when returning multiple items", 62 }) 63 break // only flag one 64 } 65 } 66 return w 67 }