mirror of
https://github.com/golang/go
synced 2024-11-19 23:34:40 -07:00
govet: handle '*' in print format strings.
While we're on govet, fix a couple of mistakes in a test. Fixes #1592. R=rsc CC=golang-dev https://golang.org/cl/4239071
This commit is contained in:
parent
f3ed1ad50c
commit
8138654aa8
@ -18,6 +18,7 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"utf8"
|
||||
)
|
||||
|
||||
var verbose = flag.Bool("v", false, "verbose")
|
||||
@ -265,23 +266,65 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) {
|
||||
}
|
||||
// Hard part: check formats against args.
|
||||
// Trivial but useful test: count.
|
||||
numPercent := 0
|
||||
for i := 0; i < len(lit.Value); i++ {
|
||||
numArgs := 0
|
||||
for i, w := 0, 0; i < len(lit.Value); i += w {
|
||||
w = 1
|
||||
if lit.Value[i] == '%' {
|
||||
if i+1 < len(lit.Value) && lit.Value[i+1] == '%' {
|
||||
// %% doesn't count.
|
||||
i++
|
||||
} else {
|
||||
numPercent++
|
||||
}
|
||||
nbytes, nargs := parsePrintfVerb(lit.Value[i:])
|
||||
w = nbytes
|
||||
numArgs += nargs
|
||||
}
|
||||
}
|
||||
expect := len(call.Args) - (skip + 1)
|
||||
if numPercent != expect {
|
||||
f.Badf(call.Pos(), "wrong number of formatting directives in %s call: %d percent(s) for %d args", name, numPercent, expect)
|
||||
if numArgs != expect {
|
||||
f.Badf(call.Pos(), "wrong number of args in %s call: %d needed but %d args", name, numArgs, expect)
|
||||
}
|
||||
}
|
||||
|
||||
// parsePrintfVerb returns the number of bytes and number of arguments
|
||||
// consumed by the Printf directive that begins s, including its percent sign
|
||||
// and verb.
|
||||
func parsePrintfVerb(s []byte) (nbytes, nargs int) {
|
||||
// There's guaranteed a percent sign.
|
||||
nbytes = 1
|
||||
end := len(s)
|
||||
// There may be flags
|
||||
FlagLoop:
|
||||
for nbytes < end {
|
||||
switch s[nbytes] {
|
||||
case '#', '0', '+', '-', ' ':
|
||||
nbytes++
|
||||
default:
|
||||
break FlagLoop
|
||||
}
|
||||
}
|
||||
getNum := func() {
|
||||
if nbytes < end && s[nbytes] == '*' {
|
||||
nbytes++
|
||||
nargs++
|
||||
} else {
|
||||
for nbytes < end && '0' <= s[nbytes] && s[nbytes] <= '9' {
|
||||
nbytes++
|
||||
}
|
||||
}
|
||||
}
|
||||
// There may be a width
|
||||
getNum()
|
||||
// If there's a period, there may be a precision.
|
||||
if nbytes < end && s[nbytes] == '.' {
|
||||
nbytes++
|
||||
getNum()
|
||||
}
|
||||
// Now a verb.
|
||||
c, w := utf8.DecodeRune(s[nbytes:])
|
||||
nbytes += w
|
||||
if c != '%' {
|
||||
nargs++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
var terminalNewline = []byte(`\n"`) // \n at end of interpreted string
|
||||
|
||||
// checkPrint checks a call to an unformatted print routine such as Println.
|
||||
@ -320,6 +363,8 @@ func BadFunctionUsedInTests() {
|
||||
fmt.Println("%s", "hi") // % in call to Println
|
||||
fmt.Printf("%s", "hi", 3) // wrong # percents
|
||||
fmt.Printf("%s%%%d", "hi", 3) // right # percents
|
||||
fmt.Printf("%.*d", 3, 3) // right # percents, with a *
|
||||
fmt.Printf("%.*d", 3, 3, 3) // wrong # percents, with a *
|
||||
Printf("now is the time", "buddy") // no %s
|
||||
f := new(File)
|
||||
f.Warn(0, "%s", "hello", 3) // % in call to added function
|
||||
|
@ -820,12 +820,12 @@ func testScanInts(t *testing.T, scan func(*RecursiveInt, *bytes.Buffer) os.Error
|
||||
i := 1
|
||||
for ; r != nil; r = r.next {
|
||||
if r.i != i {
|
||||
t.Fatal("bad scan: expected %d got %d", i, r.i)
|
||||
t.Fatalf("bad scan: expected %d got %d", i, r.i)
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i-1 != intCount {
|
||||
t.Fatal("bad scan count: expected %d got %d", intCount, i-1)
|
||||
t.Fatalf("bad scan count: expected %d got %d", intCount, i-1)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user