diff options
author | Robert Griesemer <gri@golang.org> | 2009-10-19 13:57:51 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2009-10-19 13:57:51 -0700 |
commit | 76a608808e7979a77e34722fa40f22480b7d549f (patch) | |
tree | ebefc7f88b6a2ee05509aa9006ee5d00894672d5 | |
parent | dde38c3a32b2eb0b7ce5dc83e90c9182593dad46 (diff) | |
download | golang-76a608808e7979a77e34722fa40f22480b7d549f.tar.gz |
support one-line functions
R=rsc
DELTA=207 (160 added, 42 deleted, 5 changed)
OCL=35854
CL=35887
-rw-r--r-- | src/pkg/go/printer/printer.go | 140 | ||||
-rw-r--r-- | src/pkg/go/printer/testdata/declarations.go | 10 | ||||
-rw-r--r-- | src/pkg/go/printer/testdata/declarations.golden | 10 | ||||
-rw-r--r-- | src/pkg/go/printer/testdata/expressions.go | 20 | ||||
-rw-r--r-- | src/pkg/go/printer/testdata/expressions.golden | 12 | ||||
-rw-r--r-- | src/pkg/go/printer/testdata/expressions.raw | 12 |
6 files changed, 161 insertions, 43 deletions
diff --git a/src/pkg/go/printer/printer.go b/src/pkg/go/printer/printer.go index 1db836fb3..0e799eceb 100644 --- a/src/pkg/go/printer/printer.go +++ b/src/pkg/go/printer/printer.go @@ -81,6 +81,7 @@ type printer struct { // Configuration (does not change after initialization) output io.Writer; mode uint; + tabwidth int; errors chan os.Error; // Current state @@ -110,9 +111,10 @@ type printer struct { } -func (p *printer) init(output io.Writer, mode uint) { +func (p *printer) init(output io.Writer, mode uint, tabwidth int) { p.output = output; p.mode = mode; + p.tabwidth = tabwidth; p.errors = make(chan os.Error); p.buffer = make([]whiteSpace, 0, 16); // whitespace sequences are short } @@ -999,8 +1001,7 @@ func (p *printer) expr1(expr ast.Expr, prec1 int) (optSemi bool) { case *ast.FuncLit: p.expr(x.Type); - p.print(blank); - p.block(x.Body, 1); + p.funcBody(x.Body, true); case *ast.ParenExpr: p.print(token.LPAREN); @@ -1448,55 +1449,108 @@ func (p *printer) spec(spec ast.Spec, n int, context declContext) { } -func (p *printer) decl(decl ast.Decl, context declContext) { - switch d := decl.(type) { - case *ast.BadDecl: - p.print(d.Pos(), "BadDecl"); +func (p *printer) genDecl(d *ast.GenDecl, context declContext) { + p.leadComment(d.Doc); + p.print(lineTag(d.Pos()), d.Tok, blank); - case *ast.GenDecl: - p.leadComment(d.Doc); - p.print(lineTag(d.Pos()), d.Tok, blank); - - if d.Lparen.IsValid() { - // group of parenthesized declarations - p.print(d.Lparen, token.LPAREN); - if len(d.Specs) > 0 { - p.print(indent, formfeed); - for i, s := range d.Specs { - if i > 0 { - p.print(newline); - } - p.spec(s, len(d.Specs), inGroup); + if d.Lparen.IsValid() { + // group of parenthesized declarations + p.print(d.Lparen, token.LPAREN); + if len(d.Specs) > 0 { + p.print(indent, formfeed); + for i, s := range d.Specs { + if i > 0 { + p.print(newline); } - p.print(unindent, formfeed); + p.spec(s, len(d.Specs), inGroup); } - p.print(d.Rparen, token.RPAREN); + p.print(unindent, formfeed); + } + p.print(d.Rparen, token.RPAREN); - } else { - // single declaration - p.spec(d.Specs[0], 1, context); + } else { + // single declaration + p.spec(d.Specs[0], 1, context); + } +} + + +func (p *printer) isOneLiner(b *ast.BlockStmt) bool { + if len(b.List) != 1 || p.commentBefore(b.Rbrace) { + // too many statements or there is a comment - all bets are off + return false; + } + + // test-print the statement and see if it would fit + var buf bytes.Buffer; + _, err := Fprint(&buf, b.List[0], p.mode, p.tabwidth); + if err != nil { + return false; // don't try + } + + if buf.Len() > 40 { + return false; // too long + } + + for _, ch := range buf.Bytes() { + if ch < ' ' { + return false; // contains control chars (tabs, newlines) } + } - case *ast.FuncDecl: - p.leadComment(d.Doc); - p.print(lineTag(d.Pos()), token.FUNC, blank); - if recv := d.Recv; recv != nil { - // method: print receiver - p.print(token.LPAREN); - if len(recv.Names) > 0 { - p.expr(recv.Names[0]); - p.print(blank); - } - p.expr(recv.Type); - p.print(token.RPAREN, blank); + return true; +} + + +func (p *printer) funcBody(b *ast.BlockStmt, isLit bool) { + if b == nil { + return; + } + + // TODO(gri): enable for function declarations, eventually. + if isLit && p.isOneLiner(b) { + sep := vtab; + if isLit { + sep = blank; } - p.expr(d.Name); - p.signature(d.Type.Params, d.Type.Results); - if d.Body != nil { + p.print(sep, b.Pos(), token.LBRACE, blank); + p.stmt(b.List[0]); + p.print(blank, b.Rbrace, token.RBRACE); + return; + } + + p.print(blank); + p.block(b, 1); +} + + +func (p *printer) funcDecl(d *ast.FuncDecl) { + p.leadComment(d.Doc); + p.print(lineTag(d.Pos()), token.FUNC, blank); + if recv := d.Recv; recv != nil { + // method: print receiver + p.print(token.LPAREN); + if len(recv.Names) > 0 { + p.expr(recv.Names[0]); p.print(blank); - p.block(d.Body, 1); } + p.expr(recv.Type); + p.print(token.RPAREN, blank); + } + p.expr(d.Name); + p.signature(d.Type.Params, d.Type.Results); + p.funcBody(d.Body, false); +} + +func (p *printer) decl(decl ast.Decl, context declContext) { + switch d := decl.(type) { + case *ast.BadDecl: + p.print(d.Pos(), "BadDecl"); + case *ast.GenDecl: + p.genDecl(d, context); + case *ast.FuncDecl: + p.funcDecl(d); default: panic("unreachable"); } @@ -1667,7 +1721,7 @@ func Fprint(output io.Writer, node interface{}, mode uint, tabwidth int) (int, o // setup printer and print node var p printer; - p.init(output, mode); + p.init(output, mode, tabwidth); go func() { switch n := node.(type) { case ast.Expr: diff --git a/src/pkg/go/printer/testdata/declarations.go b/src/pkg/go/printer/testdata/declarations.go index 577e32cdd..3e926664f 100644 --- a/src/pkg/go/printer/testdata/declarations.go +++ b/src/pkg/go/printer/testdata/declarations.go @@ -360,3 +360,13 @@ func _() {} func _() {} // an empty line before this function func _() {} func _() {} + +func _() { + f(1, 2, 3); +} +func _(x int) int { + return x+1 +} +func _() int { + type T struct{} +} diff --git a/src/pkg/go/printer/testdata/declarations.golden b/src/pkg/go/printer/testdata/declarations.golden index 0b2f23c9f..3a8fa8546 100644 --- a/src/pkg/go/printer/testdata/declarations.golden +++ b/src/pkg/go/printer/testdata/declarations.golden @@ -360,3 +360,13 @@ func _() {} func _() {} // an empty line before this function func _() {} func _() {} + +func _() { + f(1, 2, 3); +} +func _(x int) int { + return x+1; +} +func _() int { + type T struct{} +} diff --git a/src/pkg/go/printer/testdata/expressions.go b/src/pkg/go/printer/testdata/expressions.go index f771bfcee..07cb261aa 100644 --- a/src/pkg/go/printer/testdata/expressions.go +++ b/src/pkg/go/printer/testdata/expressions.go @@ -118,6 +118,26 @@ _ = `foo func _() { + // one-line function literals + _ = func() {}; + _ = func() int { + return 0; + }; + _ = func(x, y int) bool { + return x < y + }; + + f(func() {}); + f(func() int { + return 0; + }); + f(func(x, y int) bool { + return x < y + }); +} + + +func _() { // not not add extra indentation to multi-line string lists _ = "foo" "bar"; _ = "foo" diff --git a/src/pkg/go/printer/testdata/expressions.golden b/src/pkg/go/printer/testdata/expressions.golden index b7a4493e8..48a6e6a4a 100644 --- a/src/pkg/go/printer/testdata/expressions.golden +++ b/src/pkg/go/printer/testdata/expressions.golden @@ -118,6 +118,18 @@ func _() { func _() { + // one-line function literals + _ = func() {}; + _ = func() int { return 0 }; + _ = func(x, y int) bool { return x < y }; + + f(func() {}); + f(func() int { return 0 }); + f(func(x, y int) bool { return x < y }); +} + + +func _() { // not not add extra indentation to multi-line string lists _ = "foo" "bar"; _ = "foo" diff --git a/src/pkg/go/printer/testdata/expressions.raw b/src/pkg/go/printer/testdata/expressions.raw index a9b7b9436..6ee80ed94 100644 --- a/src/pkg/go/printer/testdata/expressions.raw +++ b/src/pkg/go/printer/testdata/expressions.raw @@ -118,6 +118,18 @@ func _() { func _() { + // one-line function literals + _ = func() {}; + _ = func() int { return 0 }; + _ = func(x, y int) bool { return x < y }; + + f(func() {}); + f(func() int { return 0 }); + f(func(x, y int) bool { return x < y }); +} + + +func _() { // not not add extra indentation to multi-line string lists _ = "foo" "bar"; _ = "foo" |