Commit 9eac1c87 authored by Robert Griesemer's avatar Robert Griesemer

go/types: gotype to always report the same first error now

The old code may have reported different errors given an
erroneous package depending on the order in which files
were parsed concurrently. The new code always reports
errors in "file order", independent of processing order.

Also:
- simplified parsing code and internal concurrency control
- removed -seq flag which didn't really add useful functionality

Change-Id: I18e24e630f458f2bc107a7b83926ae761d63c334
Reviewed-on: https://go-review.googlesource.com/37655Reviewed-by: 's avatarAlan Donovan <adonovan@google.com>
parent 3a90bfb2
...@@ -38,9 +38,7 @@ The flags are: ...@@ -38,9 +38,7 @@ The flags are:
-c -c
compiler used for installed packages (gc, gccgo, or source); default: source compiler used for installed packages (gc, gccgo, or source); default: source
Debugging flags: Flags controlling additional output:
-seq
parse sequentially, rather than in parallel
-ast -ast
print AST (forces -seq) print AST (forces -seq)
-trace -trace
...@@ -82,6 +80,7 @@ import ( ...@@ -82,6 +80,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"sync"
"time" "time"
) )
...@@ -93,7 +92,6 @@ var ( ...@@ -93,7 +92,6 @@ var (
compiler = flag.String("c", "source", "compiler used for installed packages (gc, gccgo, or source)") compiler = flag.String("c", "source", "compiler used for installed packages (gc, gccgo, or source)")
// debugging support // debugging support
sequential = flag.Bool("seq", false, "parse sequentially, rather than in parallel")
printAST = flag.Bool("ast", false, "print AST (forces -seq)") printAST = flag.Bool("ast", false, "print AST (forces -seq)")
printTrace = flag.Bool("trace", false, "print parse trace (forces -seq)") printTrace = flag.Bool("trace", false, "print parse trace (forces -seq)")
parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)") parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)")
...@@ -102,6 +100,7 @@ var ( ...@@ -102,6 +100,7 @@ var (
var ( var (
fset = token.NewFileSet() fset = token.NewFileSet()
errorCount = 0 errorCount = 0
sequential = false
parserMode parser.Mode parserMode parser.Mode
) )
...@@ -109,8 +108,12 @@ func initParserMode() { ...@@ -109,8 +108,12 @@ func initParserMode() {
if *allErrors { if *allErrors {
parserMode |= parser.AllErrors parserMode |= parser.AllErrors
} }
if *printAST {
sequential = true
}
if *printTrace { if *printTrace {
parserMode |= parser.Trace parserMode |= parser.Trace
sequential = true
} }
if *parseComments && (*printAST || *printTrace) { if *parseComments && (*printAST || *printTrace) {
parserMode |= parser.ParseComments parserMode |= parser.ParseComments
...@@ -152,46 +155,36 @@ func parseStdin() (*ast.File, error) { ...@@ -152,46 +155,36 @@ func parseStdin() (*ast.File, error) {
return parse("<standard input>", src) return parse("<standard input>", src)
} }
func parseFiles(filenames []string) ([]*ast.File, error) { func parseFiles(dir string, filenames []string) ([]*ast.File, error) {
files := make([]*ast.File, len(filenames)) files := make([]*ast.File, len(filenames))
errors := make([]error, len(filenames))
if *sequential { var wg sync.WaitGroup
for i, filename := range filenames { for i, filename := range filenames {
var err error wg.Add(1)
files[i], err = parse(filename, nil) go func(i int, filepath string) {
if err != nil { defer wg.Done()
return nil, err // leave unfinished goroutines hanging files[i], errors[i] = parse(filepath, nil)
} }(i, filepath.Join(dir, filename))
} if sequential {
} else { wg.Wait()
type parseResult struct {
file *ast.File
err error
}
out := make(chan parseResult)
for _, filename := range filenames {
go func(filename string) {
file, err := parse(filename, nil)
out <- parseResult{file, err}
}(filename)
} }
}
wg.Wait()
for i := range filenames { // if there are errors, return the first one for deterministic results
res := <-out for _, err := range errors {
if res.err != nil { if err != nil {
return nil, res.err // leave unfinished goroutines hanging return nil, err
}
files[i] = res.file
} }
} }
return files, nil return files, nil
} }
func parseDir(dirname string) ([]*ast.File, error) { func parseDir(dir string) ([]*ast.File, error) {
ctxt := build.Default ctxt := build.Default
pkginfo, err := ctxt.ImportDir(dirname, 0) pkginfo, err := ctxt.ImportDir(dir, 0)
if _, nogo := err.(*build.NoGoError); err != nil && !nogo { if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
return nil, err return nil, err
} }
...@@ -200,12 +193,7 @@ func parseDir(dirname string) ([]*ast.File, error) { ...@@ -200,12 +193,7 @@ func parseDir(dirname string) ([]*ast.File, error) {
filenames = append(filenames, pkginfo.TestGoFiles...) filenames = append(filenames, pkginfo.TestGoFiles...)
} }
// complete file names return parseFiles(dir, filenames)
for i, filename := range filenames {
filenames[i] = filepath.Join(dirname, filename)
}
return parseFiles(filenames)
} }
func getPkgFiles(args []string) ([]*ast.File, error) { func getPkgFiles(args []string) ([]*ast.File, error) {
...@@ -231,7 +219,7 @@ func getPkgFiles(args []string) ([]*ast.File, error) { ...@@ -231,7 +219,7 @@ func getPkgFiles(args []string) ([]*ast.File, error) {
} }
// list of files // list of files
return parseFiles(args) return parseFiles("", args)
} }
func checkPkgFiles(files []*ast.File) { func checkPkgFiles(files []*ast.File) {
...@@ -282,9 +270,6 @@ func printStats(d time.Duration) { ...@@ -282,9 +270,6 @@ func printStats(d time.Duration) {
func main() { func main() {
flag.Usage = usage flag.Usage = usage
flag.Parse() flag.Parse()
if *printAST || *printTrace {
*sequential = true
}
initParserMode() initParserMode()
start := time.Now() start := time.Now()
......
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