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 }