mirror of
https://github.com/golang/go
synced 2024-10-01 05:18:33 -06:00
go/printer: do not remove parens around composite literals starting with a type name in control clauses
(even when they are nested inside an expression). Fixes #1243. R=rsc CC=golang-dev https://golang.org/cl/2817041
This commit is contained in:
parent
9384fdc96a
commit
7996924c89
@ -796,9 +796,15 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
|
||||
p.funcBody(x.Body, distance(x.Type.Pos(), p.pos), true, multiLine)
|
||||
|
||||
case *ast.ParenExpr:
|
||||
p.print(token.LPAREN)
|
||||
p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth
|
||||
p.print(x.Rparen, token.RPAREN)
|
||||
if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
|
||||
// don't print parentheses around an already parenthesized expression
|
||||
// TODO(gri) consider making this more general and incorporate precedence levels
|
||||
p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth
|
||||
} else {
|
||||
p.print(token.LPAREN)
|
||||
p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth
|
||||
p.print(x.Rparen, token.RPAREN)
|
||||
}
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
parts := selectorExprList(expr)
|
||||
@ -969,16 +975,27 @@ func isTypeName(x ast.Expr) bool {
|
||||
}
|
||||
|
||||
|
||||
// TODO(gri): Decide if this should be used more broadly. The printing code
|
||||
// knows when to insert parentheses for precedence reasons, but
|
||||
// need to be careful to keep them around type expressions.
|
||||
func stripParens(x ast.Expr, inControlClause bool) ast.Expr {
|
||||
for px, hasParens := x.(*ast.ParenExpr); hasParens; px, hasParens = x.(*ast.ParenExpr) {
|
||||
x = px.X
|
||||
if cx, isCompositeLit := x.(*ast.CompositeLit); inControlClause && isCompositeLit && isTypeName(cx.Type) {
|
||||
// composite literals inside control clauses need parens if they start with a type name;
|
||||
// don't strip innermost layer
|
||||
return px
|
||||
func stripParens(x ast.Expr) ast.Expr {
|
||||
if px, strip := x.(*ast.ParenExpr); strip {
|
||||
// parentheses must not be stripped if there are any
|
||||
// unparenthesized composite literals starting with
|
||||
// a type name
|
||||
ast.Inspect(px.X, func(node interface{}) bool {
|
||||
switch x := node.(type) {
|
||||
case *ast.ParenExpr:
|
||||
// parentheses protect enclosed composite literals
|
||||
return false
|
||||
case *ast.CompositeLit:
|
||||
if isTypeName(x.Type) {
|
||||
strip = false // do not strip parentheses
|
||||
}
|
||||
return false
|
||||
}
|
||||
// in all other cases, keep inspecting
|
||||
return true
|
||||
})
|
||||
if strip {
|
||||
return stripParens(px.X)
|
||||
}
|
||||
}
|
||||
return x
|
||||
@ -991,7 +1008,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
|
||||
if init == nil && post == nil {
|
||||
// no semicolons required
|
||||
if expr != nil {
|
||||
p.expr(stripParens(expr, true), ignoreMultiLine)
|
||||
p.expr(stripParens(expr), ignoreMultiLine)
|
||||
needsBlank = true
|
||||
}
|
||||
} else {
|
||||
@ -1002,7 +1019,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
|
||||
}
|
||||
p.print(token.SEMICOLON, blank)
|
||||
if expr != nil {
|
||||
p.expr(stripParens(expr, true), ignoreMultiLine)
|
||||
p.expr(stripParens(expr), ignoreMultiLine)
|
||||
needsBlank = true
|
||||
}
|
||||
if isForStmt {
|
||||
@ -1183,7 +1200,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
|
||||
p.expr(s.Value, multiLine)
|
||||
}
|
||||
p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank)
|
||||
p.expr(stripParens(s.X, true), multiLine)
|
||||
p.expr(stripParens(s.X), multiLine)
|
||||
p.print(blank)
|
||||
p.block(s.Body, 1)
|
||||
*multiLine = true
|
||||
|
30
src/pkg/go/printer/testdata/statements.golden
vendored
30
src/pkg/go/printer/testdata/statements.golden
vendored
@ -209,6 +209,36 @@ func _() {
|
||||
|
||||
for _ = range (T1{T{42}}) {
|
||||
}
|
||||
|
||||
if x == (T{42}[0]) {
|
||||
}
|
||||
if (x == T{42}[0]) {
|
||||
}
|
||||
if x == (T{42}[0]) {
|
||||
}
|
||||
if x == (T{42}[0]) {
|
||||
}
|
||||
if x == (T{42}[0]) {
|
||||
}
|
||||
if x == a+b*(T{42}[0]) {
|
||||
}
|
||||
if (x == a+b*T{42}[0]) {
|
||||
}
|
||||
if x == a+b*(T{42}[0]) {
|
||||
}
|
||||
if x == a+(b * (T{42}[0])) {
|
||||
}
|
||||
if x == a+b*(T{42}[0]) {
|
||||
}
|
||||
if (a + b*(T{42}[0])) == x {
|
||||
}
|
||||
if (a + b*(T{42}[0])) == x {
|
||||
}
|
||||
|
||||
if struct{ x bool }{false}.x {
|
||||
}
|
||||
if struct{ x bool }{false}.x == false {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
17
src/pkg/go/printer/testdata/statements.input
vendored
17
src/pkg/go/printer/testdata/statements.input
vendored
@ -146,6 +146,23 @@ func _() {
|
||||
switch ; ((((T{})))) {}
|
||||
|
||||
for _ = range (((T1{T{42}}))) {}
|
||||
|
||||
if x == (T{42}[0]) {}
|
||||
if (x == T{42}[0]) {}
|
||||
if (x == (T{42}[0])) {}
|
||||
if (x == (((T{42}[0])))) {}
|
||||
if (((x == (T{42}[0])))) {}
|
||||
if x == a + b*(T{42}[0]) {}
|
||||
if (x == a + b*T{42}[0]) {}
|
||||
if (x == a + b*(T{42}[0])) {}
|
||||
if (x == a + ((b * (T{42}[0])))) {}
|
||||
if (((x == a + b * (T{42}[0])))) {}
|
||||
if (((a + b * (T{42}[0])) == x)) {}
|
||||
if (((a + b * (T{42}[0])))) == x {}
|
||||
|
||||
if (struct{x bool}{false}.x) {}
|
||||
if (struct{x bool}{false}.x) == false {}
|
||||
if (struct{x bool}{false}.x == false) {}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user