diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-01 19:26:59 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-01 19:26:59 +0000 |
commit | 9af4cb9545ce481b8d9d4a13acfe26512032e21b (patch) | |
tree | 7e7e6083ebe59999943a211a17f8ef6f07f17c2f /libgo/go/go/printer | |
parent | 6b6cd722f329a168f98d1f421834cf40bb33a77d (diff) |
libgo: Update to weekly.2012-01-27.
From-SVN: r183810
Diffstat (limited to 'libgo/go/go/printer')
-rw-r--r-- | libgo/go/go/printer/nodes.go | 90 | ||||
-rw-r--r-- | libgo/go/go/printer/printer.go | 30 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/declarations.golden | 50 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/linebreaks.golden | 52 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/linebreaks.input | 48 |
5 files changed, 211 insertions, 59 deletions
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go index 6817cc42add..5f3b4d4a740 100644 --- a/libgo/go/go/printer/nodes.go +++ b/libgo/go/go/printer/nodes.go @@ -72,7 +72,7 @@ func (p *printer) setComment(g *ast.CommentGroup) { // for some reason there are pending comments; this // should never happen - handle gracefully and flush // all comments up to g, ignore anything after that - p.flush(p.fset.Position(g.List[0].Pos()), token.ILLEGAL) + p.flush(p.posFor(g.List[0].Pos()), token.ILLEGAL) } p.comments[0] = g p.cindex = 0 @@ -122,10 +122,10 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp p.print(blank) } - prev := p.fset.Position(prev0) - next := p.fset.Position(next0) - line := p.fset.Position(list[0].Pos()).Line - endLine := p.fset.Position(list[len(list)-1].End()).Line + prev := p.posFor(prev0) + next := p.posFor(next0) + line := p.lineFor(list[0].Pos()) + endLine := p.lineFor(list[len(list)-1].End()) if prev.IsValid() && prev.Line == line && line == endLine { // all list entries on a single line @@ -169,7 +169,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp // print all list elements for i, x := range list { prevLine := line - line = p.fset.Position(x.Pos()).Line + line = p.lineFor(x.Pos()) // determine if the next linebreak, if any, needs to use formfeed: // in general, use the entire node size to make the decision; for @@ -272,23 +272,32 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { p.print(fields.Opening, token.LPAREN) if len(fields.List) > 0 { + prevLine := p.lineFor(fields.Opening) ws := indent - var prevLine, line int for i, par := range fields.List { + // determine par begin and end line (may be different + // if there are multiple parameter names for this par + // or the type is on a separate line) + var parLineBeg int + var parLineEnd = p.lineFor(par.Type.Pos()) + if len(par.Names) > 0 { + parLineBeg = p.lineFor(par.Names[0].Pos()) + } else { + parLineBeg = parLineEnd + } + // separating "," if needed if i > 0 { p.print(token.COMMA) - if len(par.Names) > 0 { - line = p.fset.Position(par.Names[0].Pos()).Line - } else { - line = p.fset.Position(par.Type.Pos()).Line - } - if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ws, true) { - ws = ignore - *multiLine = true - } else { - p.print(blank) - } } + // separator if needed (linebreak or blank) + if 0 < prevLine && prevLine < parLineBeg && 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) + } + // parameter names if len(par.Names) > 0 { // Very subtle: If we indented before (ws == ignore), identList // won't indent again. If we didn't (ws == indent), identList will @@ -299,11 +308,18 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { p.identList(par.Names, ws == indent, multiLine) p.print(blank) } + // parameter type p.expr(par.Type, multiLine) - prevLine = p.fset.Position(par.Type.Pos()).Line + prevLine = parLineEnd } + // if the closing ")" is on a separate line from the last parameter, + // print an additional "," and line break + if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing { + p.print(",") + p.linebreak(closing, 0, ignore, true) + } + // unindent if we indented if ws == ignore { - // unindent if we indented p.print(unindent) } } @@ -364,8 +380,8 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) lbrace := fields.Opening list := fields.List rbrace := fields.Closing - hasComments := isIncomplete || p.commentBefore(p.fset.Position(rbrace)) - srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.fset.Position(lbrace).Line == p.fset.Position(rbrace).Line + hasComments := isIncomplete || p.commentBefore(p.posFor(rbrace)) + srcIsOneLine := lbrace.IsValid() && rbrace.IsValid() && p.lineFor(lbrace) == p.lineFor(rbrace) if !hasComments && srcIsOneLine { // possibly a one-line struct/interface @@ -408,7 +424,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) var ml bool for i, f := range list { if i > 0 { - p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml) + p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml) } ml = false extraTabs := 0 @@ -443,7 +459,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) if len(list) > 0 { p.print(formfeed) } - p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't lose the last line comment + p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment p.setLineComment("// contains filtered or unexported fields") } @@ -452,7 +468,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) var ml bool for i, f := range list { if i > 0 { - p.linebreak(p.fset.Position(f.Pos()).Line, 1, ignore, ml) + p.linebreak(p.lineFor(f.Pos()), 1, ignore, ml) } ml = false p.setComment(f.Doc) @@ -470,7 +486,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) if len(list) > 0 { p.print(formfeed) } - p.flush(p.fset.Position(rbrace), token.RBRACE) // make sure we don't lose the last line comment + p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment p.setLineComment("// contains filtered or unexported methods") } @@ -626,7 +642,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL p.print(blank) } xline := p.pos.Line // before the operator (it may be on the next line!) - yline := p.fset.Position(x.Y.Pos()).Line + yline := p.lineFor(x.Y.Pos()) p.print(x.OpPos, x.Op) if xline != yline && xline > 0 && yline > 0 { // at least one line break, but respect an extra empty line @@ -919,7 +935,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) { 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.fset.Position(s.Pos()).Line, 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, &multiLine) } @@ -932,7 +948,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) { func (p *printer) block(s *ast.BlockStmt, indent int) { p.print(s.Pos(), token.LBRACE) p.stmtList(s.List, indent, true) - p.linebreak(p.fset.Position(s.Rbrace).Line, 1, ignore, true) + p.linebreak(p.lineFor(s.Rbrace), 1, ignore, true) p.print(s.Rbrace, token.RBRACE) } @@ -1033,7 +1049,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { break } } else { - p.linebreak(p.fset.Position(s.Stmt.Pos()).Line, 1, ignore, true) + p.linebreak(p.lineFor(s.Stmt.Pos()), 1, ignore, true) } p.stmt(s.Stmt, nextIsRBrace, multiLine) @@ -1145,7 +1161,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { case *ast.SelectStmt: p.print(token.SELECT, blank) body := s.Body - if len(body.List) == 0 && !p.commentBefore(p.fset.Position(body.Rbrace)) { + if len(body.List) == 0 && !p.commentBefore(p.posFor(body.Rbrace)) { // print empty select statement w/o comments on one line p.print(body.Lbrace, token.LBRACE, body.Rbrace, token.RBRACE) } else { @@ -1337,7 +1353,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) { var ml bool for i, s := range d.Specs { if i > 0 { - p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml) + p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml) } ml = false p.valueSpec(s.(*ast.ValueSpec), keepType[i], false, &ml) @@ -1346,7 +1362,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) { var ml bool for i, s := range d.Specs { if i > 0 { - p.linebreak(p.fset.Position(s.Pos()).Line, 1, ignore, ml) + p.linebreak(p.lineFor(s.Pos()), 1, ignore, ml) } ml = false p.spec(s, n, false, &ml) @@ -1403,11 +1419,11 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) { func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool { pos1 := b.Pos() pos2 := b.Rbrace - if pos1.IsValid() && pos2.IsValid() && p.fset.Position(pos1).Line != p.fset.Position(pos2).Line { + if pos1.IsValid() && pos2.IsValid() && p.lineFor(pos1) != p.lineFor(pos2) { // opening and closing brace are on different lines - don't make it a one-liner return false } - if len(b.List) > 5 || p.commentBefore(p.fset.Position(pos2)) { + if len(b.List) > 5 || p.commentBefore(p.posFor(pos2)) { // too many statements or there is a comment inside - don't make it a one-liner return false } @@ -1458,7 +1474,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi // are on the same line; if they are on different lines (or unknown) // the result is infinity. func (p *printer) distance(from0 token.Pos, to token.Position) int { - from := p.fset.Position(from0) + from := p.posFor(from0) if from.IsValid() && to.IsValid() && from.Line == to.Line { return to.Column - from.Column } @@ -1527,7 +1543,7 @@ func (p *printer) file(src *ast.File) { if prev != tok || getDoc(d) != nil { min = 2 } - p.linebreak(p.fset.Position(d.Pos()).Line, min, ignore, false) + p.linebreak(p.lineFor(d.Pos()), min, ignore, false) p.decl(d, ignoreMultiLine) } } diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go index c720f2e665c..52dfff6f4b3 100644 --- a/libgo/go/go/printer/printer.go +++ b/libgo/go/go/printer/printer.go @@ -75,6 +75,10 @@ type printer struct { // Cache of already computed node sizes. nodeSizes map[ast.Node]int + + // Cache of most recently computed line position. + cachedPos token.Pos + cachedLine int // line corresponding to cachedPos } func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node]int) { @@ -82,6 +86,7 @@ func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node] p.fset = fset p.wsbuf = make([]whiteSpace, 0, 16) // whitespace sequences are short p.nodeSizes = nodeSizes + p.cachedPos = -1 } func (p *printer) internalError(msg ...interface{}) { @@ -92,6 +97,19 @@ func (p *printer) internalError(msg ...interface{}) { } } +func (p *printer) posFor(pos token.Pos) token.Position { + // not used frequently enough to cache entire token.Position + return p.fset.Position(pos) +} + +func (p *printer) lineFor(pos token.Pos) int { + if pos != p.cachedPos { + p.cachedPos = pos + p.cachedLine = p.fset.Position(pos).Line + } + return p.cachedLine +} + // writeByte writes ch to p.output and updates p.pos. func (p *printer) writeByte(ch byte) { p.output.WriteByte(ch) @@ -529,7 +547,7 @@ func (p *printer) writeComment(comment *ast.Comment) { // shortcut common case of //-style comments if text[1] == '/' { - p.writeItem(p.fset.Position(comment.Pos()), text, true) + p.writeItem(p.posFor(comment.Pos()), text, true) return } @@ -540,7 +558,7 @@ func (p *printer) writeComment(comment *ast.Comment) { // write comment lines, separated by formfeed, // without a line break after the last line - pos := p.fset.Position(comment.Pos()) + pos := p.posFor(comment.Pos()) for i, line := range lines { if i > 0 { p.writeByte('\f') @@ -602,14 +620,14 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (wro var last *ast.Comment for ; p.commentBefore(next); p.cindex++ { for _, c := range p.comments[p.cindex].List { - p.writeCommentPrefix(p.fset.Position(c.Pos()), next, last, c, tok.IsKeyword()) + p.writeCommentPrefix(p.posFor(c.Pos()), next, last, c, tok.IsKeyword()) p.writeComment(c) last = c } } if last != nil { - if last.Text[1] == '*' && p.fset.Position(last.Pos()).Line == next.Line { + if last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line { // the last comment is a /*-style comment and the next item // follows on the same line: separate with an extra blank p.writeByte(' ') @@ -770,7 +788,7 @@ func (p *printer) print(args ...interface{}) { tok = x case token.Pos: if x.IsValid() { - next = p.fset.Position(x) // accurate position of next item + next = p.posFor(x) // accurate position of next item } tok = p.lastTok case string: @@ -813,7 +831,7 @@ func (p *printer) print(args ...interface{}) { // before the next position in the source code. // func (p *printer) commentBefore(next token.Position) bool { - return p.cindex < len(p.comments) && p.fset.Position(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset + return p.cindex < len(p.comments) && p.posFor(p.comments[p.cindex].List[0].Pos()).Offset < next.Offset } // Flush prints any pending comments and whitespace occurring textually diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden index 239ba890304..928b8ce0a9f 100644 --- a/libgo/go/go/printer/testdata/declarations.golden +++ b/libgo/go/go/printer/testdata/declarations.golden @@ -773,30 +773,39 @@ func ManageStatus(in <-chan *Status, req <-chan Request, TargetHistorySize int) { } -func MultiLineSignature0(a, b, c int) { +func MultiLineSignature0( + a, b, c int, +) { } -func MultiLineSignature1(a, b, c int, - u, v, w float) { +func MultiLineSignature1( + a, b, c int, + u, v, w float, +) { } -func MultiLineSignature2(a, b, - c int) { +func MultiLineSignature2( + a, b, + c int, +) { } -func MultiLineSignature3(a, b, +func MultiLineSignature3( + a, b, c int, u, v, w float, x ...int) { } -func MultiLineSignature4(a, b, c int, +func MultiLineSignature4( + a, b, c int, u, v, w float, x ...int) { } -func MultiLineSignature5(a, b, c int, +func MultiLineSignature5( + a, b, c int, u, v, w float, p, q, r string, @@ -805,25 +814,34 @@ func MultiLineSignature5(a, b, c int, // make sure it also works for methods in interfaces type _ interface { - MultiLineSignature0(a, b, c int) + MultiLineSignature0( + a, b, c int, + ) - MultiLineSignature1(a, b, c int, - u, v, w float) + MultiLineSignature1( + a, b, c int, + u, v, w float, + ) - MultiLineSignature2(a, b, - c int) + MultiLineSignature2( + a, b, + c int, + ) - MultiLineSignature3(a, b, + MultiLineSignature3( + a, b, c int, u, v, w float, x ...int) - MultiLineSignature4(a, b, c int, + MultiLineSignature4( + a, b, c int, u, v, w float, x ...int) - MultiLineSignature5(a, b, c int, + MultiLineSignature5( + a, b, c int, u, v, w float, p, q, r string, diff --git a/libgo/go/go/printer/testdata/linebreaks.golden b/libgo/go/go/printer/testdata/linebreaks.golden index be780da677a..006cf171848 100644 --- a/libgo/go/go/printer/testdata/linebreaks.golden +++ b/libgo/go/go/printer/testdata/linebreaks.golden @@ -220,4 +220,56 @@ testLoop: } } +// Respect line breaks in function calls. +func _() { + f(x) + f(x, + x) + f(x, + x, + ) + f( + x, + x) + f( + x, + x, + ) +} + +// Respect line breaks in function declarations. +func _(x T) {} +func _(x T, + y T) { +} +func _(x T, + y T, +) { +} +func _( + x T, + y T) { +} +func _( + x T, + y T, +) { +} + +// Example from issue 2597. +func ManageStatus0( + in <-chan *Status, + req <-chan Request, + stat chan<- *TargetInfo, + TargetHistorySize int) { +} + +func ManageStatus1( + in <-chan *Status, + req <-chan Request, + stat chan<- *TargetInfo, + TargetHistorySize int, +) { +} + // There should be exactly one linebreak after this comment. diff --git a/libgo/go/go/printer/testdata/linebreaks.input b/libgo/go/go/printer/testdata/linebreaks.input index 457b491e6d2..e782bb04443 100644 --- a/libgo/go/go/printer/testdata/linebreaks.input +++ b/libgo/go/go/printer/testdata/linebreaks.input @@ -220,4 +220,52 @@ testLoop: } } +// Respect line breaks in function calls. +func _() { + f(x) + f(x, + x) + f(x, + x, + ) + f( + x, + x) + f( + x, + x, + ) +} + +// Respect line breaks in function declarations. +func _(x T) {} +func _(x T, + y T) {} +func _(x T, + y T, +) {} +func _( + x T, + y T) {} +func _( + x T, + y T, +) {} + +// Example from issue 2597. +func ManageStatus0( + in <-chan *Status, + req <-chan Request, + stat chan<- *TargetInfo, + TargetHistorySize int) { +} + +func ManageStatus1( + in <-chan *Status, + req <-chan Request, + stat chan<- *TargetInfo, + TargetHistorySize int, +) { +} + // There should be exactly one linebreak after this comment. |