go/printer: fix invalid output for empty decls

The current output for empty declarations such as var, const, import
results in "var", "const", "import" respectively. These are not valid
syntax and the parser will promptly reject them as invalid syntax.

This CL updates this behavior by adding "()" to the output of empty
decls so the syntax becomes valid, e.g "var ()" instead of "var".

Fixes #63566
This commit is contained in:
Mauri de Souza Meneguzzo 2023-10-17 11:03:42 -03:00
parent 5873bd1d7e
commit 8948fa0ea3
2 changed files with 41 additions and 0 deletions

View File

@ -1739,6 +1739,15 @@ func (p *printer) genDecl(d *ast.GenDecl) {
p.setPos(d.Pos())
p.print(d.Tok, blank)
// Empty decls for "var ()", "const ()", "import ()"
if len(d.Specs) == 0 {
switch d.Tok {
case token.VAR, token.CONST, token.IMPORT:
p.print(token.LPAREN, token.RPAREN)
return
}
}
if d.Lparen.IsValid() || len(d.Specs) > 1 {
// group of parenthesized declarations
p.setPos(d.Lparen)

View File

@ -848,3 +848,35 @@ func TestSourcePosNewline(t *testing.T) {
t.Errorf("unexpected Fprint output:\n%s", buf.Bytes())
}
}
// TestEmptyDecl tests that empty decls for const, var, import are printed with
// valid syntax e.g "var ()" instead of just "var", which is invalid and cannot
// be parsed.
func TestEmptyDecl(t *testing.T) { // issue 63566
var tableTests = []struct {
tok token.Token
expected string
}{
{
tok: token.VAR,
expected: "var ()",
},
{
tok: token.CONST,
expected: "const ()",
},
{
tok: token.IMPORT,
expected: "import ()",
},
}
for _, tt := range tableTests {
var buf bytes.Buffer
Fprint(&buf, token.NewFileSet(), &ast.GenDecl{Tok: tt.tok})
got := buf.String()
if got != tt.expected {
t.Errorf("got %q, expected %q\n", got, tt.expected)
}
}
}