summaryrefslogtreecommitdiff
path: root/src/pkg/go/printer
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/go/printer')
-rw-r--r--src/pkg/go/printer/nodes.go90
-rw-r--r--src/pkg/go/printer/printer.go42
-rw-r--r--src/pkg/go/printer/testdata/comments.golden6
-rw-r--r--src/pkg/go/printer/testdata/comments.input6
4 files changed, 88 insertions, 56 deletions
diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go
index 1ee0846f6..7933c2f18 100644
--- a/src/pkg/go/printer/nodes.go
+++ b/src/pkg/go/printer/nodes.go
@@ -228,7 +228,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
useFF = false
} else {
const r = 4 // threshold
- ratio := float(size) / float(prevSize)
+ ratio := float64(size) / float64(prevSize)
useFF = ratio <= 1/r || r <= ratio
}
}
@@ -506,12 +506,12 @@ const (
)
-func walkBinary(e *ast.BinaryExpr) (has5, has6 bool, maxProblem int) {
+func walkBinary(e *ast.BinaryExpr) (has4, has5 bool, maxProblem int) {
switch e.Op.Precedence() {
+ case 4:
+ has4 = true
case 5:
has5 = true
- case 6:
- has6 = true
}
switch l := e.X.(type) {
@@ -521,9 +521,9 @@ func walkBinary(e *ast.BinaryExpr) (has5, has6 bool, maxProblem int) {
// pretend this is an *ast.ParenExpr and do nothing.
break
}
- h5, h6, mp := walkBinary(l)
+ h4, h5, mp := walkBinary(l)
+ has4 = has4 || h4
has5 = has5 || h5
- has6 = has6 || h6
if maxProblem < mp {
maxProblem = mp
}
@@ -536,25 +536,25 @@ func walkBinary(e *ast.BinaryExpr) (has5, has6 bool, maxProblem int) {
// pretend this is an *ast.ParenExpr and do nothing.
break
}
- h5, h6, mp := walkBinary(r)
+ h4, h5, mp := walkBinary(r)
+ has4 = has4 || h4
has5 = has5 || h5
- has6 = has6 || h6
if maxProblem < mp {
maxProblem = mp
}
case *ast.StarExpr:
if e.Op.String() == "/" {
- maxProblem = 6
+ maxProblem = 5
}
case *ast.UnaryExpr:
switch e.Op.String() + r.Op.String() {
case "/*", "&&", "&^":
- maxProblem = 6
+ maxProblem = 5
case "++", "--":
- if maxProblem < 5 {
- maxProblem = 5
+ if maxProblem < 4 {
+ maxProblem = 4
}
}
}
@@ -563,20 +563,20 @@ func walkBinary(e *ast.BinaryExpr) (has5, has6 bool, maxProblem int) {
func cutoff(e *ast.BinaryExpr, depth int) int {
- has5, has6, maxProblem := walkBinary(e)
+ has4, has5, maxProblem := walkBinary(e)
if maxProblem > 0 {
return maxProblem + 1
}
- if has5 && has6 {
+ if has4 && has5 {
if depth == 1 {
- return 6
+ return 5
}
- return 5
+ return 4
}
if depth == 1 {
- return 7
+ return 6
}
- return 5
+ return 4
}
@@ -603,15 +603,14 @@ func reduceDepth(depth int) int {
// (Algorithm suggestion by Russ Cox.)
//
// The precedences are:
-// 6 * / % << >> & &^
-// 5 + - | ^
-// 4 == != < <= > >=
-// 3 <-
+// 5 * / % << >> & &^
+// 4 + - | ^
+// 3 == != < <= > >=
// 2 &&
// 1 ||
//
-// The only decision is whether there will be spaces around levels 5 and 6.
-// There are never spaces at level 7 (unary), and always spaces at levels 4 and below.
+// The only decision is whether there will be spaces around levels 4 and 5.
+// There are never spaces at level 6 (unary), and always spaces at levels 3 and below.
//
// To choose the cutoff, look at the whole expression but excluding primary
// expressions (function calls, parenthesized exprs), and apply these rules:
@@ -619,21 +618,21 @@ func reduceDepth(depth int) int {
// 1) If there is a binary operator with a right side unary operand
// that would clash without a space, the cutoff must be (in order):
//
-// /* 7
-// && 7
-// &^ 7
-// ++ 6
-// -- 6
+// /* 6
+// && 6
+// &^ 6
+// ++ 5
+// -- 5
//
// (Comparison operators always have spaces around them.)
//
-// 2) If there is a mix of level 6 and level 5 operators, then the cutoff
-// is 6 (use spaces to distinguish precedence) in Normal mode
-// and 5 (never use spaces) in Compact mode.
+// 2) If there is a mix of level 5 and level 4 operators, then the cutoff
+// is 5 (use spaces to distinguish precedence) in Normal mode
+// and 4 (never use spaces) in Compact mode.
//
-// 3) If there are no level 5 operators or no level 6 operators, then the
-// cutoff is 7 (always use spaces) in Normal mode
-// and 5 (never use spaces) in Compact mode.
+// 3) If there are no level 4 operators or no level 5 operators, then the
+// cutoff is 6 (always use spaces) in Normal mode
+// and 4 (never use spaces) in Compact mode.
//
// Sets multiLine to true if the binary expression spans multiple lines.
func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiLine *bool) {
@@ -872,7 +871,10 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
}
p.print(x.Lbrace, token.LBRACE)
p.exprList(x.Lbrace, x.Elts, 1, commaSep|commaTerm, multiLine, x.Rbrace)
- p.print(x.Rbrace, token.RBRACE)
+ // do not insert extra line breaks because of comments before
+ // the closing '}' as it might break the code if there is no
+ // trailing ','
+ p.print(noExtraLinebreak, x.Rbrace, token.RBRACE, noExtraLinebreak)
case *ast.Ellipsis:
p.print(token.ELLIPSIS)
@@ -1080,6 +1082,12 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
const depth = 1
p.expr0(s.X, depth, multiLine)
+ case *ast.SendStmt:
+ const depth = 1
+ p.expr0(s.Chan, depth, multiLine)
+ p.print(blank, s.Arrow, token.ARROW, blank)
+ p.expr0(s.Value, depth, multiLine)
+
case *ast.IncDecStmt:
const depth = 1
p.expr0(s.X, depth+1, multiLine)
@@ -1176,13 +1184,9 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
*multiLine = true
case *ast.CommClause:
- if s.Rhs != nil {
+ if s.Comm != nil {
p.print(token.CASE, blank)
- if s.Lhs != nil {
- p.expr(s.Lhs, multiLine)
- p.print(blank, s.Tok, blank)
- }
- p.expr(s.Rhs, multiLine)
+ p.stmt(s.Comm, false, ignoreMultiLine)
} else {
p.print(token.DEFAULT)
}
@@ -1388,7 +1392,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
if isLit {
sep = blank
}
- p.print(sep, b.Pos(), token.LBRACE)
+ p.print(sep, b.Lbrace, token.LBRACE)
if len(b.List) > 0 {
p.print(blank)
for i, s := range b.List {
diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go
index a4ddad50e..34b0c4e2d 100644
--- a/src/pkg/go/printer/printer.go
+++ b/src/pkg/go/printer/printer.go
@@ -58,6 +58,15 @@ var infinity = 1 << 30
var ignoreMultiLine = new(bool)
+// A pmode value represents the current printer mode.
+type pmode int
+
+const (
+ inLiteral pmode = 1 << iota
+ noExtraLinebreak
+)
+
+
type printer struct {
// Configuration (does not change after initialization)
output io.Writer
@@ -69,7 +78,7 @@ type printer struct {
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
+ mode pmode // current printer mode
lastTok token.Token // the last token printed (token.ILLEGAL if it's whitespace)
// Buffered whitespace
@@ -162,7 +171,7 @@ func (p *printer) write(data []byte) {
p.pos.Line++
p.pos.Column = 1
- if !p.escape {
+ if p.mode&inLiteral == 0 {
// write indentation
// use "hard" htabs - indentation columns
// must not be discarded by the tabwriter
@@ -211,7 +220,7 @@ func (p *printer) write(data []byte) {
}
case tabwriter.Escape:
- p.escape = !p.escape
+ p.mode ^= inLiteral
// ignore escape chars introduced by printer - they are
// invisible and must not affect p.pos (was issue #1089)
@@ -272,7 +281,7 @@ func (p *printer) writeItem(pos token.Position, data []byte, tag HTMLTag) {
// (used when printing merged ASTs of different files
// e.g., the result of ast.MergePackageFiles)
p.indent = 0
- p.escape = false
+ p.mode = 0
p.buffer = p.buffer[0:0]
fileChanged = true
}
@@ -683,9 +692,13 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (dro
// follows on the same line: separate with an extra blank
p.write([]byte{' '})
}
- // ensure that there is a newline after a //-style comment
- // or if we are before a closing '}' or at the end of a file
- return p.writeCommentSuffix(last.Text[1] == '/' || tok == token.RBRACE || tok == token.EOF)
+ // ensure that there is a line break after a //-style comment,
+ // before a closing '}' unless explicitly disabled, or at eof
+ needsLinebreak :=
+ last.Text[1] == '/' ||
+ tok == token.RBRACE && p.mode&noExtraLinebreak == 0 ||
+ tok == token.EOF
+ return p.writeCommentSuffix(needsLinebreak)
}
// no comment was written - we should never reach here since
@@ -787,6 +800,9 @@ func (p *printer) print(args ...interface{}) {
var tok token.Token
switch x := f.(type) {
+ case pmode:
+ // toggle printer mode
+ p.mode ^= x
case whiteSpace:
if x == ignore {
// don't add ignore's to the buffer; they
@@ -818,10 +834,14 @@ func (p *printer) print(args ...interface{}) {
data = x.Value
}
// escape all literals so they pass through unchanged
- // (note that valid Go programs cannot contain esc ('\xff')
- // bytes since they do not appear in legal UTF-8 sequences)
- // TODO(gri): do this more efficiently.
- data = []byte("\xff" + string(data) + "\xff")
+ // (note that valid Go programs cannot contain
+ // tabwriter.Escape bytes since they do not appear in
+ // legal UTF-8 sequences)
+ escData := make([]byte, 0, len(data)+2)
+ escData = append(escData, tabwriter.Escape)
+ escData = append(escData, data...)
+ escData = append(escData, tabwriter.Escape)
+ data = escData
tok = x.Kind
case token.Token:
s := x.String()
diff --git a/src/pkg/go/printer/testdata/comments.golden b/src/pkg/go/printer/testdata/comments.golden
index 200ea332f..a86d66174 100644
--- a/src/pkg/go/printer/testdata/comments.golden
+++ b/src/pkg/go/printer/testdata/comments.golden
@@ -422,7 +422,7 @@ func _() {
func ( /* comment1 */ T /* comment2 */ ) _() {}
-func _() { /* one-liner */
+func _() { /* one-line functions with comments are formatted as multi-line functions */
}
func _() {
@@ -430,6 +430,10 @@ func _() {
/* closing curly brace should be on new line */
}
+func _() {
+ _ = []int{0, 1 /* don't introduce a newline after this comment - was issue 1365 */ }
+}
+
// Comments immediately adjacent to punctuation (for which the go/printer
// may obly have estimated position information) must remain after the punctuation.
diff --git a/src/pkg/go/printer/testdata/comments.input b/src/pkg/go/printer/testdata/comments.input
index 4a9ea4742..14cd4cf7a 100644
--- a/src/pkg/go/printer/testdata/comments.input
+++ b/src/pkg/go/printer/testdata/comments.input
@@ -422,12 +422,16 @@ func _() {
func (/* comment1 */ T /* comment2 */) _() {}
-func _() { /* one-liner */ }
+func _() { /* one-line functions with comments are formatted as multi-line functions */ }
func _() {
_ = 0
/* closing curly brace should be on new line */ }
+func _() {
+ _ = []int{0, 1 /* don't introduce a newline after this comment - was issue 1365 */}
+}
+
// Comments immediately adjacent to punctuation (for which the go/printer
// may obly have estimated position information) must remain after the punctuation.