Commit 211932b9 authored by Daniel Martí's avatar Daniel Martí Committed by Robert Griesemer

go/printer: never print a newline before the returned results

Otherwise, if one ends up with a "return result" where the two nodes are
in separate lines, the printer would incorrectly print a naked return:

	return
		result

The fix is simple - by not telling exprList what the previous position
is, it never adds a leading linebreak. This is the same mechanism used
for identifier lists and values, so it seems appropriate.

All other exprList calls that can produce a leading linebreak don't seem
buggy, because closing tokens such as parentheses and colons are needed
to finish the statement.

Verified that the test failed before the patch as well:

	--- FAIL: TestIssue32854 (0.00s)
	    printer_test.go:806: got "return\n\tcall()", want "return call()"

Finally, verified that 'gofmt -l -w src misc' doesn't make any new
changes, just in case we introduced any regression.

Fixes #32854.

Change-Id: I3384fbd711de06e742407df874c9ad85626d5d6a
Reviewed-on: https://go-review.googlesource.com/c/go/+/184121
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 7eef0ca1
......@@ -1237,10 +1237,12 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
// lead to more nicely formatted code in general.
if p.indentList(s.Results) {
p.print(indent)
p.exprList(s.Pos(), s.Results, 1, noIndent, token.NoPos, false)
// Use NoPos so that a newline never goes before
// the results (see issue #32854).
p.exprList(token.NoPos, s.Results, 1, noIndent, token.NoPos, false)
p.print(unindent)
} else {
p.exprList(s.Pos(), s.Results, 1, 0, token.NoPos, false)
p.exprList(token.NoPos, s.Results, 1, 0, token.NoPos, false)
}
}
......
......@@ -775,3 +775,34 @@ func TestParenthesizedDecl(t *testing.T) {
t.Errorf("got %q, want %q", noparen, original)
}
}
// Verify that we don't print a newline between "return" and its results, as
// that would incorrectly cause a naked return.
func TestIssue32854(t *testing.T) {
src := `package foo
func f() {
return Composite{
call(),
}
}`
fset := token.NewFileSet()
file, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
panic(err)
}
// Replace the result with call(), which is on the next line.
fd := file.Decls[0].(*ast.FuncDecl)
ret := fd.Body.List[0].(*ast.ReturnStmt)
ret.Results[0] = ret.Results[0].(*ast.CompositeLit).Elts[0]
var buf bytes.Buffer
if err := Fprint(&buf, fset, ret); err != nil {
t.Fatal(err)
}
want := "return call()"
if got := buf.String(); got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment