From f8997e6cf33afb448daced363c104b29014631ee Mon Sep 17 00:00:00 2001 From: Korjavin Ivan Date: Sat, 21 Sep 2019 15:54:26 +0300 Subject: [PATCH] Whitelist regexp and fmt.Errorf global vars --- pkg/golinters/gochecknoglobals.go | 52 +++++++++++++++++++++++++++++-- test/testdata/gochecknoglobals.go | 4 +++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/pkg/golinters/gochecknoglobals.go b/pkg/golinters/gochecknoglobals.go index c1a67ad7c643..530c0ae73b7f 100644 --- a/pkg/golinters/gochecknoglobals.go +++ b/pkg/golinters/gochecknoglobals.go @@ -60,8 +60,56 @@ func (lint Gochecknoglobals) checkFile(f *ast.File, fset *token.FileSet) []resul return res } -func isWhitelisted(i *ast.Ident) bool { - return i.Name == "_" || i.Name == "version" || looksLikeError(i) +type whitelistedExpression struct { + Name string + SelName string +} + +func isWhitelisted(v ast.Node) bool { + switch i := v.(type) { + case *ast.Ident: + return i.Name == "_" || i.Name == "version" || looksLikeError(i) + case *ast.CallExpr: + if expr, ok := i.Fun.(*ast.SelectorExpr); ok { + return isWhitelistedSelectorExpression(expr) + } + case *ast.CompositeLit: + if expr, ok := i.Type.(*ast.SelectorExpr); ok { + return isWhitelistedSelectorExpression(expr) + } + } + + return false +} + +func isWhitelistedSelectorExpression(v *ast.SelectorExpr) bool { + x, ok := v.X.(*ast.Ident) + if !ok { + return false + } + + whitelist := []whitelistedExpression{ + { + Name: "errors", + SelName: "New", + }, + { + Name: "fmt", + SelName: "Errorf", + }, + { + Name: "regexp", + SelName: "MustCompile", + }, + } + + for _, i := range whitelist { + if x.Name == i.Name && v.Sel.Name == i.SelName { + return true + } + } + + return false } // looksLikeError returns true if the AST identifier starts diff --git a/test/testdata/gochecknoglobals.go b/test/testdata/gochecknoglobals.go index d802bee3f0da..57e4c6deee09 100644 --- a/test/testdata/gochecknoglobals.go +++ b/test/testdata/gochecknoglobals.go @@ -8,7 +8,11 @@ import ( var noGlobalsVar int // ERROR "`noGlobalsVar` is a global variable" var ErrSomeType = errors.New("test that global erorrs aren't warned") +var ErrFmt1 = fmt.Errorf("test that global errors made with fmt aren't warned") + +//var re1 = regexp.MustComplile("/test that regexp aren't warned/") func NoGlobals() { + _ = ErrFmt1 fmt.Print(noGlobalsVar) }