github.com/pankona/gometalinter@v2.0.11+incompatible/_linters/src/4d63.com/gochecknoglobals/check_no_globals.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/parser"
     7  	"go/token"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  )
    12  
    13  func isWhitelisted(i *ast.Ident) bool {
    14  	return i.Name == "_" || looksLikeError(i)
    15  }
    16  
    17  // looksLikeError returns true if the AST identifier starts
    18  // with 'err' or 'Err', or false otherwise.
    19  //
    20  // TODO: https://github.com/leighmcculloch/gochecknoglobals/issues/5
    21  func looksLikeError(i *ast.Ident) bool {
    22  	prefix := "err"
    23  	if i.IsExported() {
    24  		prefix = "Err"
    25  	}
    26  	return strings.HasPrefix(i.Name, prefix)
    27  }
    28  
    29  func checkNoGlobals(rootPath string, includeTests bool) ([]string, error) {
    30  	const recursiveSuffix = string(filepath.Separator) + "..."
    31  	recursive := false
    32  	if strings.HasSuffix(rootPath, recursiveSuffix) {
    33  		recursive = true
    34  		rootPath = rootPath[:len(rootPath)-len(recursiveSuffix)]
    35  	}
    36  
    37  	messages := []string{}
    38  
    39  	err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {
    40  		if err != nil {
    41  			return err
    42  		}
    43  		if info.IsDir() {
    44  			if !recursive && path != rootPath {
    45  				return filepath.SkipDir
    46  			}
    47  			return nil
    48  		}
    49  		if !strings.HasSuffix(path, ".go") {
    50  			return nil
    51  		}
    52  		if !includeTests && strings.HasSuffix(path, "_test.go") {
    53  			return nil
    54  		}
    55  
    56  		fset := token.NewFileSet()
    57  		file, err := parser.ParseFile(fset, path, nil, 0)
    58  		if err != nil {
    59  			return err
    60  		}
    61  
    62  		for _, decl := range file.Decls {
    63  			genDecl, ok := decl.(*ast.GenDecl)
    64  			if !ok {
    65  				continue
    66  			}
    67  			if genDecl.Tok != token.VAR {
    68  				continue
    69  			}
    70  			filename := fset.Position(genDecl.TokPos).Filename
    71  			line := fset.Position(genDecl.TokPos).Line
    72  			for _, spec := range genDecl.Specs {
    73  				valueSpec := spec.(*ast.ValueSpec)
    74  				for _, vn := range valueSpec.Names {
    75  					if isWhitelisted(vn) {
    76  						continue
    77  					}
    78  					message := fmt.Sprintf("%s:%d %s is a global variable", filename, line, vn.Name)
    79  					messages = append(messages, message)
    80  				}
    81  			}
    82  		}
    83  		return nil
    84  	})
    85  
    86  	return messages, err
    87  }