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 {
}
}
// 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 {
......
......@@ -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
......
......@@ -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)
......
......@@ -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)
}
}
......
......@@ -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("&#34;") // shorter than "&quot;"
esc_apos = []byte("&#39;") // shorter than "&apos;"
......@@ -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)
......
......@@ -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()
}
......@@ -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()
}
......@@ -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())
......
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