]> Cypherpunks repositories - gostls13.git/commitdiff
govet: allow directories as arguments, process recursively.
authorRob Pike <r@golang.org>
Wed, 15 Dec 2010 01:09:24 +0000 (17:09 -0800)
committerRob Pike <r@golang.org>
Wed, 15 Dec 2010 01:09:24 +0000 (17:09 -0800)
R=gri
CC=golang-dev
https://golang.org/cl/3652041

src/cmd/govet/doc.go
src/cmd/govet/govet.go

index fd66d3c0b015a4310dcc381790b9be1cae913b0f..5a2489fca7c5cff43681641fa265e10f396854ff 100644 (file)
@@ -19,6 +19,7 @@ complains about arguments that look like format descriptor strings.
 Usage:
 
        govet [flag] [file.go ...]
+       govet [flag] [directory ...] # Scan all .go files under directory, recursively
 
 The flags are:
        -v
index b49e32e12cf05f0eeeeef8e8f986b8b40060f229..1d775ff28cdf881fcba834fdf40c0d84883b202e 100644 (file)
@@ -15,6 +15,7 @@ import (
        "go/parser"
        "go/token"
        "os"
+       "path"
        "strconv"
        "strings"
 )
@@ -73,8 +74,13 @@ func main() {
        if flag.NArg() == 0 {
                doFile("stdin", os.Stdin)
        } else {
-               for _, arg := range flag.Args() {
-                       doFile(arg, nil)
+               for _, name := range flag.Args() {
+                       // Is it a directory?
+                       if fi, err := os.Stat(name); err == nil && fi.IsDirectory() {
+                               walkDir(name)
+                       } else {
+                               doFile(name, nil)
+                       }
                }
        }
        os.Exit(exitCode)
@@ -83,7 +89,6 @@ func main() {
 // doFile analyzes one file.  If the reader is nil, the source code is read from the
 // named file.
 func doFile(name string, reader io.Reader) {
-       // TODO: process directories?
        fs := token.NewFileSet()
        parsedFile, err := parser.ParseFile(fs, name, reader, 0)
        if err != nil {
@@ -94,6 +99,36 @@ func doFile(name string, reader io.Reader) {
        file.checkFile(name, parsedFile)
 }
 
+// Visitor for path.Walk - trivial.  Just calls doFile on each file.
+// TODO: if govet becomes richer, might want to process
+// a directory (package) at a time.
+type V struct{}
+
+func (v V) VisitDir(path string, f *os.FileInfo) bool {
+       return true
+}
+
+func (v V) VisitFile(path string, f *os.FileInfo) {
+       if strings.HasSuffix(path, ".go") {
+               doFile(path, nil)
+       }
+}
+
+// walkDir recursively walks the tree looking for .go files.
+func walkDir(root string) {
+       errors := make(chan os.Error)
+       done := make(chan bool)
+       go func() {
+               for e := range errors {
+                       error("walk error: %s", e)
+               }
+               done <- true
+       }()
+       path.Walk(root, V{}, errors)
+       close(errors)
+       <-done
+}
+
 // error formats the error to standard error, adding program
 // identification and a newline
 func error(format string, args ...interface{}) {
@@ -143,7 +178,7 @@ func (f *File) Warnf(pos token.Pos, format string, args ...interface{}) {
 
 // checkFile checks all the top-level declarations in a file.
 func (f *File) checkFile(name string, file *ast.File) {
-       Println("Checking", name)
+       Println("Checking file", name)
        ast.Walk(f, file)
 }