-
Notifications
You must be signed in to change notification settings - Fork 18k
x/tools/gopls: not returning semanticTokensProvider capability #54531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Just to be clear, the specification states:
|
Thanks for the bug report. For our own prioritization, could you tell us what problem this protocol issue presents to the end user? |
I am the author of a language server protocol client. The impact is that semantic highlighting doesn't work without gopls-specific hacks. I have made this work for our users, but would like to remove hacks or undocumented deviations from the specification, as any new version of gopls could break this workaround. |
Thanks for clarifying. It doesn't sound like your need is urgent, but rest assured that we consider it a bug too. |
sure, it's not urgent - thought I'd point it out as other clients may also benefit if they don't have the capability to do something bespoke. |
I tried to force semantic tokens with neovim's built-in client copying @puremourning 's code in ycm, but no dice require 'lspconfig'.gopls.setup({
-- …
settings = {
gopls = {
hints = {
assignVariableTypes = true,
compositeLiteralFields = true,
compositeLiteralTypes = true,
constantValues = true,
functionTypeParameters = true,
parameterNames = true,
rangeVariableTypes = true,
},
semanticTokens = true,
},
},
})
|
"no dice" is kinda hard to debug. |
here's the filtered log (
|
You'd still need to manually amend the server capabilities. Copying the YCM stuff I'd get: vim.lsp.start({
-- ...
settings = {
gopls = {
semanticTokens = true,
},
}
) Then, in your on_attach or LspAttach handler: if client.name == "gopls" and not client.server_capabilities.semanticTokensProvider then
-- Generate a synthetic semanticTokensProvider (https://github.com/golang/go/issues/54531).
-- WARNING: This is wrong, it seems to be mismatched with what gopls actually provides.
client.server_capabilities.semanticTokensProvider = {
full = true,
legend = {
tokenModifiers = {},
tokenTypes = {
"class",
"comment",
"enum",
"enumMember",
"event",
"function",
"interface",
"keyword",
"macro",
"member",
"method",
"modifier",
"namespace",
"number",
"operator",
"parameter",
"property",
"regexp",
"string",
"struct",
"type",
"typeParameter",
"variable",
},
}
}
end Which makes my editor light up like a Christmas tree (so gopls is actually sending semantic tokens), but not in a good way. Comparing this with a company-internal LSP that also provides semantic tokens for Go and a proper |
@aktau Manually adding the legend won’t work if the indexes for the types don’t match the encoding used internally by the server (ordering is important). So you probably just don’t have a 1:1 mapping in your legend vs the one gopls is using. gopls definitely needs to be updated to send its legend back in the initialize response. |
cc @pjweinb |
Presently gopls is supposed to be using the information it gets from the client. That is, it is supposed to be using the ordering the client sent in the 'initialize' message for the tokens and the modifiers. Is that not what it seems to be doing, or should it be doing something else, or is the problem just that it is not echoing back in its response what the client sent it? [I'd believe any of these, and it we'd like to get it right.] |
What the client sends in capabilities and the legend returned by the server are not the same thing technically, but a valid approach would be for gopls to return the clients supported token types and modifiers as its legend and complete the semanticTokensProvider interface. This would work, as that’s what is happening now (my YCM hack does essentially exactly that: pretends that what gopls returned was what we sent at client capability.) |
Gopls sends a Semantic Token legend in a client/registerCapability message, if the client supports dynamic registration, as vscode does. But it doesn't respond with a legend if not, which is a bug. We'll try to get this right. |
Change https://go.dev/cl/459561 mentions this issue: |
Change https://go.dev/cl/462215 mentions this issue: |
Even though this issue is closed, it seems that Neovim does not pick up on I figured out a workaround which avoids hard-coding the existing token modifiers and types: if client.name == 'gopls' and not client.server_capabilities.semanticTokensProvider then
local semantic = client.config.capabilities.textDocument.semanticTokens
client.server_capabilities.semanticTokensProvider = {
full = true,
legend = {tokenModifiers = semantic.tokenModifiers, tokenTypes = semantic.tokenTypes},
range = true,
}
end |
waiting on gopls new version release
https://go.googlesource.com/tools/+/refs/tags/v0.8.0/gopls/doc/semantictokens.md The necessity for a custom on_attach callback function is temporary. In the next release of gopls, semantic tokens will be registered statically (golang/go#54531).
gopls version
go env
What did you do?
semanticTokens: true
What did you expect to see?
The initialise response should include
semanticTokensProvider
including thelegend
required to decode the tokens:What did you see instead?
gopls does not declare that it supports semantic Tokens.
Editor and settings
ycmd
Settings:
Logs
https://gist.github.com/puremourning/6a531965b8a6ef2bcde713e6cf9f2ae2
The text was updated successfully, but these errors were encountered: