Commit 8f9aeb5a authored by Robert Griesemer's avatar Robert Griesemer

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
parent 199e17ba
...@@ -270,7 +270,6 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 { ...@@ -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 // Somethings is wrong if at the end, the top level is null or hasn't used
// all of the leaves. // all of the leaves.
if top.lastChain.leafCount != n { if top.lastChain.leafCount != n {
......
...@@ -102,7 +102,6 @@ func (h *huffmanDecoder) init(bits []int) bool { ...@@ -102,7 +102,6 @@ func (h *huffmanDecoder) init(bits []int) bool {
h.min = min h.min = min
h.max = max h.max = max
// For each code range, compute // For each code range, compute
// nextcode (first code of that length), // nextcode (first code of that length),
// limit (last code of that length), and // limit (last code of that length), and
......
...@@ -224,7 +224,6 @@ func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) { ...@@ -224,7 +224,6 @@ func emphasize(w io.Writer, line []byte, words map[string]string, nice bool) {
italics = false // don't italicize URLs italics = false // don't italicize URLs
} }
// write match // write match
if len(url) > 0 { if len(url) > 0 {
w.Write(html_a) w.Write(html_a)
......
...@@ -28,32 +28,30 @@ import ( ...@@ -28,32 +28,30 @@ import (
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Common AST nodes. // Common AST nodes.
// Print as many newlines as necessary (but at least min and and at most // Print as many newlines as necessary (but at least min newlines) to get to
// max newlines) to get to the current line. ws is printed before the first // the current line. ws is printed before the first line break. If newSection
// line break. If newSection is set, the first line break is printed as // is set, the first line break is printed as formfeed. Returns true if any
// formfeed. Returns true if any line break was printed; returns false otherwise. // 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) { func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (printedBreak bool) {
n := line - p.pos.Line n := p.nlines(line-p.pos.Line, min)
switch {
case n < min:
n = min
case n > max:
n = max
}
if n > 0 { if n > 0 {
p.print(ws) p.print(ws)
if newSection { if newSection {
p.print(formfeed) p.print(formfeed)
n-- n--
printedBreak = true
} }
} for ; n > 0; n-- {
for ; n > 0; n-- { p.print(newline)
p.print(newline) }
printedBreak = true printedBreak = true
} }
return return
...@@ -190,7 +188,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode ...@@ -190,7 +188,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode
// lines for them. // lines for them.
linebreakMin = 0 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 ws = ignore
*multiLine = true *multiLine = true
prevBreak = 0 prevBreak = 0
...@@ -252,7 +250,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, depth int, mode ...@@ -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 // unless forceFF is set or there are multiple expressions on
// the same line in which case formfeed is used // the same line in which case formfeed is used
// broken with a formfeed // 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 ws = ignore
*multiLine = true *multiLine = true
prevBreak = i prevBreak = i
...@@ -371,6 +369,11 @@ func (p *printer) setLineComment(text string) { ...@@ -371,6 +369,11 @@ func (p *printer) setLineComment(text string) {
func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprContext) { func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprContext) {
p.nesting++
defer func() {
p.nesting--
}()
lbrace := fields.Opening lbrace := fields.Opening
list := fields.List list := fields.List
rbrace := fields.Closing rbrace := fields.Closing
...@@ -413,7 +416,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC ...@@ -413,7 +416,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
var ml bool var ml bool
for i, f := range list { for i, f := range list {
if i > 0 { if i > 0 {
p.linebreak(f.Pos().Line, 1, 2, ignore, ml) p.linebreak(f.Pos().Line, 1, ignore, ml)
} }
ml = false ml = false
extraTabs := 0 extraTabs := 0
...@@ -457,7 +460,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC ...@@ -457,7 +460,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
var ml bool var ml bool
for i, f := range list { for i, f := range list {
if i > 0 { if i > 0 {
p.linebreak(f.Pos().Line, 1, 2, ignore, ml) p.linebreak(f.Pos().Line, 1, ignore, ml)
} }
ml = false ml = false
p.setComment(f.Doc) p.setComment(f.Doc)
...@@ -648,7 +651,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL ...@@ -648,7 +651,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL
if xline != yline && xline > 0 && yline > 0 { if xline != yline && xline > 0 && yline > 0 {
// at least one line break, but respect an extra empty line // at least one line break, but respect an extra empty line
// in the source // in the source
if p.linebreak(yline, 1, 2, ws, true) { if p.linebreak(yline, 1, ws, true) {
ws = ignore ws = ignore
*multiLine = true *multiLine = true
printBlank = false // no blank after line break printBlank = false // no blank after line break
...@@ -917,8 +920,6 @@ func (p *printer) expr(x ast.Expr, multiLine *bool) { ...@@ -917,8 +920,6 @@ func (p *printer) expr(x ast.Expr, multiLine *bool) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
const maxStmtNewlines = 2 // maximum number of newlines between statements
// Print the statement list indented, but without a newline after the last statement. // 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 // Extra line breaks between statements in the source are respected but at most one
// empty line is printed between statements. // empty line is printed between statements.
...@@ -931,7 +932,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) { ...@@ -931,7 +932,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
for i, s := range list { for i, s := range list {
// _indent == 0 only for lists of switch/select case clauses; // _indent == 0 only for lists of switch/select case clauses;
// in those cases each clause is a new section // 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 multiLine = false
p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine) p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine)
} }
...@@ -945,7 +946,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) { ...@@ -945,7 +946,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
func (p *printer) block(s *ast.BlockStmt, indent int) { func (p *printer) block(s *ast.BlockStmt, indent int) {
p.print(s.Pos(), token.LBRACE) p.print(s.Pos(), token.LBRACE)
p.stmtList(s.List, indent, true) 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) p.print(s.Rbrace, token.RBRACE)
} }
...@@ -1039,7 +1040,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1039,7 +1040,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
break break
} }
} else { } else {
p.print(newline) p.linebreak(s.Stmt.Pos().Line, 1, ignore, true)
} }
p.stmt(s.Stmt, nextIsRBrace, multiLine) p.stmt(s.Stmt, nextIsRBrace, multiLine)
...@@ -1271,7 +1272,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) { ...@@ -1271,7 +1272,7 @@ func (p *printer) genDecl(d *ast.GenDecl, multiLine *bool) {
var ml bool var ml bool
for i, s := range d.Specs { for i, s := range d.Specs {
if i > 0 { if i > 0 {
p.linebreak(s.Pos().Line, 1, 2, ignore, ml) p.linebreak(s.Pos().Line, 1, ignore, ml)
} }
ml = false ml = false
p.spec(s, len(d.Specs), false, &ml) p.spec(s, len(d.Specs), false, &ml)
...@@ -1345,6 +1346,11 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi ...@@ -1345,6 +1346,11 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
return return
} }
p.nesting++
defer func() {
p.nesting--
}()
if p.isOneLineFunc(b, headerSize) { if p.isOneLineFunc(b, headerSize) {
sep := vtab sep := vtab
if isLit { if isLit {
...@@ -1414,8 +1420,6 @@ func (p *printer) decl(decl ast.Decl, multiLine *bool) { ...@@ -1414,8 +1420,6 @@ func (p *printer) decl(decl ast.Decl, multiLine *bool) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Files // Files
const maxDeclNewlines = 3 // maximum number of newlines between declarations
func declToken(decl ast.Decl) (tok token.Token) { func declToken(decl ast.Decl) (tok token.Token) {
tok = token.ILLEGAL tok = token.ILLEGAL
switch d := decl.(type) { switch d := decl.(type) {
...@@ -1444,7 +1448,7 @@ func (p *printer) file(src *ast.File) { ...@@ -1444,7 +1448,7 @@ func (p *printer) file(src *ast.File) {
if prev != tok { if prev != tok {
min = 2 min = 2
} }
p.linebreak(d.Pos().Line, min, maxDeclNewlines, ignore, false) p.linebreak(d.Pos().Line, min, ignore, false)
p.decl(d, ignoreMultiLine) p.decl(d, ignoreMultiLine)
} }
} }
......
...@@ -18,10 +18,7 @@ import ( ...@@ -18,10 +18,7 @@ import (
) )
const ( const debug = false // enable for debugging
debug = false // enable for debugging
maxNewlines = 3 // maximum vertical white space
)
type whiteSpace int type whiteSpace int
...@@ -41,8 +38,8 @@ var ( ...@@ -41,8 +38,8 @@ var (
esc = []byte{tabwriter.Escape} esc = []byte{tabwriter.Escape}
htab = []byte{'\t'} htab = []byte{'\t'}
htabs = []byte("\t\t\t\t\t\t\t\t") htabs = []byte("\t\t\t\t\t\t\t\t")
newlines = []byte("\n\n\n\n\n\n\n\n") // 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 maxNewlines formfeeds = []byte("\f\f\f\f\f\f\f\f") // more than the max determined by nlines
esc_quot = []byte("&#34;") // shorter than "&quot;" esc_quot = []byte("&#34;") // shorter than "&quot;"
esc_apos = []byte("&#39;") // shorter than "&apos;" esc_apos = []byte("&#39;") // shorter than "&apos;"
...@@ -68,6 +65,7 @@ type printer struct { ...@@ -68,6 +65,7 @@ type printer struct {
errors chan os.Error errors chan os.Error
// Current state // Current state
nesting int // nesting level (0: top-level (package scope), >0: functions/decls.)
written int // number of bytes written written int // number of bytes written
indent int // current indentation indent int // current indentation
escape bool // true if in escape sequence escape bool // true if in escape sequence
...@@ -112,6 +110,25 @@ func (p *printer) internalError(msg ...interface{}) { ...@@ -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 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. // 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) { ...@@ -207,9 +224,7 @@ func (p *printer) write(data []byte) {
func (p *printer) writeNewlines(n int, useFF bool) { func (p *printer) writeNewlines(n int, useFF bool) {
if n > 0 { if n > 0 {
if n > maxNewlines { n = p.nlines(n, 0)
n = maxNewlines
}
if useFF { if useFF {
p.write(formfeeds[0:n]) p.write(formfeeds[0:n])
} else { } else {
...@@ -292,8 +307,8 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, isFirst, isKeywor ...@@ -292,8 +307,8 @@ func (p *printer) writeCommentPrefix(pos, next token.Position, isFirst, isKeywor
} }
if pos.IsValid() && pos.Filename != p.last.Filename { if pos.IsValid() && pos.Filename != p.last.Filename {
// comment in a different file - separate with newlines // comment in a different file - separate with newlines (writeNewlines will limit the number)
p.writeNewlines(maxNewlines, true) p.writeNewlines(10, true)
return return
} }
...@@ -1004,9 +1019,11 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) { ...@@ -1004,9 +1019,11 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
go func() { go func() {
switch n := node.(type) { switch n := node.(type) {
case ast.Expr: case ast.Expr:
p.nesting = 1
p.useNodeComments = true p.useNodeComments = true
p.expr(n, ignoreMultiLine) p.expr(n, ignoreMultiLine)
case ast.Stmt: case ast.Stmt:
p.nesting = 1
p.useNodeComments = true p.useNodeComments = true
// A labeled statement will un-indent to position the // A labeled statement will un-indent to position the
// label. Set indent to 1 so we don't get indent "underflow". // 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) { ...@@ -1015,12 +1032,15 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
} }
p.stmt(n, false, ignoreMultiLine) p.stmt(n, false, ignoreMultiLine)
case ast.Decl: case ast.Decl:
p.nesting = 1
p.useNodeComments = true p.useNodeComments = true
p.decl(n, ignoreMultiLine) p.decl(n, ignoreMultiLine)
case ast.Spec: case ast.Spec:
p.nesting = 1
p.useNodeComments = true p.useNodeComments = true
p.spec(n, 1, false, ignoreMultiLine) p.spec(n, 1, false, ignoreMultiLine)
case *ast.File: case *ast.File:
p.nesting = 0
p.comments = n.Comments p.comments = n.Comments
p.useNodeComments = n.Comments == nil p.useNodeComments = n.Comments == nil
p.file(n) p.file(n)
......
...@@ -227,7 +227,8 @@ func _() { ...@@ -227,7 +227,8 @@ func _() {
var x = 1 var x = 1
// Each use(x) call below should have at most one empty line before and after. // 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) use(x)
...@@ -336,3 +337,49 @@ AnOverlongLabel: ...@@ -336,3 +337,49 @@ AnOverlongLabel:
L: L:
_ = 0 _ = 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()
}
...@@ -164,6 +164,8 @@ func _() { ...@@ -164,6 +164,8 @@ func _() {
var x = 1 var x = 1
// Each use(x) call below should have at most one empty line before and after. // 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: ...@@ -266,3 +268,54 @@ AnOverlongLabel:
L: _ = 0 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()
}
...@@ -154,7 +154,6 @@ Body. ...@@ -154,7 +154,6 @@ Body.
t.Fatal("newnews should work: " + err.String()) t.Fatal("newnews should work: " + err.String())
} }
// NewGroups // NewGroups
if _, err = conn.NewGroups(tt); err != nil { if _, err = conn.NewGroups(tt); err != nil {
t.Fatal("newgroups shouldn't error " + err.String()) t.Fatal("newgroups shouldn't error " + err.String())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment