Skip to content

Commit

Permalink
go/printer: never print a newline before the returned results
Browse files Browse the repository at this point in the history
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 golang#32854.

Change-Id: I3384fbd711de06e742407df874c9ad85626d5d6a
Reviewed-on: https://go-review.googlesource.com/c/go/+/184121
Run-TryBot: Daniel Martí <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Robert Griesemer <[email protected]>
  • Loading branch information
mvdan authored and griesemer committed Sep 23, 2019
1 parent 7eef0ca commit 211932b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/go/printer/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
31 changes: 31 additions & 0 deletions src/go/printer/printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

0 comments on commit 211932b

Please sign in to comment.