Skip to content

Commit e96dacd

Browse files
authored
Merge pull request #145 from bananaumai/skip-generated-code-proto
skip processing generated code
2 parents 55d8f50 + dbecf20 commit e96dacd

File tree

3 files changed

+114
-3
lines changed

3 files changed

+114
-3
lines changed

internal/errcheck/errcheck.go

+30
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"strings"
1818
"sync"
1919

20+
"go/parser"
2021
"golang.org/x/tools/go/loader"
2122
)
2223

@@ -108,6 +109,9 @@ type Checker struct {
108109
// If true, checking of _test.go files is disabled
109110
WithoutTests bool
110111

112+
// If true, checking of files with generated code is disabled
113+
WithoutGeneratedCode bool
114+
111115
exclude map[string]bool
112116
}
113117

@@ -169,6 +173,11 @@ func (c *Checker) load(paths ...string) (*loader.Program, error) {
169173
loadcfg := loader.Config{
170174
Build: &ctx,
171175
}
176+
177+
if c.WithoutGeneratedCode {
178+
loadcfg.ParserMode = parser.ParseComments
179+
}
180+
172181
rest, err := loadcfg.FromArgs(paths, !c.WithoutTests)
173182
if err != nil {
174183
return nil, fmt.Errorf("could not parse arguments: %s", err)
@@ -180,6 +189,24 @@ func (c *Checker) load(paths ...string) (*loader.Program, error) {
180189
return loadcfg.Load()
181190
}
182191

192+
var generatedCodeRegexp = regexp.MustCompile("^// Code generated .* DO NOT EDIT\\.$")
193+
194+
func (c *Checker) shouldSkipFile(file *ast.File) bool {
195+
if !c.WithoutGeneratedCode {
196+
return false
197+
}
198+
199+
for _, cg := range file.Comments {
200+
for _, comment := range cg.List {
201+
if generatedCodeRegexp.MatchString(comment.Text) {
202+
return true
203+
}
204+
}
205+
}
206+
207+
return false
208+
}
209+
183210
// CheckPackages checks packages for errors.
184211
func (c *Checker) CheckPackages(paths ...string) error {
185212
program, err := c.load(paths...)
@@ -212,6 +239,9 @@ func (c *Checker) CheckPackages(paths ...string) error {
212239
}
213240

214241
for _, astFile := range v.pkg.Files {
242+
if c.shouldSkipFile(astFile) {
243+
continue
244+
}
215245
ast.Walk(v, astFile)
216246
}
217247
u.Append(v.errors...)

internal/errcheck/errcheck_test.go

+83-3
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ func TestWhitelist(t *testing.T) {
9393

9494
}
9595

96-
const testVendorMain = `
96+
func TestIgnore(t *testing.T) {
97+
const testVendorMain = `
9798
package main
9899
99100
import "github.com/testlog"
@@ -102,14 +103,13 @@ const testVendorMain = `
102103
// returns an error that is not checked
103104
testlog.Info()
104105
}`
105-
const testLog = `
106+
const testLog = `
106107
package testlog
107108
108109
func Info() error {
109110
return nil
110111
}`
111112

112-
func TestIgnore(t *testing.T) {
113113
if strings.HasPrefix(runtime.Version(), "go1.5") && os.Getenv("GO15VENDOREXPERIMENT") != "1" {
114114
// skip tests if running in go1.5 and vendoring is not enabled
115115
t.SkipNow()
@@ -179,6 +179,86 @@ func TestIgnore(t *testing.T) {
179179
}
180180
}
181181

182+
func TestWithoutGeneratedCode(t *testing.T) {
183+
const testVendorMain = `
184+
// Code generated by protoc-gen-go. DO NOT EDIT.
185+
package main
186+
187+
import "github.com/testlog"
188+
189+
func main() {
190+
// returns an error that is not checked
191+
testlog.Info()
192+
}`
193+
const testLog = `
194+
package testlog
195+
196+
func Info() error {
197+
return nil
198+
}`
199+
200+
if strings.HasPrefix(runtime.Version(), "go1.5") && os.Getenv("GO15VENDOREXPERIMENT") != "1" {
201+
// skip tests if running in go1.5 and vendoring is not enabled
202+
t.SkipNow()
203+
}
204+
205+
// copy testvendor directory into current directory for test
206+
testVendorDir, err := ioutil.TempDir(".", "testvendor")
207+
if err != nil {
208+
t.Fatalf("unable to create testvendor directory: %v", err)
209+
}
210+
defer os.RemoveAll(testVendorDir)
211+
212+
if err := ioutil.WriteFile(path.Join(testVendorDir, "main.go"), []byte(testVendorMain), 0755); err != nil {
213+
t.Fatalf("Failed to write testvendor main: %v", err)
214+
}
215+
if err := os.MkdirAll(path.Join(testVendorDir, "vendor/github.com/testlog"), 0755); err != nil {
216+
t.Fatalf("MkdirAll failed: %v", err)
217+
}
218+
if err := ioutil.WriteFile(path.Join(testVendorDir, "vendor/github.com/testlog/testlog.go"), []byte(testLog), 0755); err != nil {
219+
t.Fatalf("Failed to write testlog: %v", err)
220+
}
221+
222+
cases := []struct {
223+
withoutGeneratedCode bool
224+
numExpectedErrs int
225+
}{
226+
// basic case has one error
227+
{
228+
withoutGeneratedCode: false,
229+
numExpectedErrs: 1,
230+
},
231+
// ignoring vendored import works
232+
{
233+
withoutGeneratedCode: true,
234+
numExpectedErrs: 0,
235+
},
236+
}
237+
238+
for i, currCase := range cases {
239+
checker := NewChecker()
240+
checker.WithoutGeneratedCode = currCase.withoutGeneratedCode
241+
err := checker.CheckPackages(path.Join("github.com/kisielk/errcheck/internal/errcheck", testVendorDir))
242+
243+
if currCase.numExpectedErrs == 0 {
244+
if err != nil {
245+
t.Errorf("Case %d: expected no errors, but got: %v", i, err)
246+
}
247+
continue
248+
}
249+
250+
uerr, ok := err.(*UncheckedErrors)
251+
if !ok {
252+
t.Errorf("Case %d: wrong error type returned", i)
253+
continue
254+
}
255+
256+
if currCase.numExpectedErrs != len(uerr.Errors) {
257+
t.Errorf("Case %d:\nExpected: %d errors\nActual: %d errors", i, currCase.numExpectedErrs, len(uerr.Errors))
258+
}
259+
}
260+
}
261+
182262
func test(t *testing.T, f flags) {
183263
var (
184264
asserts bool = f&CheckAsserts != 0

main.go

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ func parseFlags(checker *errcheck.Checker, args []string) ([]string, int) {
133133
flags.BoolVar(&checker.Blank, "blank", false, "if true, check for errors assigned to blank identifier")
134134
flags.BoolVar(&checker.Asserts, "asserts", false, "if true, check for ignored type assertion results")
135135
flags.BoolVar(&checker.WithoutTests, "ignoretests", false, "if true, checking of _test.go files is disabled")
136+
flags.BoolVar(&checker.WithoutGeneratedCode, "ignoregenerated", false, "if true, checking of files with generated code is disabled")
136137
flags.BoolVar(&checker.Verbose, "verbose", false, "produce more verbose logging")
137138

138139
flags.BoolVar(&abspath, "abspath", false, "print absolute paths to files")

0 commit comments

Comments
 (0)