lint: avoid false positives with custom errors-package
When using `errors.New(fmt.Sprintf(...))`,
lint will alert that you should use `fmt.Errorf(...)`.
Before this patch, this alert was also displayed
when using a custom errors-package.
There are valid use cases to use `errors.New(fmt.Sprintf(...))`
in a custom errors-package context.
This patch avoids the "false positive" alert
when a custom errors-package is imported in the current file.
Fixes golang/lint#350
Change-Id: I7cc82a3435b184f8b4cad0752a75d44f33536dce
GitHub-Last-Rev: ad257d26802aca316d6b83758fcb143083934587
GitHub-Pull-Request: golang/lint#360
Reviewed-on: https://go-review.googlesource.com/96091
Reviewed-by: Andrew Bonventre <andybons@golang.org>
diff --git a/lint.go b/lint.go
index cc6fef2..f60106c 100644
--- a/lint.go
+++ b/lint.go
@@ -23,6 +23,7 @@
"unicode"
"unicode/utf8"
+ "golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/go/gcexportdata"
)
@@ -1126,6 +1127,9 @@
if !isErrorsNew && !isTestingError {
return true
}
+ if !f.imports("errors") {
+ return true
+ }
arg := ce.Args[0]
ce, ok = arg.(*ast.CallExpr)
if !ok || !isPkgDot(ce.Fun, "fmt", "Sprintf") {
@@ -1694,6 +1698,20 @@
return rx.FindStringSubmatch(line)
}
+// imports returns true if the current file imports the specified package path.
+func (f *file) imports(importPath string) bool {
+ all := astutil.Imports(f.fset, f.f)
+ for _, p := range all {
+ for _, i := range p {
+ uq, err := strconv.Unquote(i.Path.Value)
+ if err == nil && importPath == uq {
+ return true
+ }
+ }
+ }
+ return false
+}
+
// srcLine returns the complete line at p, including the terminating newline.
func srcLine(src []byte, p token.Position) string {
// Run to end of line in both directions if not at line start/end.
diff --git a/testdata/errorf-custom.go b/testdata/errorf-custom.go
new file mode 100644
index 0000000..7980c8d
--- /dev/null
+++ b/testdata/errorf-custom.go
@@ -0,0 +1,25 @@
+// Test for allowed errors.New(fmt.Sprintf()) when a custom errors package is imported.
+
+// Package foo ...
+package foo
+
+import (
+ "fmt"
+
+ "github.com/pkg/errors"
+)
+
+func f(x int) error {
+ if x > 10 {
+ return errors.New(fmt.Sprintf("something %d", x)) // OK
+ }
+ if x > 5 {
+ return errors.New(g("blah")) // OK
+ }
+ if x > 4 {
+ return errors.New("something else") // OK
+ }
+ return nil
+}
+
+func g(s string) string { return "prefix: " + s }