Commit ab14797f authored by Michal Bohuslávek's avatar Michal Bohuslávek Committed by Robert Griesemer

go/printer: fix indentation of *ast.CallExpr parameters

The current version of go/printer formats the following code
like this:

	foo.Bar().
		Run(func() {
		do()
	}).
		Set(map[string]interface{}{
		"x": "three",
		"y": 4,
	}).
		Run(
		func() {
			do()
		},
	)

This CL changes the go/printer behaviour to make the code look
like this.

	foo.Bar().
		Run(func() {
			do()
		}).
		Set(map[string]interface{}{
			"x": "three",
			"y": 4,
		}).
		Run(
			func() {
				do()
			},
		)

Fixes #12066.

Change-Id: If0f525dae1a5d45f9ba40534dbb65715d7e8001b
Reviewed-on: https://go-review.googlesource.com/13928Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 67ddae87
...@@ -747,13 +747,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { ...@@ -747,13 +747,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
} }
case *ast.SelectorExpr: case *ast.SelectorExpr:
p.expr1(x.X, token.HighestPrec, depth) p.selectorExpr(x, depth, false)
p.print(token.PERIOD)
if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line {
p.print(indent, newline, x.Sel.Pos(), x.Sel, unindent)
} else {
p.print(x.Sel.Pos(), x.Sel)
}
case *ast.TypeAssertExpr: case *ast.TypeAssertExpr:
p.expr1(x.X, token.HighestPrec, depth) p.expr1(x.X, token.HighestPrec, depth)
...@@ -802,13 +796,14 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { ...@@ -802,13 +796,14 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
if len(x.Args) > 1 { if len(x.Args) > 1 {
depth++ depth++
} }
var wasIndented bool
if _, ok := x.Fun.(*ast.FuncType); ok { if _, ok := x.Fun.(*ast.FuncType); ok {
// conversions to literal function types require parentheses around the type // conversions to literal function types require parentheses around the type
p.print(token.LPAREN) p.print(token.LPAREN)
p.expr1(x.Fun, token.HighestPrec, depth) wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
p.print(token.RPAREN) p.print(token.RPAREN)
} else { } else {
p.expr1(x.Fun, token.HighestPrec, depth) wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
} }
p.print(x.Lparen, token.LPAREN) p.print(x.Lparen, token.LPAREN)
if x.Ellipsis.IsValid() { if x.Ellipsis.IsValid() {
...@@ -821,6 +816,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { ...@@ -821,6 +816,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen) p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen)
} }
p.print(x.Rparen, token.RPAREN) p.print(x.Rparen, token.RPAREN)
if wasIndented {
p.print(unindent)
}
case *ast.CompositeLit: case *ast.CompositeLit:
// composite literal elements that are composite literals themselves may have the type omitted // composite literal elements that are composite literals themselves may have the type omitted
...@@ -891,6 +889,30 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { ...@@ -891,6 +889,30 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
return return
} }
func (p *printer) possibleSelectorExpr(expr ast.Expr, prec1, depth int) bool {
if x, ok := expr.(*ast.SelectorExpr); ok {
return p.selectorExpr(x, depth, true)
}
p.expr1(expr, prec1, depth)
return false
}
// selectorExpr handles an *ast.SelectorExpr node and returns whether x spans
// multiple lines.
func (p *printer) selectorExpr(x *ast.SelectorExpr, depth int, isMethod bool) bool {
p.expr1(x.X, token.HighestPrec, depth)
p.print(token.PERIOD)
if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line {
p.print(indent, newline, x.Sel.Pos(), x.Sel)
if !isMethod {
p.print(unindent)
}
return true
}
p.print(x.Sel.Pos(), x.Sel)
return false
}
func (p *printer) expr0(x ast.Expr, depth int) { func (p *printer) expr0(x ast.Expr, depth int) {
p.expr1(x, token.LowestPrec, depth) p.expr1(x, token.LowestPrec, depth)
} }
......
...@@ -567,7 +567,7 @@ func _() { ...@@ -567,7 +567,7 @@ func _() {
// handle multiline argument list correctly // handle multiline argument list correctly
_ = new(T). _ = new(T).
foo( foo(
1). 1).
foo(2) foo(2)
_ = new(T).foo( _ = new(T).foo(
...@@ -614,7 +614,7 @@ func _() { ...@@ -614,7 +614,7 @@ func _() {
Blob.(*Type). Blob.(*Type).
Slices[1:4]. Slices[1:4].
Method(1, 2, Method(1, 2,
3). 3).
Thingy Thingy
_ = a.b.c _ = a.b.c
...@@ -684,3 +684,21 @@ func _() { ...@@ -684,3 +684,21 @@ func _() {
_ = (func(x int) float)(nil) _ = (func(x int) float)(nil)
_ = (func() func() func())(nil) _ = (func() func() func())(nil)
} }
func _() {
_ = f().
f(func() {
f()
}).
f(map[int]int{
1: 2,
3: 4,
})
_ = f().
f(
func() {
f()
},
)
}
...@@ -713,3 +713,21 @@ func _() { ...@@ -713,3 +713,21 @@ func _() {
_ = (func(x int)(float))(nil) _ = (func(x int)(float))(nil)
_ = (func() func() func()())(nil) _ = (func() func() func()())(nil)
} }
func _() {
_ = f().
f(func() {
f()
}).
f(map[int]int{
1: 2,
3: 4,
})
_ = f().
f(
func() {
f()
},
)
}
...@@ -567,7 +567,7 @@ func _() { ...@@ -567,7 +567,7 @@ func _() {
// handle multiline argument list correctly // handle multiline argument list correctly
_ = new(T). _ = new(T).
foo( foo(
1). 1).
foo(2) foo(2)
_ = new(T).foo( _ = new(T).foo(
...@@ -614,7 +614,7 @@ func _() { ...@@ -614,7 +614,7 @@ func _() {
Blob.(*Type). Blob.(*Type).
Slices[1:4]. Slices[1:4].
Method(1, 2, Method(1, 2,
3). 3).
Thingy Thingy
_ = a.b.c _ = a.b.c
...@@ -684,3 +684,21 @@ func _() { ...@@ -684,3 +684,21 @@ func _() {
_ = (func(x int) float)(nil) _ = (func(x int) float)(nil)
_ = (func() func() func())(nil) _ = (func() func() func())(nil)
} }
func _() {
_ = f().
f(func() {
f()
}).
f(map[int]int{
1: 2,
3: 4,
})
_ = f().
f(
func() {
f()
},
)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment