From: Robert Griesemer Date: Wed, 29 Feb 2012 16:38:31 +0000 (-0800) Subject: go/printer: replace multiline logic X-Git-Tag: weekly.2012-03-04~93 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b1b0ed1e60af93bc83298da80d0293a2b23fcb5e;p=gostls13.git 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 --- diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index 7249658956..1f212a0bcd 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -69,7 +69,7 @@ var ( // search index indexEnabled = flag.Bool("index", false, "enable search index") indexFiles = flag.String("index_files", "", "glob pattern specifying index files;"+ - "if not empty, the index is read from these files in sorted order") + "if not empty, the index is read from these files in sorted order") maxResults = flag.Int("maxresults", 10000, "maximum number of full text search results shown") indexThrottle = flag.Float64("index_throttle", 0.75, "index throttle value; 0.0 = no time allocated, 1.0 = full throttle") diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go index 2205f633f1..16fc9de1ee 100644 --- a/src/pkg/go/printer/nodes.go +++ b/src/pkg/go/printer/nodes.go @@ -89,10 +89,9 @@ const ( 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 // 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 xlist := make([]ast.Expr, len(list)) for i, x := range list { @@ -102,18 +101,17 @@ func (p *printer) identList(list []*ast.Ident, indent bool, multiLine *bool) { if !indent { 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 // source lines, the original line breaks are respected between -// expressions. Sets multiLine to true if the list spans multiple -// lines. +// expressions. // // TODO(gri) Consider rewriting this to be independent of []ast.Expr // so that we can use the algorithm for any kind of list // (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 { return } @@ -138,7 +136,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp } p.print(blank) } - p.expr0(x, depth, multiLine) + p.expr0(x, depth) } if mode&blankEnd != 0 { p.print(blank) @@ -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 if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) { ws = ignore - *multiLine = true prevBreak = 0 } @@ -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 if p.linebreak(line, 0, ws, useFF || prevBreak+1 < i) { ws = ignore - *multiLine = true prevBreak = i 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 // 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 // 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.expr(pair.Value, multiLine) + p.expr(pair.Value) } 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 } } -// Sets multiLine to true if the the parameter list spans multiple lines. -func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { +func (p *printer) parameters(fields *ast.FieldList) { p.print(fields.Opening, token.LPAREN) if len(fields.List) > 0 { prevLine := p.lineFor(fields.Opening) @@ -306,7 +301,6 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) { // break line if the opening "(" or previous parameter ended on a different line ws = ignore - *multiLine = true } else if i > 0 { p.print(blank) } @@ -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 // by a linebreak call after a type, or in the next multi-line identList // will do the right thing. - p.identList(par.Names, ws == indent, multiLine) + p.identList(par.Names, ws == indent) p.print(blank) } // parameter type - p.expr(par.Type, multiLine) + p.expr(par.Type) prevLine = parLineEnd } // 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) { p.print(fields.Closing, token.RPAREN) } -// Sets multiLine to true if the signature spans multiple lines. -func (p *printer) signature(params, result *ast.FieldList, multiLine *bool) { - p.parameters(params, multiLine) +func (p *printer) signature(params, result *ast.FieldList) { + p.parameters(params) n := result.NumFields() if n > 0 { p.print(blank) if n == 1 && result.List[0].Names == nil { // single anonymous result; no ()'s - p.expr(result.List[0].Type, multiLine) + p.expr(result.List[0].Type) return } - p.parameters(result, multiLine) + p.parameters(result) } } @@ -389,6 +382,10 @@ func (p *printer) setLineComment(text string) { 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) { lbrace := fields.Opening list := fields.List @@ -412,12 +409,12 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) // no comments so no need for comma position p.print(token.COMMA, blank) } - p.expr(x, ignoreMultiLine) + p.expr(x) } if len(f.Names) > 0 { p.print(blank) } - p.expr(f.Type, ignoreMultiLine) + p.expr(f.Type) p.print(blank, rbrace, token.RBRACE) return } @@ -435,23 +432,22 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) if len(list) == 1 { sep = blank } - var ml bool + newSection := false for i, f := range list { 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 p.setComment(f.Doc) if len(f.Names) > 0 { // named fields - p.identList(f.Names, false, &ml) + p.identList(f.Names, false) p.print(sep) - p.expr(f.Type, &ml) + p.expr(f.Type) extraTabs = 1 } else { // anonymous field - p.expr(f.Type, &ml) + p.expr(f.Type) extraTabs = 2 } if f.Tag != nil { @@ -459,7 +455,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) p.print(sep) } p.print(sep) - p.expr(f.Tag, &ml) + p.expr(f.Tag) extraTabs = 0 } if f.Comment != nil { @@ -468,6 +464,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) } p.setComment(f.Comment) } + newSection = p.isMultiLine(f) } if isIncomplete { if len(list) > 0 { @@ -479,22 +476,22 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) } else { // interface - var ml bool + newSection := false for i, f := range list { 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) if ftyp, isFtyp := f.Type.(*ast.FuncType); isFtyp { // method - p.expr(f.Names[0], &ml) - p.signature(ftyp.Params, ftyp.Results, &ml) + p.expr(f.Names[0]) + p.signature(ftyp.Params, ftyp.Results) } else { // embedded interface - p.expr(f.Type, &ml) + p.expr(f.Type) } p.setComment(f.Comment) + newSection = p.isMultiLine(f) } if isIncomplete { if len(list) > 0 { @@ -635,15 +632,14 @@ func reduceDepth(depth int) int { // cutoff is 6 (always use spaces) in Normal 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, multiLine *bool) { +func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) { prec := x.Op.Precedence() if prec < prec1 { // parenthesis needed // Note: The parser inserts an ast.ParenExpr node; thus this case // can only occur if the AST is created in a different way. 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) return } @@ -651,7 +647,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL printBlank := prec < cutoff 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 { p.print(blank) } @@ -663,14 +659,13 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL // in the source if p.linebreak(yline, 1, ws, true) { ws = ignore - *multiLine = true printBlank = false // no blank after line break } } if printBlank { p.print(blank) } - p.expr1(x.Y, prec+1, depth+1, multiLine) + p.expr1(x.Y, prec+1, depth+1) if ws == ignore { p.print(unindent) } @@ -681,8 +676,7 @@ func isBinary(expr ast.Expr) bool { return ok } -// Sets multiLine to true if the expression spans multiple lines. -func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { +func (p *printer) expr1(expr ast.Expr, prec1, depth int) { p.print(expr.Pos()) switch x := expr.(type) { @@ -697,12 +691,12 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { p.internalError("depth < 1:", depth) depth = 1 } - p.binaryExpr(x, prec1, cutoff(x, depth), depth, multiLine) + p.binaryExpr(x, prec1, cutoff(x, depth), depth) case *ast.KeyValueExpr: - p.expr(x.Key, multiLine) + p.expr(x.Key) p.print(x.Colon, token.COLON, blank) - p.expr(x.Value, multiLine) + p.expr(x.Value) case *ast.StarExpr: const prec = token.UnaryPrec @@ -710,12 +704,12 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { // parenthesis needed p.print(token.LPAREN) p.print(token.MUL) - p.expr(x.X, multiLine) + p.expr(x.X) p.print(token.RPAREN) } else { // no parenthesis needed p.print(token.MUL) - p.expr(x.X, multiLine) + p.expr(x.X) } case *ast.UnaryExpr: @@ -723,7 +717,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { if prec < prec1 { // parenthesis needed p.print(token.LPAREN) - p.expr(x, multiLine) + p.expr(x) p.print(token.RPAREN) } else { // no parenthesis needed @@ -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. p.print(blank) } - p.expr1(x.X, prec, depth, multiLine) + p.expr1(x.X, prec, depth) } case *ast.BasicLit: p.print(x) case *ast.FuncLit: - p.expr(x.Type, multiLine) - p.funcBody(x.Body, p.distance(x.Type.Pos(), p.pos), true, multiLine) + p.expr(x.Type) + p.funcBody(x.Body, p.distance(x.Type.Pos(), p.pos), true) case *ast.ParenExpr: 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 + p.expr0(x.X, reduceDepth(depth)) // 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.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth p.print(x.Rparen, token.RPAREN) } case *ast.SelectorExpr: - p.expr1(x.X, token.HighestPrec, depth, multiLine) + 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, unindent) - *multiLine = true } else { p.print(x.Sel.Pos(), x.Sel) } case *ast.TypeAssertExpr: - p.expr1(x.X, token.HighestPrec, depth, multiLine) + p.expr1(x.X, token.HighestPrec, depth) p.print(token.PERIOD, token.LPAREN) if x.Type != nil { - p.expr(x.Type, multiLine) + p.expr(x.Type) } else { p.print(token.TYPE) } @@ -775,17 +768,17 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { case *ast.IndexExpr: // 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.expr0(x.Index, depth+1, multiLine) + p.expr0(x.Index, depth+1) p.print(x.Rbrack, token.RBRACK) case *ast.SliceExpr: // 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) 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 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) { p.print(token.COLON) } if x.High != nil { - p.expr0(x.High, depth+1, multiLine) + p.expr0(x.High, depth+1) } p.print(x.Rbrack, token.RBRACK) @@ -802,26 +795,26 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { if len(x.Args) > 1 { depth++ } - p.expr1(x.Fun, token.HighestPrec, depth, multiLine) + p.expr1(x.Fun, token.HighestPrec, depth) p.print(x.Lparen, token.LPAREN) 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) if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) { p.print(token.COMMA, formfeed) } } 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) case *ast.CompositeLit: // composite literal elements that are composite literals themselves may have the type omitted 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.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 // the closing '}' as it might break the code if there is no // trailing ',' @@ -830,16 +823,16 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { case *ast.Ellipsis: p.print(token.ELLIPSIS) if x.Elt != nil { - p.expr(x.Elt, multiLine) + p.expr(x.Elt) } case *ast.ArrayType: p.print(token.LBRACK) if x.Len != nil { - p.expr(x.Len, multiLine) + p.expr(x.Len) } p.print(token.RBRACK) - p.expr(x.Elt, multiLine) + p.expr(x.Elt) case *ast.StructType: p.print(token.STRUCT) @@ -847,7 +840,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { case *ast.FuncType: p.print(token.FUNC) - p.signature(x.Params, x.Results, multiLine) + p.signature(x.Params, x.Results) case *ast.InterfaceType: p.print(token.INTERFACE) @@ -855,9 +848,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { case *ast.MapType: p.print(token.MAP, token.LBRACK) - p.expr(x.Key, multiLine) + p.expr(x.Key) p.print(token.RBRACK) - p.expr(x.Value, multiLine) + p.expr(x.Value) case *ast.ChanType: switch x.Dir { @@ -869,7 +862,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { p.print(token.CHAN, token.ARROW) } p.print(blank) - p.expr(x.Value, multiLine) + p.expr(x.Value) default: panic("unreachable") @@ -878,14 +871,13 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, multiLine *bool) { return } -func (p *printer) expr0(x ast.Expr, depth int, multiLine *bool) { - p.expr1(x, token.LowestPrec, depth, multiLine) +func (p *printer) expr0(x ast.Expr, depth int) { + p.expr1(x, token.LowestPrec, depth) } -// Sets multiLine to true if the expression spans multiple lines. -func (p *printer) expr(x ast.Expr, multiLine *bool) { +func (p *printer) expr(x ast.Expr) { 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) { if _indent > 0 { p.print(indent) } - var multiLine bool + multiLine := false for i, s := range list { // _indent == 0 only for lists of switch/select case clauses; // in those cases each clause is a new section p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || _indent == 0 || multiLine) - multiLine = false - p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine) + p.stmt(s, nextIsRBrace && i == len(list)-1) + multiLine = p.isMultiLine(s) } if _indent > 0 { p.print(unindent) @@ -962,25 +954,25 @@ 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), ignoreMultiLine) + p.expr(stripParens(expr)) needsBlank = true } } else { // all semicolons required // (they are not separators, print them explicitly) if init != nil { - p.stmt(init, false, ignoreMultiLine) + p.stmt(init, false) } p.print(token.SEMICOLON, blank) if expr != nil { - p.expr(stripParens(expr), ignoreMultiLine) + p.expr(stripParens(expr)) needsBlank = true } if isForStmt { p.print(token.SEMICOLON, blank) needsBlank = false if post != nil { - p.stmt(post, false, ignoreMultiLine) + p.stmt(post, false) needsBlank = true } } @@ -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, multiLine *bool) { +func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) { p.print(stmt.Pos()) switch s := stmt.(type) { @@ -999,7 +990,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { p.print("BadStmt") case *ast.DeclStmt: - p.decl(s.Decl, multiLine) + p.decl(s.Decl) case *ast.EmptyStmt: // nothing to do @@ -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 // between (see writeWhitespace) p.print(unindent) - p.expr(s.Label, multiLine) + p.expr(s.Label) p.print(s.Colon, token.COLON, indent) if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty { if !nextIsRBrace { @@ -1019,21 +1010,21 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { } else { p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true) } - p.stmt(s.Stmt, nextIsRBrace, multiLine) + p.stmt(s.Stmt, nextIsRBrace) case *ast.ExprStmt: const depth = 1 - p.expr0(s.X, depth, multiLine) + p.expr0(s.X, depth) case *ast.SendStmt: const depth = 1 - p.expr0(s.Chan, depth, multiLine) + p.expr0(s.Chan, depth) p.print(blank, s.Arrow, token.ARROW, blank) - p.expr0(s.Value, depth, multiLine) + p.expr0(s.Value, depth) case *ast.IncDecStmt: const depth = 1 - p.expr0(s.X, depth+1, multiLine) + p.expr0(s.X, depth+1) p.print(s.TokPos, s.Tok) case *ast.AssignStmt: @@ -1041,48 +1032,46 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { if len(s.Lhs) > 1 && len(s.Rhs) > 1 { 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.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: p.print(token.GO, blank) - p.expr(s.Call, multiLine) + p.expr(s.Call) case *ast.DeferStmt: p.print(token.DEFER, blank) - p.expr(s.Call, multiLine) + p.expr(s.Call) case *ast.ReturnStmt: p.print(token.RETURN) 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: p.print(s.Tok) if s.Label != nil { p.print(blank) - p.expr(s.Label, multiLine) + p.expr(s.Label) } case *ast.BlockStmt: p.block(s, 1) - *multiLine = true case *ast.IfStmt: p.print(token.IF) p.controlClause(false, s.Init, s.Cond, nil) p.block(s.Body, 1) - *multiLine = true if s.Else != nil { p.print(blank, token.ELSE, blank) switch s.Else.(type) { case *ast.BlockStmt, *ast.IfStmt: - p.stmt(s.Else, nextIsRBrace, ignoreMultiLine) + p.stmt(s.Else, nextIsRBrace) default: p.print(token.LBRACE, indent, formfeed) - p.stmt(s.Else, true, ignoreMultiLine) + p.stmt(s.Else, true) p.print(unindent, formfeed, token.RBRACE) } } @@ -1090,7 +1079,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { case *ast.CaseClause: if s.List != nil { 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 { p.print(token.DEFAULT) } @@ -1101,25 +1090,23 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { p.print(token.SWITCH) p.controlClause(false, s.Init, s.Tag, nil) p.block(s.Body, 0) - *multiLine = true case *ast.TypeSwitchStmt: p.print(token.SWITCH) if s.Init != nil { p.print(blank) - p.stmt(s.Init, false, ignoreMultiLine) + p.stmt(s.Init, false) p.print(token.SEMICOLON) } p.print(blank) - p.stmt(s.Assign, false, ignoreMultiLine) + p.stmt(s.Assign, false) p.print(blank) p.block(s.Body, 0) - *multiLine = true case *ast.CommClause: if s.Comm != nil { p.print(token.CASE, blank) - p.stmt(s.Comm, false, ignoreMultiLine) + p.stmt(s.Comm, false) } else { p.print(token.DEFAULT) } @@ -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) } else { p.block(body, 0) - *multiLine = true } case *ast.ForStmt: p.print(token.FOR) p.controlClause(true, s.Init, s.Cond, s.Post) p.block(s.Body, 1) - *multiLine = true case *ast.RangeStmt: p.print(token.FOR, blank) - p.expr(s.Key, multiLine) + p.expr(s.Key) if s.Value != nil { // use position of value following the comma as // comma position for correct comment placement 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.expr(stripParens(s.X), multiLine) + p.expr(stripParens(s.X)) p.print(blank) p.block(s.Body, 1) - *multiLine = true default: panic("unreachable") @@ -1233,20 +1217,20 @@ func keepTypeColumn(specs []ast.Spec) []bool { 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.identList(s.Names, doIndent, multiLine) // always present + p.identList(s.Names, doIndent) // always present extraTabs := 3 if s.Type != nil || keepType { p.print(vtab) extraTabs-- } if s.Type != nil { - p.expr(s.Type, multiLine) + p.expr(s.Type) } if s.Values != nil { 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-- } if s.Comment != nil { @@ -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, // multi-line identifier lists in the spec are indented when the first // 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) { case *ast.ImportSpec: p.setComment(s.Doc) if s.Name != nil { - p.expr(s.Name, multiLine) + p.expr(s.Name) p.print(blank) } - p.expr(s.Path, multiLine) + p.expr(s.Path) p.setComment(s.Comment) p.print(s.EndPos) @@ -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.setComment(s.Doc) - p.identList(s.Names, doIndent, multiLine) // always present + p.identList(s.Names, doIndent) // always present if s.Type != nil { p.print(blank) - p.expr(s.Type, multiLine) + p.expr(s.Type) } if s.Values != nil { 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) case *ast.TypeSpec: p.setComment(s.Doc) - p.expr(s.Name, multiLine) + p.expr(s.Name) if n == 1 { p.print(blank) } else { p.print(vtab) } - p.expr(s.Type, multiLine) + p.expr(s.Type) p.setComment(s.Comment) default: @@ -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, multiLine *bool) { +func (p *printer) genDecl(d *ast.GenDecl) { p.setComment(d.Doc) p.print(d.Pos(), d.Tok, blank) @@ -1320,32 +1302,31 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) { // two or more grouped const/var declarations: // determine if the type column must be kept keepType := keepTypeColumn(d.Specs) - var ml bool + newSection := false for i, s := range d.Specs { 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, &ml) + p.valueSpec(s.(*ast.ValueSpec), keepType[i], false) + newSection = p.isMultiLine(s) } } else { - var ml bool + newSection := false for i, s := range d.Specs { 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, &ml) + p.spec(s, n, false) + newSection = p.isMultiLine(s) } } p.print(unindent, formfeed) - *multiLine = true } p.print(d.Rparen, token.RPAREN) } else { // 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 { 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, multiLine *bool) { +func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool) { if b == nil { return } @@ -1427,7 +1407,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi if i > 0 { 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) } @@ -1437,7 +1417,6 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi p.print(blank) p.block(b, 1) - *multiLine = true } // 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 { return infinity } -// Sets multiLine to true if the declaration spans multiple lines. -func (p *printer) funcDecl(d *ast.FuncDecl, multiLine *bool) { +func (p *printer) funcDecl(d *ast.FuncDecl) { p.setComment(d.Doc) p.print(d.Pos(), token.FUNC, blank) if d.Recv != nil { - p.parameters(d.Recv, multiLine) // method: print receiver + p.parameters(d.Recv) // method: print receiver p.print(blank) } - p.expr(d.Name, multiLine) - p.signature(d.Type.Params, d.Type.Results, multiLine) - p.funcBody(d.Body, p.distance(d.Pos(), p.pos), false, multiLine) + p.expr(d.Name) + p.signature(d.Type.Params, d.Type.Results) + 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, multiLine *bool) { +func (p *printer) decl(decl ast.Decl) { switch d := decl.(type) { case *ast.BadDecl: p.print(d.Pos(), "BadDecl") case *ast.GenDecl: - p.genDecl(d, multiLine) + p.genDecl(d) case *ast.FuncDecl: - p.funcDecl(d, multiLine) + p.funcDecl(d) default: panic("unreachable") } @@ -1495,7 +1472,7 @@ func declToken(decl ast.Decl) (tok token.Token) { func (p *printer) file(src *ast.File) { p.setComment(src.Doc) p.print(src.Pos(), token.PACKAGE, blank) - p.expr(src.Name, ignoreMultiLine) + p.expr(src.Name) if len(src.Decls) > 0 { tok := token.ILLEGAL @@ -1514,7 +1491,7 @@ func (p *printer) file(src *ast.File) { min = 2 } p.linebreak(p.lineFor(d.Pos()), min, ignore, false) - p.decl(d, ignoreMultiLine) + p.decl(d) } } diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go index 72f65a1d85..1ab4456e83 100644 --- a/src/pkg/go/printer/printer.go +++ b/src/pkg/go/printer/printer.go @@ -34,9 +34,6 @@ const ( unindent = whiteSpace('<') ) -// Use ignoreMultiLine if the multiLine information is not important. -var ignoreMultiLine = new(bool) - // A pmode value represents the current printer mode. type pmode int @@ -1011,18 +1008,18 @@ func (p *printer) printNode(node interface{}) error { // format node switch n := node.(type) { case ast.Expr: - p.expr(n, ignoreMultiLine) + p.expr(n) case ast.Stmt: // A labeled statement will un-indent to position the // label. Set indent to 1 so we don't get indent "underflow". if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt { p.indent = 1 } - p.stmt(n, false, ignoreMultiLine) + p.stmt(n, false) case ast.Decl: - p.decl(n, ignoreMultiLine) + p.decl(n) case ast.Spec: - p.spec(n, 1, false, ignoreMultiLine) + p.spec(n, 1, false) case *ast.File: p.file(n) default: diff --git a/src/pkg/go/printer/testdata/declarations.golden b/src/pkg/go/printer/testdata/declarations.golden index a46463e56e..7ed7cb61ae 100644 --- a/src/pkg/go/printer/testdata/declarations.golden +++ b/src/pkg/go/printer/testdata/declarations.golden @@ -500,7 +500,7 @@ type _ struct { type _ struct { a, b, - c, d int // this line should be indented + c, d int // this line should be indented u, v, w, x float // this line should be indented p, q, r, s float // this line should be indented @@ -562,7 +562,7 @@ var a2, b2, var ( a3, b3, - c3, d3 int // this line should be indented + c3, d3 int // this line should be indented a4, b4, c4 int // this line should be indented )