gofmt'ed parts of go

R=rsc
http://go/go-review/1023001
This commit is contained in:
Robert Griesemer 2009-11-05 15:58:28 -08:00
parent 65063bc61d
commit 10242e806f
3 changed files with 136 additions and 126 deletions

View File

@ -18,9 +18,9 @@ import (
// Disabled formatting - enable eventually and remove the flag. // Disabled formatting - enable eventually and remove the flag.
const ( const (
oneLineFuncDecls = false; oneLineFuncDecls = false;
compositeLitBlank = false; compositeLitBlank = false;
stringListMode = exprListMode(0); // previously: noIndent stringListMode = exprListMode(0); // previously: noIndent
) )
@ -37,8 +37,10 @@ const (
func (p *printer) linebreak(line, min, max int, ws whiteSpace, newSection bool) (printedBreak bool) { func (p *printer) linebreak(line, min, max int, ws whiteSpace, newSection bool) (printedBreak bool) {
n := line - p.pos.Line; n := line - p.pos.Line;
switch { switch {
case n < min: n = min; case n < min:
case n > max: n = max; n = min;
case n > max:
n = max;
} }
if n > 0 { if n > 0 {
p.print(ws); p.print(ws);
@ -118,12 +120,13 @@ func (p *printer) stringList(list []*ast.BasicLit, multiLine *bool) {
} }
type exprListMode uint; type exprListMode uint
const ( const (
blankStart exprListMode = 1 << iota; // print a blank before the list blankStart exprListMode = 1<<iota; // print a blank before the list
commaSep; // elements are separated by commas commaSep; // elements are separated by commas
commaTerm; // elements are terminated by comma commaTerm; // elements are terminated by comma
noIndent; // no extra indentation in multi-line lists noIndent; // no extra indentation in multi-line lists
) )
@ -150,7 +153,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, mode exprListMo
// all list entries on a single line // all list entries on a single line
for i, x := range list { for i, x := range list {
if i > 0 { if i > 0 {
if mode & commaSep != 0 { if mode&commaSep != 0 {
p.print(token.COMMA); p.print(token.COMMA);
} }
p.print(blank); p.print(blank);
@ -179,7 +182,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, mode exprListMo
prev := line; prev := line;
line = x.Pos().Line; line = x.Pos().Line;
if i > 0 { if i > 0 {
if mode & commaSep != 0 { if mode&commaSep != 0 {
p.print(token.COMMA); p.print(token.COMMA);
} }
if prev < line { if prev < line {
@ -200,7 +203,7 @@ func (p *printer) exprList(prev token.Position, list []ast.Expr, mode exprListMo
// expression list - be conservative and check anyway // expression list - be conservative and check anyway
p.print(unindent); p.print(unindent);
} }
p.print(formfeed); // terminating comma needs a line break to look good p.print(formfeed); // terminating comma needs a line break to look good
} else if ws == ignore && mode&noIndent == 0 { } else if ws == ignore && mode&noIndent == 0 {
p.print(unindent); p.print(unindent);
} }
@ -304,7 +307,7 @@ func (p *printer) fieldList(lbrace token.Position, list []*ast.Field, rbrace tok
p.print("// contains unexported fields"); p.print("// contains unexported fields");
} }
} else { // interface } else { // interface
var ml bool; var ml bool;
for i, f := range list { for i, f := range list {
@ -353,7 +356,7 @@ func needsBlanks(expr ast.Expr) bool {
return false; return false;
case *ast.IndexExpr: case *ast.IndexExpr:
// index expressions don't need blanks if the indexed expressions are simple // index expressions don't need blanks if the indexed expressions are simple
return needsBlanks(x.X) return needsBlanks(x.X);
case *ast.CallExpr: case *ast.CallExpr:
// call expressions need blanks if they have more than one // call expressions need blanks if they have more than one
// argument or if the function expression needs blanks // argument or if the function expression needs blanks
@ -539,7 +542,7 @@ func (p *printer) expr1(expr ast.Expr, prec1 int, multiLine *bool) (optSemi bool
p.print(blank); p.print(blank);
} }
p.print(x.Lbrace, token.LBRACE); p.print(x.Lbrace, token.LBRACE);
p.exprList(x.Lbrace, x.Elts, commaSep|commaTerm, multiLine); p.exprList(x.Lbrace, x.Elts, commaSep | commaTerm, multiLine);
p.print(x.Rbrace, token.RBRACE); p.print(x.Rbrace, token.RBRACE);
case *ast.Ellipsis: case *ast.Ellipsis:
@ -603,7 +606,7 @@ func (p *printer) expr(x ast.Expr, multiLine *bool) (optSemi bool) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
const maxStmtNewlines = 2 // maximum number of newlines between statements const maxStmtNewlines = 2 // maximum number of newlines between statements
// Print the statement list indented, but without a newline after the last statement. // Print the statement list indented, but without a newline after the last statement.
// Extra line breaks between statements in the source are respected but at most one // Extra line breaks between statements in the source are respected but at most one
@ -695,7 +698,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) (optSemi bool) {
case *ast.DeclStmt: case *ast.DeclStmt:
p.decl(s.Decl, inStmtList, multiLine); p.decl(s.Decl, inStmtList, multiLine);
optSemi = true; // decl prints terminating semicolon if necessary optSemi = true; // decl prints terminating semicolon if necessary
case *ast.EmptyStmt: case *ast.EmptyStmt:
// nothing to do // nothing to do
@ -775,7 +778,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) (optSemi bool) {
} }
p.print(s.Colon, token.COLON); p.print(s.Colon, token.COLON);
p.stmtList(s.Body, 1); p.stmtList(s.Body, 1);
optSemi = true; // "block" without {}'s optSemi = true; // "block" without {}'s
case *ast.SwitchStmt: case *ast.SwitchStmt:
p.print(token.SWITCH); p.print(token.SWITCH);
@ -793,7 +796,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) (optSemi bool) {
} }
p.print(s.Colon, token.COLON); p.print(s.Colon, token.COLON);
p.stmtList(s.Body, 1); p.stmtList(s.Body, 1);
optSemi = true; // "block" without {}'s optSemi = true; // "block" without {}'s
case *ast.TypeSwitchStmt: case *ast.TypeSwitchStmt:
p.print(token.SWITCH); p.print(token.SWITCH);
@ -822,7 +825,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) (optSemi bool) {
} }
p.print(s.Colon, token.COLON); p.print(s.Colon, token.COLON);
p.stmtList(s.Body, 1); p.stmtList(s.Body, 1);
optSemi = true; // "block" without {}'s optSemi = true; // "block" without {}'s
case *ast.SelectStmt: case *ast.SelectStmt:
p.print(token.SELECT, blank); p.print(token.SELECT, blank);
@ -862,9 +865,10 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) (optSemi bool) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Declarations // Declarations
type declContext uint; type declContext uint
const ( const (
atTop declContext = iota; atTop declContext = iota;
inGroup; inGroup;
inStmtList; inStmtList;
) )
@ -876,9 +880,9 @@ const (
// //
func (p *printer) spec(spec ast.Spec, n int, context declContext, multiLine *bool) { func (p *printer) spec(spec ast.Spec, n int, context declContext, multiLine *bool) {
var ( var (
optSemi bool; // true if a semicolon is optional optSemi bool; // true if a semicolon is optional
comment *ast.CommentGroup; // a line comment, if any comment *ast.CommentGroup; // a line comment, if any
extraTabs int; // number of extra tabs before comment, if any extraTabs int; // number of extra tabs before comment, if any
) )
switch s := spec.(type) { switch s := spec.(type) {
@ -893,7 +897,7 @@ func (p *printer) spec(spec ast.Spec, n int, context declContext, multiLine *boo
case *ast.ValueSpec: case *ast.ValueSpec:
p.leadComment(s.Doc); p.leadComment(s.Doc);
p.identList(s.Names, multiLine); // always present p.identList(s.Names, multiLine); // always present
if n == 1 { if n == 1 {
if s.Type != nil { if s.Type != nil {
p.print(blank); p.print(blank);
@ -984,25 +988,25 @@ func (p *printer) genDecl(d *ast.GenDecl, context declContext, multiLine *bool)
func (p *printer) isOneLiner(b *ast.BlockStmt) bool { func (p *printer) isOneLiner(b *ast.BlockStmt) bool {
switch { switch {
case len(b.List) > 1 || p.commentBefore(b.Rbrace): case len(b.List) > 1 || p.commentBefore(b.Rbrace):
return false; // too many statements or there is a comment - all bets are off return false; // too many statements or there is a comment - all bets are off
case len(b.List) == 0: case len(b.List) == 0:
return true; // empty block and no comments return true; // empty block and no comments
} }
// test-print the statement and see if it would fit // test-print the statement and see if it would fit
var buf bytes.Buffer; var buf bytes.Buffer;
_, err := p.Config.Fprint(&buf, b.List[0]); _, err := p.Config.Fprint(&buf, b.List[0]);
if err != nil { if err != nil {
return false; // don't try return false; // don't try
} }
if buf.Len() > 40 { if buf.Len() > 40 {
return false; // too long return false; // too long
} }
for _, ch := range buf.Bytes() { for _, ch := range buf.Bytes() {
if ch < ' ' { if ch < ' ' {
return false; // contains control chars (tabs, newlines) return false; // contains control chars (tabs, newlines)
} }
} }
@ -1075,7 +1079,7 @@ func (p *printer) decl(decl ast.Decl, context declContext, multiLine *bool) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Files // Files
const maxDeclNewlines = 3 // maximum number of newlines between declarations const maxDeclNewlines = 3 // maximum number of newlines between declarations
func declToken(decl ast.Decl) (tok token.Token) { func declToken(decl ast.Decl) (tok token.Token) {
tok = token.ILLEGAL; tok = token.ILLEGAL;

View File

@ -20,35 +20,35 @@ import (
const ( const (
debug = false; // enable for debugging debug = false; // enable for debugging
maxNewlines = 3; // maximum vertical white space maxNewlines = 3; // maximum vertical white space
) )
type whiteSpace int type whiteSpace int
const ( const (
ignore = whiteSpace(0); ignore = whiteSpace(0);
blank = whiteSpace(' '); blank = whiteSpace(' ');
vtab = whiteSpace('\v'); vtab = whiteSpace('\v');
newline = whiteSpace('\n'); newline = whiteSpace('\n');
formfeed = whiteSpace('\f'); formfeed = whiteSpace('\f');
indent = whiteSpace('>'); indent = whiteSpace('>');
unindent = whiteSpace('<'); unindent = whiteSpace('<');
) )
var ( var (
esc = []byte{tabwriter.Escape}; esc = []byte{tabwriter.Escape};
htab = []byte{'\t'}; htab = []byte{'\t'};
htabs = [...]byte{'\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t'}; htabs = [...]byte{'\t', '\t', '\t', '\t', '\t', '\t', '\t', '\t'};
newlines = [...]byte{'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; // more than maxNewlines newlines = [...]byte{'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; // more than maxNewlines
esc_quot = strings.Bytes("&#34;"); // shorter than "&quot;" esc_quot = strings.Bytes("&#34;"); // shorter than "&quot;"
esc_apos = strings.Bytes("&#39;"); // shorter than "&apos;" esc_apos = strings.Bytes("&#39;"); // shorter than "&apos;"
esc_amp = strings.Bytes("&amp;"); esc_amp = strings.Bytes("&amp;");
esc_lt = strings.Bytes("&lt;"); esc_lt = strings.Bytes("&lt;");
esc_gt = strings.Bytes("&gt;"); esc_gt = strings.Bytes("&gt;");
) )
@ -57,38 +57,38 @@ var noPos token.Position
// Use ignoreMultiLine if the multiLine information is not important. // Use ignoreMultiLine if the multiLine information is not important.
var ignoreMultiLine = new(bool); var ignoreMultiLine = new(bool)
type printer struct { type printer struct {
// Configuration (does not change after initialization) // Configuration (does not change after initialization)
output io.Writer; output io.Writer;
Config; Config;
errors chan os.Error; errors chan os.Error;
// Current state // Current state
written int; // number of bytes written written int; // number of bytes written
indent int; // current indentation indent int; // current indentation
escape bool; // true if in escape sequence escape bool; // true if in escape sequence
// Buffered whitespace // Buffered whitespace
buffer []whiteSpace; buffer []whiteSpace;
// The (possibly estimated) position in the generated output; // The (possibly estimated) position in the generated output;
// in AST space (i.e., pos is set whenever a token position is // in AST space (i.e., pos is set whenever a token position is
// known accurately, and updated dependending on what has been // known accurately, and updated dependending on what has been
// written) // written)
pos token.Position; pos token.Position;
// The value of pos immediately after the last item has been // The value of pos immediately after the last item has been
// written using writeItem. // written using writeItem.
last token.Position; last token.Position;
// HTML support // HTML support
lastTaggedLine int; // last line for which a line tag was written lastTaggedLine int; // last line for which a line tag was written
// The list of comments; or nil. // The list of comments; or nil.
comment *ast.CommentGroup; comment *ast.CommentGroup;
} }
@ -96,7 +96,7 @@ func (p *printer) init(output io.Writer, cfg *Config) {
p.output = output; p.output = output;
p.Config = *cfg; p.Config = *cfg;
p.errors = make(chan os.Error); p.errors = make(chan os.Error);
p.buffer = make([]whiteSpace, 0, 16); // whitespace sequences are short p.buffer = make([]whiteSpace, 0, 16); // whitespace sequences are short
} }
@ -126,7 +126,7 @@ func (p *printer) write(data []byte) {
p.write0(data[i0 : i+1]); p.write0(data[i0 : i+1]);
// update p.pos // update p.pos
p.pos.Offset += i+1 - i0; p.pos.Offset += i+1-i0;
p.pos.Line++; p.pos.Line++;
p.pos.Column = 1; p.pos.Column = 1;
@ -151,21 +151,26 @@ func (p *printer) write(data []byte) {
case '"', '\'', '&', '<', '>': case '"', '\'', '&', '<', '>':
if p.Mode & GenHTML != 0 { if p.Mode & GenHTML != 0 {
// write segment ending in b // write segment ending in b
p.write0(data[i0 : i]); p.write0(data[i0:i]);
// write HTML-escaped b // write HTML-escaped b
var esc []byte; var esc []byte;
switch b { switch b {
case '"': esc = esc_quot; case '"':
case '\'': esc = esc_apos; esc = esc_quot;
case '&': esc = esc_amp; case '\'':
case '<': esc = esc_lt; esc = esc_apos;
case '>': esc = esc_gt; case '&':
esc = esc_amp;
case '<':
esc = esc_lt;
case '>':
esc = esc_gt;
} }
p.write0(esc); p.write0(esc);
// update p.pos // update p.pos
d := i+1 - i0; d := i+1-i0;
p.pos.Offset += d; p.pos.Offset += d;
p.pos.Column += d; p.pos.Column += d;
@ -179,10 +184,10 @@ func (p *printer) write(data []byte) {
} }
// write remaining segment // write remaining segment
p.write0(data[i0 : len(data)]); p.write0(data[i0:len(data)]);
// update p.pos // update p.pos
d := len(data) - i0; d := len(data)-i0;
p.pos.Offset += d; p.pos.Offset += d;
p.pos.Column += d; p.pos.Column += d;
} }
@ -193,7 +198,7 @@ func (p *printer) writeNewlines(n int) {
if n > maxNewlines { if n > maxNewlines {
n = maxNewlines; n = maxNewlines;
} }
p.write(newlines[0 : n]); p.write(newlines[0:n]);
} }
} }
@ -367,8 +372,8 @@ func split(text []byte) [][]byte {
i := 0; i := 0;
for j, c := range text { for j, c := range text {
if c == '\n' { if c == '\n' {
lines[n] = text[i:j]; // exclude newline lines[n] = text[i:j]; // exclude newline
i = j+1; // discard newline i = j+1; // discard newline
n++; n++;
} }
} }
@ -393,15 +398,15 @@ func commonPrefix(a, b []byte) []byte {
for i < len(a) && i < len(b) && a[i] == b[i] && (a[i] <= ' ' || a[i] == '*') { for i < len(a) && i < len(b) && a[i] == b[i] && (a[i] <= ' ' || a[i] == '*') {
i++; i++;
} }
return a[0 : i]; return a[0:i];
} }
func stripCommonPrefix(lines [][]byte) { func stripCommonPrefix(lines [][]byte) {
if len(lines) < 2 { if len(lines) < 2 {
return; // at most one line - nothing to do return; // at most one line - nothing to do
} }
// The heuristic in this function tries to handle a few // The heuristic in this function tries to handle a few
// common patterns of /*-style comments: Comments where // common patterns of /*-style comments: Comments where
// the opening /* and closing */ are aligned and the // the opening /* and closing */ are aligned and the
@ -434,7 +439,7 @@ func stripCommonPrefix(lines [][]byte) {
if i := bytes.Index(prefix, []byte{'*'}); i >= 0 { if i := bytes.Index(prefix, []byte{'*'}); i >= 0 {
// Line of stars present. // Line of stars present.
if i > 0 && prefix[i-1] == ' ' { if i > 0 && prefix[i-1] == ' ' {
i--; // remove trailing blank from prefix so stars remain aligned i--; // remove trailing blank from prefix so stars remain aligned
} }
prefix = prefix[0:i]; prefix = prefix[0:i];
lineOfStars = true; lineOfStars = true;
@ -447,7 +452,7 @@ func stripCommonPrefix(lines [][]byte) {
// for the opening /*, assume up to 3 blanks or a tab. This // for the opening /*, assume up to 3 blanks or a tab. This
// whitespace may be found as suffix in the common prefix. // whitespace may be found as suffix in the common prefix.
first := lines[0]; first := lines[0];
if isBlank(first[2 : len(first)]) { if isBlank(first[2:len(first)]) {
// no comment text on the first line: // no comment text on the first line:
// reduce prefix by up to 3 blanks or a tab // reduce prefix by up to 3 blanks or a tab
// if present - this keeps comment text indented // if present - this keeps comment text indented
@ -480,7 +485,7 @@ func stripCommonPrefix(lines [][]byte) {
// Shorten the computed common prefix by the length of // Shorten the computed common prefix by the length of
// suffix, if it is found as suffix of the prefix. // suffix, if it is found as suffix of the prefix.
if bytes.HasSuffix(prefix, suffix) { if bytes.HasSuffix(prefix, suffix) {
prefix = prefix[0 : len(prefix) - len(suffix)]; prefix = prefix[0 : len(prefix)-len(suffix)];
} }
} }
} }
@ -508,7 +513,7 @@ func stripCommonPrefix(lines [][]byte) {
// Remove the common prefix from all but the first and empty lines. // Remove the common prefix from all but the first and empty lines.
for i, line := range lines { for i, line := range lines {
if i > 0 && len(line) != 0 { if i > 0 && len(line) != 0 {
lines[i] = line[len(prefix) : len(line)]; lines[i] = line[len(prefix):len(line)];
} }
} }
} }
@ -636,7 +641,7 @@ func (p *printer) writeWhitespace(n int) {
// of lines before the label; effectively leading to wrong // of lines before the label; effectively leading to wrong
// indentation. // indentation.
p.buffer[i], p.buffer[i+1] = unindent, formfeed; p.buffer[i], p.buffer[i+1] = unindent, formfeed;
i--; // do it again i--; // do it again
continue; continue;
} }
fallthrough; fallthrough;
@ -675,7 +680,7 @@ func (p *printer) print(args ...) {
for i := 0; i < v.NumField(); i++ { for i := 0; i < v.NumField(); i++ {
f := v.Field(i); f := v.Field(i);
next := p.pos; // estimated position of next item next := p.pos; // estimated position of next item
var data []byte; var data []byte;
var tag HtmlTag; var tag HtmlTag;
isKeyword := false; isKeyword := false;
@ -721,7 +726,7 @@ func (p *printer) print(args ...) {
// (note that valid Go programs cannot contain esc ('\xff') // (note that valid Go programs cannot contain esc ('\xff')
// bytes since they do not appear in legal UTF-8 sequences) // bytes since they do not appear in legal UTF-8 sequences)
// TODO(gri): this this more efficiently. // TODO(gri): this this more efficiently.
data = strings.Bytes("\xff" + string(data) + "\xff"); data = strings.Bytes("\xff"+string(data)+"\xff");
case token.Token: case token.Token:
if p.Styler != nil { if p.Styler != nil {
data, tag = p.Styler.Token(x); data, tag = p.Styler.Token(x);
@ -731,7 +736,7 @@ func (p *printer) print(args ...) {
isKeyword = x.IsKeyword(); isKeyword = x.IsKeyword();
case token.Position: case token.Position:
if x.IsValid() { if x.IsValid() {
next = x; // accurate position of next item next = x; // accurate position of next item
} }
default: default:
panicln("print: unsupported argument type", f.Type().String()); panicln("print: unsupported argument type", f.Type().String());
@ -782,8 +787,8 @@ func (p *printer) flush(next token.Position, isKeyword bool) {
// is used). // is used).
// //
type trimmer struct { type trimmer struct {
output io.Writer; output io.Writer;
buf bytes.Buffer; buf bytes.Buffer;
} }
@ -815,7 +820,7 @@ func (p *trimmer) Write(data []byte) (n int, err os.Error) {
} }
case '\v': case '\v':
b = '\t'; // convert to htab b = '\t'; // convert to htab
fallthrough; fallthrough;
case '\t', ' ', tabwriter.Escape: case '\t', ' ', tabwriter.Escape:
@ -828,7 +833,7 @@ func (p *trimmer) Write(data []byte) (n int, err os.Error) {
} }
// collect whitespace but discard tabrwiter.Escapes. // collect whitespace but discard tabrwiter.Escapes.
if b != tabwriter.Escape { if b != tabwriter.Escape {
p.buf.WriteByte(b); // WriteByte returns no errors p.buf.WriteByte(b); // WriteByte returns no errors
} }
case '\f', '\n': case '\f', '\n':
@ -865,15 +870,15 @@ func (p *trimmer) Write(data []byte) (n int, err os.Error) {
// General printing is controlled with these Config.Mode flags. // General printing is controlled with these Config.Mode flags.
const ( const (
GenHTML uint = 1 << iota; // generate HTML GenHTML uint = 1<<iota; // generate HTML
RawFormat; // do not use a tabwriter; if set, UseSpaces is ignored RawFormat; // do not use a tabwriter; if set, UseSpaces is ignored
UseSpaces; // use spaces instead of tabs for indentation and alignment UseSpaces; // use spaces instead of tabs for indentation and alignment
) )
// An HtmlTag specifies a start and end tag. // An HtmlTag specifies a start and end tag.
type HtmlTag struct { type HtmlTag struct {
Start, End string; // empty if tags are absent Start, End string; // empty if tags are absent
} }
@ -882,18 +887,18 @@ type HtmlTag struct {
// //
type Styler interface { type Styler interface {
LineTag(line int) ([]byte, HtmlTag); LineTag(line int) ([]byte, HtmlTag);
Comment(c *ast.Comment, line []byte) ([]byte, HtmlTag); Comment(c *ast.Comment, line []byte) ([]byte, HtmlTag);
BasicLit(x *ast.BasicLit) ([]byte, HtmlTag); BasicLit(x *ast.BasicLit) ([]byte, HtmlTag);
Ident(id *ast.Ident) ([]byte, HtmlTag); Ident(id *ast.Ident) ([]byte, HtmlTag);
Token(tok token.Token) ([]byte, HtmlTag); Token(tok token.Token) ([]byte, HtmlTag);
} }
// A Config node controls the output of Fprint. // A Config node controls the output of Fprint.
type Config struct { type Config struct {
Mode uint; // default: 0 Mode uint; // default: 0
Tabwidth int; // default: 8 Tabwidth int; // default: 8
Styler Styler; // default: nil Styler Styler; // default: nil
} }
@ -942,14 +947,14 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
p.errors <- os.NewError(fmt.Sprintf("printer.Fprint: unsupported node type %T", n)); p.errors <- os.NewError(fmt.Sprintf("printer.Fprint: unsupported node type %T", n));
runtime.Goexit(); runtime.Goexit();
} }
p.flush(token.Position{Offset: 1<<30, Line: 1<<30}, false); // flush to "infinity" p.flush(token.Position{Offset: 1<<30, Line: 1<<30}, false); // flush to "infinity"
p.errors <- nil; // no errors p.errors <- nil; // no errors
}(); }();
err := <-p.errors; // wait for completion of goroutine err := <-p.errors; // wait for completion of goroutine
// flush tabwriter, if any // flush tabwriter, if any
if tw != nil { if tw != nil {
tw.Flush(); // ignore errors tw.Flush(); // ignore errors
} }
return p.written, err; return p.written, err;
@ -960,6 +965,6 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
// It calls Config.Fprint with default settings. // It calls Config.Fprint with default settings.
// //
func Fprint(output io.Writer, node interface{}) os.Error { func Fprint(output io.Writer, node interface{}) os.Error {
_, err := (&Config{Tabwidth: 8}).Fprint(output, node); // don't care about number of bytes written _, err := (&Config{Tabwidth: 8}).Fprint(output, node); // don't care about number of bytes written
return err; return err;
} }

View File

@ -16,12 +16,12 @@ import (
const ( const (
dataDir = "testdata"; dataDir = "testdata";
tabwidth = 8; tabwidth = 8;
) )
var update = flag.Bool("update", false, "update golden files"); var update = flag.Bool("update", false, "update golden files")
func lineString(text []byte, i int) string { func lineString(text []byte, i int) string {
@ -29,13 +29,14 @@ func lineString(text []byte, i int) string {
for i < len(text) && text[i] != '\n' { for i < len(text) && text[i] != '\n' {
i++; i++;
} }
return string(text[i0 : i]); return string(text[i0:i]);
} }
type checkMode uint; type checkMode uint
const ( const (
export checkMode = 1<<iota; export checkMode = 1<<iota;
rawFormat; rawFormat;
) )
@ -50,13 +51,13 @@ func check(t *testing.T, source, golden string, mode checkMode) {
// filter exports if necessary // filter exports if necessary
if mode&export != 0 { if mode&export != 0 {
ast.FileExports(prog); // ignore result ast.FileExports(prog); // ignore result
prog.Comments = nil; // don't print comments that are not in AST prog.Comments = nil; // don't print comments that are not in AST
} }
// determine printer configuration // determine printer configuration
cfg := Config{Tabwidth: tabwidth}; cfg := Config{Tabwidth: tabwidth};
if mode&rawFormat != 0 { if mode & rawFormat != 0 {
cfg.Mode |= RawFormat; cfg.Mode |= RawFormat;
} }
@ -105,20 +106,20 @@ func check(t *testing.T, source, golden string, mode checkMode) {
type entry struct { type entry struct {
source, golden string; source, golden string;
mode checkMode; mode checkMode;
} }
// Use gotest -update to create/update the respective golden files. // Use gotest -update to create/update the respective golden files.
var data = []entry{ var data = []entry{
entry{ "empty.input", "empty.golden", 0 }, entry{"empty.input", "empty.golden", 0},
entry{ "comments.input", "comments.golden", 0 }, entry{"comments.input", "comments.golden", 0},
entry{ "comments.input", "comments.x", export }, entry{"comments.input", "comments.x", export},
entry{ "linebreaks.input", "linebreaks.golden", 0 }, entry{"linebreaks.input", "linebreaks.golden", 0},
entry{ "expressions.input", "expressions.golden", 0 }, entry{"expressions.input", "expressions.golden", 0},
entry{ "expressions.input", "expressions.raw", rawFormat }, entry{"expressions.input", "expressions.raw", rawFormat},
entry{ "declarations.input", "declarations.golden", 0 }, entry{"declarations.input", "declarations.golden", 0},
entry{ "statements.input", "statements.golden", 0 }, entry{"statements.input", "statements.golden", 0},
} }