]> Cypherpunks repositories - gostls13.git/commitdiff
godoc: don't convert multi-line functions into one-liners by default
authorRobert Griesemer <gri@golang.org>
Thu, 25 Mar 2010 23:59:02 +0000 (16:59 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 25 Mar 2010 23:59:02 +0000 (16:59 -0700)
- new heuristic: if both the opening { and closing } braces are on the
  same line, and the function body doesn't contain comments or is other-
  wise too long (e.g. signature too long), it is formatted as a one-line
  function

- related cleanups along the way

- gofmt -w src misc led to no additional changes as expected

R=rsc, rsc1
CC=golang-dev, ken2, r
https://golang.org/cl/758041

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
src/pkg/go/printer/testdata/expressions.golden
src/pkg/go/printer/testdata/expressions.input
src/pkg/go/printer/testdata/expressions.raw

index 8a6ac1a171e107bf40bcfc1923a77db10517eecc..5e02b0bd44c38f2cc786ca0226c45b21371255ca 100644 (file)
@@ -74,7 +74,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(g.List[0].Pos(), false)
+               p.flush(g.List[0].Pos(), token.ILLEGAL)
        }
        p.comments[0] = g
        p.cindex = 0
@@ -112,7 +112,6 @@ func (p *printer) identList(list []*ast.Ident, indent bool, multiLine *bool) {
 // Compute the key size of a key:value expression.
 // Returns 0 if the expression doesn't fit onto a single line.
 func (p *printer) keySize(pair *ast.KeyValueExpr) int {
-       const infinity = 1e6 // larger than any source line
        if p.nodeSize(pair, infinity) <= infinity {
                // entire expression fits on one line - return key size
                return p.nodeSize(pair.Key, infinity)
@@ -431,7 +430,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
                        if len(list) > 0 {
                                p.print(formfeed)
                        }
-                       p.flush(rbrace, false) // make sure we don't loose the last line comment
+                       p.flush(rbrace, token.RBRACE) // make sure we don't loose the last line comment
                        p.setLineComment("// contains unexported fields")
                }
 
@@ -458,7 +457,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
                        if len(list) > 0 {
                                p.print(formfeed)
                        }
-                       p.flush(rbrace, false) // make sure we don't loose the last line comment
+                       p.flush(rbrace, token.RBRACE) // make sure we don't loose the last line comment
                        p.setLineComment("// contains unexported methods")
                }
 
@@ -1224,16 +1223,26 @@ func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
 
 
 func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
-       const maxSize = 90 // adjust as appropriate, this is an approximate value
+       pos1 := b.Pos()
+       pos2 := b.Rbrace
+       if pos1.IsValid() && pos2.IsValid() && pos1.Line != pos2.Line {
+               // opening and closing brace are on different lines - don't make it a one-liner
+               return false
+       }
+       if len(b.List) > 5 || p.commentBefore(pos2) {
+               // too many statements or there is a comment inside - don't make it a one-liner
+               return false
+       }
+       // otherwise, estimate body size
+       const maxSize = 100
        bodySize := 0
-       switch {
-       case len(b.List) > 1 || p.commentBefore(b.Rbrace):
-               return false // too many statements or there is a comment - all bets are off
-       case len(b.List) == 1:
-               bodySize = p.nodeSize(b.List[0], maxSize)
+       for i, s := range b.List {
+               if i > 0 {
+                       bodySize += 2 // space for a semicolon and blank
+               }
+               bodySize += p.nodeSize(s, maxSize)
        }
-       // require both headers and overall size to be not "too large"
-       return headerSize <= maxSize/2 && headerSize+bodySize <= maxSize
+       return headerSize+bodySize <= maxSize
 }
 
 
@@ -1248,13 +1257,18 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
                if isLit {
                        sep = blank
                }
+               p.print(sep, b.Pos(), token.LBRACE)
                if len(b.List) > 0 {
-                       p.print(sep, b.Pos(), token.LBRACE, blank)
-                       p.stmt(b.List[0], ignoreMultiLine)
-                       p.print(blank, b.Rbrace, token.RBRACE)
-               } else {
-                       p.print(sep, b.Pos(), token.LBRACE, b.Rbrace, token.RBRACE)
+                       p.print(blank)
+                       for i, s := range b.List {
+                               if i > 0 {
+                                       p.print(token.SEMICOLON, blank)
+                               }
+                               p.stmt(s, ignoreMultiLine)
+                       }
+                       p.print(blank)
                }
+               p.print(b.Rbrace, token.RBRACE)
                return
        }
 
@@ -1266,12 +1280,12 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
 
 // distance returns the column difference between from and to if both
 // are on the same line; if they are on different lines (or unknown)
-// the result is infinity (1<<30).
+// the result is infinity.
 func distance(from, to token.Position) int {
        if from.IsValid() && to.IsValid() && from.Line == to.Line {
                return to.Column - from.Column
        }
-       return 1 << 30
+       return infinity
 }
 
 
index f7b55ae3c4107909c4916049fccc4802845f64f3..d9df2e819d390ad59664df4ea9686f48e76e0595 100644 (file)
@@ -53,8 +53,8 @@ var (
 
 
 // Special positions
-var noPos token.Position                                      // use noPos when a position is needed but not known
-var infinity = token.Position{Offset: 1 << 30, Line: 1 << 30} // use infinity to indicate the end of the source
+var noPos token.Position // use noPos when a position is needed but not known
+var infinity = 1 << 30
 
 
 // Use ignoreMultiLine if the multiLine information is not important.
@@ -640,17 +640,16 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
 
 
 // intersperseComments consumes all comments that appear before the next token
-// and prints it together with the buffered whitespace (i.e., the whitespace
+// tok and prints it together with the buffered whitespace (i.e., the whitespace
 // that needs to be written before the next token). A heuristic is used to mix
-// the comments and whitespace. The isKeyword parameter indicates if the next
-// token is a keyword or not. intersperseComments returns true if a pending
+// the comments and whitespace. intersperseComments returns true if a pending
 // formfeed was dropped from the whitespace buffer.
 //
-func (p *printer) intersperseComments(next token.Position, isKeyword bool) (droppedFF bool) {
+func (p *printer) intersperseComments(next token.Position, tok token.Token) (droppedFF bool) {
        var last *ast.Comment
        for ; p.commentBefore(next); p.cindex++ {
                for _, c := range p.comments[p.cindex].List {
-                       p.writeCommentPrefix(c.Pos(), next, last == nil, isKeyword)
+                       p.writeCommentPrefix(c.Pos(), next, last == nil, tok.IsKeyword())
                        p.writeComment(c)
                        last = c
                }
@@ -663,8 +662,8 @@ func (p *printer) intersperseComments(next token.Position, isKeyword bool) (drop
                        p.write([]byte{' '})
                }
                // ensure that there is a newline after a //-style comment
-               // or if we are at the end of a file after a /*-style comment
-               return p.writeCommentSuffix(last.Text[1] == '/' || next.Offset == infinity.Offset)
+               // or if we are before a closing '}' or at the end of a file
+               return p.writeCommentSuffix(last.Text[1] == '/' || tok == token.RBRACE || tok == token.EOF)
        }
 
        // no comment was written - we should never reach here since
@@ -743,7 +742,7 @@ func (p *printer) print(args ...interface{}) {
                next := p.pos // estimated position of next item
                var data []byte
                var tag HTMLTag
-               isKeyword := false
+               var tok token.Token
                switch x := f.(type) {
                case whiteSpace:
                        if x == ignore {
@@ -785,7 +784,7 @@ func (p *printer) print(args ...interface{}) {
                        } else {
                                data = []byte(x.String())
                        }
-                       isKeyword = x.IsKeyword()
+                       tok = x
                case token.Position:
                        if x.IsValid() {
                                next = x // accurate position of next item
@@ -797,7 +796,7 @@ func (p *printer) print(args ...interface{}) {
                p.pos = next
 
                if data != nil {
-                       droppedFF := p.flush(next, isKeyword)
+                       droppedFF := p.flush(next, tok)
 
                        // intersperse extra newlines if present in the source
                        // (don't do this in flush as it will cause extra newlines
@@ -820,14 +819,15 @@ func (p *printer) commentBefore(next token.Position) bool {
 
 
 // Flush prints any pending comments and whitespace occuring
-// textually before the position of the next item. Flush returns
-// true if a pending formfeed character was dropped from the
-// whitespace buffer as a result of interspersing comments.
+// textually before the position of the next token tok. Flush
+// returns true if a pending formfeed character was dropped
+// from the whitespace buffer as a result of interspersing
+// comments.
 //
-func (p *printer) flush(next token.Position, isKeyword bool) (droppedFF bool) {
+func (p *printer) flush(next token.Position, tok token.Token) (droppedFF bool) {
        if p.commentBefore(next) {
                // if there are comments before the next item, intersperse them
-               droppedFF = p.intersperseComments(next, isKeyword)
+               droppedFF = p.intersperseComments(next, tok)
        } else {
                // otherwise, write any leftover whitespace
                p.writeWhitespace(len(p.buffer))
@@ -1026,7 +1026,7 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
                        p.errors <- os.NewError(fmt.Sprintf("printer.Fprint: unsupported node type %T", n))
                        runtime.Goexit()
                }
-               p.flush(infinity, false)
+               p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF)
                p.errors <- nil // no errors
        }()
        err := <-p.errors // wait for completion of goroutine
index f216b0b6440278b263a376a62f77e09b7d6c6968..4c9f71d95b7ea2edde725a952bcedd64b4a628c1 100644 (file)
@@ -411,7 +411,8 @@ func _() {
 
 
 // Some interesting interspersed comments
-func _( /* this */ x /* is */ /* an */ int)    {}
+func _( /* this */ x /* is */ /* an */ int) {
+}
 
 func _( /* no params */ )      {}
 
@@ -421,7 +422,13 @@ func _() {
 
 func ( /* comment1 */ T /* comment2 */ ) _()   {}
 
-func _() { /* one-liner */ }
+func _() { /* one-liner */
+}
+
+func _() {
+       _ = 0
+       /* closing curly brace should be on new line */
+}
 
 
 // Line comments with tabs
index 8ed26c5ab1fd78e27da34da92240b7bdff1d2d79..335e813918d804631b96e1177049e83a47e31cb0 100644 (file)
@@ -424,6 +424,10 @@ func (/* comment1 */ T /* comment2 */) _() {}
 
 func _() { /* one-liner */ }
 
+func _() {
+       _ = 0
+       /* closing curly brace should be on new line */ }
+
 
 // Line comments with tabs
 func _() {
index 9772e837f3d1fca3d02e6266023da353b0148ecd..67f16b80522d4512010627864b41db5f2952ff35 100644 (file)
@@ -356,7 +356,8 @@ func _() {
 // formatting of structs
 type _ struct{}
 
-type _ struct { /* this comment should be visible */ }
+type _ struct { /* this comment should be visible */
+}
 
 type _ struct {
        // this comment should be visible and properly indented
@@ -588,15 +589,31 @@ func _()  {}
 func _()       {}
 
 func _()               { f(1, 2, 3) }
-func _(x int) int      { return x + 1 }
-func _() int           { type T struct{} }
+func _(x int) int      { y := x; return y + 1 }
+func _() int           { type T struct{}; var x T; return x }
+
+// these must remain multi-line since they are multi-line in the source
+func _() {
+       f(1, 2, 3)
+}
+func _(x int) int {
+       y := x
+       return y + 1
+}
+func _() int {
+       type T struct{}
+       var x T
+       return x
+}
 
 
 // making function declarations safe for new semicolon rules
-func _() { /* one-line func */ }
+func _() { /* multi-line func because of comment */
+}
 
 func _() {
-       /* one-line func */ }
+       /* multi-line func because block is on multiple lines */
+}
 
 
 // ellipsis parameters
index 8d63ab7b453a2e21904d2169e868591c54a11e56..095d1ddacefe4e4eb52e5e88c56a7ab59615a0f1 100644 (file)
@@ -581,22 +581,27 @@ func _() {}  // an empty line before this function
 func _() {}
 func _() {}
 
+func _() { f(1, 2, 3) }
+func _(x int) int { y := x; return y+1 }
+func _() int { type T struct{}; var x T; return x }
+
+// these must remain multi-line since they are multi-line in the source
 func _() {
        f(1, 2, 3)
 }
 func _(x int) int {
-       return x+1
+       y := x; return y+1
 }
 func _() int {
-       type T struct{}
+       type T struct{}; var x T; return x
 }
 
 
 // making function declarations safe for new semicolon rules
-func _() { /* one-line func */ }
+func _() { /* multi-line func because of comment */ }
 
 func _() {
-/* one-line func */ }
+/* multi-line func because block is on multiple lines */ }
 
 
 // ellipsis parameters
index c35efb83032004c35a496929be2e9d15771cafb4..21888f62691e105577ee390fdb5717c48cc85a40 100644 (file)
@@ -210,14 +210,31 @@ func _() {
 
 
 func _() {
-       // one-line function literals
+       // one-line function literals (body is on a single line)
        _ = func() {}
        _ = func() int { return 0 }
-       _ = func(x, y int) bool { return x < y }
+       _ = func(x, y int) bool { m := (x + y) / 2; return m < 0 }
 
-       f(func() {})
-       f(func() int { return 0 })
-       f(func(x, y int) bool { return x < y })
+       // multi-line function literals (body is not on one line)
+       _ = func() {
+       }
+       _ = func() int {
+               return 0
+       }
+       _ = func(x, y int) bool {
+               m := (x + y) / 2
+               return x < y
+       }
+
+       f(func() {
+       })
+       f(func() int {
+               return 0
+       })
+       f(func(x, y int) bool {
+               m := (x + y) / 2
+               return x < y
+       })
 }
 
 
index b9fc976a9b9a5969d9800f310a7fd5704dad1a04..91e5c49ddaf2b9fade0d7f9f024da117cfecb98c 100644 (file)
@@ -206,22 +206,27 @@ _ = `foo
 
 
 func _() {
-       // one-line function literals
+       // one-line function literals (body is on a single line)
        _ = func() {}
+       _ = func() int { return 0 }
+       _ = func(x, y int) bool { m := (x+y)/2; return m < 0 }
+
+       // multi-line function literals (body is not on one line)
+       _ = func() {
+       }
        _ = func() int {
                return 0
        }
        _ = func(x, y int) bool {
-               return x < y
-       }
+               m := (x+y)/2; return x < y }
 
-       f(func() {})
+       f(func() {
+       })
        f(func() int {
                return 0
        })
        f(func(x, y int) bool {
-               return x < y
-       })
+               m := (x+y)/2; return x < y })
 }
 
 
index 6ecfe13b56a7287cc01b1ed36da8e40e7e19f02a..8a5c64b7f3646b1417570a3315b08ff9c4e6c349 100644 (file)
@@ -210,14 +210,31 @@ func _() {
 
 
 func _() {
-       // one-line function literals
+       // one-line function literals (body is on a single line)
        _ = func() {}
        _ = func() int { return 0 }
-       _ = func(x, y int) bool { return x < y }
+       _ = func(x, y int) bool { m := (x + y) / 2; return m < 0 }
 
-       f(func() {})
-       f(func() int { return 0 })
-       f(func(x, y int) bool { return x < y })
+       // multi-line function literals (body is not on one line)
+       _ = func() {
+       }
+       _ = func() int {
+               return 0
+       }
+       _ = func(x, y int) bool {
+               m := (x + y) / 2
+               return x < y
+       }
+
+       f(func() {
+       })
+       f(func() int {
+               return 0
+       })
+       f(func(x, y int) bool {
+               m := (x + y) / 2
+               return x < y
+       })
 }