Commit 670e77b5 authored by Rob Pike's avatar Rob Pike

govet: allow directories as arguments, process recursively.

R=gri
CC=golang-dev
https://golang.org/cl/3652041
parent 5742ded3
...@@ -19,6 +19,7 @@ complains about arguments that look like format descriptor strings. ...@@ -19,6 +19,7 @@ complains about arguments that look like format descriptor strings.
Usage: Usage:
govet [flag] [file.go ...] govet [flag] [file.go ...]
govet [flag] [directory ...] # Scan all .go files under directory, recursively
The flags are: The flags are:
-v -v
......
...@@ -15,6 +15,7 @@ import ( ...@@ -15,6 +15,7 @@ import (
"go/parser" "go/parser"
"go/token" "go/token"
"os" "os"
"path"
"strconv" "strconv"
"strings" "strings"
) )
...@@ -73,8 +74,13 @@ func main() { ...@@ -73,8 +74,13 @@ func main() {
if flag.NArg() == 0 { if flag.NArg() == 0 {
doFile("stdin", os.Stdin) doFile("stdin", os.Stdin)
} else { } else {
for _, arg := range flag.Args() { for _, name := range flag.Args() {
doFile(arg, nil) // Is it a directory?
if fi, err := os.Stat(name); err == nil && fi.IsDirectory() {
walkDir(name)
} else {
doFile(name, nil)
}
} }
} }
os.Exit(exitCode) os.Exit(exitCode)
...@@ -83,7 +89,6 @@ func main() { ...@@ -83,7 +89,6 @@ func main() {
// doFile analyzes one file. If the reader is nil, the source code is read from the // doFile analyzes one file. If the reader is nil, the source code is read from the
// named file. // named file.
func doFile(name string, reader io.Reader) { func doFile(name string, reader io.Reader) {
// TODO: process directories?
fs := token.NewFileSet() fs := token.NewFileSet()
parsedFile, err := parser.ParseFile(fs, name, reader, 0) parsedFile, err := parser.ParseFile(fs, name, reader, 0)
if err != nil { if err != nil {
...@@ -94,6 +99,36 @@ func doFile(name string, reader io.Reader) { ...@@ -94,6 +99,36 @@ func doFile(name string, reader io.Reader) {
file.checkFile(name, parsedFile) 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 // error formats the error to standard error, adding program
// identification and a newline // identification and a newline
func error(format string, args ...interface{}) { func error(format string, args ...interface{}) {
...@@ -143,7 +178,7 @@ func (f *File) Warnf(pos token.Pos, 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. // checkFile checks all the top-level declarations in a file.
func (f *File) checkFile(name string, file *ast.File) { func (f *File) checkFile(name string, file *ast.File) {
Println("Checking", name) Println("Checking file", name)
ast.Walk(f, file) ast.Walk(f, file)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment