1
0
mirror of https://github.com/mgechev/revive.git synced 2025-02-01 13:07:44 +02:00

Merge 'ads-lost-err'

Conflicts:
	config.go
This commit is contained in:
chavacava 2018-06-29 13:43:04 +02:00
commit 8ffd0e86d3
4 changed files with 116 additions and 0 deletions

View File

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

9
fixtures/ads-lost-err.go Normal file
View File

@ -0,0 +1,9 @@
package fixtures
import "errors"
func foo(a, b, c, d int) {
errors.New("aaa")
errors.New(errors.InternalError, errors.MessageOption("nice error message "+err.Error())) // MATCH /original error is lost, consider using errors.NewFromError/
errors.MessageOption("nice error message " + err.Error())
}

95
rule/ads-lost-err.go Normal file
View File

@ -0,0 +1,95 @@
package rule
import (
"go/ast"
"github.com/mgechev/revive/lint"
)
// ADSLostErrRule lints program exit at functions other than main or init.
type ADSLostErrRule struct{}
// Apply applies the rule to given file.
func (r *ADSLostErrRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure {
var failures []lint.Failure
onFailure := func(failure lint.Failure) {
failures = append(failures, failure)
}
w := lintLostErr{onFailure, "errors", "New"}
ast.Walk(w, file.AST)
return failures
}
// Name returns the rule name.
func (r *ADSLostErrRule) Name() string {
return "ads-lost-err"
}
type lintLostErr struct {
onFailure func(lint.Failure)
targetPkg string
targetFunc string
}
func (w lintLostErr) 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 *lintLostErr
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",
Failure: "original error is lost, consider using errors.NewFromError",
})
}
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
}

11
test/ads-lost-err_test.go Normal file
View File

@ -0,0 +1,11 @@
package test
import (
"testing"
"github.com/mgechev/revive/rule"
)
func TestADSLostErr(t *testing.T) {
testRule(t, "ads-lost-err", &rule.ADSLostErrRule{})
}