gopls/completion: don't take address of interfaces for "%p" values
When completing printf calls, we previously only preferred
pointers and slices. This meant to make an interface object acceptable
for "%p", we would take its address to turn it into a pointer.
Change "%p" to also prefer interface types in addition to chan, map, and
func, which all have pointer semantics. Note that interface types
don't necessarily contain pointers, but they might, so tacking on "&"
automatically is annoying.
Fixes golang/go#65609
Change-Id: Idf2ba9cf27fa4ea8e721396cded5a7743d79807b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/593575
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/gopls/internal/golang/completion/completion.go b/gopls/internal/golang/completion/completion.go
index bdd1218..cc235ce 100644
--- a/gopls/internal/golang/completion/completion.go
+++ b/gopls/internal/golang/completion/completion.go
@@ -2128,6 +2128,7 @@
kindBool
kindBytes
kindPtr
+ kindInterface
kindFloat
kindComplex
kindError
@@ -3270,6 +3271,8 @@
if _, isArray := t.Elem().Underlying().(*types.Array); isArray {
kind |= kindArray
}
+ case *types.Interface:
+ kind |= kindInterface
case *types.Basic:
switch info := t.Info(); {
case info&types.IsString > 0:
diff --git a/gopls/internal/golang/completion/printf.go b/gopls/internal/golang/completion/printf.go
index a7413bc..958d77e 100644
--- a/gopls/internal/golang/completion/printf.go
+++ b/gopls/internal/golang/completion/printf.go
@@ -152,7 +152,9 @@
// Omit kindStringer and kindError though technically allowed.
addVerb(kindString | kindBytes | kindInt | kindFloat | kindComplex)
case 'p':
- addVerb(kindPtr | kindSlice)
+ // Accept kindInterface even though it doesn't necessarily contain a pointer.
+ // This avoids us offering "&foo" when "foo" is an interface type.
+ addVerb(kindPtr | kindSlice | kindMap | kindFunc | kindInterface)
case 'w':
addVerb(kindError)
case '+', '-', '#', ' ', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
diff --git a/gopls/internal/golang/completion/printf_test.go b/gopls/internal/golang/completion/printf_test.go
index 19d295b..1a3d971 100644
--- a/gopls/internal/golang/completion/printf_test.go
+++ b/gopls/internal/golang/completion/printf_test.go
@@ -41,7 +41,7 @@
{"%s", 1, kindString | kindBytes | kindStringer | kindError},
{"%x", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},
{"%X", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},
- {"%p", 1, kindPtr | kindSlice},
+ {"%p", 1, kindPtr | kindSlice | kindMap | kindFunc | kindInterface},
{"%w", 1, kindError},
{"%1.2f", 1, kindFloat | kindComplex},
diff --git a/gopls/internal/test/marker/testdata/completion/printf.txt b/gopls/internal/test/marker/testdata/completion/printf.txt
index 99b8a1e..270927e 100644
--- a/gopls/internal/test/marker/testdata/completion/printf.txt
+++ b/gopls/internal/test/marker/testdata/completion/printf.txt
@@ -36,4 +36,7 @@
a, //@rank(",", printfInt, printfFloat)
a, //@rank(",", printfFloat, printfInt)
)
+
+ // Don't insert as "&aStringer"
+ fmt.Printf("%p", a) //@snippet(")", printfStringer, "aStringer")
}