]> Cypherpunks repositories - gostls13.git/commitdiff
go/printer: refine handling of one-line functions
authorRobert Griesemer <gri@golang.org>
Wed, 26 Feb 2014 21:39:49 +0000 (13:39 -0800)
committerRobert Griesemer <gri@golang.org>
Wed, 26 Feb 2014 21:39:49 +0000 (13:39 -0800)
Functions that "fit" on one line and were on one
line in the original source are not broken up into
two lines anymore simply because they contain a comment.

- Fine-tuned use of separating blanks after /*-style comments, so:

( /* extra blank after this comment */ )
(a int /* no extra blank after this comment*/)

- Factored out comment state (from printer state) into commentInfo.
- No impact on $GOROOT/src, misc formatting.

Fixes #5543.

LGTM=r
R=golang-codereviews, r
CC=golang-codereviews
https://golang.org/cl/68630043

src/pkg/go/printer/nodes.go
src/pkg/go/printer/printer.go
src/pkg/go/printer/testdata/comments.golden
src/pkg/go/printer/testdata/comments.input
src/pkg/go/printer/testdata/declarations.golden
src/pkg/go/printer/testdata/declarations.input

index 494ce948f40c4bb3f77fd086ce8923cae5fe3d53..3a93177b1b57845d910680ca3ac5f4b4aad690d6 100644 (file)
@@ -826,10 +826,16 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
                }
                p.print(x.Lbrace, token.LBRACE)
                p.exprList(x.Lbrace, x.Elts, 1, 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 ','
-               p.print(noExtraLinebreak, x.Rbrace, token.RBRACE, noExtraLinebreak)
+               // do not insert extra line break following a /*-style comment
+               // before the closing '}' as it might break the code if there
+               // is no trailing ','
+               mode := noExtraLinebreak
+               // do not insert extra blank following a /*-style comment
+               // before the closing '}' unless the literal is empty
+               if len(x.Elts) > 0 {
+                       mode |= noExtraBlank
+               }
+               p.print(mode, x.Rbrace, token.RBRACE, mode)
 
        case *ast.Ellipsis:
                p.print(token.ELLIPSIS)
@@ -1461,13 +1467,16 @@ func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int {
                // opening and closing brace are on different lines - don't make it a one-liner
                return maxSize + 1
        }
-       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
+       if len(b.List) > 5 {
+               // too many statements - don't make it a one-liner
                return maxSize + 1
        }
        // otherwise, estimate body size
-       bodySize := 0
+       bodySize := p.commentSizeBefore(p.posFor(pos2))
        for i, s := range b.List {
+               if bodySize > maxSize {
+                       break // no need to continue
+               }
                if i > 0 {
                        bodySize += 2 // space for a semicolon and blank
                }
@@ -1501,7 +1510,7 @@ func (p *printer) adjBlock(headerSize int, sep whiteSpace, b *ast.BlockStmt) {
                        }
                        p.print(blank)
                }
-               p.print(b.Rbrace, token.RBRACE)
+               p.print(noExtraLinebreak, b.Rbrace, token.RBRACE, noExtraLinebreak)
                return
        }
 
index e06d2edfb21c2e8da51d07c2c9f572c21a99c3e3..a86ce8a3f017d8eafa912d7ff3543fb4ad7f614d 100644 (file)
@@ -39,9 +39,17 @@ const (
 type pmode int
 
 const (
-       noExtraLinebreak pmode = 1 << iota
+       noExtraBlank     pmode = 1 << iota // disables extra blank after /*-style comment
+       noExtraLinebreak                   // disables extra line break after /*-style comment
 )
 
+type commentInfo struct {
+       cindex         int               // current comment index
+       comment        *ast.CommentGroup // = printer.comments[cindex]; or nil
+       commentOffset  int               // = printer.posFor(printer.comments[cindex].List[0].Pos()).Offset; or infinity
+       commentNewline bool              // true if the comment group contains newlines
+}
+
 type printer struct {
        // Configuration (does not change after initialization)
        Config
@@ -52,7 +60,8 @@ type printer struct {
        indent      int          // current indentation
        mode        pmode        // current printer mode
        impliedSemi bool         // if set, a linebreak implies a semicolon
-       lastTok     token.Token  // the last token printed (token.ILLEGAL if it's whitespace)
+       lastTok     token.Token  // last token printed (token.ILLEGAL if it's whitespace)
+       prevOpen    token.Token  // previous non-brace "open" token (, [, or token.ILLEGAL
        wsbuf       []whiteSpace // delayed white space
 
        // Positions
@@ -67,13 +76,10 @@ type printer struct {
 
        // The list of all source comments, in order of appearance.
        comments        []*ast.CommentGroup // may be nil
-       cindex          int                 // current comment index
        useNodeComments bool                // if not set, ignore lead and line comments of nodes
 
        // Information about p.comments[p.cindex]; set up by nextComment.
-       comment        *ast.CommentGroup // = p.comments[p.cindex]; or nil
-       commentOffset  int               // = p.posFor(p.comments[p.cindex].List[0].Pos()).Offset; or infinity
-       commentNewline bool              // true if the comment group contains newlines
+       commentInfo
 
        // Cache of already computed node sizes.
        nodeSizes map[ast.Node]int
@@ -129,6 +135,33 @@ func (p *printer) nextComment() {
        p.commentOffset = infinity
 }
 
+// commentBefore returns true iff the current comment group occurs
+// before the next position in the source code and printing it does
+// not introduce implicit semicolons.
+//
+func (p *printer) commentBefore(next token.Position) bool {
+       return p.commentOffset < next.Offset && (!p.impliedSemi || !p.commentNewline)
+}
+
+// commentSizeBefore returns the estimated size of the
+// comments on the same line before the next position.
+//
+func (p *printer) commentSizeBefore(next token.Position) int {
+       // save/restore current p.commentInfo (p.nextComment() modifies it)
+       defer func(info commentInfo) {
+               p.commentInfo = info
+       }(p.commentInfo)
+
+       size := 0
+       for p.commentBefore(next) {
+               for _, c := range p.comment.List {
+                       size += len(c.Text)
+               }
+               p.nextComment()
+       }
+       return size
+}
+
 func (p *printer) internalError(msg ...interface{}) {
        if debug {
                fmt.Print(p.pos.String() + ": ")
@@ -675,10 +708,14 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (wro
 
        if last != nil {
                // if the last comment is a /*-style comment and the next item
-               // follows on the same line but is not a comma or a "closing"
-               // token, add an extra blank for separation
-               if last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line && tok != token.COMMA &&
-                       tok != token.RPAREN && tok != token.RBRACK && tok != token.RBRACE {
+               // follows on the same line but is not a comma, and not a "closing"
+               // token immediately following its corresponding "opening" token,
+               // add an extra blank for separation unless explicitly disabled
+               if p.mode&noExtraBlank == 0 &&
+                       last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line &&
+                       tok != token.COMMA &&
+                       (tok != token.RPAREN || p.prevOpen == token.LPAREN) &&
+                       (tok != token.RBRACK || p.prevOpen == token.LBRACK) {
                        p.writeByte(' ', 1)
                }
                // ensure that there is a line break after a //-style comment,
@@ -735,12 +772,8 @@ func (p *printer) writeWhitespace(n int) {
        }
 
        // shift remaining entries down
-       i := 0
-       for ; n < len(p.wsbuf); n++ {
-               p.wsbuf[i] = p.wsbuf[n]
-               i++
-       }
-       p.wsbuf = p.wsbuf[0:i]
+       l := copy(p.wsbuf, p.wsbuf[n:])
+       p.wsbuf = p.wsbuf[:l]
 }
 
 // ----------------------------------------------------------------------------
@@ -790,6 +823,17 @@ func (p *printer) print(args ...interface{}) {
                var isLit bool
                var impliedSemi bool // value for p.impliedSemi after this arg
 
+               // record previous opening token, if any
+               switch p.lastTok {
+               case token.ILLEGAL:
+                       // ignore (white space)
+               case token.LPAREN, token.LBRACK:
+                       p.prevOpen = p.lastTok
+               default:
+                       // other tokens followed any opening token
+                       p.prevOpen = token.ILLEGAL
+               }
+
                switch x := arg.(type) {
                case pmode:
                        // toggle printer mode
@@ -904,14 +948,6 @@ func (p *printer) print(args ...interface{}) {
        }
 }
 
-// commentBefore returns true iff the current comment group occurs
-// before the next position in the source code and printing it does
-// not introduce implicit semicolons.
-//
-func (p *printer) commentBefore(next token.Position) (result bool) {
-       return p.commentOffset < next.Offset && (!p.impliedSemi || !p.commentNewline)
-}
-
 // flush prints any pending comments and whitespace occurring textually
 // before the position of the next token tok. The flush result indicates
 // if a newline was written or if a formfeed was dropped from the whitespace
index 610a42a68bda5bf1b9ea7258404c9a11b5d114a7..b1af7958a96fd93e12ea9b3b181006011030dba5 100644 (file)
@@ -494,16 +494,21 @@ func _() {
 func _( /* this */ x /* is */ /* an */ int) {
 }
 
-func _( /* no params */)       {}
+func _( /* no params - extra blank before and after comment */ )       {}
+func _(a, b int /* params - no extra blank after comment */)           {}
+
+func _()       { f( /* no args - extra blank before and after comment */ ) }
+func _()       { f(a, b /* args - no extra blank after comment */) }
 
 func _() {
-       f( /* no args */)
+       f( /* no args - extra blank before and after comment */ )
+       f(a, b /* args - no extra blank after comment */)
 }
 
 func ( /* comment1 */ T /* comment2 */) _()    {}
 
-func _() { /* one-line functions with comments are formatted as multi-line functions */
-}
+func _()       { /* "short-ish one-line functions with comments are formatted as multi-line functions */ }
+func _()       { x := 0; /* comment */ y = x /* comment */ }
 
 func _() {
        _ = 0
index d121dd4be77d706162dad3db38132247a85d3aef..983e2b2c97e25a54bd0b96ba1d7e7a05985ebeb0 100644 (file)
@@ -500,15 +500,21 @@ func _() {
 func _(/* this */x/* is *//* an */ int) {
 }
 
-func _(/* no params */) {}
+func _(/* no params - extra blank before and after comment */) {}
+func _(a, b int /* params - no extra blank after comment */) {}
+
+func _() { f(/* no args - extra blank before and after comment */) }
+func _() { f(a, b /* args - no extra blank after comment */) }
 
 func _() {
-       f(/* no args */)
+       f(/* no args - extra blank before and after comment */)
+       f(a, b /* args - no extra blank after comment */)
 }
 
 func (/* comment1 */ T /* comment2 */) _() {}
 
-func _() { /* one-line functions with comments are formatted as multi-line functions */ }
+func _() { /* "short-ish one-line functions with comments are formatted as multi-line functions */ }
+func _() { x := 0; /* comment */ y = x /* comment */ }
 
 func _() {
        _ = 0
index 0331615e5195bc99e7dd50d2fd6d9f9acab90157..735e489379cc919e792058f6b01356822726139a 100644 (file)
@@ -723,7 +723,8 @@ func _() int {
 }
 
 // making function declarations safe for new semicolon rules
-func _() { /* multi-line func because of comment */
+func _()       { /* single-line function because of "short-ish" comment */ }
+func _() { /* multi-line function because of "long-ish" comment - much more comment text is following here */ /* and more */
 }
 
 func _() {
index dbdbdfe7422db109a99c991a19e25ea2db256eba..53f7a2ef731efe12f8e3d521bfc89211f0545832 100644 (file)
@@ -737,7 +737,8 @@ func _() int {
 
 
 // making function declarations safe for new semicolon rules
-func _() { /* multi-line func because of comment */ }
+func _() { /* single-line function because of "short-ish" comment */ }
+func _() { /* multi-line function because of "long-ish" comment - much more comment text is following here */ /* and more */ }
 
 func _() {
 /* multi-line func because block is on multiple lines */ }