From 8f9aeb5a66c0acbca2844cc98d71320711fb4a82 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 20 Jul 2010 09:29:31 -0700 Subject: [PATCH] gofmt: fix some linebreak issues - don't lose empty lines after labels - canonicalize number of line breaks - gofmt src misc, fixes a couple of irregular breaks R=rsc CC=golang-dev https://golang.org/cl/1843044 --- src/pkg/compress/flate/huffman_code.go | 1 - src/pkg/compress/flate/inflate.go | 1 - src/pkg/go/doc/comment.go | 1 - src/pkg/go/printer/nodes.go | 68 ++++++++++--------- src/pkg/go/printer/printer.go | 42 +++++++++--- src/pkg/go/printer/testdata/statements.golden | 49 ++++++++++++- src/pkg/go/printer/testdata/statements.input | 53 +++++++++++++++ src/pkg/nntp/nntp_test.go | 1 - 8 files changed, 168 insertions(+), 48 deletions(-) diff --git a/src/pkg/compress/flate/huffman_code.go b/src/pkg/compress/flate/huffman_code.go index 38cbf43968..6be605f0a5 100644 --- a/src/pkg/compress/flate/huffman_code.go +++ b/src/pkg/compress/flate/huffman_code.go @@ -270,7 +270,6 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 { } } - // Somethings is wrong if at the end, the top level is null or hasn't used // all of the leaves. if top.lastChain.leafCount != n { diff --git a/src/pkg/compress/flate/inflate.go b/src/pkg/compress/flate/inflate.go index f0bd005318..e46cbeff65 100644 --- a/src/pkg/compress/flate/inflate.go +++ b/src/pkg/compress/flate/inflate.go @@ -102,7 +102,6 @@ func (h *huffmanDecoder) init(bits []int) bool { h.min = min h.max = max - // For each code range, compute // nextcode (first code of that length), // limit (last code of that length), and diff --git a/src/pkg/go/doc/comment.go b/src/pkg/go/doc/comment.go index bbbc6a3c25..55ddf8b755 100644 --- a/src/pkg/go/doc/comment.go +++ b/src/pkg/go/doc/comment.go @@ -224,7 +224,6 @@ func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) { italics = false // don't italicize URLs } - // write match if len(url) > 0 { w.Write(html_a) diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go index a98af4a2af..132c52073e 100644 --- a/src/pkg/go/printer/nodes.go +++ b/src/pkg/go/printer/nodes.go @@ -28,32 +28,30 @@ import ( // ---------------------------------------------------------------------------- // Common AST nodes. -// Print as many newlines as necessary (but at least min and and at most -// max newlines) to get to the current line. ws is printed before the first -// line break. If newSection is set, the first line break is printed as -// formfeed. Returns true if any line break was printed; returns false otherwise. +// Print as many newlines as necessary (but at least min newlines) to get to +// the current line. ws is printed before the first line break. If newSection +// is set, the first line break is printed as formfeed. Returns true if any +// line break was printed; returns false otherwise. // -// TODO(gri): Reconsider signature (provide position instead of line) +// TODO(gri): linebreak may add too many lines if the next statement at "line" +// is preceeded by comments because the computation of n assumes +// the current position before the comment and the target position +// after the comment. Thus, after interspersing such comments, the +// space taken up by them is not considered to reduce the number of +// linebreaks. At the moment there is no easy way to know about +// future (not yet interspersed) comments in this function. // -func (p *printer) linebreak(line, min, max int, ws whiteSpace, newSection bool) (printedBreak bool) { - n := line - p.pos.Line - switch { - case n < min: - n = min - case n > max: - n = max - } - +func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (printedBreak bool) { + n := p.nlines(line-p.pos.Line, min) if n > 0 { p.print(ws) if newSection { p.print(formfeed) n-- - printedBreak = true } - } - for ; n > 0; n-- { - p.print(newline) + for ; n > 0; n-- { + p.print(newline) + } printedBreak = true } return @@ -190,7 +188,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode // lines for them. linebreakMin = 0 } - if prev.IsValid() && prev.Line < line && p.linebreak(line, linebreakMin, 2, ws, true) { + if prev.IsValid() && prev.Line < line && p.linebreak(line, linebreakMin, ws, true) { ws = ignore *multiLine = true prevBreak = 0 @@ -252,7 +250,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode // unless forceFF is set or there are multiple expressions on // the same line in which case formfeed is used // broken with a formfeed - if p.linebreak(line, linebreakMin, 2, ws, useFF || prevBreak+1 < i) { + if p.linebreak(line, linebreakMin, ws, useFF || prevBreak+1 < i) { ws = ignore *multiLine = true prevBreak = i @@ -371,6 +369,11 @@ func (p *printer) setLineComment(text string) { func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprContext) { + p.nesting++ + defer func() { + p.nesting-- + }() + lbrace := fields.Opening list := fields.List rbrace := fields.Closing @@ -413,7 +416,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC var ml bool for i, f := range list { if i > 0 { - p.linebreak(f.Pos().Line, 1, 2, ignore, ml) + p.linebreak(f.Pos().Line, 1, ignore, ml) } ml = false extraTabs := 0 @@ -457,7 +460,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC var ml bool for i, f := range list { if i > 0 { - p.linebreak(f.Pos().Line, 1, 2, ignore, ml) + p.linebreak(f.Pos().Line, 1, ignore, ml) } ml = false p.setComment(f.Doc) @@ -648,7 +651,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL if xline != yline && xline > 0 && yline > 0 { // at least one line break, but respect an extra empty line // in the source - if p.linebreak(yline, 1, 2, ws, true) { + if p.linebreak(yline, 1, ws, true) { ws = ignore *multiLine = true printBlank = false // no blank after line break @@ -917,8 +920,6 @@ func (p *printer) expr(x ast.Expr, multiLine *bool) { // ---------------------------------------------------------------------------- // Statements -const maxStmtNewlines = 2 // maximum number of newlines between statements - // Print the statement list indented, but without a newline after the last statement. // Extra line breaks between statements in the source are respected but at most one // empty line is printed between statements. @@ -931,7 +932,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) { for i, s := range list { // _indent == 0 only for lists of switch/select case clauses; // in those cases each clause is a new section - p.linebreak(s.Pos().Line, 1, maxStmtNewlines, ignore, i == 0 || _indent == 0 || multiLine) + p.linebreak(s.Pos().Line, 1, ignore, i == 0 || _indent == 0 || multiLine) multiLine = false p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine) } @@ -945,7 +946,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) { func (p *printer) block(s *ast.BlockStmt, indent int) { p.print(s.Pos(), token.LBRACE) p.stmtList(s.List, indent, true) - p.linebreak(s.Rbrace.Line, 1, maxStmtNewlines, ignore, true) + p.linebreak(s.Rbrace.Line, 1, ignore, true) p.print(s.Rbrace, token.RBRACE) } @@ -1039,7 +1040,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { break } } else { - p.print(newline) + p.linebreak(s.Stmt.Pos().Line, 1, ignore, true) } p.stmt(s.Stmt, nextIsRBrace, multiLine) @@ -1271,7 +1272,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) { var ml bool for i, s := range d.Specs { if i > 0 { - p.linebreak(s.Pos().Line, 1, 2, ignore, ml) + p.linebreak(s.Pos().Line, 1, ignore, ml) } ml = false p.spec(s, len(d.Specs), false, &ml) @@ -1345,6 +1346,11 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi return } + p.nesting++ + defer func() { + p.nesting-- + }() + if p.isOneLineFunc(b, headerSize) { sep := vtab if isLit { @@ -1414,8 +1420,6 @@ func (p *printer) decl(decl ast.Decl, multiLine *bool) { // ---------------------------------------------------------------------------- // Files -const maxDeclNewlines = 3 // maximum number of newlines between declarations - func declToken(decl ast.Decl) (tok token.Token) { tok = token.ILLEGAL switch d := decl.(type) { @@ -1444,7 +1448,7 @@ func (p *printer) file(src *ast.File) { if prev != tok { min = 2 } - p.linebreak(d.Pos().Line, min, maxDeclNewlines, ignore, false) + p.linebreak(d.Pos().Line, min, ignore, false) p.decl(d, ignoreMultiLine) } } diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go index 53632c83dd..9adc540b95 100644 --- a/src/pkg/go/printer/printer.go +++ b/src/pkg/go/printer/printer.go @@ -18,10 +18,7 @@ import ( ) -const ( - debug = false // enable for debugging - maxNewlines = 3 // maximum vertical white space -) +const debug = false // enable for debugging type whiteSpace int @@ -41,8 +38,8 @@ var ( esc = []byte{tabwriter.Escape} htab = []byte{'\t'} htabs = []byte("\t\t\t\t\t\t\t\t") - newlines = []byte("\n\n\n\n\n\n\n\n") // more than maxNewlines - formfeeds = []byte("\f\f\f\f\f\f\f\f") // more than maxNewlines + newlines = []byte("\n\n\n\n\n\n\n\n") // more than the max determined by nlines + formfeeds = []byte("\f\f\f\f\f\f\f\f") // more than the max determined by nlines esc_quot = []byte(""") // shorter than """ esc_apos = []byte("'") // shorter than "'" @@ -68,6 +65,7 @@ type printer struct { errors chan os.Error // Current state + nesting int // nesting level (0: top-level (package scope), >0: functions/decls.) written int // number of bytes written indent int // current indentation escape bool // true if in escape sequence @@ -112,6 +110,25 @@ 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 where max depends on the current +// nesting level. +// +func (p *printer) nlines(n, min int) int { + if n < min { + return min + } + max := 3 // max. number of newlines at the top level (p.nesting == 0) + if p.nesting > 0 { + max = 2 // max. number of newlines everywhere else + } + if n > max { + return max + } + return n +} + + // write0 writes raw (uninterpreted) data to p.output and handles errors. // write0 does not indent after newlines, and does not HTML-escape or update p.pos. // @@ -207,9 +224,7 @@ func (p *printer) write(data []byte) { func (p *printer) writeNewlines(n int, useFF bool) { if n > 0 { - if n > maxNewlines { - n = maxNewlines - } + n = p.nlines(n, 0) if useFF { p.write(formfeeds[0:n]) } else { @@ -292,8 +307,8 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, isFirst, isKeywor } if pos.IsValid() && pos.Filename != p.last.Filename { - // comment in a different file - separate with newlines - p.writeNewlines(maxNewlines, true) + // comment in a different file - separate with newlines (writeNewlines will limit the number) + p.writeNewlines(10, true) return } @@ -1004,9 +1019,11 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) { go func() { switch n := node.(type) { case ast.Expr: + p.nesting = 1 p.useNodeComments = true p.expr(n, ignoreMultiLine) case ast.Stmt: + p.nesting = 1 p.useNodeComments = true // A labeled statement will un-indent to position the // label. Set indent to 1 so we don't get indent "underflow". @@ -1015,12 +1032,15 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) { } p.stmt(n, false, ignoreMultiLine) case ast.Decl: + p.nesting = 1 p.useNodeComments = true p.decl(n, ignoreMultiLine) case ast.Spec: + p.nesting = 1 p.useNodeComments = true p.spec(n, 1, false, ignoreMultiLine) case *ast.File: + p.nesting = 0 p.comments = n.Comments p.useNodeComments = n.Comments == nil p.file(n) diff --git a/src/pkg/go/printer/testdata/statements.golden b/src/pkg/go/printer/testdata/statements.golden index 73a3e12368..461fd13f95 100644 --- a/src/pkg/go/printer/testdata/statements.golden +++ b/src/pkg/go/printer/testdata/statements.golden @@ -227,7 +227,8 @@ func _() { var x = 1 // Each use(x) call below should have at most one empty line before and after. - + // Known bug: The first use call may have more than one empty line before + // (see go/printer/nodes.go, func linebreak). use(x) @@ -336,3 +337,49 @@ AnOverlongLabel: L: _ = 0 } + + +func _() { + for { + goto L + } +L: + + MoreCode() +} + + +func _() { + for { + goto L + } +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() +} + + +func _() { + for { + goto L + } +L: + + // There should be a single empty line before this comment. + MoreCode() +} + + +func _() { + for { + goto AVeryLongLabelThatShouldNotAffectFormatting + } +AVeryLongLabelThatShouldNotAffectFormatting: + // There should be a single empty line after this comment. + + // There should be a single empty line before this comment. + MoreCode() +} diff --git a/src/pkg/go/printer/testdata/statements.input b/src/pkg/go/printer/testdata/statements.input index 53f16c050a..5437eb5f19 100644 --- a/src/pkg/go/printer/testdata/statements.input +++ b/src/pkg/go/printer/testdata/statements.input @@ -164,6 +164,8 @@ func _() { var x = 1 // Each use(x) call below should have at most one empty line before and after. + // Known bug: The first use call may have more than one empty line before + // (see go/printer/nodes.go, func linebreak). @@ -266,3 +268,54 @@ AnOverlongLabel: L: _ = 0 } + + +func _() { + for { + goto L + } +L: + + MoreCode() +} + + +func _() { + for { + goto L + } +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() +} + + +func _() { + for { + goto L + } +L: + + + + + // There should be a single empty line before this comment. + MoreCode() +} + + +func _() { + for { + goto AVeryLongLabelThatShouldNotAffectFormatting + } +AVeryLongLabelThatShouldNotAffectFormatting: + // There should be a single empty line after this comment. + + // There should be a single empty line before this comment. + MoreCode() +} diff --git a/src/pkg/nntp/nntp_test.go b/src/pkg/nntp/nntp_test.go index bca1857224..8f5032c6a0 100644 --- a/src/pkg/nntp/nntp_test.go +++ b/src/pkg/nntp/nntp_test.go @@ -154,7 +154,6 @@ Body. t.Fatal("newnews should work: " + err.String()) } - // NewGroups if _, err = conn.NewGroups(tt); err != nil { t.Fatal("newgroups shouldn't error " + err.String()) -- 2.48.1