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{}) {
t.Error(err)
return
}
found.RemoveMultiples()
// we are expecting the following errors
// (collect these after parsing a file so that it is found in the file set)
......
......@@ -52,12 +52,13 @@ func readSource(filename string, src interface{}) ([]byte, error) {
type Mode uint
const (
PackageClauseOnly Mode = 1 << iota // parsing stops after package clause
ImportsOnly // parsing stops after import declarations
ParseComments // parse comments and add them to AST
Trace // print a trace of parsed productions
DeclarationErrors // report declaration errors
SpuriousErrors // report all (not just the first) errors per line
PackageClauseOnly Mode = 1 << iota // parsing stops after package clause
ImportsOnly // parsing stops after import declarations
ParseComments // parse comments and add them to AST
Trace // print a trace of parsed productions
DeclarationErrors // report declaration errors
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
......@@ -79,35 +80,39 @@ const (
// representing the fragments of erroneous source code). Multiple errors
// 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
text, err := readSource(filename, src)
if err != nil {
return nil, err
}
// parse source
var p parser
p.init(fset, filename, text, mode)
f := p.parseFile()
if f == nil {
// source is not a valid Go source file - satisfy
// ParseFile API and return a valid (but) empty
// *ast.File
f = &ast.File{
Name: new(ast.Ident),
Scope: ast.NewScope(nil),
defer func() {
if e := recover(); e != nil {
_ = e.(bailout) // re-panics if it's not a bailout
}
// set result values
if f == nil {
// source is not a valid Go source file - satisfy
// ParseFile API and return a valid (but) empty
// *ast.File
f = &ast.File{
Name: new(ast.Ident),
Scope: ast.NewScope(nil),
}
}
}
// sort errors
if p.mode&SpuriousErrors == 0 {
p.errors.RemoveMultiples()
} else {
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
......
......@@ -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) {
if p.mode&SpuriousErrors == 0 && p.errors.Len() >= 10 {
panic(bailout{})
}
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