gopls/semantic: report type parameters in the type of a receiver
The code was misclassifying K, V in the reciever, as in
func (s *Foo[K, V]) Get(k K) (V, bool)...
Fixes: golang/go#57619
Change-Id: I77eae7929c4b9434c8c25bbc337151dcf90f8452
Reviewed-on: https://go-review.googlesource.com/c/tools/+/463316
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Peter Weinberger <pjw@google.com>
diff --git a/gopls/internal/lsp/semantic.go b/gopls/internal/lsp/semantic.go
index 0406311..5b7655a 100644
--- a/gopls/internal/lsp/semantic.go
+++ b/gopls/internal/lsp/semantic.go
@@ -743,7 +743,11 @@
return tokFunction, mods
}
// if x < ... < FieldList < FuncDecl, this is the receiver, a variable
+ // PJW: maybe not. it might be a typeparameter in the type of the receiver
if _, ok := e.stack[i+1].(*ast.FieldList); ok {
+ if _, ok := def.(*types.TypeName); ok {
+ return tokTypeParam, mods
+ }
return tokVariable, nil
}
// if x < ... < FieldList < FuncType < FuncDecl, this is a param
diff --git a/gopls/internal/regtest/misc/semantictokens_test.go b/gopls/internal/regtest/misc/semantictokens_test.go
index e083faa..a0e2245 100644
--- a/gopls/internal/regtest/misc/semantictokens_test.go
+++ b/gopls/internal/regtest/misc/semantictokens_test.go
@@ -113,6 +113,53 @@
}
+// fix inconsistency in TypeParameters
+// https://github.com/golang/go/issues/57619
+func TestSemantic_57619(t *testing.T) {
+ if !typeparams.Enabled {
+ t.Skip("type parameters are needed for this test")
+ }
+ src := `
+-- go.mod --
+module example.com
+
+go 1.19
+-- main.go --
+package foo
+type Smap[K int, V any] struct {
+ Store map[K]V
+}
+func (s *Smap[K, V]) Get(k K) (V, bool) {
+ v, ok := s.Store[k]
+ return v, ok
+}
+func New[K int, V any]() Smap[K, V] {
+ return Smap[K, V]{Store: make(map[K]V)}
+}
+`
+ WithOptions(
+ Modes(Default),
+ Settings{"semanticTokens": true},
+ ).Run(t, src, func(t *testing.T, env *Env) {
+ env.OpenFile("main.go")
+ p := &protocol.SemanticTokensParams{
+ TextDocument: protocol.TextDocumentIdentifier{
+ URI: env.Sandbox.Workdir.URI("main.go"),
+ },
+ }
+ v, err := env.Editor.Server.SemanticTokensFull(env.Ctx, p)
+ if err != nil {
+ t.Fatal(err)
+ }
+ seen := interpret(v.Data, env.BufferText("main.go"))
+ for i, s := range seen {
+ if (s.Token == "K" || s.Token == "V") && s.TokenType != "typeParameter" {
+ t.Errorf("%d: expected K and V to be type parameters, but got %v", i, s)
+ }
+ }
+ })
+}
+
type result struct {
Token string
TokenType string