mirror of
https://github.com/golang/go
synced 2024-11-20 04:14:49 -07:00
go/printer (gofmt): don't lose mandatory semicolons
Fixes #779. R=r CC=golang-dev https://golang.org/cl/1218042
This commit is contained in:
parent
3af4803704
commit
650cc32739
@ -491,7 +491,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
|
||||
type exprContext uint
|
||||
|
||||
const (
|
||||
compositeLit = 1 << iota
|
||||
compositeLit exprContext = 1 << iota
|
||||
structType
|
||||
)
|
||||
|
||||
@ -922,7 +922,7 @@ const maxStmtNewlines = 2 // maximum number of newlines between statements
|
||||
// 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
|
||||
// empty line is printed between statements.
|
||||
func (p *printer) stmtList(list []ast.Stmt, _indent int) {
|
||||
func (p *printer) stmtList(list []ast.Stmt, _indent int, nextIsRBrace bool) {
|
||||
// TODO(gri): fix _indent code
|
||||
if _indent > 0 {
|
||||
p.print(indent)
|
||||
@ -933,7 +933,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int) {
|
||||
// in those cases each clause is a new section
|
||||
p.linebreak(s.Pos().Line, 1, maxStmtNewlines, ignore, i == 0 || _indent == 0 || multiLine)
|
||||
multiLine = false
|
||||
p.stmt(s, &multiLine)
|
||||
p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine)
|
||||
}
|
||||
if _indent > 0 {
|
||||
p.print(unindent)
|
||||
@ -944,7 +944,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int) {
|
||||
// block prints an *ast.BlockStmt; it always spans at least two lines.
|
||||
func (p *printer) block(s *ast.BlockStmt, indent int) {
|
||||
p.print(s.Pos(), token.LBRACE)
|
||||
p.stmtList(s.List, indent)
|
||||
p.stmtList(s.List, indent, true)
|
||||
p.linebreak(s.Rbrace.Line, 1, maxStmtNewlines, ignore, true)
|
||||
p.print(s.Rbrace, token.RBRACE)
|
||||
}
|
||||
@ -990,7 +990,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
|
||||
// all semicolons required
|
||||
// (they are not separators, print them explicitly)
|
||||
if init != nil {
|
||||
p.stmt(init, ignoreMultiLine)
|
||||
p.stmt(init, false, ignoreMultiLine)
|
||||
}
|
||||
p.print(token.SEMICOLON, blank)
|
||||
if expr != nil {
|
||||
@ -1001,7 +1001,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
|
||||
p.print(token.SEMICOLON, blank)
|
||||
needsBlank = false
|
||||
if post != nil {
|
||||
p.stmt(post, ignoreMultiLine)
|
||||
p.stmt(post, false, ignoreMultiLine)
|
||||
needsBlank = true
|
||||
}
|
||||
}
|
||||
@ -1013,7 +1013,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
|
||||
|
||||
|
||||
// Sets multiLine to true if the statements spans multiple lines.
|
||||
func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
|
||||
func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
|
||||
p.print(stmt.Pos())
|
||||
|
||||
switch s := stmt.(type) {
|
||||
@ -1033,8 +1033,12 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
|
||||
p.print(unindent)
|
||||
p.expr(s.Label, multiLine)
|
||||
p.print(token.COLON, vtab, indent)
|
||||
if _, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty && !nextIsRBrace {
|
||||
p.print(token.SEMICOLON)
|
||||
break
|
||||
}
|
||||
p.linebreak(s.Stmt.Pos().Line, 0, 1, ignore, true)
|
||||
p.stmt(s.Stmt, multiLine)
|
||||
p.stmt(s.Stmt, nextIsRBrace, multiLine)
|
||||
|
||||
case *ast.ExprStmt:
|
||||
const depth = 1
|
||||
@ -1088,10 +1092,10 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
|
||||
p.print(blank, token.ELSE, blank)
|
||||
switch s.Else.(type) {
|
||||
case *ast.BlockStmt, *ast.IfStmt:
|
||||
p.stmt(s.Else, ignoreMultiLine)
|
||||
p.stmt(s.Else, nextIsRBrace, ignoreMultiLine)
|
||||
default:
|
||||
p.print(token.LBRACE, indent, formfeed)
|
||||
p.stmt(s.Else, ignoreMultiLine)
|
||||
p.stmt(s.Else, true, ignoreMultiLine)
|
||||
p.print(unindent, formfeed, token.RBRACE)
|
||||
}
|
||||
}
|
||||
@ -1104,7 +1108,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
|
||||
p.print(token.DEFAULT)
|
||||
}
|
||||
p.print(s.Colon, token.COLON)
|
||||
p.stmtList(s.Body, 1)
|
||||
p.stmtList(s.Body, 1, nextIsRBrace)
|
||||
|
||||
case *ast.SwitchStmt:
|
||||
p.print(token.SWITCH)
|
||||
@ -1120,17 +1124,17 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
|
||||
p.print(token.DEFAULT)
|
||||
}
|
||||
p.print(s.Colon, token.COLON)
|
||||
p.stmtList(s.Body, 1)
|
||||
p.stmtList(s.Body, 1, nextIsRBrace)
|
||||
|
||||
case *ast.TypeSwitchStmt:
|
||||
p.print(token.SWITCH)
|
||||
if s.Init != nil {
|
||||
p.print(blank)
|
||||
p.stmt(s.Init, ignoreMultiLine)
|
||||
p.stmt(s.Init, false, ignoreMultiLine)
|
||||
p.print(token.SEMICOLON)
|
||||
}
|
||||
p.print(blank)
|
||||
p.stmt(s.Assign, ignoreMultiLine)
|
||||
p.stmt(s.Assign, false, ignoreMultiLine)
|
||||
p.print(blank)
|
||||
p.block(s.Body, 0)
|
||||
*multiLine = true
|
||||
@ -1147,7 +1151,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
|
||||
p.print(token.DEFAULT)
|
||||
}
|
||||
p.print(s.Colon, token.COLON)
|
||||
p.stmtList(s.Body, 1)
|
||||
p.stmtList(s.Body, 1, nextIsRBrace)
|
||||
|
||||
case *ast.SelectStmt:
|
||||
p.print(token.SELECT, blank)
|
||||
@ -1359,7 +1363,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
|
||||
if i > 0 {
|
||||
p.print(token.SEMICOLON, blank)
|
||||
}
|
||||
p.stmt(s, ignoreMultiLine)
|
||||
p.stmt(s, i == len(b.List)-1, ignoreMultiLine)
|
||||
}
|
||||
p.print(blank)
|
||||
}
|
||||
|
@ -767,6 +767,7 @@ func (p *printer) print(args ...interface{}) {
|
||||
} else {
|
||||
data = []byte(x.Name())
|
||||
}
|
||||
tok = token.IDENT
|
||||
case *ast.BasicLit:
|
||||
if p.Styler != nil {
|
||||
data, tag = p.Styler.BasicLit(x)
|
||||
@ -778,6 +779,7 @@ func (p *printer) print(args ...interface{}) {
|
||||
// bytes since they do not appear in legal UTF-8 sequences)
|
||||
// TODO(gri): do this more efficiently.
|
||||
data = []byte("\xff" + string(data) + "\xff")
|
||||
tok = token.INT // representing all literal tokens
|
||||
case token.Token:
|
||||
if p.Styler != nil {
|
||||
data, tag = p.Styler.Token(x)
|
||||
@ -1011,7 +1013,7 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
|
||||
if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
|
||||
p.indent = 1
|
||||
}
|
||||
p.stmt(n, ignoreMultiLine)
|
||||
p.stmt(n, false, ignoreMultiLine)
|
||||
case ast.Decl:
|
||||
p.useNodeComments = true
|
||||
p.decl(n, atTop, ignoreMultiLine)
|
||||
|
18
src/pkg/go/printer/testdata/statements.golden
vendored
18
src/pkg/go/printer/testdata/statements.golden
vendored
@ -251,6 +251,24 @@ L:
|
||||
}
|
||||
|
||||
|
||||
func _() {
|
||||
// this comment should be indented
|
||||
L: // no semicolon needed
|
||||
}
|
||||
|
||||
|
||||
func _() {
|
||||
switch 0 {
|
||||
case 0:
|
||||
L0: ; // semicolon required
|
||||
case 1:
|
||||
L1: ; // semicolon required
|
||||
default:
|
||||
L2: // no semicolon needed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func _() {
|
||||
// this comment should be indented
|
||||
L:
|
||||
|
18
src/pkg/go/printer/testdata/statements.input
vendored
18
src/pkg/go/printer/testdata/statements.input
vendored
@ -187,6 +187,24 @@ func _() {
|
||||
}
|
||||
|
||||
|
||||
func _() {
|
||||
// this comment should be indented
|
||||
L: ; // no semicolon needed
|
||||
}
|
||||
|
||||
|
||||
func _() {
|
||||
switch 0 {
|
||||
case 0:
|
||||
L0: ; // semicolon required
|
||||
case 1:
|
||||
L1: ; // semicolon required
|
||||
default:
|
||||
L2: ; // no semicolon needed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func _() {
|
||||
// this comment should be indented
|
||||
L:
|
||||
|
Loading…
Reference in New Issue
Block a user