internal/lsp: produce "method" in place of "member" as per the spec
As per the current specification, the correct token name that represents methods is `method`. The current implementation does not produce the correct set of result and results in methods being incorrectly highlighted. Furthermore, the parameter names of interface methods are treated as `method` which is not true, so a fix has been applied to handle `ast.FuncType` being `parameter`.
Spec: https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#textDocument_semanticTokens
Change-Id: Id5d2fafe9f948a4a175ae19b4c94cca8f48a4b79
GitHub-Last-Rev: 9a3b65ca4dd3bb0542969c043a2042001c7fcb63
GitHub-Pull-Request: golang/tools#340
Reviewed-on: https://go-review.googlesource.com/c/tools/+/349449
Run-TryBot: Peter Weinberger <pjw@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Rebecca Stambler <rstambler@golang.org>
Trust: Peter Weinberger <pjw@google.com>
Reviewed-by: Peter Weinberger <pjw@google.com>
diff --git a/gopls/doc/semantictokens.md b/gopls/doc/semantictokens.md
index fc541fb..c9124b7 100644
--- a/gopls/doc/semantictokens.md
+++ b/gopls/doc/semantictokens.md
@@ -16,7 +16,7 @@
The 22 semantic tokens are `namespace`, `type`, `class`, `enum`, `interface`,
`struct`, `typeParameter`, `parameter`, `variable`, `property`, `enumMember`,
- `event`, `function`, `member`, `macro`, `keyword`, `modifier`, `comment`,
+ `event`, `function`, `method`, `macro`, `keyword`, `modifier`, `comment`,
`string`, `number`, `regexp`, `operator`.
The 10 modifiers are `declaration`, `definition`, `readonly`, `static`,
@@ -72,7 +72,7 @@
1. __`type`__ Objects of type ```types.TypeName``` are marked `type`.
If they are also ```types.Basic```
the modifier is `defaultLibrary`. (And in ```type B struct{C}```, ```B``` has modifier `definition`.)
-1. __`parameter`__ The formal arguments in ```ast.FuncDecl``` nodes are marked `parameter`.
+1. __`parameter`__ The formal arguments in ```ast.FuncDecl``` and ```ast.FuncType``` nodes are marked `parameter`.
1. __`variable`__ Identifiers in the
scope of ```const``` are modified with `readonly`. ```nil``` is usually a `variable` modified with both
`readonly` and `defaultLibrary`. (```nil``` is a predefined identifier; the user can redefine it,
@@ -80,8 +80,8 @@
not surprisingly, marked `variable`. Identifiers being defined (node ```ast.GenDecl```) are modified
by `definition` and, if appropriate, `readonly`. Receivers (in method declarations) are
`variable`.
-1. __`member`__ Members are marked at their definition (```func (x foo) bar() {}```) or declaration
-in an ```interface```. Members are not marked where they are used.
+1. __`method`__ Methods are marked at their definition (```func (x foo) bar() {}```) or declaration
+in an ```interface```. Methods are not marked where they are used.
In ```x.bar()```, ```x``` will be marked
either as a `namespace` if it is a package name, or as a `variable` if it is an interface value,
so distinguishing ```bar``` seemed superfluous.
diff --git a/internal/lsp/semantic.go b/internal/lsp/semantic.go
index 29bcf95..6a98b6c 100644
--- a/internal/lsp/semantic.go
+++ b/internal/lsp/semantic.go
@@ -155,7 +155,7 @@
tokInterface tokenType = "interface"
tokParameter tokenType = "parameter"
tokVariable tokenType = "variable"
- tokMember tokenType = "member"
+ tokMethod tokenType = "method"
tokFunction tokenType = "function"
tokKeyword tokenType = "keyword"
tokComment tokenType = "comment"
@@ -598,7 +598,7 @@
_, okit := e.stack[n-2].(*ast.InterfaceType)
_, okfl := e.stack[n-1].(*ast.FieldList)
if okit && okfl {
- tok(tokMember, def)
+ tok(tokMethod, def)
return
}
}
@@ -645,7 +645,7 @@
if x.Name == "_" {
return "", nil // not really a variable
}
- return "variable", mods
+ return tokVariable, mods
case *ast.GenDecl:
if isDeprecated(y.Doc) {
mods = append(mods, "deprecated")
@@ -661,7 +661,7 @@
mods = append(mods, "deprecated")
}
if y.Recv != nil {
- return tokMember, mods
+ return tokMethod, mods
}
return tokFunction, mods
}
@@ -671,8 +671,10 @@
}
// if x < ... < FieldList < FuncType < FuncDecl, this is a param
return tokParameter, mods
+ case *ast.FuncType:
+ return tokParameter, mods
case *ast.InterfaceType:
- return tokMember, mods
+ return tokMethod, mods
case *ast.TypeSpec:
// GenDecl/Typespec/FuncType/FieldList/Field/Ident
// (type A func(b uint64)) (err error)
@@ -878,7 +880,7 @@
semanticTypes = [...]string{
"namespace", "type", "class", "enum", "interface",
"struct", "typeParameter", "parameter", "variable", "property", "enumMember",
- "event", "function", "member", "macro", "keyword", "modifier", "comment",
+ "event", "function", "method", "macro", "keyword", "modifier", "comment",
"string", "number", "regexp", "operator",
}
semanticModifiers = [...]string{
diff --git a/internal/lsp/testdata/semantic/a.go.golden b/internal/lsp/testdata/semantic/a.go.golden
index cc522a1..4622ae4 100644
--- a/internal/lsp/testdata/semantic/a.go.golden
+++ b/internal/lsp/testdata/semantic/a.go.golden
@@ -31,12 +31,12 @@
}
/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/B /*⇒9,keyword,[]*/interface {
/*⇒1,type,[]*/A
- /*⇒3,member,[definition]*/sad(/*⇒3,type,[defaultLibrary]*/int) /*⇒4,type,[defaultLibrary]*/bool
+ /*⇒3,method,[definition]*/sad(/*⇒3,type,[defaultLibrary]*/int) /*⇒4,type,[defaultLibrary]*/bool
}
/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/F /*⇒3,type,[defaultLibrary]*/int
-/*⇒4,keyword,[]*/func (/*⇒1,variable,[]*/a /*⇒1,operator,[]*/*/*⇒1,type,[]*/A) /*⇒1,member,[definition]*/f() /*⇒4,type,[defaultLibrary]*/bool {
+/*⇒4,keyword,[]*/func (/*⇒1,variable,[]*/a /*⇒1,operator,[]*/*/*⇒1,type,[]*/A) /*⇒1,method,[definition]*/f() /*⇒4,type,[defaultLibrary]*/bool {
/*⇒3,keyword,[]*/var /*⇒1,variable,[definition]*/z /*⇒6,type,[defaultLibrary]*/string
/*⇒1,variable,[definition]*/x /*⇒2,operator,[]*/:= /*⇒5,string,[]*/"foo"
/*⇒1,variable,[]*/a(/*⇒1,variable,[]*/x)
diff --git a/internal/lsp/testdata/semantic/b.go.golden b/internal/lsp/testdata/semantic/b.go.golden
index 863a68c..203f6b1 100644
--- a/internal/lsp/testdata/semantic/b.go.golden
+++ b/internal/lsp/testdata/semantic/b.go.golden
@@ -31,6 +31,6 @@
/*⇒4,keyword,[]*/type /*⇒2,type,[definition]*/CC /*⇒6,keyword,[]*/struct {
/*⇒2,variable,[definition]*/AA /*⇒3,type,[defaultLibrary]*/int
}
-/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/D /*⇒4,keyword,[]*/func(/*⇒2,variable,[definition]*/aa /*⇒2,type,[]*/AA) (/*⇒2,variable,[definition]*/BB /*⇒5,type,[]*/error)
+/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/D /*⇒4,keyword,[]*/func(/*⇒2,parameter,[definition]*/aa /*⇒2,type,[]*/AA) (/*⇒2,parameter,[definition]*/BB /*⇒5,type,[]*/error)
/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/E /*⇒4,keyword,[]*/func(/*⇒2,type,[]*/AA) /*⇒2,type,[]*/BB