Skip to content
This repository was archived by the owner on Jun 2, 2023. It is now read-only.

Commit 5b8b7e6

Browse files
committed
Check unvendored version of package paths for ignore parameter
Fixes kisielk#102
1 parent be8bde4 commit 5b8b7e6

File tree

2 files changed

+113
-2
lines changed

2 files changed

+113
-2
lines changed

internal/errcheck/errcheck.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@ import (
1010
"go/ast"
1111
"go/build"
1212
"go/token"
13+
"go/types"
1314
"os"
1415
"regexp"
1516
"sort"
1617
"strings"
1718
"sync"
1819

19-
"go/types"
20-
2120
"golang.org/x/tools/go/loader"
2221
)
2322

@@ -220,12 +219,31 @@ func (v *visitor) ignoreCall(call *ast.CallExpr) bool {
220219
if re, ok := v.ignore[pkg.Path()]; ok {
221220
return re.MatchString(id.Name)
222221
}
222+
223+
// if current package being considered is vendored, check to see if it should be ignored based
224+
// on the unvendored path.
225+
if nonVendoredPkg, ok := nonVendoredPkgPath(pkg.Path()); ok {
226+
if re, ok := v.ignore[nonVendoredPkg]; ok {
227+
return re.MatchString(id.Name)
228+
}
229+
}
223230
}
224231
}
225232

226233
return false
227234
}
228235

236+
// nonVendoredPkgPath returns the unvendored version of the provided package path (or returns the provided path if it
237+
// does not represent a vendored path). The second return value is true if the provided package was vendored, false
238+
// otherwise.
239+
func nonVendoredPkgPath(pkgPath string) (string, bool) {
240+
lastVendorIndex := strings.LastIndex(pkgPath, "/vendor/")
241+
if lastVendorIndex == -1 {
242+
return pkgPath, false
243+
}
244+
return pkgPath[lastVendorIndex+len("/vendor/"):], true
245+
}
246+
229247
// errorsByArg returns a slice s such that
230248
// len(s) == number of return types of call
231249
// s[i] == true iff return type at position i from left is an error type

internal/errcheck/errcheck_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import (
55
"go/build"
66
"go/parser"
77
"go/token"
8+
"io/ioutil"
9+
"os"
10+
"path"
11+
"regexp"
12+
"runtime"
13+
"strings"
814
"testing"
915
)
1016

@@ -83,6 +89,93 @@ func TestAll(t *testing.T) {
8389
test(t, CheckAsserts|CheckBlank)
8490
}
8591

92+
const testVendorMain = `
93+
package main
94+
95+
import "github.com/testlog"
96+
97+
func main() {
98+
// returns an error that is not checked
99+
testlog.Info()
100+
}`
101+
const testLog = `
102+
package testlog
103+
104+
func Info() error {
105+
return nil
106+
}`
107+
108+
func TestIgnore(t *testing.T) {
109+
if strings.HasPrefix(runtime.Version(), "go1.5") && os.Getenv("GO15VENDOREXPERIMENT") != "1" {
110+
// skip tests if running in go1.5 and vendoring is not enabled
111+
t.SkipNow()
112+
}
113+
114+
// copy testvendor directory into current directory for test
115+
testVendorDir, err := ioutil.TempDir(".", "testvendor")
116+
if err != nil {
117+
t.Fatalf("unable to create testvendor directory: %v", err)
118+
}
119+
defer os.RemoveAll(testVendorDir)
120+
121+
if err := ioutil.WriteFile(path.Join(testVendorDir, "main.go"), []byte(testVendorMain), 0755); err != nil {
122+
t.Fatalf("Failed to write testvendor main: %v", err)
123+
}
124+
if err := os.MkdirAll(path.Join(testVendorDir, "vendor/github.com/testlog"), 0755); err != nil {
125+
t.Fatalf("MkdirAll failed: %v", err)
126+
}
127+
if err := ioutil.WriteFile(path.Join(testVendorDir, "vendor/github.com/testlog/testlog.go"), []byte(testLog), 0755); err != nil {
128+
t.Fatalf("Failed to write testlog: %v", err)
129+
}
130+
131+
cases := []struct {
132+
ignore map[string]*regexp.Regexp
133+
numExpectedErrs int
134+
}{
135+
// basic case has one error
136+
{
137+
ignore: nil,
138+
numExpectedErrs: 1,
139+
},
140+
// ignoring vendored import works
141+
{
142+
ignore: map[string]*regexp.Regexp{
143+
path.Join("github.com/kisielk/errcheck/internal/errcheck", testVendorDir, "vendor/github.com/testlog"): regexp.MustCompile("Info"),
144+
},
145+
},
146+
// non-vendored path ignores vendored import
147+
{
148+
ignore: map[string]*regexp.Regexp{
149+
"github.com/testlog": regexp.MustCompile("Info"),
150+
},
151+
},
152+
}
153+
154+
for i, currCase := range cases {
155+
checker := &Checker{
156+
Ignore: currCase.ignore,
157+
}
158+
err := checker.CheckPackages(path.Join("github.com/kisielk/errcheck/internal/errcheck", testVendorDir))
159+
160+
if currCase.numExpectedErrs == 0 {
161+
if err != nil {
162+
t.Errorf("Case %d: expected no errors, but got: %v", i, err)
163+
}
164+
continue
165+
}
166+
167+
uerr, ok := err.(*UncheckedErrors)
168+
if !ok {
169+
t.Errorf("Case %d: wrong error type returned", i)
170+
continue
171+
}
172+
173+
if currCase.numExpectedErrs != len(uerr.Errors) {
174+
t.Errorf("Case %d:\nExpected: %d errors\nActual: %d errors", i, currCase.numExpectedErrs, len(uerr.Errors))
175+
}
176+
}
177+
}
178+
86179
func test(t *testing.T, f flags) {
87180
var (
88181
asserts bool = f&CheckAsserts != 0

0 commit comments

Comments
 (0)