1
0
mirror of https://github.com/mgechev/revive.git synced 2025-01-10 03:17:11 +02:00

new ADS rule: newerr

This commit is contained in:
chavacava 2018-06-28 11:06:43 +02:00
parent 27a18a3b82
commit 3dc86d87c8
3 changed files with 105 additions and 0 deletions

View File

@ -52,6 +52,7 @@ var allRules = append([]lint.Rule{
&rule.GetReturnRule{},
&rule.ModifiesParamRule{},
&rule.DeepExitRule{},
&rule.ADSNewErrRule{},
}, defaultRules...)
var allFormatters = []lint.Formatter{

7
fixtures/ads-newerror.go Normal file
View File

@ -0,0 +1,7 @@
package fixtures
import "errors"
func foo(a, b, c, d int) {
errors.New("aaa")
}

97
rule/ads-newerr.go Normal file
View File

@ -0,0 +1,97 @@
package rule
import (
"go/ast"
"github.com/mgechev/revive/lint"
)
// ADSNewErrRule lints program exit at functions other than main or init.
type ADSNewErrRule struct{}
// Apply applies the rule to given file.
func (r *ADSNewErrRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
var failures []lint.Failure
onFailure := func(failure lint.Failure) {
failures = append(failures, failure)
}
w := lintNewErr{onFailure, "errors", "New"}
ast.Walk(w, file.AST)
return failures
}
// Name returns the rule name.
func (r *ADSNewErrRule) Name() string {
return "ads-newerr"
}
type lintNewErr struct {
onFailure func(lint.Failure)
targetPkg string
targetFunc string
}
func (w lintNewErr) Visit(node ast.Node) ast.Visitor {
ce, ok := node.(*ast.CallExpr)
if !ok {
return w
}
pkg, fn := getPkgFunc(ce)
if pkg == w.targetPkg && fn == w.targetFunc {
if pkg == "errors" && fn == "New" {
w.targetFunc = "MessageOption"
return w
}
s := searchErr{&w, ce}
for _, exp := range ce.Args {
ast.Walk(s, exp)
}
w.targetFunc = "New"
}
return w
}
type searchErr struct {
w *lintNewErr
fc *ast.CallExpr
}
func (s searchErr) Visit(node ast.Node) ast.Visitor {
id, ok := node.(*ast.Ident)
if !ok {
return s
}
if id.Name == "err" {
s.w.onFailure(lint.Failure{
Confidence: 0.8,
Node: s.fc,
Category: "bad practice",
URL: "#ads-newerr",
Failure: "consider errors.Wrap instead of errors.New",
})
}
return s
}
func getPkgFunc(ce *ast.CallExpr) (string, string) {
fc, ok := ce.Fun.(*ast.SelectorExpr)
if !ok {
return "", ""
}
id, ok := fc.X.(*ast.Ident)
if !ok {
return "", ""
}
return id.Name, fc.Sel.Name
}