]> Cypherpunks repositories - gostls13.git/commitdiff
go/printer: fix format with leading comments in composite literal
authorRobert Griesemer <gri@golang.org>
Wed, 25 Jan 2017 23:05:39 +0000 (15:05 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 26 Jan 2017 00:06:54 +0000 (00:06 +0000)
This fix is less pervasive than it seems. The only change affecting
formatting is on printer.go:760. The remaining changes have no effect
on formatting since the value of p.level is ignored except on this
specific line.

The remaining changes are:
- renamed adjBlock to funcBody since that's how it is used
- introduced new printer field 'level' tracking the composite
  literal nesting level
- update/restore the composite literal nesting level as needed

Fixes #18782.

Change-Id: Ie833a9b5a559c4ec0f2eef2c5dc97aa263dca53a
Reviewed-on: https://go-review.googlesource.com/35811
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/go/printer/nodes.go
src/go/printer/printer.go
src/go/printer/testdata/comments2.golden
src/go/printer/testdata/comments2.input

index 11f26d45ea39429afb6eed2f4ee03588812dbaf5..ea432860a8e5ac2b159b48fbb8941182108fec00 100644 (file)
@@ -733,7 +733,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 
        case *ast.FuncLit:
                p.expr(x.Type)
-               p.adjBlock(p.distanceFrom(x.Type.Pos()), blank, x.Body)
+               p.funcBody(p.distanceFrom(x.Type.Pos()), blank, x.Body)
 
        case *ast.ParenExpr:
                if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
@@ -825,6 +825,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
                if x.Type != nil {
                        p.expr1(x.Type, token.HighestPrec, depth)
                }
+               p.level++
                p.print(x.Lbrace, token.LBRACE)
                p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace)
                // do not insert extra line break following a /*-style comment
@@ -837,6 +838,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
                        mode |= noExtraBlank
                }
                p.print(mode, x.Rbrace, token.RBRACE, mode)
+               p.level--
 
        case *ast.Ellipsis:
                p.print(token.ELLIPSIS)
@@ -1557,18 +1559,23 @@ func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int {
        return bodySize
 }
 
-// adjBlock prints an "adjacent" block (e.g., a for-loop or function body) following
-// a header (e.g., a for-loop control clause or function signature) of given headerSize.
+// funcBody prints a function body following a function header of given headerSize.
 // If the header's and block's size are "small enough" and the block is "simple enough",
 // the block is printed on the current line, without line breaks, spaced from the header
 // by sep. Otherwise the block's opening "{" is printed on the current line, followed by
 // lines for the block's statements and its closing "}".
 //
-func (p *printer) adjBlock(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
+func (p *printer) funcBody(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
        if b == nil {
                return
        }
 
+       // save/restore composite literal nesting level
+       defer func(level int) {
+               p.level = level
+       }(p.level)
+       p.level = 0
+
        const maxSize = 100
        if headerSize+p.bodySize(b, maxSize) <= maxSize {
                p.print(sep, b.Lbrace, token.LBRACE)
@@ -1613,7 +1620,7 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
        }
        p.expr(d.Name)
        p.signature(d.Type.Params, d.Type.Results)
-       p.adjBlock(p.distanceFrom(d.Pos()), vtab, d.Body)
+       p.funcBody(p.distanceFrom(d.Pos()), vtab, d.Body)
 }
 
 func (p *printer) decl(decl ast.Decl) {
index eabf23e8b28691ec975c0fdcb5aee2584081f893..be61dad590eea02012364ae32c9c602d256f9c11 100644 (file)
@@ -58,6 +58,7 @@ type printer struct {
        // Current state
        output      []byte       // raw printer result
        indent      int          // current indentation
+       level       int          // level == 0: outside composite literal; level > 0: inside composite literal
        mode        pmode        // current printer mode
        impliedSemi bool         // if set, a linebreak implies a semicolon
        lastTok     token.Token  // last token printed (token.ILLEGAL if it's whitespace)
@@ -744,15 +745,19 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (wro
                // follows on the same line but is not a comma, and not a "closing"
                // token immediately following its corresponding "opening" token,
                // add an extra separator unless explicitly disabled. Use a blank
-               // as separator unless we have pending linebreaks and they are not
-               // disabled, in which case we want a linebreak (issue 15137).
+               // as separator unless we have pending linebreaks, they are not
+               // disabled, and we are outside a composite literal, in which case
+               // we want a linebreak (issue 15137).
+               // TODO(gri) This has become overly complicated. We should be able
+               // to track whether we're inside an expression or statement and
+               // use that information to decide more directly.
                needsLinebreak := false
                if p.mode&noExtraBlank == 0 &&
                        last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line &&
                        tok != token.COMMA &&
                        (tok != token.RPAREN || p.prevOpen == token.LPAREN) &&
                        (tok != token.RBRACK || p.prevOpen == token.LBRACK) {
-                       if p.containsLinebreak() && p.mode&noExtraLinebreak == 0 {
+                       if p.containsLinebreak() && p.mode&noExtraLinebreak == 0 && p.level == 0 {
                                needsLinebreak = true
                        } else {
                                p.writeByte(' ', 1)
index 7676a26c1259eec0a56ca1a3c2930bc593f86de6..8b3a94ddcd03a0ac75ab7e6c2bbfa5dbb88c2b95 100644 (file)
@@ -103,3 +103,62 @@ label:
        mask := uint64(1)<<c - 1                // Allocation mask
        used := atomic.LoadUint64(&h.used)      // Current allocations
 }
+
+// Test cases for issue 18782
+var _ = [][]int{
+       /*       a, b, c, d, e */
+       /* a */ {0, 0, 0, 0, 0},
+       /* b */ {0, 5, 4, 4, 4},
+       /* c */ {0, 4, 5, 4, 4},
+       /* d */ {0, 4, 4, 5, 4},
+       /* e */ {0, 4, 4, 4, 5},
+}
+
+var _ = T{ /* a */ 0}
+
+var _ = T{ /* a */ /* b */ 0}
+
+var _ = T{     /* a */ /* b */
+       /* c */ 0,
+}
+
+var _ = T{     /* a */ /* b */
+       /* c */
+       /* d */ 0,
+}
+
+var _ = T{
+       /* a */
+       /* b */ 0,
+}
+
+var _ = T{ /* a */ {}}
+
+var _ = T{ /* a */ /* b */ {}}
+
+var _ = T{     /* a */ /* b */
+       /* c */ {},
+}
+
+var _ = T{     /* a */ /* b */
+       /* c */
+       /* d */ {},
+}
+
+var _ = T{
+       /* a */
+       /* b */ {},
+}
+
+var _ = []T{
+       func() {
+               var _ = [][]int{
+                       /*       a, b, c, d, e */
+                       /* a */ {0, 0, 0, 0, 0},
+                       /* b */ {0, 5, 4, 4, 4},
+                       /* c */ {0, 4, 5, 4, 4},
+                       /* d */ {0, 4, 4, 5, 4},
+                       /* e */ {0, 4, 4, 4, 5},
+               }
+       },
+}
index 4a055c82772886a0b2ea165d7b2abc987e458235..8d38c4194bbcd73e3ba0f58d59775edfa09b6501 100644 (file)
@@ -103,3 +103,66 @@ label:
    mask := uint64(1)<<c - 1 // Allocation mask
    used := atomic.LoadUint64(&h.used) // Current allocations
 }
+
+// Test cases for issue 18782
+var _ = [][]int{
+   /*       a, b, c, d, e */
+   /* a */ {0, 0, 0, 0, 0},
+   /* b */ {0, 5, 4, 4, 4},
+   /* c */ {0, 4, 5, 4, 4},
+   /* d */ {0, 4, 4, 5, 4},
+   /* e */ {0, 4, 4, 4, 5},
+}
+
+var _ = T{ /* a */ 0,
+}
+
+var _ = T{ /* a */ /* b */ 0,
+}
+
+var _ = T{ /* a */ /* b */
+   /* c */ 0,
+}
+
+var _ = T{ /* a */ /* b */
+   /* c */
+   /* d */ 0,
+}
+
+var _ = T{
+   /* a */
+   /* b */ 0,
+}
+
+var _ = T{ /* a */ {},
+}
+
+var _ = T{ /* a */ /* b */ {},
+}
+
+var _ = T{ /* a */ /* b */
+   /* c */ {},
+}
+
+var _ = T{ /* a */ /* b */
+   /* c */
+   /* d */ {},
+}
+
+var _ = T{
+   /* a */
+   /* b */ {},
+}
+
+var _ = []T{
+   func() {
+      var _ = [][]int{
+         /*       a, b, c, d, e */
+         /* a */ {0, 0, 0, 0, 0},
+         /* b */ {0, 5, 4, 4, 4},
+         /* c */ {0, 4, 5, 4, 4},
+         /* d */ {0, 4, 4, 5, 4},
+         /* e */ {0, 4, 4, 4, 5},
+      }
+   },
+}