mirror of https://github.com/golang/go.git
cmd/vet: extra args if any formats are indexed are ok
For example, the following program is valid:
func main() {
fmt.Printf("%[1]d", 1, 2, 3)
}
If any of the formats are indexed, fmt will not complain about unused
extra arguments. See #22867 for more detail.
Make vet follow the same logic, to avoid erroring on programs that would
run without fmt complaining.
Fixes #23564.
Change-Id: Ic9dede5d4c37d1cd4fa24714216944897b5bb7cc
Reviewed-on: https://go-review.googlesource.com/90495
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
4072608b58
commit
14f8027a10
|
|
@ -295,6 +295,7 @@ type formatState struct {
|
||||||
file *File
|
file *File
|
||||||
call *ast.CallExpr
|
call *ast.CallExpr
|
||||||
argNum int // Which argument we're expecting to format now.
|
argNum int // Which argument we're expecting to format now.
|
||||||
|
hasIndex bool // Whether the argument is indexed.
|
||||||
indexPending bool // Whether we have an indexed argument that has not resolved.
|
indexPending bool // Whether we have an indexed argument that has not resolved.
|
||||||
nbytes int // number of bytes of the format string consumed.
|
nbytes int // number of bytes of the format string consumed.
|
||||||
}
|
}
|
||||||
|
|
@ -319,6 +320,7 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
|
||||||
// Hard part: check formats against args.
|
// Hard part: check formats against args.
|
||||||
argNum := firstArg
|
argNum := firstArg
|
||||||
maxArgNum := firstArg
|
maxArgNum := firstArg
|
||||||
|
anyIndex := false
|
||||||
for i, w := 0, 0; i < len(format); i += w {
|
for i, w := 0, 0; i < len(format); i += w {
|
||||||
w = 1
|
w = 1
|
||||||
if format[i] != '%' {
|
if format[i] != '%' {
|
||||||
|
|
@ -332,6 +334,9 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
|
||||||
if !f.okPrintfArg(call, state) { // One error per format is enough.
|
if !f.okPrintfArg(call, state) { // One error per format is enough.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if state.hasIndex {
|
||||||
|
anyIndex = true
|
||||||
|
}
|
||||||
if len(state.argNums) > 0 {
|
if len(state.argNums) > 0 {
|
||||||
// Continue with the next sequential argument.
|
// Continue with the next sequential argument.
|
||||||
argNum = state.argNums[len(state.argNums)-1] + 1
|
argNum = state.argNums[len(state.argNums)-1] + 1
|
||||||
|
|
@ -346,6 +351,10 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
|
||||||
if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 {
|
if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// If any formats are indexed, extra arguments are ignored.
|
||||||
|
if anyIndex {
|
||||||
|
return
|
||||||
|
}
|
||||||
// There should be no leftover arguments.
|
// There should be no leftover arguments.
|
||||||
if maxArgNum != len(call.Args) {
|
if maxArgNum != len(call.Args) {
|
||||||
expect := maxArgNum - firstArg
|
expect := maxArgNum - firstArg
|
||||||
|
|
@ -404,6 +413,7 @@ func (s *formatState) parseIndex() bool {
|
||||||
arg := int(arg32)
|
arg := int(arg32)
|
||||||
arg += s.firstArg - 1 // We want to zero-index the actual arguments.
|
arg += s.firstArg - 1 // We want to zero-index the actual arguments.
|
||||||
s.argNum = arg
|
s.argNum = arg
|
||||||
|
s.hasIndex = true
|
||||||
s.indexPending = true
|
s.indexPending = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -270,8 +270,9 @@ func PrintfTests() {
|
||||||
Printf("%d %[3]d %d %[-2]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[-2\]"
|
Printf("%d %[3]d %d %[-2]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[-2\]"
|
||||||
Printf("%d %[3]d %d %[2234234234234]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[2234234234234\]"
|
Printf("%d %[3]d %d %[2234234234234]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[2234234234234\]"
|
||||||
Printf("%d %[3]d %-10d %[2]d x", 1, 2, 3) // ERROR "Printf format %-10d reads arg #4, but call has only 3 args"
|
Printf("%d %[3]d %-10d %[2]d x", 1, 2, 3) // ERROR "Printf format %-10d reads arg #4, but call has only 3 args"
|
||||||
Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // ERROR "Printf call needs 4 args but has 5 args"
|
|
||||||
Printf("%[1][3]d x", 1, 2) // ERROR "Printf format %\[1\]\[ has unknown verb \["
|
Printf("%[1][3]d x", 1, 2) // ERROR "Printf format %\[1\]\[ has unknown verb \["
|
||||||
|
Printf("%[1]d x", 1, 2) // OK
|
||||||
|
Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // OK
|
||||||
|
|
||||||
// wrote Println but meant Fprintln
|
// wrote Println but meant Fprintln
|
||||||
Printf("%p\n", os.Stdout) // OK
|
Printf("%p\n", os.Stdout) // OK
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue