Commit 2cd96806 authored by Michael Matloob's avatar Michael Matloob Committed by Robert Griesemer

go/parser: stop ParseFile after ten errors.

There wil be a panic if more than ten errors are encountered. ParseFile
will recover and return the ErrorList.

Fixes #3943.

R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/7307085
parent 208c8309
...@@ -145,6 +145,7 @@ func checkErrors(t *testing.T, filename string, input interface{}) { ...@@ -145,6 +145,7 @@ func checkErrors(t *testing.T, filename string, input interface{}) {
t.Error(err) t.Error(err)
return return
} }
found.RemoveMultiples()
// we are expecting the following errors // we are expecting the following errors
// (collect these after parsing a file so that it is found in the file set) // (collect these after parsing a file so that it is found in the file set)
......
...@@ -57,7 +57,8 @@ const ( ...@@ -57,7 +57,8 @@ const (
ParseComments // parse comments and add them to AST ParseComments // parse comments and add them to AST
Trace // print a trace of parsed productions Trace // print a trace of parsed productions
DeclarationErrors // report declaration errors DeclarationErrors // report declaration errors
SpuriousErrors // report all (not just the first) errors per line SpuriousErrors // same as AllErrors, for backward-compatibility
AllErrors = SpuriousErrors // report all (not just the first 10) errors per file
) )
// ParseFile parses the source code of a single Go source file and returns // ParseFile parses the source code of a single Go source file and returns
...@@ -79,17 +80,20 @@ const ( ...@@ -79,17 +80,20 @@ const (
// representing the fragments of erroneous source code). Multiple errors // representing the fragments of erroneous source code). Multiple errors
// are returned via a scanner.ErrorList which is sorted by file position. // are returned via a scanner.ErrorList which is sorted by file position.
// //
func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (*ast.File, error) { func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) {
// get source // get source
text, err := readSource(filename, src) text, err := readSource(filename, src)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// parse source
var p parser var p parser
p.init(fset, filename, text, mode) defer func() {
f := p.parseFile() if e := recover(); e != nil {
_ = e.(bailout) // re-panics if it's not a bailout
}
// set result values
if f == nil { if f == nil {
// source is not a valid Go source file - satisfy // source is not a valid Go source file - satisfy
// ParseFile API and return a valid (but) empty // ParseFile API and return a valid (but) empty
...@@ -100,14 +104,15 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) ...@@ -100,14 +104,15 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode)
} }
} }
// sort errors
if p.mode&SpuriousErrors == 0 {
p.errors.RemoveMultiples()
} else {
p.errors.Sort() p.errors.Sort()
} err = p.errors.Err()
}()
return f, p.errors.Err() // parse source
p.init(fset, filename, text, mode)
f = p.parseFile()
return
} }
// ParseDir calls ParseFile for the files in the directory specified by path and // ParseDir calls ParseFile for the files in the directory specified by path and
......
...@@ -340,7 +340,13 @@ func (p *parser) next() { ...@@ -340,7 +340,13 @@ func (p *parser) next() {
} }
} }
// A bailout panic is raised to indicate early termination.
type bailout struct{}
func (p *parser) error(pos token.Pos, msg string) { func (p *parser) error(pos token.Pos, msg string) {
if p.mode&SpuriousErrors == 0 && p.errors.Len() >= 10 {
panic(bailout{})
}
p.errors.Add(p.file.Position(pos), msg) p.errors.Add(p.file.Position(pos), msg)
} }
......
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