diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-01-13 05:11:45 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-01-13 05:11:45 +0000 |
commit | df4aa89a5e7acb315655f193e7f549e8d32367e2 (patch) | |
tree | eb5eccc07097c5fcf940967f33ab84a7d47c96fe /libgo/go/go/printer | |
parent | f83fa0bf8f411697ec908cfa86ee6faf4cd9c476 (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.go | 23 | ||||
-rw-r--r-- | libgo/go/go/printer/printer.go | 145 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/comments.golden | 5 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/comments.input | 6 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/declarations.golden | 21 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/declarations.input | 26 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/statements.golden | 2 |
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() } |