mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/compile/internal/syntax: better errors for syntax errors in lists
For syntax errors in various (syntactic) lists, instead of reporting a set of "expected" tokens (which may be incomplete), provide context and mention "possibly missing" tokens. The result is a friendlier and more accurate error message. Fixes #49205. Change-Id: I38ae7bf62febfe790075e62deb33ec8c17d64476 Reviewed-on: https://go-review.googlesource.com/c/go/+/396914 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
3b7fce24cd
commit
0775730180
@ -472,7 +472,7 @@ func isEmptyFuncDecl(dcl Decl) bool {
|
|||||||
//
|
//
|
||||||
// list = [ f { sep f } [sep] ] close .
|
// list = [ f { sep f } [sep] ] close .
|
||||||
//
|
//
|
||||||
func (p *parser) list(sep, close token, f func() bool) Pos {
|
func (p *parser) list(context string, sep, close token, f func() bool) Pos {
|
||||||
if debug && (sep != _Comma && sep != _Semi || close != _Rparen && close != _Rbrace && close != _Rbrack) {
|
if debug && (sep != _Comma && sep != _Semi || close != _Rparen && close != _Rbrace && close != _Rbrack) {
|
||||||
panic("invalid sep or close argument for list")
|
panic("invalid sep or close argument for list")
|
||||||
}
|
}
|
||||||
@ -482,7 +482,7 @@ func (p *parser) list(sep, close token, f func() bool) Pos {
|
|||||||
done = f()
|
done = f()
|
||||||
// sep is optional before close
|
// sep is optional before close
|
||||||
if !p.got(sep) && p.tok != close {
|
if !p.got(sep) && p.tok != close {
|
||||||
p.syntaxError(fmt.Sprintf("expecting %s or %s", tokstring(sep), tokstring(close)))
|
p.syntaxError(fmt.Sprintf("in %s; possibly missing %s or %s", context, tokstring(sep), tokstring(close)))
|
||||||
p.advance(_Rparen, _Rbrack, _Rbrace)
|
p.advance(_Rparen, _Rbrack, _Rbrace)
|
||||||
if p.tok != close {
|
if p.tok != close {
|
||||||
// position could be better but we had an error so we don't care
|
// position could be better but we had an error so we don't care
|
||||||
@ -502,7 +502,7 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl {
|
|||||||
g := new(Group)
|
g := new(Group)
|
||||||
p.clearPragma()
|
p.clearPragma()
|
||||||
p.next() // must consume "(" after calling clearPragma!
|
p.next() // must consume "(" after calling clearPragma!
|
||||||
p.list(_Semi, _Rparen, func() bool {
|
p.list("grouped declaration", _Semi, _Rparen, func() bool {
|
||||||
if x := f(g); x != nil {
|
if x := f(g); x != nil {
|
||||||
list = append(list, x)
|
list = append(list, x)
|
||||||
}
|
}
|
||||||
@ -1233,7 +1233,7 @@ func (p *parser) complitexpr() *CompositeLit {
|
|||||||
|
|
||||||
p.xnest++
|
p.xnest++
|
||||||
p.want(_Lbrace)
|
p.want(_Lbrace)
|
||||||
x.Rbrace = p.list(_Comma, _Rbrace, func() bool {
|
x.Rbrace = p.list("composite literal", _Comma, _Rbrace, func() bool {
|
||||||
// value
|
// value
|
||||||
e := p.bare_complitexpr()
|
e := p.bare_complitexpr()
|
||||||
if p.tok == _Colon {
|
if p.tok == _Colon {
|
||||||
@ -1477,7 +1477,7 @@ func (p *parser) structType() *StructType {
|
|||||||
|
|
||||||
p.want(_Struct)
|
p.want(_Struct)
|
||||||
p.want(_Lbrace)
|
p.want(_Lbrace)
|
||||||
p.list(_Semi, _Rbrace, func() bool {
|
p.list("struct type", _Semi, _Rbrace, func() bool {
|
||||||
p.fieldDecl(typ)
|
p.fieldDecl(typ)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@ -1497,7 +1497,7 @@ func (p *parser) interfaceType() *InterfaceType {
|
|||||||
|
|
||||||
p.want(_Interface)
|
p.want(_Interface)
|
||||||
p.want(_Lbrace)
|
p.want(_Lbrace)
|
||||||
p.list(_Semi, _Rbrace, func() bool {
|
p.list("interface type", _Semi, _Rbrace, func() bool {
|
||||||
switch p.tok {
|
switch p.tok {
|
||||||
case _Name:
|
case _Name:
|
||||||
f := p.methodDecl()
|
f := p.methodDecl()
|
||||||
@ -1980,7 +1980,7 @@ func (p *parser) paramList(name *Name, typ Expr, close token, requireNames bool)
|
|||||||
|
|
||||||
var named int // number of parameters that have an explicit name and type
|
var named int // number of parameters that have an explicit name and type
|
||||||
var typed int // number of parameters that have an explicit type
|
var typed int // number of parameters that have an explicit type
|
||||||
end := p.list(_Comma, close, func() bool {
|
end := p.list("parameter list", _Comma, close, func() bool {
|
||||||
var par *Field
|
var par *Field
|
||||||
if typ != nil {
|
if typ != nil {
|
||||||
if debug && name == nil {
|
if debug && name == nil {
|
||||||
@ -2660,7 +2660,7 @@ func (p *parser) argList() (list []Expr, hasDots bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.xnest++
|
p.xnest++
|
||||||
p.list(_Comma, _Rparen, func() bool {
|
p.list("argument list", _Comma, _Rparen, func() bool {
|
||||||
list = append(list, p.expr())
|
list = append(list, p.expr())
|
||||||
hasDots = p.got(_DotDotDot)
|
hasDots = p.got(_DotDotDot)
|
||||||
return hasDots
|
return hasDots
|
||||||
|
27
src/cmd/compile/internal/syntax/testdata/issue49205.go
vendored
Normal file
27
src/cmd/compile/internal/syntax/testdata/issue49205.go
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
// test case from issue
|
||||||
|
|
||||||
|
type _ interface{
|
||||||
|
m /* ERROR unexpected int in interface type; possibly missing semicolon or newline or } */ int
|
||||||
|
}
|
||||||
|
|
||||||
|
// other cases where the fix for this issue affects the error message
|
||||||
|
|
||||||
|
const (
|
||||||
|
x int = 10 /* ERROR unexpected literal "foo" in grouped declaration; possibly missing semicolon or newline or \) */ "foo"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = []int{1, 2, 3 /* ERROR unexpected int in composite literal; possibly missing comma or } */ int }
|
||||||
|
|
||||||
|
type _ struct {
|
||||||
|
x y /* ERROR syntax error: unexpected comma in struct type; possibly missing semicolon or newline or } */ ,
|
||||||
|
}
|
||||||
|
|
||||||
|
func f(a, b c /* ERROR unexpected d in parameter list; possibly missing comma or \) */ d) {
|
||||||
|
f(a, b, c /* ERROR unexpected d in argument list; possibly missing comma or \) */ d)
|
||||||
|
}
|
@ -9,10 +9,10 @@ package main
|
|||||||
func f(int, int) {
|
func f(int, int) {
|
||||||
switch x {
|
switch x {
|
||||||
case 1:
|
case 1:
|
||||||
f(1, g() // ERROR "expecting \)|expecting comma or \)"
|
f(1, g() // ERROR "expecting \)|possibly missing comma or \)"
|
||||||
case 2:
|
case 2:
|
||||||
f()
|
f()
|
||||||
case 3:
|
case 3:
|
||||||
f(1, g() // ERROR "expecting \)|expecting comma or \)"
|
f(1, g() // ERROR "expecting \)|possibly missing comma or \)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,5 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
var a = []int{
|
var a = []int{
|
||||||
3 // ERROR "need trailing comma before newline in composite literal|expecting comma or }"
|
3 // ERROR "need trailing comma before newline in composite literal|possibly missing comma or }"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user