Commit 650cc327 authored by Robert Griesemer's avatar Robert Griesemer

go/printer (gofmt): don't lose mandatory semicolons

Fixes #779.

R=r
CC=golang-dev
https://golang.org/cl/1218042
parent 3af48037
...@@ -491,7 +491,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC ...@@ -491,7 +491,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isIncomplete bool, ctxt exprC
type exprContext uint type exprContext uint
const ( const (
compositeLit = 1 << iota compositeLit exprContext = 1 << iota
structType structType
) )
...@@ -922,7 +922,7 @@ const maxStmtNewlines = 2 // maximum number of newlines between statements ...@@ -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. // 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
// empty line is printed between statements. // 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 // TODO(gri): fix _indent code
if _indent > 0 { if _indent > 0 {
p.print(indent) p.print(indent)
...@@ -933,7 +933,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int) { ...@@ -933,7 +933,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int) {
// in those cases each clause is a new section // in those cases each clause is a new section
p.linebreak(s.Pos().Line, 1, maxStmtNewlines, ignore, i == 0 || _indent == 0 || multiLine) p.linebreak(s.Pos().Line, 1, maxStmtNewlines, ignore, i == 0 || _indent == 0 || multiLine)
multiLine = false multiLine = false
p.stmt(s, &multiLine) p.stmt(s, nextIsRBrace && i == len(list)-1, &multiLine)
} }
if _indent > 0 { if _indent > 0 {
p.print(unindent) p.print(unindent)
...@@ -944,7 +944,7 @@ func (p *printer) stmtList(list []ast.Stmt, _indent int) { ...@@ -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. // block prints an *ast.BlockStmt; it always spans at least two lines.
func (p *printer) block(s *ast.BlockStmt, indent int) { func (p *printer) block(s *ast.BlockStmt, indent int) {
p.print(s.Pos(), token.LBRACE) 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.linebreak(s.Rbrace.Line, 1, maxStmtNewlines, ignore, true)
p.print(s.Rbrace, token.RBRACE) p.print(s.Rbrace, token.RBRACE)
} }
...@@ -990,7 +990,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po ...@@ -990,7 +990,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
// all semicolons required // all semicolons required
// (they are not separators, print them explicitly) // (they are not separators, print them explicitly)
if init != nil { if init != nil {
p.stmt(init, ignoreMultiLine) p.stmt(init, false, ignoreMultiLine)
} }
p.print(token.SEMICOLON, blank) p.print(token.SEMICOLON, blank)
if expr != nil { if expr != nil {
...@@ -1001,7 +1001,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po ...@@ -1001,7 +1001,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
p.print(token.SEMICOLON, blank) p.print(token.SEMICOLON, blank)
needsBlank = false needsBlank = false
if post != nil { if post != nil {
p.stmt(post, ignoreMultiLine) p.stmt(post, false, ignoreMultiLine)
needsBlank = true needsBlank = true
} }
} }
...@@ -1013,7 +1013,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po ...@@ -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. // 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()) p.print(stmt.Pos())
switch s := stmt.(type) { switch s := stmt.(type) {
...@@ -1033,8 +1033,12 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) { ...@@ -1033,8 +1033,12 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
p.print(unindent) p.print(unindent)
p.expr(s.Label, multiLine) p.expr(s.Label, multiLine)
p.print(token.COLON, vtab, indent) 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.linebreak(s.Stmt.Pos().Line, 0, 1, ignore, true)
p.stmt(s.Stmt, multiLine) p.stmt(s.Stmt, nextIsRBrace, multiLine)
case *ast.ExprStmt: case *ast.ExprStmt:
const depth = 1 const depth = 1
...@@ -1088,10 +1092,10 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) { ...@@ -1088,10 +1092,10 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
p.print(blank, token.ELSE, blank) p.print(blank, token.ELSE, blank)
switch s.Else.(type) { switch s.Else.(type) {
case *ast.BlockStmt, *ast.IfStmt: case *ast.BlockStmt, *ast.IfStmt:
p.stmt(s.Else, ignoreMultiLine) p.stmt(s.Else, nextIsRBrace, ignoreMultiLine)
default: default:
p.print(token.LBRACE, indent, formfeed) p.print(token.LBRACE, indent, formfeed)
p.stmt(s.Else, ignoreMultiLine) p.stmt(s.Else, true, ignoreMultiLine)
p.print(unindent, formfeed, token.RBRACE) p.print(unindent, formfeed, token.RBRACE)
} }
} }
...@@ -1104,7 +1108,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) { ...@@ -1104,7 +1108,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
p.print(token.DEFAULT) p.print(token.DEFAULT)
} }
p.print(s.Colon, token.COLON) p.print(s.Colon, token.COLON)
p.stmtList(s.Body, 1) p.stmtList(s.Body, 1, nextIsRBrace)
case *ast.SwitchStmt: case *ast.SwitchStmt:
p.print(token.SWITCH) p.print(token.SWITCH)
...@@ -1120,17 +1124,17 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) { ...@@ -1120,17 +1124,17 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
p.print(token.DEFAULT) p.print(token.DEFAULT)
} }
p.print(s.Colon, token.COLON) p.print(s.Colon, token.COLON)
p.stmtList(s.Body, 1) p.stmtList(s.Body, 1, nextIsRBrace)
case *ast.TypeSwitchStmt: case *ast.TypeSwitchStmt:
p.print(token.SWITCH) p.print(token.SWITCH)
if s.Init != nil { if s.Init != nil {
p.print(blank) p.print(blank)
p.stmt(s.Init, ignoreMultiLine) p.stmt(s.Init, false, ignoreMultiLine)
p.print(token.SEMICOLON) p.print(token.SEMICOLON)
} }
p.print(blank) p.print(blank)
p.stmt(s.Assign, ignoreMultiLine) p.stmt(s.Assign, false, ignoreMultiLine)
p.print(blank) p.print(blank)
p.block(s.Body, 0) p.block(s.Body, 0)
*multiLine = true *multiLine = true
...@@ -1147,7 +1151,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) { ...@@ -1147,7 +1151,7 @@ func (p *printer) stmt(stmt ast.Stmt, multiLine *bool) {
p.print(token.DEFAULT) p.print(token.DEFAULT)
} }
p.print(s.Colon, token.COLON) p.print(s.Colon, token.COLON)
p.stmtList(s.Body, 1) p.stmtList(s.Body, 1, nextIsRBrace)
case *ast.SelectStmt: case *ast.SelectStmt:
p.print(token.SELECT, blank) p.print(token.SELECT, blank)
...@@ -1359,7 +1363,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi ...@@ -1359,7 +1363,7 @@ func (p *printer) funcBody(b *ast.BlockStmt, headerSize int, isLit bool, multiLi
if i > 0 { if i > 0 {
p.print(token.SEMICOLON, blank) p.print(token.SEMICOLON, blank)
} }
p.stmt(s, ignoreMultiLine) p.stmt(s, i == len(b.List)-1, ignoreMultiLine)
} }
p.print(blank) p.print(blank)
} }
......
...@@ -767,6 +767,7 @@ func (p *printer) print(args ...interface{}) { ...@@ -767,6 +767,7 @@ func (p *printer) print(args ...interface{}) {
} else { } else {
data = []byte(x.Name()) data = []byte(x.Name())
} }
tok = token.IDENT
case *ast.BasicLit: case *ast.BasicLit:
if p.Styler != nil { if p.Styler != nil {
data, tag = p.Styler.BasicLit(x) data, tag = p.Styler.BasicLit(x)
...@@ -778,6 +779,7 @@ func (p *printer) print(args ...interface{}) { ...@@ -778,6 +779,7 @@ func (p *printer) print(args ...interface{}) {
// bytes since they do not appear in legal UTF-8 sequences) // bytes since they do not appear in legal UTF-8 sequences)
// TODO(gri): do this more efficiently. // TODO(gri): do this more efficiently.
data = []byte("\xff" + string(data) + "\xff") data = []byte("\xff" + string(data) + "\xff")
tok = token.INT // representing all literal tokens
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)
...@@ -1011,7 +1013,7 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) { ...@@ -1011,7 +1013,7 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt { if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
p.indent = 1 p.indent = 1
} }
p.stmt(n, ignoreMultiLine) p.stmt(n, false, ignoreMultiLine)
case ast.Decl: case ast.Decl:
p.useNodeComments = true p.useNodeComments = true
p.decl(n, atTop, ignoreMultiLine) p.decl(n, atTop, ignoreMultiLine)
......
...@@ -251,6 +251,24 @@ L: ...@@ -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 _() { func _() {
// this comment should be indented // this comment should be indented
L: L:
......
...@@ -187,6 +187,24 @@ func _() { ...@@ -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 _() { func _() {
// this comment should be indented // this comment should be indented
L: L:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment