Skip to content

Commit

Permalink
Merge pull request #145 from bananaumai/skip-generated-code-proto
Browse files Browse the repository at this point in the history
skip processing generated code
  • Loading branch information
kisielk committed Jul 1, 2018
2 parents 55d8f50 + dbecf20 commit e96dacd
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 3 deletions.
30 changes: 30 additions & 0 deletions internal/errcheck/errcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"strings"
"sync"

"go/parser"
"golang.org/x/tools/go/loader"
)

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

// If true, checking of files with generated code is disabled
WithoutGeneratedCode bool

exclude map[string]bool
}

Expand Down Expand Up @@ -169,6 +173,11 @@ func (c *Checker) load(paths ...string) (*loader.Program, error) {
loadcfg := loader.Config{
Build: &ctx,
}

if c.WithoutGeneratedCode {
loadcfg.ParserMode = parser.ParseComments
}

rest, err := loadcfg.FromArgs(paths, !c.WithoutTests)
if err != nil {
return nil, fmt.Errorf("could not parse arguments: %s", err)
Expand All @@ -180,6 +189,24 @@ func (c *Checker) load(paths ...string) (*loader.Program, error) {
return loadcfg.Load()
}

var generatedCodeRegexp = regexp.MustCompile("^// Code generated .* DO NOT EDIT\\.$")

func (c *Checker) shouldSkipFile(file *ast.File) bool {
if !c.WithoutGeneratedCode {
return false
}

for _, cg := range file.Comments {
for _, comment := range cg.List {
if generatedCodeRegexp.MatchString(comment.Text) {
return true
}
}
}

return false
}

// CheckPackages checks packages for errors.
func (c *Checker) CheckPackages(paths ...string) error {
program, err := c.load(paths...)
Expand Down Expand Up @@ -212,6 +239,9 @@ func (c *Checker) CheckPackages(paths ...string) error {
}

for _, astFile := range v.pkg.Files {
if c.shouldSkipFile(astFile) {
continue
}
ast.Walk(v, astFile)
}
u.Append(v.errors...)
Expand Down
86 changes: 83 additions & 3 deletions internal/errcheck/errcheck_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ func TestWhitelist(t *testing.T) {

}

const testVendorMain = `
func TestIgnore(t *testing.T) {
const testVendorMain = `
package main
import "github.com/testlog"
Expand All @@ -102,14 +103,13 @@ const testVendorMain = `
// returns an error that is not checked
testlog.Info()
}`
const testLog = `
const testLog = `
package testlog
func Info() error {
return nil
}`

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

func TestWithoutGeneratedCode(t *testing.T) {
const testVendorMain = `
// Code generated by protoc-gen-go. DO NOT EDIT.
package main
import "github.com/testlog"
func main() {
// returns an error that is not checked
testlog.Info()
}`
const testLog = `
package testlog
func Info() error {
return nil
}`

if strings.HasPrefix(runtime.Version(), "go1.5") && os.Getenv("GO15VENDOREXPERIMENT") != "1" {
// skip tests if running in go1.5 and vendoring is not enabled
t.SkipNow()
}

// copy testvendor directory into current directory for test
testVendorDir, err := ioutil.TempDir(".", "testvendor")
if err != nil {
t.Fatalf("unable to create testvendor directory: %v", err)
}
defer os.RemoveAll(testVendorDir)

if err := ioutil.WriteFile(path.Join(testVendorDir, "main.go"), []byte(testVendorMain), 0755); err != nil {
t.Fatalf("Failed to write testvendor main: %v", err)
}
if err := os.MkdirAll(path.Join(testVendorDir, "vendor/github.com/testlog"), 0755); err != nil {
t.Fatalf("MkdirAll failed: %v", err)
}
if err := ioutil.WriteFile(path.Join(testVendorDir, "vendor/github.com/testlog/testlog.go"), []byte(testLog), 0755); err != nil {
t.Fatalf("Failed to write testlog: %v", err)
}

cases := []struct {
withoutGeneratedCode bool
numExpectedErrs int
}{
// basic case has one error
{
withoutGeneratedCode: false,
numExpectedErrs: 1,
},
// ignoring vendored import works
{
withoutGeneratedCode: true,
numExpectedErrs: 0,
},
}

for i, currCase := range cases {
checker := NewChecker()
checker.WithoutGeneratedCode = currCase.withoutGeneratedCode
err := checker.CheckPackages(path.Join("github.com/kisielk/errcheck/internal/errcheck", testVendorDir))

if currCase.numExpectedErrs == 0 {
if err != nil {
t.Errorf("Case %d: expected no errors, but got: %v", i, err)
}
continue
}

uerr, ok := err.(*UncheckedErrors)
if !ok {
t.Errorf("Case %d: wrong error type returned", i)
continue
}

if currCase.numExpectedErrs != len(uerr.Errors) {
t.Errorf("Case %d:\nExpected: %d errors\nActual: %d errors", i, currCase.numExpectedErrs, len(uerr.Errors))
}
}
}

func test(t *testing.T, f flags) {
var (
asserts bool = f&CheckAsserts != 0
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func parseFlags(checker *errcheck.Checker, args []string) ([]string, int) {
flags.BoolVar(&checker.Blank, "blank", false, "if true, check for errors assigned to blank identifier")
flags.BoolVar(&checker.Asserts, "asserts", false, "if true, check for ignored type assertion results")
flags.BoolVar(&checker.WithoutTests, "ignoretests", false, "if true, checking of _test.go files is disabled")
flags.BoolVar(&checker.WithoutGeneratedCode, "ignoregenerated", false, "if true, checking of files with generated code is disabled")
flags.BoolVar(&checker.Verbose, "verbose", false, "produce more verbose logging")

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

0 comments on commit e96dacd

Please sign in to comment.