mirror of
https://github.com/golang/go
synced 2024-11-23 09:10:08 -07:00
go/parser: more tolerant parsing of import declarations
This is a port of CL 427156 from the syntax package's parser to go/parser. While at it, remove an unused token.Pos parameter from parseSpecFunction and dependent declarations. Also, consolidate the respective test file. For #54511. Change-Id: Id6a28eb3d23a46fa5fa1d85d2c4e634b7015513c Reviewed-on: https://go-review.googlesource.com/c/go/+/427157 Run-TryBot: Robert Griesemer <gri@google.com> Auto-Submit: Robert Griesemer <gri@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
a330ca5c54
commit
d394f99f49
@ -2,6 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The errors below are produced by the parser, but we check
|
||||
// them here for consistency with the types2 tests.
|
||||
|
||||
package p
|
||||
|
||||
import ; // ERROR missing import path
|
||||
|
@ -399,9 +399,10 @@ var stmtStart = map[token.Token]bool{
|
||||
}
|
||||
|
||||
var declStart = map[token.Token]bool{
|
||||
token.CONST: true,
|
||||
token.TYPE: true,
|
||||
token.VAR: true,
|
||||
token.IMPORT: true,
|
||||
token.CONST: true,
|
||||
token.TYPE: true,
|
||||
token.VAR: true,
|
||||
}
|
||||
|
||||
var exprEnd = map[token.Token]bool{
|
||||
@ -2416,9 +2417,9 @@ func (p *parser) parseStmt() (s ast.Stmt) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// Declarations
|
||||
|
||||
type parseSpecFunction func(doc *ast.CommentGroup, pos token.Pos, keyword token.Token, iota int) ast.Spec
|
||||
type parseSpecFunction func(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec
|
||||
|
||||
func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token, _ int) ast.Spec {
|
||||
func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
|
||||
if p.trace {
|
||||
defer un(trace(p, "ImportSpec"))
|
||||
}
|
||||
@ -2442,10 +2443,7 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Tok
|
||||
p.next()
|
||||
} else {
|
||||
p.error(pos, "missing import path")
|
||||
// don't advance if we're at a semicolon or closing parenthesis
|
||||
if p.tok != token.SEMICOLON && p.tok != token.RPAREN {
|
||||
p.next()
|
||||
}
|
||||
p.advance(exprEnd)
|
||||
}
|
||||
p.expectSemi() // call before accessing p.linecomment
|
||||
|
||||
@ -2461,7 +2459,7 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Tok
|
||||
return spec
|
||||
}
|
||||
|
||||
func (p *parser) parseValueSpec(doc *ast.CommentGroup, _ token.Pos, keyword token.Token, iota int) ast.Spec {
|
||||
func (p *parser) parseValueSpec(doc *ast.CommentGroup, keyword token.Token, iota int) ast.Spec {
|
||||
if p.trace {
|
||||
defer un(trace(p, keyword.String()+"Spec"))
|
||||
}
|
||||
@ -2520,7 +2518,7 @@ func (p *parser) parseGenericType(spec *ast.TypeSpec, openPos token.Pos, name0 *
|
||||
spec.Type = p.parseType()
|
||||
}
|
||||
|
||||
func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Token, _ int) ast.Spec {
|
||||
func (p *parser) parseTypeSpec(doc *ast.CommentGroup, _ token.Token, _ int) ast.Spec {
|
||||
if p.trace {
|
||||
defer un(trace(p, "TypeSpec"))
|
||||
}
|
||||
@ -2673,12 +2671,12 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen
|
||||
lparen = p.pos
|
||||
p.next()
|
||||
for iota := 0; p.tok != token.RPAREN && p.tok != token.EOF; iota++ {
|
||||
list = append(list, f(p.leadComment, pos, keyword, iota))
|
||||
list = append(list, f(p.leadComment, keyword, iota))
|
||||
}
|
||||
rparen = p.expect(token.RPAREN)
|
||||
p.expectSemi()
|
||||
} else {
|
||||
list = append(list, f(nil, pos, keyword, 0))
|
||||
list = append(list, f(nil, keyword, 0))
|
||||
}
|
||||
|
||||
return &ast.GenDecl{
|
||||
@ -2754,6 +2752,9 @@ func (p *parser) parseDecl(sync map[token.Token]bool) ast.Decl {
|
||||
|
||||
var f parseSpecFunction
|
||||
switch p.tok {
|
||||
case token.IMPORT:
|
||||
f = p.parseImportSpec
|
||||
|
||||
case token.CONST, token.VAR:
|
||||
f = p.parseValueSpec
|
||||
|
||||
@ -2813,7 +2814,14 @@ func (p *parser) parseFile() *ast.File {
|
||||
|
||||
if p.mode&ImportsOnly == 0 {
|
||||
// rest of package body
|
||||
prev := token.IMPORT
|
||||
for p.tok != token.EOF {
|
||||
// Continue to accept import declarations for error tolerance, but complain.
|
||||
if p.tok == token.IMPORT && prev != token.IMPORT {
|
||||
p.error(p.pos, "imports must appear before other declarations")
|
||||
}
|
||||
prev = p.tok
|
||||
|
||||
decls = append(decls, p.parseDecl(declStart))
|
||||
}
|
||||
}
|
||||
|
18
src/go/types/testdata/fixedbugs/issue43190.go
vendored
18
src/go/types/testdata/fixedbugs/issue43190.go
vendored
@ -1,4 +1,4 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@ -8,12 +8,14 @@
|
||||
package p
|
||||
|
||||
import ; // ERROR missing import path
|
||||
import ';' // ERROR import path must be a string
|
||||
// TODO(gri) The parser should accept mixing imports with other
|
||||
// top-level declarations for better error recovery.
|
||||
// var _ int
|
||||
import . ; // ERROR missing import path
|
||||
import
|
||||
var /* ERROR missing import path */ _ int
|
||||
import .; // ERROR missing import path
|
||||
import 'x' // ERROR import path must be a string
|
||||
var _ int
|
||||
import /* ERROR imports must appear before other declarations */ _ "math"
|
||||
|
||||
// Don't repeat previous error for each immediately following import ...
|
||||
import ()
|
||||
import (.) // ERROR missing import path
|
||||
import (
|
||||
@ -21,4 +23,8 @@ import (
|
||||
.
|
||||
) // ERROR missing import path
|
||||
|
||||
// ... but remind with error again if we start a new import section after
|
||||
// other declarations
|
||||
var _ = fmt.Println
|
||||
import /* ERROR imports must appear before other declarations */ _ "math"
|
||||
import _ "math"
|
||||
|
Loading…
Reference in New Issue
Block a user