mirror of
https://github.com/golang/go
synced 2024-11-22 02:34:40 -07:00
parent
65063bc61d
commit
10242e806f
@ -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;
|
||||||
|
@ -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("""); // shorter than """
|
esc_quot = strings.Bytes("""); // shorter than """
|
||||||
esc_apos = strings.Bytes("'"); // shorter than "'"
|
esc_apos = strings.Bytes("'"); // shorter than "'"
|
||||||
esc_amp = strings.Bytes("&");
|
esc_amp = strings.Bytes("&");
|
||||||
esc_lt = strings.Bytes("<");
|
esc_lt = strings.Bytes("<");
|
||||||
esc_gt = strings.Bytes(">");
|
esc_gt = strings.Bytes(">");
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user