From a31c062c9fbf212b244fbece6295a2a4279459e0 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 31 Aug 2022 11:26:43 -0700 Subject: [PATCH] go/parser: parse import specs the same way as the syntax parser This results in better error recovery and allows us to use the same tests for go/types and types2. For #54511. Change-Id: Ic11a9dafb8c62e0cb952b3924d55a28b438241c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/427154 Run-TryBot: Robert Griesemer Auto-Submit: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- src/go/parser/parser.go | 13 ++++++++++--- src/go/types/resolver.go | 3 +++ src/go/types/testdata/fixedbugs/issue43190.go | 18 ++++++++++-------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index cc3c048094..fcd6a4adcc 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -2425,11 +2425,11 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Tok var ident *ast.Ident switch p.tok { + case token.IDENT: + ident = p.parseIdent() case token.PERIOD: ident = &ast.Ident{NamePos: p.pos, Name: "."} p.next() - case token.IDENT: - ident = p.parseIdent() } pos := p.pos @@ -2437,8 +2437,15 @@ func (p *parser) parseImportSpec(doc *ast.CommentGroup, _ token.Pos, _ token.Tok if p.tok == token.STRING { path = p.lit p.next() + } else if p.tok.IsLiteral() { + p.error(pos, "import path must be a string") + p.next() } else { - p.expect(token.STRING) // use expect() error handling + 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.expectSemi() // call before accessing p.linecomment diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 09fb7b45ad..c4a973a5b9 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -254,6 +254,9 @@ func (check *Checker) collectObjects() { switch d := d.(type) { case importDecl: // import package + if d.spec.Path.Value == "" { + return // error reported by parser + } path, err := validatedImportPath(d.spec.Path.Value) if err != nil { check.errorf(d.spec.Path, _BadImportPath, "invalid import path (%s)", err) diff --git a/src/go/types/testdata/fixedbugs/issue43190.go b/src/go/types/testdata/fixedbugs/issue43190.go index 96acb3a2e3..3a36a1eef5 100644 --- a/src/go/types/testdata/fixedbugs/issue43190.go +++ b/src/go/types/testdata/fixedbugs/issue43190.go @@ -2,21 +2,23 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Most of the errors below are actually produced by the parser, but we check +// The errors below are produced by the parser, but we check // them here for consistency with the types2 tests. package p -import ; /* ERROR invalid import path */ /* ERROR expected 'STRING' */ -import // ERROR expected ';' -var _ int -import /* ERROR expected declaration */ .; +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 () -import (.) +import (.) // ERROR missing import path import ( "fmt" . -) +) // ERROR missing import path -var _ = fmt /* ERROR "undeclared name" */ .Println +var _ = fmt.Println -- 2.48.1