]> Cypherpunks repositories - gostls13.git/commitdiff
go/printer: never print a newline before the returned results
authorDaniel Martí <mvdan@mvdan.cc>
Sat, 29 Jun 2019 15:57:16 +0000 (17:57 +0200)
committerRobert Griesemer <gri@golang.org>
Mon, 23 Sep 2019 22:33:23 +0000 (22:33 +0000)
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: Robert Griesemer <gri@golang.org>
src/go/printer/nodes.go
src/go/printer/printer_test.go

index fa7589e86841a62683ddd6523b0307bf0e367161..44ec7f866535c59bfb9994448d5d5c1696455cdf 100644 (file)
@@ -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)
                        }
                }
 
index a240bf48465e8fe90e3d8b4134b2f9f7e3d1ae1a..8f9cd534b434ccb3d6a2c473ba633f7a1ace8f9b 100644 (file)
@@ -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)
+       }
+}