go.tools/cmd/vet: assume implementations of fmt.Formatter print just fine
Update golang/go#6212 See issue 6259. When that is resolved, we can do a better job. Until then, we just see if the type has a method called Format and, if so, assume it's a Formatter and so there's nothing to check. R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/13267043
This commit is contained in:
parent
2e6fbd84f8
commit
bc5f637240
|
|
@ -88,6 +88,7 @@ func PrintfTests() {
|
|||
fmt.Printf("%s", stringerarrayv)
|
||||
fmt.Printf("%v", notstringerarrayv)
|
||||
fmt.Printf("%T", notstringerarrayv)
|
||||
fmt.Printf("%d", new(Formatter))
|
||||
fmt.Printf("%*%", 2) // Ridiculous but allowed.
|
||||
fmt.Printf("%s", interface{}(nil)) // Nothing useful we can say.
|
||||
|
||||
|
|
@ -121,6 +122,7 @@ func PrintfTests() {
|
|||
fmt.Printf("%t", stringerarrayv) // ERROR "arg stringerarrayv for printf verb %t of wrong type"
|
||||
fmt.Printf("%t", notstringerarrayv) // ERROR "arg notstringerarrayv for printf verb %t of wrong type"
|
||||
fmt.Printf("%q", notstringerarrayv) // ERROR "arg notstringerarrayv for printf verb %q of wrong type"
|
||||
fmt.Printf("%d", Formatter(true)) // ERROR "arg Formatter\(true\) for printf verb %d of wrong type"
|
||||
fmt.Printf("%s", nonemptyinterface) // ERROR "for printf verb %s of wrong type" (Disabled temporarily because of bug in IsAssignableTo)
|
||||
fmt.Printf("%.*s %d %g", 3, "hi", 23, 'x') // ERROR "arg 'x' for printf verb %g of wrong type"
|
||||
fmt.Println() // not an error
|
||||
|
|
@ -286,3 +288,8 @@ func (p *recursivePtrStringer) String() string {
|
|||
fmt.Sprintf("%v", *p)
|
||||
return fmt.Sprintln(p) // ERROR "arg p for print causes recursive call to String method"
|
||||
}
|
||||
|
||||
type Formatter bool
|
||||
|
||||
func (*Formatter) Format(fmt.State, rune) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ var (
|
|||
stringerMethodType = types.New("func() string")
|
||||
errorType = types.New("interface{ Error() string }")
|
||||
stringerType = types.New("interface{ String() string }")
|
||||
// One day this might work. See issue 6259.
|
||||
// formatterType = types.New("interface{Format(f fmt.State, c rune)}")
|
||||
)
|
||||
|
||||
// matchArgType reports an error if printf verb t is not appropriate
|
||||
|
|
@ -86,6 +88,14 @@ func (f *File) matchArgType(t printfArgType, typ types.Type, arg ast.Expr) bool
|
|||
return true // probably a type check problem
|
||||
}
|
||||
}
|
||||
// If the type implements fmt.Formatter, we have nothing to check.
|
||||
// But (see issue 6259) that's not easy to verify, so instead we see
|
||||
// if its method set contains a Format function. We could do better,
|
||||
// even now, but we don't need to be 100% accurate. Wait for 6259 to
|
||||
// be fixed instead. TODO.
|
||||
if hasMethod(typ, "Format") {
|
||||
return true
|
||||
}
|
||||
// If we can use a string, does arg implement the Stringer or Error interface?
|
||||
if t&argString != 0 {
|
||||
if types.IsAssignableTo(typ, errorType) || types.IsAssignableTo(typ, stringerType) {
|
||||
|
|
@ -281,3 +291,16 @@ func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
|
|||
// It must have return type "string" from the universe.
|
||||
return sig.Results().At(0).Type() == types.Typ[types.String]
|
||||
}
|
||||
|
||||
// hasMethod reports whether the type contains a method with the given name.
|
||||
// It is part of the workaround for Formatters and should be deleted when
|
||||
// that workaround is no longer necessary. TODO: delete when fixed.
|
||||
func hasMethod(typ types.Type, name string) bool {
|
||||
set := typ.MethodSet()
|
||||
for i := 0; i < set.Len(); i++ {
|
||||
if set.At(i).Obj().Name() == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue