mirror of
https://github.com/golang/go
synced 2024-11-18 16:14:46 -07:00
9ac8e33b36
We now rank printf operand candidates according to the corresponding formatting verb. We follow what fmt allows for the most part, but I omitted some things because they are uncommon and would result in many false positives, or didn't seem worth it to support: - We don't prefer fmt.Stringer or error types for "%x" or "%X". - We don't prefer pointers for any verbs except "%p". - We don't prefer recursive application of verbs (e.g. we won't prefer []string for "%s"). I decided against sharing code with the printf analyzer. It was tangled somewhat with go/analysis, and I needed only a very small subset of the format parsing. I tweaked candidate type evaluation to accommodate the printf hints. We now skip expected type of "interface{}" when matching candidate types because it matches everything and would always supersede the coarser object kind checks. Fixes golang/go#40485. Change-Id: I6440702e33d5ec85d701f8be65453044b5dab746 Reviewed-on: https://go-review.googlesource.com/c/tools/+/246699 Run-TryBot: Muir Manders <muir@mnd.rs> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
73 lines
1.9 KiB
Go
73 lines
1.9 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package source
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
func TestFormatOperandKind(t *testing.T) {
|
|
cases := []struct {
|
|
f string
|
|
idx int
|
|
kind objKind
|
|
}{
|
|
{"", 1, kindAny},
|
|
{"%", 1, kindAny},
|
|
{"%%%", 1, kindAny},
|
|
{"%[1", 1, kindAny},
|
|
{"%[?%s", 2, kindAny},
|
|
{"%[abc]v", 1, kindAny},
|
|
|
|
{"%v", 1, kindAny},
|
|
{"%T", 1, kindAny},
|
|
{"%t", 1, kindBool},
|
|
{"%d", 1, kindInt},
|
|
{"%c", 1, kindInt},
|
|
{"%o", 1, kindInt},
|
|
{"%O", 1, kindInt},
|
|
{"%U", 1, kindInt},
|
|
{"%e", 1, kindFloat | kindComplex},
|
|
{"%E", 1, kindFloat | kindComplex},
|
|
{"%f", 1, kindFloat | kindComplex},
|
|
{"%F", 1, kindFloat | kindComplex},
|
|
{"%g", 1, kindFloat | kindComplex},
|
|
{"%G", 1, kindFloat | kindComplex},
|
|
{"%b", 1, kindInt | kindFloat | kindComplex | kindBytes},
|
|
{"%q", 1, kindString | kindBytes | kindStringer | kindError},
|
|
{"%s", 1, kindString | kindBytes | kindStringer | kindError},
|
|
{"%x", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},
|
|
{"%X", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},
|
|
{"%p", 1, kindPtr | kindSlice},
|
|
{"%w", 1, kindError},
|
|
|
|
{"%1.2f", 1, kindFloat | kindComplex},
|
|
{"%*f", 1, kindInt},
|
|
{"%*f", 2, kindFloat | kindComplex},
|
|
{"%*.*f", 1, kindInt},
|
|
{"%*.*f", 2, kindInt},
|
|
{"%*.*f", 3, kindFloat | kindComplex},
|
|
{"%[3]*.[2]*[1]f", 1, kindFloat | kindComplex},
|
|
{"%[3]*.[2]*[1]f", 2, kindInt},
|
|
{"%[3]*.[2]*[1]f", 3, kindInt},
|
|
|
|
{"foo %% %d", 1, kindInt},
|
|
{"%#-12.34f", 1, kindFloat | kindComplex},
|
|
{"% d", 1, kindInt},
|
|
|
|
{"%s %[1]X %d", 1, kindString | kindBytes},
|
|
{"%s %[1]X %d", 2, kindInt},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(fmt.Sprintf("%q#%d", c.f, c.idx), func(t *testing.T) {
|
|
if got := formatOperandKind(c.f, c.idx); got != c.kind {
|
|
t.Errorf("expected %d (%[1]b), got %d (%[2]b)", c.kind, got)
|
|
}
|
|
})
|
|
}
|
|
}
|