gofmt: stability improvement

There are a variety of token pairs that if printed
without separating blank may combine into a different
token sequence. Most of these (except for INT + .)
don't happen at the moment due to the spacing
introduced between expression operands. However, this
will prevent errors should the expression spacing
change.

R=rsc
CC=golang-dev
https://golang.org/cl/2207044
This commit is contained in:
Robert Griesemer 2010-09-27 15:03:15 -07:00
parent 20430f03bc
commit 9ff4565e2b
5 changed files with 65 additions and 4 deletions

View File

@ -543,7 +543,7 @@ func walkBinary(e *ast.BinaryExpr) (has5, has6 bool, maxProblem int) {
case *ast.UnaryExpr:
switch e.Op.String() + r.Op.String() {
case "/*":
case "/*", "&&", "&^":
maxProblem = 6
case "++", "--":
if maxProblem < 5 {
@ -612,11 +612,14 @@ func reduceDepth(depth int) int {
// 1) If there is a binary operator with a right side unary operand
// that would clash without a space, the cutoff must be (in order):
//
// &^ 7
// /* 7
// && 7
// &^ 7
// ++ 6
// -- 6
//
// (Comparison operators always have spaces around them.)
//
// 2) If there is a mix of level 6 and level 5 operators, then the cutoff
// is 6 (use spaces to distinguish precedence) in Normal mode
// and 5 (never use spaces) in Compact mode.

View File

@ -746,6 +746,26 @@ func (p *printer) writeWhitespace(n int) {
// ----------------------------------------------------------------------------
// Printing interface
func mayCombine(prev token.Token, next byte) (b bool) {
switch prev {
case token.INT:
b = next == '.' // 1.
case token.ADD:
b = next == '+' // ++
case token.SUB:
b = next == '-' // --
case token.QUO:
b = next == '*' // /*
case token.LSS:
b = next == '-' || next == '<' // <- or <<
case token.AND:
b = next == '&' || next == '^' // && or &^
}
return
}
// print prints a list of "items" (roughly corresponding to syntactic
// tokens, but also including whitespace and formatting information).
// It is the only print function that should be called directly from
@ -803,8 +823,13 @@ func (p *printer) print(args ...interface{}) {
tok = x.Kind
case token.Token:
s := x.String()
if p.lastTok == token.INT && s[0] == '.' {
// separate int with blank from '.' so it doesn't become a float
if mayCombine(p.lastTok, s[0]) {
// the previous and the current token must be
// separated by a blank otherwise they combine
// into a different incorrect token sequence
// (except for token.INT followed by a '.' this
// should never happen because it is taken care
// of via binary expression formatting)
if len(p.buffer) != 0 {
p.internalError("whitespace buffer not empty")
}

View File

@ -194,6 +194,17 @@ func f(x int, args ...int) {
_ = .42.x
_ = 42e0.x
_ = 42e0.x
// a blank must remain between the binary operator and the 2nd operand
_ = x / *y
_ = x < -1
_ = x < <-1
_ = x + +1
_ = x - -1
_ = x & &x
_ = x & ^x
_ = f(x / *y, x < -1, x < <-1, x + +1, x - -1, x & &x, x & ^x)
}

View File

@ -194,6 +194,17 @@ func f(x int, args ...int) {
_ = .42.x
_ = 42e0 .x
_ = 42e0.x
// a blank must remain between the binary operator and the 2nd operand
_ = x/ *y
_ = x< -1
_ = x< <-1
_ = x+ +1
_ = x- -1
_ = x& &x
_ = x& ^x
_ = f(x/ *y, x< -1, x< <-1, x+ +1, x- -1, x& &x, x& ^x)
}

View File

@ -194,6 +194,17 @@ func f(x int, args ...int) {
_ = .42.x
_ = 42e0.x
_ = 42e0.x
// a blank must remain between the binary operator and the 2nd operand
_ = x / *y
_ = x < -1
_ = x < <-1
_ = x + +1
_ = x - -1
_ = x & &x
_ = x & ^x
_ = f(x / *y, x < -1, x < <-1, x + +1, x - -1, x & &x, x & ^x)
}