Skip to content

Commit 41b9e99

Browse files
committed
cmd/gofmt: fix normalization of imaginary number literals
The old code only normalized decimal integer imaginary number literals. But with the generalized imaginary number syntax, the number value may be decimal, binary, octal, or hexadecimal, integer or floating-point. The new code only looks at the number pattern. Only for decimal integer imaginary literals do we need to strip leading zeroes. The remaining normalization code simply ignore the 'i' suffix. As a result, the new code is both simpler and shorter. Fixes golang#32718. Change-Id: If43fc962a48ed62002e65d5c81fddbb9bd283984 Reviewed-on: https://go-review.googlesource.com/c/go/+/183378 Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent 3f1422c commit 41b9e99

File tree

4 files changed

+63
-48
lines changed

4 files changed

+63
-48
lines changed

src/cmd/gofmt/gofmt.go

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -335,66 +335,49 @@ func backupFile(filename string, data []byte, perm os.FileMode) (string, error)
335335
// alone.
336336
func normalizeNumbers(n ast.Node) bool {
337337
lit, _ := n.(*ast.BasicLit)
338-
if lit == nil {
338+
if lit == nil || (lit.Kind != token.INT && lit.Kind != token.FLOAT && lit.Kind != token.IMAG) {
339339
return true
340340
}
341341
if len(lit.Value) < 2 {
342-
return false // only one digit - nothing to do
342+
return false // only one digit (common case) - nothing to do
343343
}
344344
// len(lit.Value) >= 2
345345

346+
// We ignore lit.Kind because for lit.Kind == token.IMAG the literal may be an integer
347+
// or floating-point value, decimal or not. Instead, just consider the literal pattern.
346348
x := lit.Value
347-
switch lit.Kind {
348-
case token.INT:
349-
switch x[:2] {
350-
case "0X":
351-
lit.Value = "0x" + x[2:]
352-
case "0O":
353-
lit.Value = "0o" + x[2:]
354-
case "0B":
355-
lit.Value = "0b" + x[2:]
349+
switch x[:2] {
350+
default:
351+
// 0-prefix octal, decimal int, or float (possibly with 'i' suffix)
352+
if i := strings.LastIndexByte(x, 'E'); i >= 0 {
353+
x = x[:i] + "e" + x[i+1:]
354+
break
356355
}
357-
358-
case token.FLOAT:
359-
switch lit.Value[:2] {
360-
default:
361-
if i := strings.LastIndexByte(x, 'E'); i >= 0 {
362-
lit.Value = x[:i] + "e" + x[i+1:]
363-
}
364-
case "0x":
365-
if i := strings.LastIndexByte(x, 'P'); i >= 0 {
366-
lit.Value = x[:i] + "p" + x[i+1:]
367-
}
368-
case "0X":
369-
if i := strings.LastIndexByte(x, 'P'); i >= 0 {
370-
lit.Value = "0x" + x[2:i] + "p" + x[i+1:]
371-
} else {
372-
lit.Value = "0x" + x[2:]
373-
}
374-
}
375-
376-
case token.IMAG:
377-
// Note that integer imaginary literals may contain
378-
// any decimal digit even if they start with zero.
379-
// Imaginary literals should always end in 'i' but be
380-
// conservative and check anyway before proceeding.
381-
if x[0] == '0' && x[len(x)-1] == 'i' && isDecimals(x[1:len(x)-1]) {
356+
// remove leading 0's from integer (but not floating-point) imaginary literals
357+
if x[len(x)-1] == 'i' && strings.IndexByte(x, '.') < 0 && strings.IndexByte(x, 'e') < 0 {
382358
x = strings.TrimLeft(x, "0_")
383359
if x == "i" {
384360
x = "0i"
385361
}
386-
lit.Value = x
387362
}
363+
case "0X":
364+
x = "0x" + x[2:]
365+
fallthrough
366+
case "0x":
367+
// possibly a hexadecimal float
368+
if i := strings.LastIndexByte(x, 'P'); i >= 0 {
369+
x = x[:i] + "p" + x[i+1:]
370+
}
371+
case "0O":
372+
x = "0o" + x[2:]
373+
case "0o":
374+
// nothing to do
375+
case "0B":
376+
x = "0b" + x[2:]
377+
case "0b":
378+
// nothing to do
388379
}
389380

381+
lit.Value = x
390382
return false
391383
}
392-
393-
// isDecimals reports whether x consists entirely of decimal digits and underscores.
394-
func isDecimals(x string) bool {
395-
i := 0
396-
for i < len(x) && ('0' <= x[i] && x[i] <= '9' || x[i] == '_') {
397-
i++
398-
}
399-
return i == len(x)
400-
}

src/cmd/gofmt/testdata/go2numbers.golden

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,24 @@ const (
163163
_ = 0.i
164164
_ = 123.i
165165
_ = 0123.i
166+
_ = 000123.i
167+
168+
_ = 0e0i
169+
_ = 123e0i
170+
_ = 0123e0i
171+
_ = 000123e0i
166172

167173
_ = 0.e+1i
168-
_ = 123.E-1_0i
174+
_ = 123.e-1_0i
169175
_ = 01_23.e123i
176+
_ = 00_01_23.e123i
177+
178+
_ = 0b1010i
179+
_ = 0b1010i
180+
_ = 0o660i
181+
_ = 0o660i
182+
_ = 0xabcDEFi
183+
_ = 0xabcDEFi
184+
_ = 0xabcDEFp0i
185+
_ = 0xabcDEFp0i
170186
)

src/cmd/gofmt/testdata/go2numbers.input

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,24 @@ const (
163163
_ = 0.i
164164
_ = 123.i
165165
_ = 0123.i
166+
_ = 000123.i
167+
168+
_ = 0e0i
169+
_ = 123e0i
170+
_ = 0123E0i
171+
_ = 000123E0i
166172

167173
_ = 0.e+1i
168174
_ = 123.E-1_0i
169175
_ = 01_23.e123i
176+
_ = 00_01_23.e123i
177+
178+
_ = 0b1010i
179+
_ = 0B1010i
180+
_ = 0o660i
181+
_ = 0O660i
182+
_ = 0xabcDEFi
183+
_ = 0XabcDEFi
184+
_ = 0xabcDEFP0i
185+
_ = 0XabcDEFp0i
170186
)

src/math/cmplx/cmath_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ var pow = []complex128{
222222
(-2.499956739197529585028819e+00 + 1.759751724335650228957144e+00i),
223223
(7.357094338218116311191939e+04 - 5.089973412479151648145882e+04i),
224224
(1.320777296067768517259592e+01 - 3.165621914333901498921986e+01i),
225-
(-3.123287828297300934072149e-07 - 1.9849567521490553032502223E-7i),
225+
(-3.123287828297300934072149e-07 - 1.9849567521490553032502223e-7i),
226226
(8.0622651468477229614813e+04 - 7.80028727944573092944363e+04i),
227227
(-1.0268824572103165858577141e+00 - 4.716844738244989776610672e-01i),
228228
(-4.35953819012244175753187e+01 + 2.2036445974645306917648585e+02i),

0 commit comments

Comments
 (0)