From 211932b98790df0ae112d7f680f6912514ae7d94 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Mart=C3=AD?= Date: Sat, 29 Jun 2019 17:57:16 +0200 Subject: [PATCH] go/printer: never print a newline before the returned results MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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í TryBot-Result: Gobot Gobot Reviewed-by: Robert Griesemer --- src/go/printer/nodes.go | 6 ++++-- src/go/printer/printer_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go index fa7589e868..44ec7f8665 100644 --- a/src/go/printer/nodes.go +++ b/src/go/printer/nodes.go @@ -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) } } diff --git a/src/go/printer/printer_test.go b/src/go/printer/printer_test.go index a240bf4846..8f9cd534b4 100644 --- a/src/go/printer/printer_test.go +++ b/src/go/printer/printer_test.go @@ -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) + } +} -- 2.50.0