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