summaryrefslogtreecommitdiff
path: root/libgo/go/go/printer
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-01-13 05:11:45 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-01-13 05:11:45 +0000
commitdf4aa89a5e7acb315655f193e7f549e8d32367e2 (patch)
treeeb5eccc07097c5fcf940967f33ab84a7d47c96fe /libgo/go/go/printer
parentf83fa0bf8f411697ec908cfa86ee6faf4cd9c476 (diff)
libgo: Update to weekly.2011-12-22.
From-SVN: r183150
Diffstat (limited to 'libgo/go/go/printer')
-rw-r--r--libgo/go/go/printer/nodes.go23
-rw-r--r--libgo/go/go/printer/printer.go145
-rw-r--r--libgo/go/go/printer/testdata/comments.golden5
-rw-r--r--libgo/go/go/printer/testdata/comments.input6
-rw-r--r--libgo/go/go/printer/testdata/declarations.golden21
-rw-r--r--libgo/go/go/printer/testdata/declarations.input26
-rw-r--r--libgo/go/go/printer/testdata/statements.golden2
7 files changed, 154 insertions, 74 deletions
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index b2a48c28a73..6817cc42add 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -39,7 +39,10 @@ import (
// future (not yet interspersed) comments in this function.
//
func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (printedBreak bool) {
- n := p.nlines(line-p.pos.Line, min)
+ n := nlimit(line - p.pos.Line)
+ if n < min {
+ n = min
+ }
if n > 0 {
p.print(ws)
if newSection {
@@ -361,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
@@ -388,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
@@ -1509,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)
diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go
index 8538236c2c9..a78cfc65fcc 100644
--- a/libgo/go/go/printer/printer.go
+++ b/libgo/go/go/printer/printer.go
@@ -18,8 +18,11 @@ import (
"text/tabwriter"
)
-const debug = false // enable for debugging
-const infinity = 1 << 30
+const (
+ maxNewlines = 2 // max. number of newlines between source text
+ debug = false // enable for debugging
+ infinity = 1 << 30
+)
type whiteSpace byte
@@ -89,21 +92,7 @@ func (p *printer) internalError(msg ...interface{}) {
}
}
-// nlines returns the adjusted number of linebreaks given the desired number
-// of breaks n such that min <= result <= max.
-//
-func (p *printer) nlines(n, min int) int {
- const max = 2 // max. number of newlines
- switch {
- case n < min:
- return min
- case n > max:
- return max
- }
- return n
-}
-
-// writeByte writes a single byte to p.output and updates p.pos.
+// writeByte writes ch to p.output and updates p.pos.
func (p *printer) writeByte(ch byte) {
p.output.WriteByte(ch)
p.pos.Offset++
@@ -128,13 +117,11 @@ func (p *printer) writeByte(ch byte) {
}
}
-// writeNewlines writes up to n newlines to p.output and updates p.pos.
-// The actual number of newlines written is limited by nlines.
-// nl must be one of '\n' or '\f'.
-//
-func (p *printer) writeNewlines(n int, nl byte) {
- for n = p.nlines(n, 0); n > 0; n-- {
- p.writeByte(nl)
+// writeByteN writes ch n times to p.output and updates p.pos.
+func (p *printer) writeByteN(ch byte, n int) {
+ for n > 0 {
+ p.writeByte(ch)
+ n--
}
}
@@ -223,8 +210,8 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, prev, comment *as
}
if pos.IsValid() && pos.Filename != p.last.Filename {
- // comment in a different file - separate with newlines (writeNewlines will limit the number)
- p.writeNewlines(10, '\f')
+ // comment in a different file - separate with newlines
+ p.writeByteN('\f', maxNewlines)
return
}
@@ -270,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
@@ -295,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
@@ -302,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 {
- p.writeNewlines(n, '\f')
+ // 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
}
}
@@ -550,10 +555,11 @@ func (p *printer) writeComment(comment *ast.Comment) {
// writeCommentSuffix writes a line break after a comment if indicated
// and processes any leftover indentation information. If a line break
// is needed, the kind of break (newline vs formfeed) depends on the
-// pending whitespace. writeCommentSuffix returns true if a pending
-// formfeed was dropped from the whitespace buffer.
+// pending whitespace. The writeCommentSuffix result indicates if a
+// newline was written or if a formfeed was dropped from the whitespace
+// buffer.
//
-func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
+func (p *printer) writeCommentSuffix(needsLinebreak bool) (wroteNewline, droppedFF bool) {
for i, ch := range p.wsbuf {
switch ch {
case blank, vtab:
@@ -566,6 +572,7 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
// but remember if we dropped any formfeeds
if needsLinebreak {
needsLinebreak = false
+ wroteNewline = true
} else {
if ch == formfeed {
droppedFF = true
@@ -579,6 +586,7 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
// make sure we have a line break
if needsLinebreak {
p.writeByte('\n')
+ wroteNewline = true
}
return
@@ -587,10 +595,10 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (droppedFF bool) {
// intersperseComments consumes all comments that appear before the next token
// 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. intersperseComments returns true if a pending
-// formfeed was dropped from the whitespace buffer.
+// the comments and whitespace. The intersperseComments result indicates if a
+// newline was written or if a formfeed was dropped from the whitespace buffer.
//
-func (p *printer) intersperseComments(next token.Position, tok token.Token) (droppedFF bool) {
+func (p *printer) intersperseComments(next token.Position, tok token.Token) (wroteNewline, droppedFF bool) {
var last *ast.Comment
for ; p.commentBefore(next); p.cindex++ {
for _, c := range p.comments[p.cindex].List {
@@ -618,7 +626,7 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (dro
// no comment was written - we should never reach here since
// intersperseComments should not be called in that case
p.internalError("intersperseComments called without pending comments")
- return false
+ return
}
// whiteWhitespace writes the first n whitespace entries.
@@ -671,6 +679,14 @@ func (p *printer) writeWhitespace(n int) {
// ----------------------------------------------------------------------------
// Printing interface
+// nlines limits n to maxNewlines.
+func nlimit(n int) int {
+ if n > maxNewlines {
+ n = maxNewlines
+ }
+ return n
+}
+
func mayCombine(prev token.Token, next byte) (b bool) {
switch prev {
case token.INT:
@@ -765,17 +781,22 @@ func (p *printer) print(args ...interface{}) {
p.pos = next
if data != "" {
- nl := byte('\n')
- if p.flush(next, tok) {
- nl = '\f' // dropped formfeed before
- }
+ wroteNewline, 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
- // at the end of a file) - use formfeeds if we dropped one
- // before
- if n := next.Line - p.pos.Line; n > 0 {
- p.writeNewlines(n, nl)
+ // at the end of a file)
+ n := nlimit(next.Line - p.pos.Line)
+ // don't exceed maxNewlines if we already wrote one
+ if wroteNewline && n == maxNewlines {
+ n = maxNewlines - 1
+ }
+ if n > 0 {
+ ch := byte('\n')
+ if droppedFF {
+ ch = '\f' // use formfeed since we dropped one before
+ }
+ p.writeByteN(ch, n)
}
p.writeItem(next, data, isLit)
@@ -790,16 +811,15 @@ 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
}
-// Flush prints any pending comments and whitespace occurring
-// 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.
+// 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
+// buffer.
//
-func (p *printer) flush(next token.Position, tok token.Token) (droppedFF bool) {
+func (p *printer) flush(next token.Position, tok token.Token) (wroteNewline, droppedFF bool) {
if p.commentBefore(next) {
// if there are comments before the next item, intersperse them
- droppedFF = p.intersperseComments(next, tok)
+ wroteNewline, droppedFF = p.intersperseComments(next, tok)
} else {
// otherwise, write any leftover whitespace
p.writeWhitespace(len(p.wsbuf))
@@ -810,7 +830,8 @@ func (p *printer) flush(next token.Position, tok token.Token) (droppedFF bool) {
// 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:
diff --git a/libgo/go/go/printer/testdata/comments.golden b/libgo/go/go/printer/testdata/comments.golden
index 7b332252c4e..d2ad9e3a2ff 100644
--- a/libgo/go/go/printer/testdata/comments.golden
+++ b/libgo/go/go/printer/testdata/comments.golden
@@ -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()
diff --git a/libgo/go/go/printer/testdata/comments.input b/libgo/go/go/printer/testdata/comments.input
index 2a9a86b6815..222e0a713d4 100644
--- a/libgo/go/go/printer/testdata/comments.input
+++ b/libgo/go/go/printer/testdata/comments.input
@@ -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
}
diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden
index bfa2568c21f..239ba890304 100644
--- a/libgo/go/go/printer/testdata/declarations.golden
+++ b/libgo/go/go/printer/testdata/declarations.golden
@@ -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
diff --git a/libgo/go/go/printer/testdata/declarations.input b/libgo/go/go/printer/testdata/declarations.input
index 1d69c57b517..68f90308a36 100644
--- a/libgo/go/go/printer/testdata/declarations.input
+++ b/libgo/go/go/printer/testdata/declarations.input
@@ -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
diff --git a/libgo/go/go/printer/testdata/statements.golden b/libgo/go/go/printer/testdata/statements.golden
index a6d85107f0b..90e1743557d 100644
--- a/libgo/go/go/printer/testdata/statements.golden
+++ b/libgo/go/go/printer/testdata/statements.golden
@@ -271,7 +271,6 @@ func _() {
// Known bug: The first use call may have more than one empty line before
// (see go/printer/nodes.go, func linebreak).
-
use(x)
if x < x {
@@ -386,7 +385,6 @@ L: // A comment on the same line as the label, followed by a single empty line.
// Known bug: There may be more than one empty line before MoreCode()
// (see go/printer/nodes.go, func linebreak).
-
MoreCode()
}