Skip to content

Commit 0ef01b9

Browse files
committed
gopls: semantic tokens should report modifiers for the top-level type constructor of each symbol
These new semantic type modifiers will report in type definition, type embedding, type alias, variable definition like `var foo Bar`'s `Bar', parameter type and return type
1 parent 0734f62 commit 0ef01b9

File tree

3 files changed

+44
-12
lines changed

3 files changed

+44
-12
lines changed

gopls/internal/golang/semtok.go

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,18 @@ func (tv *tokenVisitor) comment(c *ast.Comment, importByName map[string]*types.P
210210
}
211211
}
212212

213-
tokenTypeByObject := func(obj types.Object) semtok.TokenType {
213+
tokenTypeByObject := func(obj types.Object) (semtok.TokenType, []string) {
214214
switch obj.(type) {
215215
case *types.PkgName:
216-
return semtok.TokNamespace
216+
return semtok.TokNamespace, nil
217217
case *types.Func:
218-
return semtok.TokFunction
218+
return semtok.TokFunction, nil
219219
case *types.TypeName:
220-
return semtok.TokType
220+
return underlineType(obj)
221221
case *types.Const, *types.Var:
222-
return semtok.TokVariable
222+
return semtok.TokVariable, nil
223223
default:
224-
return semtok.TokComment
224+
return semtok.TokComment, nil
225225
}
226226
}
227227

@@ -244,7 +244,8 @@ func (tv *tokenVisitor) comment(c *ast.Comment, importByName map[string]*types.P
244244
}
245245
id, rest, _ := strings.Cut(name, ".")
246246
name = rest
247-
tv.token(offset, len(id), tokenTypeByObject(obj), nil)
247+
tk, mods := tokenTypeByObject(obj)
248+
tv.token(offset, len(id), tk, mods)
248249
offset += token.Pos(len(id))
249250
}
250251
last = idx[3]
@@ -483,6 +484,31 @@ func (tv *tokenVisitor) inspect(n ast.Node) (descend bool) {
483484
return true
484485
}
485486

487+
func underlineType(obj types.Object) (semtok.TokenType, []string) {
488+
switch obj.Type().Underlying().(type) {
489+
case *types.Interface:
490+
return semtok.TokType, []string{"interface"}
491+
case *types.Struct:
492+
return semtok.TokType, []string{"struct"}
493+
case *types.Signature:
494+
return semtok.TokType, []string{"signature"}
495+
case *types.Pointer:
496+
return semtok.TokType, []string{"pointer"}
497+
case *types.Array:
498+
return semtok.TokType, []string{"array"}
499+
case *types.Map:
500+
return semtok.TokType, []string{"map"}
501+
case *types.Slice:
502+
return semtok.TokType, []string{"slice"}
503+
case *types.Chan:
504+
return semtok.TokType, []string{"chan"}
505+
case *types.Basic:
506+
return semtok.TokType, []string{"defaultLibrary"}
507+
default:
508+
return semtok.TokType, nil
509+
}
510+
}
511+
486512
func (tv *tokenVisitor) ident(id *ast.Ident) {
487513
var obj types.Object
488514

@@ -535,10 +561,9 @@ func (tv *tokenVisitor) ident(id *ast.Ident) {
535561
case *types.TypeName: // could be a TypeParam
536562
if is[*types.TypeParam](aliases.Unalias(obj.Type())) {
537563
emit(semtok.TokTypeParam)
538-
} else if is[*types.Basic](obj.Type()) {
539-
emit(semtok.TokType, "defaultLibrary")
540564
} else {
541-
emit(semtok.TokType)
565+
tok, mods := underlineType(obj)
566+
emit(tok, mods...)
542567
}
543568
case *types.Var:
544569
if is[*types.Signature](aliases.Unalias(obj.Type())) {
@@ -795,11 +820,15 @@ func (tv *tokenVisitor) definitionFor(id *ast.Ident, obj types.Object) (semtok.T
795820
if fld, ok := fldm.(*ast.Field); ok {
796821
// if len(fld.names) == 0 this is a semtok.TokType, being used
797822
if len(fld.Names) == 0 {
798-
return semtok.TokType, nil
823+
tok, mods := underlineType(obj)
824+
modifiers = append(modifiers, mods...)
825+
return tok, modifiers
799826
}
800827
return semtok.TokVariable, modifiers
801828
}
802-
return semtok.TokType, modifiers
829+
tok, mods := underlineType(obj)
830+
modifiers = append(modifiers, mods...)
831+
return tok, modifiers
803832
}
804833
}
805834
// can't happen

gopls/internal/protocol/semantic.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@ var (
5252
semanticModifiers = [...]string{
5353
"declaration", "definition", "readonly", "static",
5454
"deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary",
55+
"interface", "struct", "signature", "pointer", "array", "map", "slice", "chan",
5556
}
5657
)

gopls/internal/test/integration/fake/editor.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ func clientCapabilities(cfg EditorConfig) (protocol.ClientCapabilities, error) {
353353
capabilities.TextDocument.SemanticTokens.TokenModifiers = []string{
354354
"declaration", "definition", "readonly", "static",
355355
"deprecated", "abstract", "async", "modification", "documentation", "defaultLibrary",
356+
// Additional modifiers supported by this client:
357+
"interface", "struct", "signature", "pointer", "array", "map", "slice", "chan",
356358
}
357359
// The LSP tests have historically enabled this flag,
358360
// but really we should test both ways for older editors.

0 commit comments

Comments
 (0)