1
0
mirror of https://github.com/golang/go synced 2024-09-30 18:08:33 -06:00

go.tools/cmd/vet: change reporting of incorrect error count in Printf

The old code was misleading in saying how many args were present.
Change the wording of the message to be unambiguous and change
the presentation of the format to include the full directive, making
it easier to correlate with the input (and fixing a silent bug).
Fixes golang/go#6248.

LGTM=dsymonds
R=golang-codereviews, dsymonds
CC=golang-codereviews
https://golang.org/cl/69120044
This commit is contained in:
Rob Pike 2014-03-04 15:41:49 +11:00
parent 744443b9dc
commit 31c219bef7
2 changed files with 10 additions and 13 deletions

View File

@ -9,7 +9,6 @@ package main
import (
"bytes"
"flag"
"fmt"
"go/ast"
"go/token"
"strconv"
@ -65,11 +64,10 @@ func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
// It is constructed by parsePrintfVerb.
type formatState struct {
verb rune // the format verb: 'd' for "%d"
format string // the full format string
format string // the full format directive from % through verb, "%.3d".
name string // Printf, Sprintf etc.
flags []byte // the list of # + etc.
argNums []int // the successive argument numbers that are consumed, adjusted to refer to actual arg in call
nbytes int // number of bytes of the format string consumed.
indexed bool // whether an indexing expression appears: %[1]d.
firstArg int // Index of first argument after the format in the Printf call.
// Used only during parse.
@ -77,6 +75,7 @@ type formatState struct {
call *ast.CallExpr
argNum int // Which argument we're expecting to format now.
indexPending bool // Whether we have an indexed argument that has not resolved.
nbytes int // number of bytes of the format string consumed.
}
// checkPrintf checks a call to a formatted print routine such as Printf.
@ -115,7 +114,7 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string, formatIndex int) {
if state == nil {
return
}
w = state.nbytes
w = len(state.format)
if state.indexed {
indexed = true
}
@ -267,6 +266,7 @@ func (f *File) parsePrintfVerb(call *ast.CallExpr, name, format string, firstArg
if verb != '%' {
state.argNums = append(state.argNums, state.argNum)
}
state.format = state.format[:state.nbytes]
return state
}
@ -433,13 +433,9 @@ func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, isStar bool, s
return true
}
// There are bad indexes in the format or there are fewer arguments than the format needs.
verb := fmt.Sprintf("verb %%%c", state.verb)
if isStar {
verb = "indirect *"
}
// This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi".
arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed.
f.Badf(call.Pos(), "missing argument for %s %s: need %d, have %d", state.name, verb, arg, len(call.Args)-state.firstArg)
f.Badf(call.Pos(), `missing argument for %s("%s"): format reads arg %d, have only %d args`, state.name, state.format, arg, len(call.Args)-state.firstArg)
return false
}

View File

@ -134,7 +134,7 @@ func PrintfTests() {
fmt.Printf("%08s", "woo") // correct
fmt.Printf("% 8s", "woo") // correct
fmt.Printf("%.*d", 3, 3) // correct
fmt.Printf("%.*d", 3, 3, 3) // ERROR "wrong number of args for format in Printf call"
fmt.Printf("%.*d", 3, 3, 3, 3) // ERROR "wrong number of args for format in Printf call.*4 args"
fmt.Printf("%.*d", "hi", 3) // ERROR "arg .hi. for \* in printf format not of type int"
fmt.Printf("%.*d", i, 3) // correct
fmt.Printf("%.*d", s, 3) // ERROR "arg s for \* in printf format not of type int"
@ -146,7 +146,8 @@ func PrintfTests() {
Printf("hi") // ok
const format = "%s %s\n"
Printf(format, "hi", "there")
Printf(format, "hi") // ERROR "missing argument for Printf verb %s: need 2, have 1"
Printf(format, "hi") // ERROR "missing argument for Printf..%s..: format reads arg 2, have only 1"
Printf("%s %d %.3v %q", "str", 4) // ERROR "missing argument for Printf..%.3v..: format reads arg 3, have only 2"
f := new(stringer)
f.Warn(0, "%s", "hello", 3) // ERROR "possible formatting directive in Warn call"
f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args for format in Warnf call"
@ -169,8 +170,8 @@ func PrintfTests() {
// Bad argument reorderings.
Printf("%[xd", 3) // ERROR "illegal syntax for printf argument index"
Printf("%[x]d", 3) // ERROR "illegal syntax for printf argument index"
Printf("%[3]*s", "hi", 2) // ERROR "missing argument for Printf indirect \*: need 3, have 2"
fmt.Sprintf("%[3]d", 2) // ERROR "missing argument for Sprintf verb %d: need 3, have 1"
Printf("%[3]*s", "hi", 2) // ERROR "missing argument for Printf.* reads arg 3, have only 2"
fmt.Sprintf("%[3]d", 2) // ERROR "missing argument for Sprintf.* reads arg 3, have only 1"
Printf("%[2]*.[1]*[3]d", 2, "hi", 4) // ERROR "arg .hi. for \* in printf format not of type int"
// Something that satisfies the error interface.
var e error