summaryrefslogtreecommitdiff
path: root/libgo/go/go/printer
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-10-26 23:57:58 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-10-26 23:57:58 +0000
commitd8f412571f8768df2d3239e72392dfeabbad1559 (patch)
tree19d182df05ead7ff8ba7ee00a7d57555e1383fdf /libgo/go/go/printer
parente0c39d66d4f0607177b1cf8995dda56a667e07b3 (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.go16
-rw-r--r--libgo/go/go/printer/printer.go81
-rw-r--r--libgo/go/go/printer/printer_test.go14
-rw-r--r--libgo/go/go/printer/testdata/declarations.golden111
-rw-r--r--libgo/go/go/printer/testdata/declarations.input76
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)
+}