mirror of
https://github.com/golang/go
synced 2024-11-22 03:24:41 -07:00
go/parser: report illegal label declarations at ':' rather than guessing the start
Also: - Add parser.SpuriousError flag. If set, the parser reports all (including spurious) errors rather then at most one error per line. - Add -e flag to gofmt and gotype: If set, gofmt and gotype report all (including spurious) errors rather than at most one error per line. - Updated the respective documentation. Fixes #2088. R=rsc CC=golang-dev https://golang.org/cl/4803047
This commit is contained in:
parent
3d552700ce
commit
fa497796f5
@ -14,11 +14,12 @@ Usage:
|
|||||||
gofmt [flags] [path ...]
|
gofmt [flags] [path ...]
|
||||||
|
|
||||||
The flags are:
|
The flags are:
|
||||||
|
|
||||||
-d
|
-d
|
||||||
Do not print reformatted sources to standard output.
|
Do not print reformatted sources to standard output.
|
||||||
If a file's formatting is different than gofmt's, print diffs
|
If a file's formatting is different than gofmt's, print diffs
|
||||||
to standard output.
|
to standard output.
|
||||||
|
-e
|
||||||
|
Print all (including spurious) errors.
|
||||||
-l
|
-l
|
||||||
Do not print reformatted sources to standard output.
|
Do not print reformatted sources to standard output.
|
||||||
If a file's formatting is different from gofmt's, print its name
|
If a file's formatting is different from gofmt's, print its name
|
||||||
@ -31,6 +32,8 @@ The flags are:
|
|||||||
Do not print reformatted sources to standard output.
|
Do not print reformatted sources to standard output.
|
||||||
If a file's formatting is different from gofmt's, overwrite it
|
If a file's formatting is different from gofmt's, overwrite it
|
||||||
with gofmt's version.
|
with gofmt's version.
|
||||||
|
|
||||||
|
Formatting control flags:
|
||||||
-comments=true
|
-comments=true
|
||||||
Print comments; if false, all comments are elided from the output.
|
Print comments; if false, all comments are elided from the output.
|
||||||
-spaces
|
-spaces
|
||||||
@ -40,6 +43,7 @@ The flags are:
|
|||||||
-tabwidth=8
|
-tabwidth=8
|
||||||
Tab width in spaces.
|
Tab width in spaces.
|
||||||
|
|
||||||
|
|
||||||
The rewrite rule specified with the -r flag must be a string of the form:
|
The rewrite rule specified with the -r flag must be a string of the form:
|
||||||
|
|
||||||
pattern -> replacement
|
pattern -> replacement
|
||||||
|
@ -29,6 +29,7 @@ var (
|
|||||||
rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> α[β:]')")
|
rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'α[β:len(α)] -> α[β:]')")
|
||||||
simplifyAST = flag.Bool("s", false, "simplify code")
|
simplifyAST = flag.Bool("s", false, "simplify code")
|
||||||
doDiff = flag.Bool("d", false, "display diffs instead of rewriting files")
|
doDiff = flag.Bool("d", false, "display diffs instead of rewriting files")
|
||||||
|
allErrors = flag.Bool("e", false, "print all (including spurious) errors")
|
||||||
|
|
||||||
// layout control
|
// layout control
|
||||||
comments = flag.Bool("comments", true, "print comments")
|
comments = flag.Bool("comments", true, "print comments")
|
||||||
@ -64,6 +65,9 @@ func initParserMode() {
|
|||||||
if *comments {
|
if *comments {
|
||||||
parserMode |= parser.ParseComments
|
parserMode |= parser.ParseComments
|
||||||
}
|
}
|
||||||
|
if *allErrors {
|
||||||
|
parserMode |= parser.SpuriousErrors
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initPrinterMode() {
|
func initPrinterMode() {
|
||||||
|
@ -24,18 +24,20 @@ Usage:
|
|||||||
gotype [flags] [path ...]
|
gotype [flags] [path ...]
|
||||||
|
|
||||||
The flags are:
|
The flags are:
|
||||||
|
-e
|
||||||
|
Print all (including spurious) errors.
|
||||||
-p pkgName
|
-p pkgName
|
||||||
process only those files in package pkgName.
|
Process only those files in package pkgName.
|
||||||
-r
|
-r
|
||||||
recursively process subdirectories.
|
Recursively process subdirectories.
|
||||||
-v
|
-v
|
||||||
verbose mode.
|
Verbose mode.
|
||||||
|
|
||||||
Debugging flags:
|
Debugging flags:
|
||||||
-trace
|
|
||||||
print parse trace (disables concurrent parsing).
|
|
||||||
-ast
|
-ast
|
||||||
print AST (disables concurrent parsing).
|
Print AST (disables concurrent parsing).
|
||||||
|
-trace
|
||||||
|
Print parse trace (disables concurrent parsing).
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
|
@ -23,6 +23,7 @@ var (
|
|||||||
pkgName = flag.String("p", "", "process only those files in package pkgName")
|
pkgName = flag.String("p", "", "process only those files in package pkgName")
|
||||||
recursive = flag.Bool("r", false, "recursively process subdirectories")
|
recursive = flag.Bool("r", false, "recursively process subdirectories")
|
||||||
verbose = flag.Bool("v", false, "verbose mode")
|
verbose = flag.Bool("v", false, "verbose mode")
|
||||||
|
allErrors = flag.Bool("e", false, "print all (including spurious) errors")
|
||||||
|
|
||||||
// debugging support
|
// debugging support
|
||||||
printTrace = flag.Bool("trace", false, "print parse trace")
|
printTrace = flag.Bool("trace", false, "print parse trace")
|
||||||
@ -68,6 +69,9 @@ func parse(fset *token.FileSet, filename string, src []byte) *ast.File {
|
|||||||
|
|
||||||
// parse entire file
|
// parse entire file
|
||||||
mode := parser.DeclarationErrors
|
mode := parser.DeclarationErrors
|
||||||
|
if *allErrors {
|
||||||
|
mode |= parser.SpuriousErrors
|
||||||
|
}
|
||||||
if *printTrace {
|
if *printTrace {
|
||||||
mode |= parser.Trace
|
mode |= parser.Trace
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,12 @@ func readSource(filename string, src interface{}) ([]byte, os.Error) {
|
|||||||
return ioutil.ReadFile(filename)
|
return ioutil.ReadFile(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parseEOF() os.Error {
|
func (p *parser) errors() os.Error {
|
||||||
p.expect(token.EOF)
|
mode := scanner.Sorted
|
||||||
return p.GetError(scanner.Sorted)
|
if p.mode&SpuriousErrors == 0 {
|
||||||
|
mode = scanner.NoMultiples
|
||||||
|
}
|
||||||
|
return p.GetError(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseExpr parses a Go expression and returns the corresponding
|
// ParseExpr parses a Go expression and returns the corresponding
|
||||||
@ -70,7 +73,9 @@ func ParseExpr(fset *token.FileSet, filename string, src interface{}) (ast.Expr,
|
|||||||
if p.tok == token.SEMICOLON {
|
if p.tok == token.SEMICOLON {
|
||||||
p.next() // consume automatically inserted semicolon, if any
|
p.next() // consume automatically inserted semicolon, if any
|
||||||
}
|
}
|
||||||
return x, p.parseEOF()
|
p.expect(token.EOF)
|
||||||
|
|
||||||
|
return x, p.errors()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseStmtList parses a list of Go statements and returns the list
|
// ParseStmtList parses a list of Go statements and returns the list
|
||||||
@ -86,7 +91,10 @@ func ParseStmtList(fset *token.FileSet, filename string, src interface{}) ([]ast
|
|||||||
|
|
||||||
var p parser
|
var p parser
|
||||||
p.init(fset, filename, data, 0)
|
p.init(fset, filename, data, 0)
|
||||||
return p.parseStmtList(), p.parseEOF()
|
list := p.parseStmtList()
|
||||||
|
p.expect(token.EOF)
|
||||||
|
|
||||||
|
return list, p.errors()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDeclList parses a list of Go declarations and returns the list
|
// ParseDeclList parses a list of Go declarations and returns the list
|
||||||
@ -102,7 +110,10 @@ func ParseDeclList(fset *token.FileSet, filename string, src interface{}) ([]ast
|
|||||||
|
|
||||||
var p parser
|
var p parser
|
||||||
p.init(fset, filename, data, 0)
|
p.init(fset, filename, data, 0)
|
||||||
return p.parseDeclList(), p.parseEOF()
|
list := p.parseDeclList()
|
||||||
|
p.expect(token.EOF)
|
||||||
|
|
||||||
|
return list, p.errors()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
@ -133,7 +144,9 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode uint)
|
|||||||
|
|
||||||
var p parser
|
var p parser
|
||||||
p.init(fset, filename, data, mode)
|
p.init(fset, filename, data, mode)
|
||||||
return p.parseFile(), p.GetError(scanner.NoMultiples) // parseFile() reads to EOF
|
file := p.parseFile() // parseFile reads to EOF
|
||||||
|
|
||||||
|
return file, p.errors()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseFiles calls ParseFile for each file in the filenames list and returns
|
// ParseFiles calls ParseFile for each file in the filenames list and returns
|
||||||
|
@ -26,6 +26,7 @@ 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
|
||||||
)
|
)
|
||||||
|
|
||||||
// The parser structure holds the parser's internal state.
|
// The parser structure holds the parser's internal state.
|
||||||
@ -1408,7 +1409,13 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
|
|||||||
p.declare(stmt, nil, p.labelScope, ast.Lbl, label)
|
p.declare(stmt, nil, p.labelScope, ast.Lbl, label)
|
||||||
return stmt
|
return stmt
|
||||||
}
|
}
|
||||||
p.error(x[0].Pos(), "illegal label declaration")
|
// The label declaration typically starts at x[0].Pos(), but the label
|
||||||
|
// declaration may be erroneous due to a token after that position (and
|
||||||
|
// before the ':'). If SpuriousErrors is not set, the (only) error re-
|
||||||
|
// ported for the line is the illegal label error instead of the token
|
||||||
|
// before the ':' that caused the problem. Thus, use the (latest) colon
|
||||||
|
// position for error reporting.
|
||||||
|
p.error(colon, "illegal label declaration")
|
||||||
return &ast.BadStmt{x[0].Pos(), colon + 1}
|
return &ast.BadStmt{x[0].Pos(), colon + 1}
|
||||||
|
|
||||||
case token.ARROW:
|
case token.ARROW:
|
||||||
|
Loading…
Reference in New Issue
Block a user