From 2cd96806f4b04545b056ddaa53234fd15e821a1f Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 14 Feb 2013 11:26:21 -0800 Subject: [PATCH] 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 --- src/pkg/go/parser/error_test.go | 1 + src/pkg/go/parser/interface.go | 53 ++++++++++++++++++--------------- src/pkg/go/parser/parser.go | 6 ++++ 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/pkg/go/parser/error_test.go b/src/pkg/go/parser/error_test.go index 8d06d1c843..b5d9a39cf3 100644 --- a/src/pkg/go/parser/error_test.go +++ b/src/pkg/go/parser/error_test.go @@ -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) diff --git a/src/pkg/go/parser/interface.go b/src/pkg/go/parser/interface.go index fac513e557..a732e75fd1 100644 --- a/src/pkg/go/parser/interface.go +++ b/src/pkg/go/parser/interface.go @@ -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 diff --git a/src/pkg/go/parser/parser.go b/src/pkg/go/parser/parser.go index 959af38720..e816ca3262 100644 --- a/src/pkg/go/parser/parser.go +++ b/src/pkg/go/parser/parser.go @@ -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) } -- 2.48.1