]> Cypherpunks repositories - gostls13.git/commitdiff
go/printer, gofmt: fine tuning of line spacing
authorRobert Griesemer <gri@golang.org>
Fri, 16 Dec 2011 23:43:06 +0000 (15:43 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 16 Dec 2011 23:43:06 +0000 (15:43 -0800)
- no empty lines inside empty structs and interfaces
- top-level declarations are separated by a blank line if
  a) they are of different kind (e.g. const vs type); or
  b) there are documentation comments associated with a
     declaration (this is new)
- applied gofmt -w misc src

The actual changes are in go/printer/nodes.go:397-400 (empty structs/interfaces),
and go/printer/printer.go:307-309 (extra line break). The remaining
changes are cleanups w/o changing the existing functionality.

Fixes issue  2570.

R=rsc
CC=golang-dev
https://golang.org/cl/5493057

18 files changed:
src/cmd/gofix/testdata/reflect.type.go.in
src/cmd/gofix/testdata/reflect.type.go.out
src/pkg/crypto/openpgp/keys.go
src/pkg/crypto/x509/x509.go
src/pkg/encoding/gob/codec_test.go
src/pkg/encoding/gob/type.go
src/pkg/exp/ssh/tcpip.go
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/log/syslog/syslog.go
src/pkg/math/all_test.go
src/pkg/math/sin.go
src/pkg/net/ipraw_test.go
src/pkg/sort/sort.go

index 7ed7002abfd6b98a6249a64f7ffdfd650acf9664..34963bef92af82f59914a8417259a840630228ad 100644 (file)
@@ -150,6 +150,7 @@ func userType(rt reflect.Type) *userTypeInfo {
        }
        return ut
 }
+
 // A typeId represents a gob Type as an integer that can be passed on the wire.
 // Internally, typeIds are used as keys to a map to recover the underlying type info.
 type typeId int32
index 9cd78296ddf3c71992d35ef19557e9821559789c..d729ea471a98d7bf9183d103306e575b933e97a7 100644 (file)
@@ -150,6 +150,7 @@ func userType(rt reflect.Type) *userTypeInfo {
        }
        return ut
 }
+
 // A typeId represents a gob Type as an integer that can be passed on the wire.
 // Internally, typeIds are used as keys to a map to recover the underlying type info.
 type typeId int32
index df39970c0b672d176253b22dad1cbfb1c93adb97..74e7d239e0882b2fc1ed1797c2b0befe173e5f42 100644 (file)
@@ -16,6 +16,7 @@ import (
 
 // PublicKeyType is the armor type for a PGP public key.
 var PublicKeyType = "PGP PUBLIC KEY BLOCK"
+
 // PrivateKeyType is the armor type for a PGP private key.
 var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
 
index 65ca31580035595f1a9d417f8276b97c86281dc6..28c7880e531922950c04d9a2d4bee9436103c0be 100644 (file)
@@ -981,6 +981,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
 // pemCRLPrefix is the magic string that indicates that we have a PEM encoded
 // CRL.
 var pemCRLPrefix = []byte("-----BEGIN X509 CRL")
+
 // pemType is the type of a PEM encoded CRL.
 var pemType = "X509 CRL"
 
index dc0e0078e6810d1201e21722712fdaffd7d9ad76..73844b920c14bfa00fced5fd73ffc80df749ec73 100644 (file)
@@ -102,12 +102,15 @@ func TestIntCodec(t *testing.T) {
 
 // The result of encoding a true boolean with field number 7
 var boolResult = []byte{0x07, 0x01}
+
 // The result of encoding a number 17 with field number 7
 var signedResult = []byte{0x07, 2 * 17}
 var unsignedResult = []byte{0x07, 17}
 var floatResult = []byte{0x07, 0xFE, 0x31, 0x40}
+
 // The result of encoding a number 17+19i with field number 7
 var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40}
+
 // The result of encoding "hello" with field number 7
 var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
 
index 1b20843fa2574004f7f9fa76da7736720fa702e4..71a28be7cab8a7a497145f9fdd692f95ab5dadc8 100644 (file)
@@ -130,6 +130,7 @@ func userType(rt reflect.Type) *userTypeInfo {
        }
        return ut
 }
+
 // A typeId represents a gob Type as an integer that can be passed on the wire.
 // Internally, typeIds are used as keys to a map to recover the underlying type info.
 type typeId int32
index a85044ace9cecc2c6ee2b3b29ae292de5590989b..bee41eeb0dbc64a2c13fdd7b0d594951aa482223 100644 (file)
@@ -10,6 +10,7 @@ import (
        "io"
        "net"
 )
+
 // Dial initiates a connection to the addr from the remote host.
 // addr is resolved using net.ResolveTCPAddr before connection. 
 // This could allow an observer to observe the DNS name of the 
index 9e9d5f83df10d7a4ff1df928a0b6e6b97d50cc9e..6817cc42addef4323dd9dd22dd9083b52ef35eac 100644 (file)
@@ -364,9 +364,10 @@ 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
 
-       if !isIncomplete && !p.commentBefore(p.fset.Position(rbrace)) && srcIsOneLine {
+       if !hasComments && srcIsOneLine {
                // possibly a one-line struct/interface
                if len(list) == 0 {
                        // no blank between keyword and {} in this case
@@ -391,9 +392,13 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
                        return
                }
        }
+       // hasComments || !srcIsOneLine
+
+       p.print(blank, lbrace, token.LBRACE, indent)
+       if hasComments || len(list) > 0 {
+               p.print(formfeed)
+       }
 
-       // at least one entry or incomplete
-       p.print(blank, lbrace, token.LBRACE, indent, formfeed)
        if isStruct {
 
                sep := vtab
@@ -1512,9 +1517,14 @@ func (p *printer) file(src *ast.File) {
                        prev := tok
                        tok = declToken(d)
                        // if the declaration token changed (e.g., from CONST to TYPE)
+                       // or the next declaration has documentation associated with it,
                        // print an empty line between top-level declarations
+                       // (because p.linebreak is called with the position of d, which
+                       // is past any documentation, the minimum requirement is satisfied
+                       // even w/o the extra getDoc(d) nil-check - leave it in case the
+                       // linebreak logic improves - there's already a TODO).
                        min := 1
-                       if prev != tok {
+                       if prev != tok || getDoc(d) != nil {
                                min = 2
                        }
                        p.linebreak(p.fset.Position(d.Pos()).Line, min, ignore, false)
index a0197d87c4df833921c78073184d27a65136ec33..a78cfc65fccb372399048449b35c282900599d13 100644 (file)
@@ -257,6 +257,7 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *as
        } else {
                // comment on a different line:
                // separate with at least one line break
+               droppedLinebreak := false
                if prev == nil {
                        // first comment of a comment group
                        j := 0
@@ -282,6 +283,7 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *as
                                case newline, formfeed:
                                        // TODO(gri): may want to keep formfeed info in some cases
                                        p.wsbuf[i] = ignore
+                                       droppedLinebreak = true
                                }
                                j = i
                                break
@@ -289,25 +291,41 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *as
                        p.writeWhitespace(j)
                }
 
-               // turn off indent if we're about to print a line directive.
-               indent := p.indent
-               if strings.HasPrefix(comment.Text, linePrefix) {
-                       p.indent = 0
+               // determine number of linebreaks before the comment
+               n := 0
+               if pos.IsValid() && p.last.IsValid() {
+                       n = pos.Line - p.last.Line
+                       if n < 0 { // should never happen
+                               n = 0
+                       }
+               }
+
+               // at the package scope level only (p.indent == 0),
+               // add an extra newline if we dropped one before:
+               // this preserves a blank line before documentation
+               // comments at the package scope level (issue 2570)
+               if p.indent == 0 && droppedLinebreak {
+                       n++
                }
 
-               // use formfeeds to break columns before a comment;
-               // this is analogous to using formfeeds to separate
-               // individual lines of /*-style comments - but make
-               // sure there is at least one line break if the previous
-               // comment was a line comment
-               n := pos.Line - p.last.Line // if !pos.IsValid(), pos.Line == 0, and n will be 0
-               if n <= 0 && prev != nil && prev.Text[1] == '/' {
+               // make sure there is at least one line break
+               // if the previous comment was a line comment
+               if n == 0 && prev != nil && prev.Text[1] == '/' {
                        n = 1
                }
+
                if n > 0 {
+                       // turn off indent if we're about to print a line directive
+                       indent := p.indent
+                       if strings.HasPrefix(comment.Text, linePrefix) {
+                               p.indent = 0
+                       }
+                       // use formfeeds to break columns before a comment;
+                       // this is analogous to using formfeeds to separate
+                       // individual lines of /*-style comments
                        p.writeByteN('\f', nlimit(n))
+                       p.indent = indent // restore indent
                }
-               p.indent = indent
        }
 }
 
@@ -812,7 +830,8 @@ func (p *printer) flush(next token.Position, tok token.Token) (wroteNewline, dro
 // getNode returns the ast.CommentGroup associated with n, if any.
 func getDoc(n ast.Node) *ast.CommentGroup {
        switch n := n.(type) {
-       // *ast.Fields cannot be printed separately - ignore for now
+       case *ast.Field:
+               return n.Doc
        case *ast.ImportSpec:
                return n.Doc
        case *ast.ValueSpec:
index 7b332252c4ec0ad26ca17930c92d6fc0f5ab19f3..d2ad9e3a2ff94dc4e7747ade0df954dafa2cfe81 100644 (file)
@@ -106,7 +106,7 @@ type S3 struct {
 var x int      // x
 var ()
 
-// This comment SHOULD be associated with the next declaration.
+// This comment SHOULD be associated with f0.
 func f0() {
        const pi = 3.14 // pi
        var s1 struct{} /* an empty struct */   /* foo */
@@ -115,8 +115,9 @@ func f0() {
        var s2 struct{} = struct{}{}
        x := pi
 }
+
 //
-// NO SPACE HERE
+// This comment should be associated with f1, with one blank line before the comment.
 //
 func f1() {
        f0()
index 2a9a86b681584c2748ea58fcf97a9dc4dbf859a1..222e0a713d4621786ab449c0ecfc6084d6d84a1f 100644 (file)
@@ -107,7 +107,7 @@ var x int  // x
 var ()
 
 
-// This comment SHOULD be associated with the next declaration.
+// This comment SHOULD be associated with f0.
 func f0() {
        const pi = 3.14  // pi
        var s1 struct {}  /* an empty struct */ /* foo */
@@ -117,7 +117,7 @@ func f0() {
        x := pi
 }
 //
-// NO SPACE HERE
+// This comment should be associated with f1, with one blank line before the comment.
 //
 func f1() {
        f0()
@@ -130,7 +130,7 @@ func f1() {
 
 
 func _() {
-       // this comment should be properly indented
+// this comment should be properly indented
 }
 
 
index bfa2568c21fd29ea3f8ea5697f4591be112d01f0..239ba890304599a0305f5567c666f3c518461fde 100644 (file)
@@ -115,6 +115,18 @@ import _ "io"
 
 var _ int
 
+// at least one empty line between declarations of the same kind
+// if there is associated documentation (was issue 2570)
+type T1 struct{}
+
+// T2 comment
+type T2 struct {
+}      // should be a two-line struct
+
+// T3 comment
+type T2 struct {
+}      // should be a two-line struct
+
 // printing of constant literals
 const (
        _       = "foobar"
@@ -286,6 +298,15 @@ type _ struct {
        }
 }
 
+// no blank lines in empty structs and interfaces, but leave 1- or 2-line layout alone
+type _ struct{}
+type _ struct {
+}
+
+type _ interface{}
+type _ interface {
+}
+
 // no tabs for single or ungrouped decls
 func _() {
        const xxxxxx = 0
index 1d69c57b517466994fde21dc225b58261239147b..68f90308a362b942fb55a72ffe682346d5caeddf 100644 (file)
@@ -115,6 +115,20 @@ import (
 import _ "io"
 var _ int
 
+// at least one empty line between declarations of the same kind
+// if there is associated documentation (was issue 2570)
+type T1 struct{}
+// T2 comment
+type T2 struct {
+} // should be a two-line struct
+
+
+// T3 comment
+type T2 struct {
+
+
+} // should be a two-line struct
+
 
 // printing of constant literals
 const (
@@ -293,6 +307,18 @@ type _ struct {
 }
 
 
+// no blank lines in empty structs and interfaces, but leave 1- or 2-line layout alone
+type _ struct{            }
+type _ struct {
+
+}
+
+type _ interface{            }
+type _ interface {
+
+}
+
+
 // no tabs for single or ungrouped decls
 func _() {
        const xxxxxx = 0
index 546bc296a5ffd9d4f4526f133dce0fec944b9f9e..914391af80d65132c8e9cf2151b676aaa20c5518 100644 (file)
@@ -92,11 +92,13 @@ func (w *Writer) Emerg(m string) (err error) {
        _, err = w.writeString(LOG_EMERG, m)
        return err
 }
+
 // Crit logs a message using the LOG_CRIT priority.
 func (w *Writer) Crit(m string) (err error) {
        _, err = w.writeString(LOG_CRIT, m)
        return err
 }
+
 // ERR logs a message using the LOG_ERR priority.
 func (w *Writer) Err(m string) (err error) {
        _, err = w.writeString(LOG_ERR, m)
@@ -114,11 +116,13 @@ func (w *Writer) Notice(m string) (err error) {
        _, err = w.writeString(LOG_NOTICE, m)
        return err
 }
+
 // Info logs a message using the LOG_INFO priority.
 func (w *Writer) Info(m string) (err error) {
        _, err = w.writeString(LOG_INFO, m)
        return err
 }
+
 // Debug logs a message using the LOG_DEBUG priority.
 func (w *Writer) Debug(m string) (err error) {
        _, err = w.writeString(LOG_DEBUG, m)
index 0a3cb0315d24d521a359d3e7c98aa3d52ea4a901..101c8dd85b4ac6f755fef9481738f68fef08804d 100644 (file)
@@ -22,6 +22,7 @@ var vf = []float64{
        1.8253080916808550e+00,
        -8.6859247685756013e+00,
 }
+
 // The expected results below were computed by the high precision calculators
 // at http://keisan.casio.com/.  More exact input values (array vf[], above)
 // were obtained by printing them with "%.26f".  The answers were calculated
@@ -159,6 +160,7 @@ var cos = []float64{
        -2.517729313893103197176091e-01,
        -7.39241351595676573201918e-01,
 }
+
 // Results for 100000 * Pi + vf[i]
 var cosLarge = []float64{
        2.634752141185559426744e-01,
@@ -514,6 +516,7 @@ var sin = []float64{
        9.6778633541687993721617774e-01,
        -6.734405869050344734943028e-01,
 }
+
 // Results for 100000 * Pi + vf[i]
 var sinLarge = []float64{
        -9.646661658548936063912e-01,
@@ -563,6 +566,7 @@ var tan = []float64{
        -3.843885560201130679995041e+00,
        9.10988793377685105753416e-01,
 }
+
 // Results for 100000 * Pi + vf[i]
 var tanLarge = []float64{
        -3.66131656475596512705e+00,
index ec30477eac929c54fd17905834188c495e7856c0..176ac229abb681ea124a3761110c6f7522f74526 100644 (file)
@@ -98,6 +98,7 @@ var _sin = [...]float64{
        8.33333333332211858878E-3,  // 0x3f8111111110f7d0
        -1.66666666666666307295E-1, // 0xbfc5555555555548
 }
+
 // cos coefficients
 var _cos = [...]float64{
        -1.13585365213876817300E-11, // 0xbda8fa49a0861a9b
index 60c405ab4ac0233d2eb0c3b452edcaf0f15aff02..67a4049d5d3ff885ccf1dff89467e0bd4ce295dc 100644 (file)
@@ -59,6 +59,7 @@ func parsePingReply(p []byte) (id, seq int) {
 }
 
 var srchost = flag.String("srchost", "", "Source of the ICMP ECHO request")
+
 // 127.0.0.1 because this is an IPv4-specific test.
 var dsthost = flag.String("dsthost", "127.0.0.1", "Destination for the ICMP ECHO request")
 
index 83ee170cbab2e863e5aa96b51d2029bce289883e..4aa4ca6d7da78e25bdec3b83f1a4695b487d8dfc 100644 (file)
@@ -240,14 +240,18 @@ func (p StringSlice) Sort() { Sort(p) }
 
 // Ints sorts a slice of ints in increasing order.
 func Ints(a []int) { Sort(IntSlice(a)) }
+
 // Float64s sorts a slice of float64s in increasing order.
 func Float64s(a []float64) { Sort(Float64Slice(a)) }
+
 // Strings sorts a slice of strings in increasing order.
 func Strings(a []string) { Sort(StringSlice(a)) }
 
 // IntsAreSorted tests whether a slice of ints is sorted in increasing order.
 func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }
+
 // Float64sAreSorted tests whether a slice of float64s is sorted in increasing order.
 func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }
+
 // StringsAreSorted tests whether a slice of strings is sorted in increasing order.
 func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }