summaryrefslogtreecommitdiff
path: root/src/pkg/go/printer/nodes.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/go/printer/nodes.go')
-rw-r--r--src/pkg/go/printer/nodes.go77
1 files changed, 49 insertions, 28 deletions
diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go
index 7e27b3b6e..4c2f0c57f 100644
--- a/src/pkg/go/printer/nodes.go
+++ b/src/pkg/go/printer/nodes.go
@@ -18,19 +18,21 @@ import (
// Disabled formatting - enable eventually and remove the flag.
const (
- oneLineFuncDecls = false;
compositeLitBlank = false;
stringListMode = exprListMode(0); // previously: noIndent
)
-// Other outstanding formatting issues:
+// Other formatting issues:
// - replacement of expression spacing algorithm with rsc's algorithm
// - support for one-line composite types (e.g. structs) as composite literals types
// - better comment formatting for /*-style comments at the end of a line (e.g. a declaration)
-// when the comment spans multiple lines
+// when the comment spans multiple lines; if such a comment is just two lines, formatting is
+// not idempotent
// - formatting of expression lists; especially for string lists (stringListMode)
// - blank after { and before } in one-line composite literals probably looks better
+// - should use blank instead of tab to separate one-line function bodies from
+// the function header unless there is a group of consecutive one-liners
// ----------------------------------------------------------------------------
@@ -497,7 +499,7 @@ func (p *printer) expr1(expr ast.Expr, prec1 int, multiLine *bool) (optSemi bool
case *ast.FuncLit:
p.expr(x.Type, multiLine);
- p.funcBody(x.Body, true, multiLine);
+ p.funcBody(x.Body, distance(x.Type.Pos(), p.pos), true, multiLine);
case *ast.ParenExpr:
p.print(token.LPAREN);
@@ -994,42 +996,50 @@ func (p *printer) genDecl(d *ast.GenDecl, context declContext, multiLine *bool)
}
-func (p *printer) isOneLiner(b *ast.BlockStmt) bool {
- switch {
- case len(b.List) > 1 || p.commentBefore(b.Rbrace):
- return false; // too many statements or there is a comment - all bets are off
- case len(b.List) == 0:
- return true; // empty block and no comments
- }
-
- // test-print the statement and see if it would fit
+// nodeSize determines the size of n in chars after formatting.
+// The result is <= maxSize if the node fits on one line with at
+// most maxSize chars and the formatted output doesn't contain
+// any control chars. Otherwise, the result is > maxSize.
+//
+func (p *printer) nodeSize(n ast.Node, maxSize int) (size int) {
+ size = maxSize+1; // assume n doesn't fit
var buf bytes.Buffer;
- _, err := p.Config.Fprint(&buf, b.List[0]);
- if err != nil {
- return false; // don't try
- }
-
- if buf.Len() > 40 {
- return false; // too long
+ if _, err := p.Config.Fprint(&buf, n); err != nil {
+ return;
}
-
- for _, ch := range buf.Bytes() {
- if ch < ' ' {
- return false; // contains control chars (tabs, newlines)
+ if buf.Len() <= maxSize {
+ for _, ch := range buf.Bytes() {
+ if ch < ' ' {
+ return;
+ }
}
+ size = buf.Len(); // n fits
}
+ return;
+}
- return true;
+
+func (p *printer) isOneLineFunc(b *ast.BlockStmt, headerSize int) bool {
+ const maxSize = 90; // adjust as appropriate, this is an approximate value
+ bodySize := 0;
+ switch {
+ case len(b.List) > 1 || p.commentBefore(b.Rbrace):
+ return false; // too many statements or there is a comment - all bets are off
+ case len(b.List) == 1:
+ bodySize = p.nodeSize(b.List[0], maxSize);
+ }
+ // require both headers and overall size to be not "too large"
+ return headerSize <= maxSize/2 && headerSize + bodySize <= maxSize;
}
// Sets multiLine to true if the function body spans multiple lines.
-func (p *printer) funcBody(b *ast.BlockStmt, isLit bool, multiLine *bool) {
+func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLine *bool) {
if b == nil {
return;
}
- if (oneLineFuncDecls || isLit) && p.isOneLiner(b) {
+ if p.isOneLineFunc(b, headerSize) {
sep := vtab;
if isLit {
sep = blank;
@@ -1050,6 +1060,17 @@ func (p *printer) funcBody(b *ast.BlockStmt, isLit bool, multiLine *bool) {
}
+// distance returns the column difference between from and to if both
+// are on the same line; if they are on different lines (or unknown)
+// the result is infinity (1<<30).
+func distance(from, to token.Position) int {
+ if from.IsValid() && to.IsValid() && from.Line == to.Line {
+ return to.Column - from.Column;
+ }
+ return 1<<30;
+}
+
+
// Sets multiLine to true if the declaration spans multiple lines.
func (p *printer) funcDecl(d *ast.FuncDecl, multiLine *bool) {
p.leadComment(d.Doc);
@@ -1066,7 +1087,7 @@ func (p *printer) funcDecl(d *ast.FuncDecl, multiLine *bool) {
}
p.expr(d.Name, multiLine);
p.signature(d.Type.Params, d.Type.Results, multiLine);
- p.funcBody(d.Body, false, multiLine);
+ p.funcBody(d.Body, distance(d.Pos(), p.pos), false, multiLine);
}