Commit b1b0ed1e authored by Robert Griesemer's avatar Robert Griesemer

go/printer: replace multiline logic

This CL mostly deletes code.

Using existing position information is
just as good to determine if a new section
is needed; no need to track exact multi-
line information. Eliminates the need to
carry around a multiLine parameter with
practically every function.

Applied gofmt -w src misc resulting in only
a minor change to godoc.go. In return, a couple
of test cases are now formatted better.

Not Go1-required, but nice-to-have as it will
simplify fixes going forward.

R=rsc
CC=golang-dev
https://golang.org/cl/5706055
parent fb270611
...@@ -89,10 +89,9 @@ const ( ...@@ -89,10 +89,9 @@ const (
noIndent // no extra indentation in multi-line lists noIndent // no extra indentation in multi-line lists
) )
// Sets multiLine to true if the identifier list spans multiple lines.
// If indent is set, a multi-line identifier list is indented after the // If indent is set, a multi-line identifier list is indented after the
// first linebreak encountered. // first linebreak encountered.
func (p *printer) identList(list []*ast.Ident, indent bool, multiLine *bool) { func (p *printer) identList(list []*ast.Ident, indent bool) {
// convert into an expression list so we can re-use exprList formatting // convert into an expression list so we can re-use exprList formatting
xlist := make([]ast.Expr, len(list)) xlist := make([]ast.Expr, len(list))
for i, x := range list { for i, x := range list {
...@@ -102,18 +101,17 @@ func (p *printer) identList(list []*ast.Ident, indent bool, multiLine *bool) { ...@@ -102,18 +101,17 @@ func (p *printer) identList(list []*ast.Ident, indent bool, multiLine *bool) {
if !indent { if !indent {
mode |= noIndent mode |= noIndent
} }
p.exprList(token.NoPos, xlist, 1, mode, multiLine, token.NoPos) p.exprList(token.NoPos, xlist, 1, mode, token.NoPos)
} }
// Print a list of expressions. If the list spans multiple // Print a list of expressions. If the list spans multiple
// source lines, the original line breaks are respected between // source lines, the original line breaks are respected between
// expressions. Sets multiLine to true if the list spans multiple // expressions.
// lines.
// //
// TODO(gri) Consider rewriting this to be independent of []ast.Expr // TODO(gri) Consider rewriting this to be independent of []ast.Expr
// so that we can use the algorithm for any kind of list // so that we can use the algorithm for any kind of list
// (e.g., pass list via a channel over which to range). // (e.g., pass list via a channel over which to range).
func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, multiLine *bool, next0 token.Pos) { func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos) {
if len(list) == 0 { if len(list) == 0 {
return return
} }
...@@ -138,7 +136,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp ...@@ -138,7 +136,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
} }
p.print(blank) p.print(blank)
} }
p.expr0(x, depth, multiLine) p.expr0(x, depth)
} }
if mode&blankEnd != 0 { if mode&blankEnd != 0 {
p.print(blank) p.print(blank)
...@@ -161,7 +159,6 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp ...@@ -161,7 +159,6 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
prevBreak := -1 // index of last expression that was followed by a linebreak prevBreak := -1 // index of last expression that was followed by a linebreak
if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) { if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) {
ws = ignore ws = ignore
*multiLine = true
prevBreak = 0 prevBreak = 0
} }
...@@ -231,7 +228,6 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp ...@@ -231,7 +228,6 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
// the same line in which case formfeed is used // the same line in which case formfeed is used
if p.linebreak(line, 0, ws, useFF || prevBreak+1 < i) { if p.linebreak(line, 0, ws, useFF || prevBreak+1 < i) {
ws = ignore ws = ignore
*multiLine = true
prevBreak = i prevBreak = i
needsBlank = false // we got a line break instead needsBlank = false // we got a line break instead
} }
...@@ -245,11 +241,11 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp ...@@ -245,11 +241,11 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
// we have a key:value expression that fits onto one line and // we have a key:value expression that fits onto one line and
// is in a list with more then one entry: use a column for the // is in a list with more then one entry: use a column for the
// key such that consecutive entries can align if possible // key such that consecutive entries can align if possible
p.expr(pair.Key, multiLine) p.expr(pair.Key)
p.print(pair.Colon, token.COLON, vtab) p.print(pair.Colon, token.COLON, vtab)
p.expr(pair.Value, multiLine) p.expr(pair.Value)
} else { } else {
p.expr0(x, depth, multiLine) p.expr0(x, depth)
} }
} }
...@@ -274,8 +270,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp ...@@ -274,8 +270,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
} }
} }
// Sets multiLine to true if the the parameter list spans multiple lines. func (p *printer) parameters(fields *ast.FieldList) {
func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
p.print(fields.Opening, token.LPAREN) p.print(fields.Opening, token.LPAREN)
if len(fields.List) > 0 { if len(fields.List) > 0 {
prevLine := p.lineFor(fields.Opening) prevLine := p.lineFor(fields.Opening)
...@@ -306,7 +301,6 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { ...@@ -306,7 +301,6 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) { if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) {
// break line if the opening "(" or previous parameter ended on a different line // break line if the opening "(" or previous parameter ended on a different line
ws = ignore ws = ignore
*multiLine = true
} else if i > 0 { } else if i > 0 {
p.print(blank) p.print(blank)
} }
...@@ -318,11 +312,11 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { ...@@ -318,11 +312,11 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
// again at the end (and still ws == indent). Thus, a subsequent indent // again at the end (and still ws == indent). Thus, a subsequent indent
// by a linebreak call after a type, or in the next multi-line identList // by a linebreak call after a type, or in the next multi-line identList
// will do the right thing. // will do the right thing.
p.identList(par.Names, ws == indent, multiLine) p.identList(par.Names, ws == indent)
p.print(blank) p.print(blank)
} }
// parameter type // parameter type
p.expr(par.Type, multiLine) p.expr(par.Type)
prevLine = parLineEnd prevLine = parLineEnd
} }
// if the closing ")" is on a separate line from the last parameter, // if the closing ")" is on a separate line from the last parameter,
...@@ -339,18 +333,17 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { ...@@ -339,18 +333,17 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
p.print(fields.Closing, token.RPAREN) p.print(fields.Closing, token.RPAREN)
} }
// Sets multiLine to true if the signature spans multiple lines. func (p *printer) signature(params, result *ast.FieldList) {
func (p *printer) signature(params, result *ast.FieldList, multiLine *bool) { p.parameters(params)
p.parameters(params, multiLine)
n := result.NumFields() n := result.NumFields()
if n > 0 { if n > 0 {
p.print(blank) p.print(blank)
if n == 1 && result.List[0].Names == nil { if n == 1 && result.List[0].Names == nil {
// single anonymous result; no ()'s // single anonymous result; no ()'s
p.expr(result.List[0].Type, multiLine) p.expr(result.List[0].Type)
return return
} }
p.parameters(result, multiLine) p.parameters(result)
} }
} }
...@@ -389,6 +382,10 @@ func (p *printer) setLineComment(text string) { ...@@ -389,6 +382,10 @@ func (p *printer) setLineComment(text string) {
p.setComment(&ast.CommentGroup{List: []*ast.Comment{{Slash: token.NoPos, Text: text}}}) p.setComment(&ast.CommentGroup{List: []*ast.Comment{{Slash: token.NoPos, Text: text}}})
} }
func (p *printer) isMultiLine(n ast.Node) bool {
return p.lineFor(n.End())-p.lineFor(n.Pos()) > 1
}
func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) { func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {
lbrace := fields.Opening lbrace := fields.Opening
list := fields.List list := fields.List
...@@ -412,12 +409,12 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) ...@@ -412,12 +409,12 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
// no comments so no need for comma position // no comments so no need for comma position
p.print(token.COMMA, blank) p.print(token.COMMA, blank)
} }
p.expr(x, ignoreMultiLine) p.expr(x)
} }
if len(f.Names) > 0 { if len(f.Names) > 0 {
p.print(blank) p.print(blank)
} }
p.expr(f.Type, ignoreMultiLine) p.expr(f.Type)
p.print(blank, rbrace, token.RBRACE) p.print(blank, rbrace, token.RBRACE)
return return
} }
...@@ -435,23 +432,22 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) ...@@ -435,23 +432,22 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
if len(list) == 1 { if len(list) == 1 {
sep = blank sep = blank
} }
var ml bool newSection := false
for i, f := range list { for i, f := range list {
if i > 0 { if i > 0 {
p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml) p.linebreak(p.lineFor(f.Pos()), 1, ignore, newSection)
} }
ml = false
extraTabs := 0 extraTabs := 0
p.setComment(f.Doc) p.setComment(f.Doc)
if len(f.Names) > 0 { if len(f.Names) > 0 {
// named fields // named fields
p.identList(f.Names, false, &ml) p.identList(f.Names, false)
p.print(sep) p.print(sep)
p.expr(f.Type, &ml) p.expr(f.Type)
extraTabs = 1 extraTabs = 1
} else { } else {
// anonymous field // anonymous field
p.expr(f.Type, &ml) p.expr(f.Type)
extraTabs = 2 extraTabs = 2
} }
if f.Tag != nil { if f.Tag != nil {
...@@ -459,7 +455,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) ...@@ -459,7 +455,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
p.print(sep) p.print(sep)
} }
p.print(sep) p.print(sep)
p.expr(f.Tag, &ml) p.expr(f.Tag)
extraTabs = 0 extraTabs = 0
} }
if f.Comment != nil { if f.Comment != nil {
...@@ -468,6 +464,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) ...@@ -468,6 +464,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
} }
p.setComment(f.Comment) p.setComment(f.Comment)
} }
newSection = p.isMultiLine(f)
} }
if isIncomplete { if isIncomplete {
if len(list) > 0 { if len(list) > 0 {
...@@ -479,22 +476,22 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) ...@@ -479,22 +476,22 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
} else { // interface } else { // interface
var ml bool newSection := false
for i, f := range list { for i, f := range list {
if i > 0 { if i > 0 {
p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml) p.linebreak(p.lineFor(f.Pos()), 1, ignore, newSection)
} }
ml = false
p.setComment(f.Doc) p.setComment(f.Doc)
if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp { if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp {
// method // method
p.expr(f.Names[0], &ml) p.expr(f.Names[0])
p.signature(ftyp.Params, ftyp.Results, &ml) p.signature(ftyp.Params, ftyp.Results)
} else { } else {
// embedded interface // embedded interface
p.expr(f.Type, &ml) p.expr(f.Type)
} }
p.setComment(f.Comment) p.setComment(f.Comment)
newSection = p.isMultiLine(f)
} }
if isIncomplete { if isIncomplete {
if len(list) > 0 { if len(list) > 0 {
...@@ -635,15 +632,14 @@ func reduceDepth(depth int) int { ...@@ -635,15 +632,14 @@ func reduceDepth(depth int) int {
// cutoff is 6 (always use spaces) in Normal mode // cutoff is 6 (always use spaces) in Normal mode
// and 4 (never use spaces) in Compact mode. // and 4 (never use spaces) in Compact mode.
// //
// Sets multiLine to true if the binary expression spans multiple lines. func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) {
func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiLine *bool) {
prec := x.Op.Precedence() prec := x.Op.Precedence()
if prec < prec1 { if prec < prec1 {
// parenthesis needed // parenthesis needed
// Note: The parser inserts an ast.ParenExpr node; thus this case // Note: The parser inserts an ast.ParenExpr node; thus this case
// can only occur if the AST is created in a different way. // can only occur if the AST is created in a different way.
p.print(token.LPAREN) p.print(token.LPAREN)
p.expr0(x, reduceDepth(depth), multiLine) // parentheses undo one level of depth p.expr0(x, reduceDepth(depth)) // parentheses undo one level of depth
p.print(token.RPAREN) p.print(token.RPAREN)
return return
} }
...@@ -651,7 +647,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL ...@@ -651,7 +647,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL
printBlank := prec < cutoff printBlank := prec < cutoff
ws := indent ws := indent
p.expr1(x.X, prec, depth+diffPrec(x.X, prec), multiLine) p.expr1(x.X, prec, depth+diffPrec(x.X, prec))
if printBlank { if printBlank {
p.print(blank) p.print(blank)
} }
...@@ -663,14 +659,13 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL ...@@ -663,14 +659,13 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL
// in the source // in the source
if p.linebreak(yline, 1, ws, true) { if p.linebreak(yline, 1, ws, true) {
ws = ignore ws = ignore
*multiLine = true
printBlank = false // no blank after line break printBlank = false // no blank after line break
} }
} }
if printBlank { if printBlank {
p.print(blank) p.print(blank)
} }
p.expr1(x.Y, prec+1, depth+1, multiLine) p.expr1(x.Y, prec+1, depth+1)
if ws == ignore { if ws == ignore {
p.print(unindent) p.print(unindent)
} }
...@@ -681,8 +676,7 @@ func isBinary(expr ast.Expr) bool { ...@@ -681,8 +676,7 @@ func isBinary(expr ast.Expr) bool {
return ok return ok
} }
// Sets multiLine to true if the expression spans multiple lines. func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
p.print(expr.Pos()) p.print(expr.Pos())
switch x := expr.(type) { switch x := expr.(type) {
...@@ -697,12 +691,12 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -697,12 +691,12 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
p.internalError("depth < 1:", depth) p.internalError("depth < 1:", depth)
depth = 1 depth = 1
} }
p.binaryExpr(x, prec1, cutoff(x, depth), depth, multiLine) p.binaryExpr(x, prec1, cutoff(x, depth), depth)
case *ast.KeyValueExpr: case *ast.KeyValueExpr:
p.expr(x.Key, multiLine) p.expr(x.Key)
p.print(x.Colon, token.COLON, blank) p.print(x.Colon, token.COLON, blank)
p.expr(x.Value, multiLine) p.expr(x.Value)
case *ast.StarExpr: case *ast.StarExpr:
const prec = token.UnaryPrec const prec = token.UnaryPrec
...@@ -710,12 +704,12 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -710,12 +704,12 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
// parenthesis needed // parenthesis needed
p.print(token.LPAREN) p.print(token.LPAREN)
p.print(token.MUL) p.print(token.MUL)
p.expr(x.X, multiLine) p.expr(x.X)
p.print(token.RPAREN) p.print(token.RPAREN)
} else { } else {
// no parenthesis needed // no parenthesis needed
p.print(token.MUL) p.print(token.MUL)
p.expr(x.X, multiLine) p.expr(x.X)
} }
case *ast.UnaryExpr: case *ast.UnaryExpr:
...@@ -723,7 +717,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -723,7 +717,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
if prec < prec1 { if prec < prec1 {
// parenthesis needed // parenthesis needed
p.print(token.LPAREN) p.print(token.LPAREN)
p.expr(x, multiLine) p.expr(x)
p.print(token.RPAREN) p.print(token.RPAREN)
} else { } else {
// no parenthesis needed // no parenthesis needed
...@@ -732,42 +726,41 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -732,42 +726,41 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
// TODO(gri) Remove this code if it cannot be reached. // TODO(gri) Remove this code if it cannot be reached.
p.print(blank) p.print(blank)
} }
p.expr1(x.X, prec, depth, multiLine) p.expr1(x.X, prec, depth)
} }
case *ast.BasicLit: case *ast.BasicLit:
p.print(x) p.print(x)
case *ast.FuncLit: case *ast.FuncLit:
p.expr(x.Type, multiLine) p.expr(x.Type)
p.funcBody(x.Body, p.distance(x.Type.Pos(), p.pos), true, multiLine) p.funcBody(x.Body, p.distance(x.Type.Pos(), p.pos), true)
case *ast.ParenExpr: case *ast.ParenExpr:
if _, hasParens := x.X.(*ast.ParenExpr); hasParens { if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
// don't print parentheses around an already parenthesized expression // don't print parentheses around an already parenthesized expression
// TODO(gri) consider making this more general and incorporate precedence levels // TODO(gri) consider making this more general and incorporate precedence levels
p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth p.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth
} else { } else {
p.print(token.LPAREN) p.print(token.LPAREN)
p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth p.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth
p.print(x.Rparen, token.RPAREN) p.print(x.Rparen, token.RPAREN)
} }
case *ast.SelectorExpr: case *ast.SelectorExpr:
p.expr1(x.X, token.HighestPrec, depth, multiLine) p.expr1(x.X, token.HighestPrec, depth)
p.print(token.PERIOD) p.print(token.PERIOD)
if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line { if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line {
p.print(indent, newline, x.Sel.Pos(), x.Sel, unindent) p.print(indent, newline, x.Sel.Pos(), x.Sel, unindent)
*multiLine = true
} else { } else {
p.print(x.Sel.Pos(), x.Sel) p.print(x.Sel.Pos(), x.Sel)
} }
case *ast.TypeAssertExpr: case *ast.TypeAssertExpr:
p.expr1(x.X, token.HighestPrec, depth, multiLine) p.expr1(x.X, token.HighestPrec, depth)
p.print(token.PERIOD, token.LPAREN) p.print(token.PERIOD, token.LPAREN)
if x.Type != nil { if x.Type != nil {
p.expr(x.Type, multiLine) p.expr(x.Type)
} else { } else {
p.print(token.TYPE) p.print(token.TYPE)
} }
...@@ -775,17 +768,17 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -775,17 +768,17 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
case *ast.IndexExpr: case *ast.IndexExpr:
// TODO(gri): should treat[] like parentheses and undo one level of depth // TODO(gri): should treat[] like parentheses and undo one level of depth
p.expr1(x.X, token.HighestPrec, 1, multiLine) p.expr1(x.X, token.HighestPrec, 1)
p.print(x.Lbrack, token.LBRACK) p.print(x.Lbrack, token.LBRACK)
p.expr0(x.Index, depth+1, multiLine) p.expr0(x.Index, depth+1)
p.print(x.Rbrack, token.RBRACK) p.print(x.Rbrack, token.RBRACK)
case *ast.SliceExpr: case *ast.SliceExpr:
// TODO(gri): should treat[] like parentheses and undo one level of depth // TODO(gri): should treat[] like parentheses and undo one level of depth
p.expr1(x.X, token.HighestPrec, 1, multiLine) p.expr1(x.X, token.HighestPrec, 1)
p.print(x.Lbrack, token.LBRACK) p.print(x.Lbrack, token.LBRACK)
if x.Low != nil { if x.Low != nil {
p.expr0(x.Low, depth+1, multiLine) p.expr0(x.Low, depth+1)
} }
// blanks around ":" if both sides exist and either side is a binary expression // blanks around ":" if both sides exist and either side is a binary expression
if depth <= 1 && x.Low != nil && x.High != nil && (isBinary(x.Low) || isBinary(x.High)) { if depth <= 1 && x.Low != nil && x.High != nil && (isBinary(x.Low) || isBinary(x.High)) {
...@@ -794,7 +787,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -794,7 +787,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
p.print(token.COLON) p.print(token.COLON)
} }
if x.High != nil { if x.High != nil {
p.expr0(x.High, depth+1, multiLine) p.expr0(x.High, depth+1)
} }
p.print(x.Rbrack, token.RBRACK) p.print(x.Rbrack, token.RBRACK)
...@@ -802,26 +795,26 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -802,26 +795,26 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
if len(x.Args) > 1 { if len(x.Args) > 1 {
depth++ depth++
} }
p.expr1(x.Fun, token.HighestPrec, depth, multiLine) p.expr1(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() {
p.exprList(x.Lparen, x.Args, depth, commaSep, multiLine, x.Ellipsis) p.exprList(x.Lparen, x.Args, depth, commaSep, x.Ellipsis)
p.print(x.Ellipsis, token.ELLIPSIS) p.print(x.Ellipsis, token.ELLIPSIS)
if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) { if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) {
p.print(token.COMMA, formfeed) p.print(token.COMMA, formfeed)
} }
} else { } else {
p.exprList(x.Lparen, x.Args, depth, commaSep|commaTerm, multiLine, x.Rparen) p.exprList(x.Lparen, x.Args, depth, commaSep|commaTerm, x.Rparen)
} }
p.print(x.Rparen, token.RPAREN) p.print(x.Rparen, token.RPAREN)
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
if x.Type != nil { if x.Type != nil {
p.expr1(x.Type, token.HighestPrec, depth, multiLine) p.expr1(x.Type, token.HighestPrec, depth)
} }
p.print(x.Lbrace, token.LBRACE) p.print(x.Lbrace, token.LBRACE)
p.exprList(x.Lbrace, x.Elts, 1, commaSep|commaTerm, multiLine, x.Rbrace) p.exprList(x.Lbrace, x.Elts, 1, commaSep|commaTerm, x.Rbrace)
// do not insert extra line breaks because of comments before // do not insert extra line breaks because of comments before
// the closing '}' as it might break the code if there is no // the closing '}' as it might break the code if there is no
// trailing ',' // trailing ','
...@@ -830,16 +823,16 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -830,16 +823,16 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
case *ast.Ellipsis: case *ast.Ellipsis:
p.print(token.ELLIPSIS) p.print(token.ELLIPSIS)
if x.Elt != nil { if x.Elt != nil {
p.expr(x.Elt, multiLine) p.expr(x.Elt)
} }
case *ast.ArrayType: case *ast.ArrayType:
p.print(token.LBRACK) p.print(token.LBRACK)
if x.Len != nil { if x.Len != nil {
p.expr(x.Len, multiLine) p.expr(x.Len)
} }
p.print(token.RBRACK) p.print(token.RBRACK)
p.expr(x.Elt, multiLine) p.expr(x.Elt)
case *ast.StructType: case *ast.StructType:
p.print(token.STRUCT) p.print(token.STRUCT)
...@@ -847,7 +840,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -847,7 +840,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
case *ast.FuncType: case *ast.FuncType:
p.print(token.FUNC) p.print(token.FUNC)
p.signature(x.Params, x.Results, multiLine) p.signature(x.Params, x.Results)
case *ast.InterfaceType: case *ast.InterfaceType:
p.print(token.INTERFACE) p.print(token.INTERFACE)
...@@ -855,9 +848,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -855,9 +848,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
case *ast.MapType: case *ast.MapType:
p.print(token.MAP, token.LBRACK) p.print(token.MAP, token.LBRACK)
p.expr(x.Key, multiLine) p.expr(x.Key)
p.print(token.RBRACK) p.print(token.RBRACK)
p.expr(x.Value, multiLine) p.expr(x.Value)
case *ast.ChanType: case *ast.ChanType:
switch x.Dir { switch x.Dir {
...@@ -869,7 +862,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -869,7 +862,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
p.print(token.CHAN, token.ARROW) p.print(token.CHAN, token.ARROW)
} }
p.print(blank) p.print(blank)
p.expr(x.Value, multiLine) p.expr(x.Value)
default: default:
panic("unreachable") panic("unreachable")
...@@ -878,14 +871,13 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { ...@@ -878,14 +871,13 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) {
return return
} }
func (p *printer) expr0(x ast.Expr, depth int, multiLine *bool) { func (p *printer) expr0(x ast.Expr, depth int) {
p.expr1(x, token.LowestPrec, depth, multiLine) p.expr1(x, token.LowestPrec, depth)
} }
// Sets multiLine to true if the expression spans multiple lines. func (p *printer) expr(x ast.Expr) {
func (p *printer) expr(x ast.Expr, multiLine *bool) {
const depth = 1 const depth = 1
p.expr1(x, token.LowestPrec, depth, multiLine) p.expr1(x, token.LowestPrec, depth)
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -899,13 +891,13 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) { ...@@ -899,13 +891,13 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
if _indent > 0 { if _indent > 0 {
p.print(indent) p.print(indent)
} }
var multiLine bool multiLine := false
for i, s := range list { for i, s := range list {
// _indent == 0 only for lists of switch/select case clauses; // _indent == 0 only for lists of switch/select case clauses;
// in those cases each clause is a new section // in those cases each clause is a new section
p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || _indent == 0 || multiLine) p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || _indent == 0 || multiLine)
multiLine = false p.stmt(s, nextIsRBrace && i == len(list)-1)
p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine) multiLine = p.isMultiLine(s)
} }
if _indent > 0 { if _indent > 0 {
p.print(unindent) p.print(unindent)
...@@ -962,25 +954,25 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po ...@@ -962,25 +954,25 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
if init == nil && post == nil { if init == nil && post == nil {
// no semicolons required // no semicolons required
if expr != nil { if expr != nil {
p.expr(stripParens(expr), ignoreMultiLine) p.expr(stripParens(expr))
needsBlank = true needsBlank = true
} }
} else { } else {
// all semicolons required // all semicolons required
// (they are not separators, print them explicitly) // (they are not separators, print them explicitly)
if init != nil { if init != nil {
p.stmt(init, false, ignoreMultiLine) p.stmt(init, false)
} }
p.print(token.SEMICOLON, blank) p.print(token.SEMICOLON, blank)
if expr != nil { if expr != nil {
p.expr(stripParens(expr), ignoreMultiLine) p.expr(stripParens(expr))
needsBlank = true needsBlank = true
} }
if isForStmt { if isForStmt {
p.print(token.SEMICOLON, blank) p.print(token.SEMICOLON, blank)
needsBlank = false needsBlank = false
if post != nil { if post != nil {
p.stmt(post, false, ignoreMultiLine) p.stmt(post, false)
needsBlank = true needsBlank = true
} }
} }
...@@ -990,8 +982,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po ...@@ -990,8 +982,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
} }
} }
// Sets multiLine to true if the statements spans multiple lines. func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
p.print(stmt.Pos()) p.print(stmt.Pos())
switch s := stmt.(type) { switch s := stmt.(type) {
...@@ -999,7 +990,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -999,7 +990,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
p.print("BadStmt") p.print("BadStmt")
case *ast.DeclStmt: case *ast.DeclStmt:
p.decl(s.Decl, multiLine) p.decl(s.Decl)
case *ast.EmptyStmt: case *ast.EmptyStmt:
// nothing to do // nothing to do
...@@ -1009,7 +1000,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1009,7 +1000,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
// is applied before the line break if there is no comment // is applied before the line break if there is no comment
// between (see writeWhitespace) // between (see writeWhitespace)
p.print(unindent) p.print(unindent)
p.expr(s.Label, multiLine) p.expr(s.Label)
p.print(s.Colon, token.COLON, indent) p.print(s.Colon, token.COLON, indent)
if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty { if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty {
if !nextIsRBrace { if !nextIsRBrace {
...@@ -1019,21 +1010,21 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1019,21 +1010,21 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
} else { } else {
p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true) p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true)
} }
p.stmt(s.Stmt, nextIsRBrace, multiLine) p.stmt(s.Stmt, nextIsRBrace)
case *ast.ExprStmt: case *ast.ExprStmt:
const depth = 1 const depth = 1
p.expr0(s.X, depth, multiLine) p.expr0(s.X, depth)
case *ast.SendStmt: case *ast.SendStmt:
const depth = 1 const depth = 1
p.expr0(s.Chan, depth, multiLine) p.expr0(s.Chan, depth)
p.print(blank, s.Arrow, token.ARROW, blank) p.print(blank, s.Arrow, token.ARROW, blank)
p.expr0(s.Value, depth, multiLine) p.expr0(s.Value, depth)
case *ast.IncDecStmt: case *ast.IncDecStmt:
const depth = 1 const depth = 1
p.expr0(s.X, depth+1, multiLine) p.expr0(s.X, depth+1)
p.print(s.TokPos, s.Tok) p.print(s.TokPos, s.Tok)
case *ast.AssignStmt: case *ast.AssignStmt:
...@@ -1041,48 +1032,46 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1041,48 +1032,46 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
if len(s.Lhs) > 1 && len(s.Rhs) > 1 { if len(s.Lhs) > 1 && len(s.Rhs) > 1 {
depth++ depth++
} }
p.exprList(s.Pos(), s.Lhs, depth, commaSep, multiLine, s.TokPos) p.exprList(s.Pos(), s.Lhs, depth, commaSep, s.TokPos)
p.print(blank, s.TokPos, s.Tok) p.print(blank, s.TokPos, s.Tok)
p.exprList(s.TokPos, s.Rhs, depth, blankStart|commaSep, multiLine, token.NoPos) p.exprList(s.TokPos, s.Rhs, depth, blankStart|commaSep, token.NoPos)
case *ast.GoStmt: case *ast.GoStmt:
p.print(token.GO, blank) p.print(token.GO, blank)
p.expr(s.Call, multiLine) p.expr(s.Call)
case *ast.DeferStmt: case *ast.DeferStmt:
p.print(token.DEFER, blank) p.print(token.DEFER, blank)
p.expr(s.Call, multiLine) p.expr(s.Call)
case *ast.ReturnStmt: case *ast.ReturnStmt:
p.print(token.RETURN) p.print(token.RETURN)
if s.Results != nil { if s.Results != nil {
p.exprList(s.Pos(), s.Results, 1, blankStart|commaSep, multiLine, token.NoPos) p.exprList(s.Pos(), s.Results, 1, blankStart|commaSep, token.NoPos)
} }
case *ast.BranchStmt: case *ast.BranchStmt:
p.print(s.Tok) p.print(s.Tok)
if s.Label != nil { if s.Label != nil {
p.print(blank) p.print(blank)
p.expr(s.Label, multiLine) p.expr(s.Label)
} }
case *ast.BlockStmt: case *ast.BlockStmt:
p.block(s, 1) p.block(s, 1)
*multiLine = true
case *ast.IfStmt: case *ast.IfStmt:
p.print(token.IF) p.print(token.IF)
p.controlClause(false, s.Init, s.Cond, nil) p.controlClause(false, s.Init, s.Cond, nil)
p.block(s.Body, 1) p.block(s.Body, 1)
*multiLine = true
if s.Else != nil { if s.Else != nil {
p.print(blank, token.ELSE, blank) p.print(blank, token.ELSE, blank)
switch s.Else.(type) { switch s.Else.(type) {
case *ast.BlockStmt, *ast.IfStmt: case *ast.BlockStmt, *ast.IfStmt:
p.stmt(s.Else, nextIsRBrace, ignoreMultiLine) p.stmt(s.Else, nextIsRBrace)
default: default:
p.print(token.LBRACE, indent, formfeed) p.print(token.LBRACE, indent, formfeed)
p.stmt(s.Else, true, ignoreMultiLine) p.stmt(s.Else, true)
p.print(unindent, formfeed, token.RBRACE) p.print(unindent, formfeed, token.RBRACE)
} }
} }
...@@ -1090,7 +1079,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1090,7 +1079,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
case *ast.CaseClause: case *ast.CaseClause:
if s.List != nil { if s.List != nil {
p.print(token.CASE) p.print(token.CASE)
p.exprList(s.Pos(), s.List, 1, blankStart|commaSep, multiLine, s.Colon) p.exprList(s.Pos(), s.List, 1, blankStart|commaSep, s.Colon)
} else { } else {
p.print(token.DEFAULT) p.print(token.DEFAULT)
} }
...@@ -1101,25 +1090,23 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1101,25 +1090,23 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
p.print(token.SWITCH) p.print(token.SWITCH)
p.controlClause(false, s.Init, s.Tag, nil) p.controlClause(false, s.Init, s.Tag, nil)
p.block(s.Body, 0) p.block(s.Body, 0)
*multiLine = true
case *ast.TypeSwitchStmt: case *ast.TypeSwitchStmt:
p.print(token.SWITCH) p.print(token.SWITCH)
if s.Init != nil { if s.Init != nil {
p.print(blank) p.print(blank)
p.stmt(s.Init, false, ignoreMultiLine) p.stmt(s.Init, false)
p.print(token.SEMICOLON) p.print(token.SEMICOLON)
} }
p.print(blank) p.print(blank)
p.stmt(s.Assign, false, ignoreMultiLine) p.stmt(s.Assign, false)
p.print(blank) p.print(blank)
p.block(s.Body, 0) p.block(s.Body, 0)
*multiLine = true
case *ast.CommClause: case *ast.CommClause:
if s.Comm != nil { if s.Comm != nil {
p.print(token.CASE, blank) p.print(token.CASE, blank)
p.stmt(s.Comm, false, ignoreMultiLine) p.stmt(s.Comm, false)
} else { } else {
p.print(token.DEFAULT) p.print(token.DEFAULT)
} }
...@@ -1134,29 +1121,26 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1134,29 +1121,26 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
p.print(body.Lbrace, token.LBRACE, body.Rbrace, token.RBRACE) p.print(body.Lbrace, token.LBRACE, body.Rbrace, token.RBRACE)
} else { } else {
p.block(body, 0) p.block(body, 0)
*multiLine = true
} }
case *ast.ForStmt: case *ast.ForStmt:
p.print(token.FOR) p.print(token.FOR)
p.controlClause(true, s.Init, s.Cond, s.Post) p.controlClause(true, s.Init, s.Cond, s.Post)
p.block(s.Body, 1) p.block(s.Body, 1)
*multiLine = true
case *ast.RangeStmt: case *ast.RangeStmt:
p.print(token.FOR, blank) p.print(token.FOR, blank)
p.expr(s.Key, multiLine) p.expr(s.Key)
if s.Value != nil { if s.Value != nil {
// use position of value following the comma as // use position of value following the comma as
// comma position for correct comment placement // comma position for correct comment placement
p.print(s.Value.Pos(), token.COMMA, blank) p.print(s.Value.Pos(), token.COMMA, blank)
p.expr(s.Value, multiLine) p.expr(s.Value)
} }
p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank) p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank)
p.expr(stripParens(s.X), multiLine) p.expr(stripParens(s.X))
p.print(blank) p.print(blank)
p.block(s.Body, 1) p.block(s.Body, 1)
*multiLine = true
default: default:
panic("unreachable") panic("unreachable")
...@@ -1233,20 +1217,20 @@ func keepTypeColumn(specs []ast.Spec) []bool { ...@@ -1233,20 +1217,20 @@ func keepTypeColumn(specs []ast.Spec) []bool {
return m return m
} }
func (p *printer) valueSpec(s *ast.ValueSpec, keepType, doIndent bool, multiLine *bool) { func (p *printer) valueSpec(s *ast.ValueSpec, keepType, doIndent bool) {
p.setComment(s.Doc) p.setComment(s.Doc)
p.identList(s.Names, doIndent, multiLine) // always present p.identList(s.Names, doIndent) // always present
extraTabs := 3 extraTabs := 3
if s.Type != nil || keepType { if s.Type != nil || keepType {
p.print(vtab) p.print(vtab)
extraTabs-- extraTabs--
} }
if s.Type != nil { if s.Type != nil {
p.expr(s.Type, multiLine) p.expr(s.Type)
} }
if s.Values != nil { if s.Values != nil {
p.print(vtab, token.ASSIGN) p.print(vtab, token.ASSIGN)
p.exprList(token.NoPos, s.Values, 1, blankStart|commaSep, multiLine, token.NoPos) p.exprList(token.NoPos, s.Values, 1, blankStart|commaSep, token.NoPos)
extraTabs-- extraTabs--
} }
if s.Comment != nil { if s.Comment != nil {
...@@ -1260,17 +1244,16 @@ func (p *printer) valueSpec(s *ast.ValueSpec, keepType, doIndent bool, multiLine ...@@ -1260,17 +1244,16 @@ func (p *printer) valueSpec(s *ast.ValueSpec, keepType, doIndent bool, multiLine
// The parameter n is the number of specs in the group. If doIndent is set, // The parameter n is the number of specs in the group. If doIndent is set,
// multi-line identifier lists in the spec are indented when the first // multi-line identifier lists in the spec are indented when the first
// linebreak is encountered. // linebreak is encountered.
// Sets multiLine to true if the spec spans multiple lines.
// //
func (p *printer) spec(spec ast.Spec, n int, doIndent bool, multiLine *bool) { func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
switch s := spec.(type) { switch s := spec.(type) {
case *ast.ImportSpec: case *ast.ImportSpec:
p.setComment(s.Doc) p.setComment(s.Doc)
if s.Name != nil { if s.Name != nil {
p.expr(s.Name, multiLine) p.expr(s.Name)
p.print(blank) p.print(blank)
} }
p.expr(s.Path, multiLine) p.expr(s.Path)
p.setComment(s.Comment) p.setComment(s.Comment)
p.print(s.EndPos) p.print(s.EndPos)
...@@ -1279,26 +1262,26 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool, multiLine *bool) { ...@@ -1279,26 +1262,26 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool, multiLine *bool) {
p.internalError("expected n = 1; got", n) p.internalError("expected n = 1; got", n)
} }
p.setComment(s.Doc) p.setComment(s.Doc)
p.identList(s.Names, doIndent, multiLine) // always present p.identList(s.Names, doIndent) // always present
if s.Type != nil { if s.Type != nil {
p.print(blank) p.print(blank)
p.expr(s.Type, multiLine) p.expr(s.Type)
} }
if s.Values != nil { if s.Values != nil {
p.print(blank, token.ASSIGN) p.print(blank, token.ASSIGN)
p.exprList(token.NoPos, s.Values, 1, blankStart|commaSep, multiLine, token.NoPos) p.exprList(token.NoPos, s.Values, 1, blankStart|commaSep, token.NoPos)
} }
p.setComment(s.Comment) p.setComment(s.Comment)
case *ast.TypeSpec: case *ast.TypeSpec:
p.setComment(s.Doc) p.setComment(s.Doc)
p.expr(s.Name, multiLine) p.expr(s.Name)
if n == 1 { if n == 1 {
p.print(blank) p.print(blank)
} else { } else {
p.print(vtab) p.print(vtab)
} }
p.expr(s.Type, multiLine) p.expr(s.Type)
p.setComment(s.Comment) p.setComment(s.Comment)
default: default:
...@@ -1306,8 +1289,7 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool, multiLine *bool) { ...@@ -1306,8 +1289,7 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool, multiLine *bool) {
} }
} }
// Sets multiLine to true if the declaration spans multiple lines. func (p *printer) genDecl(d *ast.GenDecl) {
func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
p.setComment(d.Doc) p.setComment(d.Doc)
p.print(d.Pos(), d.Tok, blank) p.print(d.Pos(), d.Tok, blank)
...@@ -1320,32 +1302,31 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) { ...@@ -1320,32 +1302,31 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
// two or more grouped const/var declarations: // two or more grouped const/var declarations:
// determine if the type column must be kept // determine if the type column must be kept
keepType := keepTypeColumn(d.Specs) keepType := keepTypeColumn(d.Specs)
var ml bool newSection := false
for i, s := range d.Specs { for i, s := range d.Specs {
if i > 0 { if i > 0 {
p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml) p.linebreak(p.lineFor(s.Pos()), 1, ignore, newSection)
} }
ml = false p.valueSpec(s.(*ast.ValueSpec), keepType[i], false)
p.valueSpec(s.(*ast.ValueSpec), keepType[i], false, &ml) newSection = p.isMultiLine(s)
} }
} else { } else {
var ml bool newSection := false
for i, s := range d.Specs { for i, s := range d.Specs {
if i > 0 { if i > 0 {
p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml) p.linebreak(p.lineFor(s.Pos()), 1, ignore, newSection)
} }
ml = false p.spec(s, n, false)
p.spec(s, n, false, &ml) newSection = p.isMultiLine(s)
} }
} }
p.print(unindent, formfeed) p.print(unindent, formfeed)
*multiLine = true
} }
p.print(d.Rparen, token.RPAREN) p.print(d.Rparen, token.RPAREN)
} else { } else {
// single declaration // single declaration
p.spec(d.Specs[0], 1, true, multiLine) p.spec(d.Specs[0], 1, true)
} }
} }
...@@ -1409,8 +1390,7 @@ func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool { ...@@ -1409,8 +1390,7 @@ func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
return headerSize+bodySize <= maxSize return headerSize+bodySize <= maxSize
} }
// Sets multiLine to true if the function body spans multiple lines. func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool) {
func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLine *bool) {
if b == nil { if b == nil {
return return
} }
...@@ -1427,7 +1407,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi ...@@ -1427,7 +1407,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
if i > 0 { if i > 0 {
p.print(token.SEMICOLON, blank) p.print(token.SEMICOLON, blank)
} }
p.stmt(s, i == len(b.List)-1, ignoreMultiLine) p.stmt(s, i == len(b.List)-1)
} }
p.print(blank) p.print(blank)
} }
...@@ -1437,7 +1417,6 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi ...@@ -1437,7 +1417,6 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
p.print(blank) p.print(blank)
p.block(b, 1) p.block(b, 1)
*multiLine = true
} }
// distance returns the column difference between from and to if both // distance returns the column difference between from and to if both
...@@ -1451,28 +1430,26 @@ func (p *printer) distance(from0 token.Pos, to token.Position) int { ...@@ -1451,28 +1430,26 @@ func (p *printer) distance(from0 token.Pos, to token.Position) int {
return infinity return infinity
} }
// Sets multiLine to true if the declaration spans multiple lines. func (p *printer) funcDecl(d *ast.FuncDecl) {
func (p *printer) funcDecl(d *ast.FuncDecl, multiLine *bool) {
p.setComment(d.Doc) p.setComment(d.Doc)
p.print(d.Pos(), token.FUNC, blank) p.print(d.Pos(), token.FUNC, blank)
if d.Recv != nil { if d.Recv != nil {
p.parameters(d.Recv, multiLine) // method: print receiver p.parameters(d.Recv) // method: print receiver
p.print(blank) p.print(blank)
} }
p.expr(d.Name, multiLine) p.expr(d.Name)
p.signature(d.Type.Params, d.Type.Results, multiLine) p.signature(d.Type.Params, d.Type.Results)
p.funcBody(d.Body, p.distance(d.Pos(), p.pos), false, multiLine) p.funcBody(d.Body, p.distance(d.Pos(), p.pos), false)
} }
// Sets multiLine to true if the declaration spans multiple lines. func (p *printer) decl(decl ast.Decl) {
func (p *printer) decl(decl ast.Decl, multiLine *bool) {
switch d := decl.(type) { switch d := decl.(type) {
case *ast.BadDecl: case *ast.BadDecl:
p.print(d.Pos(), "BadDecl") p.print(d.Pos(), "BadDecl")
case *ast.GenDecl: case *ast.GenDecl:
p.genDecl(d, multiLine) p.genDecl(d)
case *ast.FuncDecl: case *ast.FuncDecl:
p.funcDecl(d, multiLine) p.funcDecl(d)
default: default:
panic("unreachable") panic("unreachable")
} }
...@@ -1495,7 +1472,7 @@ func declToken(decl ast.Decl) (tok token.Token) { ...@@ -1495,7 +1472,7 @@ func declToken(decl ast.Decl) (tok token.Token) {
func (p *printer) file(src *ast.File) { func (p *printer) file(src *ast.File) {
p.setComment(src.Doc) p.setComment(src.Doc)
p.print(src.Pos(), token.PACKAGE, blank) p.print(src.Pos(), token.PACKAGE, blank)
p.expr(src.Name, ignoreMultiLine) p.expr(src.Name)
if len(src.Decls) > 0 { if len(src.Decls) > 0 {
tok := token.ILLEGAL tok := token.ILLEGAL
...@@ -1514,7 +1491,7 @@ func (p *printer) file(src *ast.File) { ...@@ -1514,7 +1491,7 @@ func (p *printer) file(src *ast.File) {
min = 2 min = 2
} }
p.linebreak(p.lineFor(d.Pos()), min, ignore, false) p.linebreak(p.lineFor(d.Pos()), min, ignore, false)
p.decl(d, ignoreMultiLine) p.decl(d)
} }
} }
......
...@@ -34,9 +34,6 @@ const ( ...@@ -34,9 +34,6 @@ const (
unindent = whiteSpace('<') unindent = whiteSpace('<')
) )
// Use ignoreMultiLine if the multiLine information is not important.
var ignoreMultiLine = new(bool)
// A pmode value represents the current printer mode. // A pmode value represents the current printer mode.
type pmode int type pmode int
...@@ -1011,18 +1008,18 @@ func (p *printer) printNode(node interface{}) error { ...@@ -1011,18 +1008,18 @@ func (p *printer) printNode(node interface{}) error {
// format node // format node
switch n := node.(type) { switch n := node.(type) {
case ast.Expr: case ast.Expr:
p.expr(n, ignoreMultiLine) p.expr(n)
case ast.Stmt: case ast.Stmt:
// A labeled statement will un-indent to position the // A labeled statement will un-indent to position the
// label. Set indent to 1 so we don't get indent "underflow". // label. Set indent to 1 so we don't get indent "underflow".
if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt { if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
p.indent = 1 p.indent = 1
} }
p.stmt(n, false, ignoreMultiLine) p.stmt(n, false)
case ast.Decl: case ast.Decl:
p.decl(n, ignoreMultiLine) p.decl(n)
case ast.Spec: case ast.Spec:
p.spec(n, 1, false, ignoreMultiLine) p.spec(n, 1, false)
case *ast.File: case *ast.File:
p.file(n) p.file(n)
default: default:
......
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