Skip to content

Commit 1cf0818

Browse files
committed
go/printer: fix format with leading comments in composite literal
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 <[email protected]>
1 parent b531eb3 commit 1cf0818

File tree

4 files changed

+142
-8
lines changed

4 files changed

+142
-8
lines changed

src/go/printer/nodes.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
733733

734734
case *ast.FuncLit:
735735
p.expr(x.Type)
736-
p.adjBlock(p.distanceFrom(x.Type.Pos()), blank, x.Body)
736+
p.funcBody(p.distanceFrom(x.Type.Pos()), blank, x.Body)
737737

738738
case *ast.ParenExpr:
739739
if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
@@ -825,6 +825,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
825825
if x.Type != nil {
826826
p.expr1(x.Type, token.HighestPrec, depth)
827827
}
828+
p.level++
828829
p.print(x.Lbrace, token.LBRACE)
829830
p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace)
830831
// do not insert extra line break following a /*-style comment
@@ -837,6 +838,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
837838
mode |= noExtraBlank
838839
}
839840
p.print(mode, x.Rbrace, token.RBRACE, mode)
841+
p.level--
840842

841843
case *ast.Ellipsis:
842844
p.print(token.ELLIPSIS)
@@ -1557,18 +1559,23 @@ func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int {
15571559
return bodySize
15581560
}
15591561

1560-
// adjBlock prints an "adjacent" block (e.g., a for-loop or function body) following
1561-
// a header (e.g., a for-loop control clause or function signature) of given headerSize.
1562+
// funcBody prints a function body following a function header of given headerSize.
15621563
// If the header's and block's size are "small enough" and the block is "simple enough",
15631564
// the block is printed on the current line, without line breaks, spaced from the header
15641565
// by sep. Otherwise the block's opening "{" is printed on the current line, followed by
15651566
// lines for the block's statements and its closing "}".
15661567
//
1567-
func (p *printer) adjBlock(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
1568+
func (p *printer) funcBody(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
15681569
if b == nil {
15691570
return
15701571
}
15711572

1573+
// save/restore composite literal nesting level
1574+
defer func(level int) {
1575+
p.level = level
1576+
}(p.level)
1577+
p.level = 0
1578+
15721579
const maxSize = 100
15731580
if headerSize+p.bodySize(b, maxSize) <= maxSize {
15741581
p.print(sep, b.Lbrace, token.LBRACE)
@@ -1613,7 +1620,7 @@ func (p *printer) funcDecl(d *ast.FuncDecl) {
16131620
}
16141621
p.expr(d.Name)
16151622
p.signature(d.Type.Params, d.Type.Results)
1616-
p.adjBlock(p.distanceFrom(d.Pos()), vtab, d.Body)
1623+
p.funcBody(p.distanceFrom(d.Pos()), vtab, d.Body)
16171624
}
16181625

16191626
func (p *printer) decl(decl ast.Decl) {

src/go/printer/printer.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type printer struct {
5858
// Current state
5959
output []byte // raw printer result
6060
indent int // current indentation
61+
level int // level == 0: outside composite literal; level > 0: inside composite literal
6162
mode pmode // current printer mode
6263
impliedSemi bool // if set, a linebreak implies a semicolon
6364
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
744745
// follows on the same line but is not a comma, and not a "closing"
745746
// token immediately following its corresponding "opening" token,
746747
// add an extra separator unless explicitly disabled. Use a blank
747-
// as separator unless we have pending linebreaks and they are not
748-
// disabled, in which case we want a linebreak (issue 15137).
748+
// as separator unless we have pending linebreaks, they are not
749+
// disabled, and we are outside a composite literal, in which case
750+
// we want a linebreak (issue 15137).
751+
// TODO(gri) This has become overly complicated. We should be able
752+
// to track whether we're inside an expression or statement and
753+
// use that information to decide more directly.
749754
needsLinebreak := false
750755
if p.mode&noExtraBlank == 0 &&
751756
last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line &&
752757
tok != token.COMMA &&
753758
(tok != token.RPAREN || p.prevOpen == token.LPAREN) &&
754759
(tok != token.RBRACK || p.prevOpen == token.LBRACK) {
755-
if p.containsLinebreak() && p.mode&noExtraLinebreak == 0 {
760+
if p.containsLinebreak() && p.mode&noExtraLinebreak == 0 && p.level == 0 {
756761
needsLinebreak = true
757762
} else {
758763
p.writeByte(' ', 1)

src/go/printer/testdata/comments2.golden

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,62 @@ label:
103103
mask := uint64(1)<<c - 1 // Allocation mask
104104
used := atomic.LoadUint64(&h.used) // Current allocations
105105
}
106+
107+
// Test cases for issue 18782
108+
var _ = [][]int{
109+
/* a, b, c, d, e */
110+
/* a */ {0, 0, 0, 0, 0},
111+
/* b */ {0, 5, 4, 4, 4},
112+
/* c */ {0, 4, 5, 4, 4},
113+
/* d */ {0, 4, 4, 5, 4},
114+
/* e */ {0, 4, 4, 4, 5},
115+
}
116+
117+
var _ = T{ /* a */ 0}
118+
119+
var _ = T{ /* a */ /* b */ 0}
120+
121+
var _ = T{ /* a */ /* b */
122+
/* c */ 0,
123+
}
124+
125+
var _ = T{ /* a */ /* b */
126+
/* c */
127+
/* d */ 0,
128+
}
129+
130+
var _ = T{
131+
/* a */
132+
/* b */ 0,
133+
}
134+
135+
var _ = T{ /* a */ {}}
136+
137+
var _ = T{ /* a */ /* b */ {}}
138+
139+
var _ = T{ /* a */ /* b */
140+
/* c */ {},
141+
}
142+
143+
var _ = T{ /* a */ /* b */
144+
/* c */
145+
/* d */ {},
146+
}
147+
148+
var _ = T{
149+
/* a */
150+
/* b */ {},
151+
}
152+
153+
var _ = []T{
154+
func() {
155+
var _ = [][]int{
156+
/* a, b, c, d, e */
157+
/* a */ {0, 0, 0, 0, 0},
158+
/* b */ {0, 5, 4, 4, 4},
159+
/* c */ {0, 4, 5, 4, 4},
160+
/* d */ {0, 4, 4, 5, 4},
161+
/* e */ {0, 4, 4, 4, 5},
162+
}
163+
},
164+
}

src/go/printer/testdata/comments2.input

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,66 @@ label:
103103
mask := uint64(1)<<c - 1 // Allocation mask
104104
used := atomic.LoadUint64(&h.used) // Current allocations
105105
}
106+
107+
// Test cases for issue 18782
108+
var _ = [][]int{
109+
/* a, b, c, d, e */
110+
/* a */ {0, 0, 0, 0, 0},
111+
/* b */ {0, 5, 4, 4, 4},
112+
/* c */ {0, 4, 5, 4, 4},
113+
/* d */ {0, 4, 4, 5, 4},
114+
/* e */ {0, 4, 4, 4, 5},
115+
}
116+
117+
var _ = T{ /* a */ 0,
118+
}
119+
120+
var _ = T{ /* a */ /* b */ 0,
121+
}
122+
123+
var _ = T{ /* a */ /* b */
124+
/* c */ 0,
125+
}
126+
127+
var _ = T{ /* a */ /* b */
128+
/* c */
129+
/* d */ 0,
130+
}
131+
132+
var _ = T{
133+
/* a */
134+
/* b */ 0,
135+
}
136+
137+
var _ = T{ /* a */ {},
138+
}
139+
140+
var _ = T{ /* a */ /* b */ {},
141+
}
142+
143+
var _ = T{ /* a */ /* b */
144+
/* c */ {},
145+
}
146+
147+
var _ = T{ /* a */ /* b */
148+
/* c */
149+
/* d */ {},
150+
}
151+
152+
var _ = T{
153+
/* a */
154+
/* b */ {},
155+
}
156+
157+
var _ = []T{
158+
func() {
159+
var _ = [][]int{
160+
/* a, b, c, d, e */
161+
/* a */ {0, 0, 0, 0, 0},
162+
/* b */ {0, 5, 4, 4, 4},
163+
/* c */ {0, 4, 5, 4, 4},
164+
/* d */ {0, 4, 4, 5, 4},
165+
/* e */ {0, 4, 4, 4, 5},
166+
}
167+
},
168+
}

0 commit comments

Comments
 (0)