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>
This commit is contained in:
Peter Weinbergr 2023-01-25 18:07:26 -05:00 коммит произвёл Peter Weinberger
Родитель b62cbb6b59
Коммит e260368884
2 изменённых файлов: 51 добавлений и 0 удалений

Просмотреть файл

@ -743,7 +743,11 @@ func (e *encoded) definitionFor(x *ast.Ident, def types.Object) (tokenType, []st
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

Просмотреть файл

@ -113,6 +113,53 @@ func Add[T int](target T, l []T) []T {
}
// 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