diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-10-26 23:57:58 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-10-26 23:57:58 +0000 |
commit | d8f412571f8768df2d3239e72392dfeabbad1559 (patch) | |
tree | 19d182df05ead7ff8ba7ee00a7d57555e1383fdf /libgo/go/go/printer | |
parent | e0c39d66d4f0607177b1cf8995dda56a667e07b3 (diff) |
Update Go library to last weekly.
From-SVN: r180552
Diffstat (limited to 'libgo/go/go/printer')
-rw-r--r-- | libgo/go/go/printer/nodes.go | 16 | ||||
-rw-r--r-- | libgo/go/go/printer/printer.go | 81 | ||||
-rw-r--r-- | libgo/go/go/printer/printer_test.go | 14 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/declarations.golden | 111 | ||||
-rw-r--r-- | libgo/go/go/printer/testdata/declarations.input | 76 |
5 files changed, 233 insertions, 65 deletions
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go index 9cd975ec1be..364530634aa 100644 --- a/libgo/go/go/printer/nodes.go +++ b/libgo/go/go/printer/nodes.go @@ -269,6 +269,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { p.print(fields.Opening, token.LPAREN) if len(fields.List) > 0 { + ws := indent var prevLine, line int for i, par := range fields.List { if i > 0 { @@ -278,19 +279,30 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) { } else { line = p.fset.Position(par.Type.Pos()).Line } - if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ignore, true) { + if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ws, true) { + ws = ignore *multiLine = true } else { p.print(blank) } } if len(par.Names) > 0 { - p.identList(par.Names, false, multiLine) + // Very subtle: If we indented before (ws == ignore), identList + // won't indent again. If we didn't (ws == indent), identList will + // indent if the identList spans multiple lines, and it will outdent + // again at the end (and still ws == indent). Thus, a subsequent indent + // by a linebreak call after a type, or in the next multi-line identList + // will do the right thing. + p.identList(par.Names, ws == indent, multiLine) p.print(blank) } p.expr(par.Type, multiLine) prevLine = p.fset.Position(par.Type.Pos()).Line } + if ws == ignore { + // unindent if we indented + p.print(unindent) + } } p.print(fields.Closing, token.RPAREN) } diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go index 871fefa0c8f..bfabd749abb 100644 --- a/libgo/go/go/printer/printer.go +++ b/libgo/go/go/printer/printer.go @@ -13,7 +13,6 @@ import ( "io" "os" "path/filepath" - "runtime" "tabwriter" ) @@ -55,12 +54,17 @@ const ( noExtraLinebreak ) +// local error wrapper so we can distinguish os.Errors we want to return +// as errors from genuine panics (which we don't want to return as errors) +type osError struct { + err os.Error +} + type printer struct { // Configuration (does not change after initialization) output io.Writer Config - fset *token.FileSet - errors chan os.Error + fset *token.FileSet // Current state written int // number of bytes written @@ -95,7 +99,6 @@ func (p *printer) init(output io.Writer, cfg *Config, fset *token.FileSet, nodeS p.output = output p.Config = *cfg p.fset = fset - p.errors = make(chan os.Error) p.wsbuf = make([]whiteSpace, 0, 16) // whitespace sequences are short p.nodeSizes = nodeSizes } @@ -143,8 +146,7 @@ func (p *printer) write0(data []byte) { n, err := p.output.Write(data) p.written += n if err != nil { - p.errors <- err - runtime.Goexit() + panic(osError{err}) } } } @@ -923,7 +925,7 @@ type Config struct { } // fprint implements Fprint and takes a nodesSizes map for setting up the printer state. -func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{}, nodeSizes map[ast.Node]int) (int, os.Error) { +func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{}, nodeSizes map[ast.Node]int) (written int, err os.Error) { // redirect output through a trimmer to eliminate trailing whitespace // (Input to a tabwriter must be untrimmed since trailing tabs provide // formatting information. The tabwriter could provide trimming @@ -950,47 +952,50 @@ func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{ output = tw } - // setup printer and print node + // setup printer var p printer p.init(output, cfg, fset, nodeSizes) - go func() { - switch n := node.(type) { - case ast.Expr: - p.useNodeComments = true - p.expr(n, ignoreMultiLine) - case ast.Stmt: - p.useNodeComments = true - // A labeled statement will un-indent to position the - // label. Set indent to 1 so we don't get indent "underflow". - if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt { - p.indent = 1 - } - p.stmt(n, false, ignoreMultiLine) - case ast.Decl: - p.useNodeComments = true - p.decl(n, ignoreMultiLine) - case ast.Spec: - p.useNodeComments = true - p.spec(n, 1, false, ignoreMultiLine) - case *ast.File: - p.comments = n.Comments - p.useNodeComments = n.Comments == nil - p.file(n) - default: - p.errors <- fmt.Errorf("printer.Fprint: unsupported node type %T", n) - runtime.Goexit() + defer func() { + written = p.written + if e := recover(); e != nil { + err = e.(osError).err // re-panics if it's not a local osError } - p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF) - p.errors <- nil // no errors }() - err := <-p.errors // wait for completion of goroutine + + // print node + switch n := node.(type) { + case ast.Expr: + p.useNodeComments = true + p.expr(n, ignoreMultiLine) + case ast.Stmt: + p.useNodeComments = true + // A labeled statement will un-indent to position the + // label. Set indent to 1 so we don't get indent "underflow". + if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt { + p.indent = 1 + } + p.stmt(n, false, ignoreMultiLine) + case ast.Decl: + p.useNodeComments = true + p.decl(n, ignoreMultiLine) + case ast.Spec: + p.useNodeComments = true + p.spec(n, 1, false, ignoreMultiLine) + case *ast.File: + p.comments = n.Comments + p.useNodeComments = n.Comments == nil + p.file(n) + default: + panic(osError{fmt.Errorf("printer.Fprint: unsupported node type %T", n)}) + } + p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF) // flush tabwriter, if any if tw != nil { tw.Flush() // ignore errors } - return p.written, err + return } // Fprint "pretty-prints" an AST node to output and returns the number diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go index ff2d906b560..a644aa383ab 100644 --- a/libgo/go/go/printer/printer_test.go +++ b/libgo/go/go/printer/printer_test.go @@ -7,10 +7,10 @@ package printer import ( "bytes" "flag" - "io/ioutil" "go/ast" "go/parser" "go/token" + "io/ioutil" "path/filepath" "testing" "time" @@ -192,3 +192,15 @@ func TestLineComments(t *testing.T) { t.Errorf("got %d, expected %d\n", nlines, expected) } } + +// Verify that the printer can be invoked during initialization. +func init() { + const name = "foobar" + var buf bytes.Buffer + if err := Fprint(&buf, fset, &ast.Ident{Name: name}); err != nil { + panic(err) + } + if s := buf.String(); s != name { + panic("got " + s + ", want " + name) + } +} diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden index 970533e8cfb..bfa2568c21f 100644 --- a/libgo/go/go/printer/testdata/declarations.golden +++ b/libgo/go/go/printer/testdata/declarations.golden @@ -692,56 +692,119 @@ func _(x ...chan int) // these parameter lists must remain multi-line since they are multi-line in the source func _(bool, -int) { + int) { } func _(x bool, -y int) { + y int) { } func _(x, -y bool) { + y bool) { } func _(bool, // comment -int) { + int) { } func _(x bool, // comment -y int) { + y int) { } func _(x, // comment -y bool) { + y bool) { } func _(bool, // comment -// comment -int) { + // comment + int) { } func _(x bool, // comment -// comment -y int) { + // comment + y int) { } func _(x, // comment -// comment -y bool) { + // comment + y bool) { } func _(bool, -// comment -int) { + // comment + int) { } func _(x bool, -// comment -y int) { + // comment + y int) { } func _(x, -// comment -y bool) { + // comment + y bool) { } func _(x, // comment -y, // comment -z bool) { + y, // comment + z bool) { } func _(x, // comment -y, // comment -z bool) { + y, // comment + z bool) { } func _(x int, // comment -y float, // comment -z bool) { + y float, // comment + z bool) { +} + +// properly indent multi-line signatures +func ManageStatus(in <-chan *Status, req <-chan Request, + stat chan<- *TargetInfo, + TargetHistorySize int) { +} + +func MultiLineSignature0(a, b, c int) { +} + +func MultiLineSignature1(a, b, c int, + u, v, w float) { +} + +func MultiLineSignature2(a, b, + c int) { +} + +func MultiLineSignature3(a, b, + c int, u, v, + w float, + x ...int) { +} + +func MultiLineSignature4(a, b, c int, + u, v, + w float, + x ...int) { +} + +func MultiLineSignature5(a, b, c int, + u, v, w float, + p, q, + r string, + x ...int) { +} + +// make sure it also works for methods in interfaces +type _ interface { + MultiLineSignature0(a, b, c int) + + MultiLineSignature1(a, b, c int, + u, v, w float) + + MultiLineSignature2(a, b, + c int) + + MultiLineSignature3(a, b, + c int, u, v, + w float, + x ...int) + + MultiLineSignature4(a, b, c int, + u, v, + w float, + x ...int) + + MultiLineSignature5(a, b, c int, + u, v, w float, + p, q, + r string, + x ...int) } diff --git a/libgo/go/go/printer/testdata/declarations.input b/libgo/go/go/printer/testdata/declarations.input index c6134096bf1..1d69c57b517 100644 --- a/libgo/go/go/printer/testdata/declarations.input +++ b/libgo/go/go/printer/testdata/declarations.input @@ -755,3 +755,79 @@ func _(x int, // comment y float, // comment z bool) { } + + +// properly indent multi-line signatures +func ManageStatus(in <-chan *Status, req <-chan Request, +stat chan<- *TargetInfo, +TargetHistorySize int) { +} + +func MultiLineSignature0( +a, b, c int, +) {} + +func MultiLineSignature1( +a, b, c int, +u, v, w float, +) {} + +func MultiLineSignature2( +a, b, +c int, +) {} + +func MultiLineSignature3( +a, b, +c int, u, v, +w float, + x ...int) {} + +func MultiLineSignature4( +a, b, c int, +u, v, +w float, + x ...int) {} + +func MultiLineSignature5( +a, b, c int, +u, v, w float, +p, q, +r string, + x ...int) {} + +// make sure it also works for methods in interfaces +type _ interface { +MultiLineSignature0( +a, b, c int, +) + +MultiLineSignature1( +a, b, c int, +u, v, w float, +) + +MultiLineSignature2( +a, b, +c int, +) + +MultiLineSignature3( +a, b, +c int, u, v, +w float, + x ...int) + +MultiLineSignature4( +a, b, c int, +u, v, +w float, + x ...int) + +MultiLineSignature5( +a, b, c int, +u, v, w float, +p, q, +r string, + x ...int) +} |