1
0
mirror of https://github.com/golang/go synced 2024-11-05 14:46:11 -07:00
go/internal/lsp/source/completion_printf_test.go
Muir Manders 9ac8e33b36 internal/lsp/source: improve completion of printf operands
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>
2020-08-21 13:58:45 +00:00

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)
}
})
}
}