Open StefanFanaru opened 1 month ago
It looks like nvim and roslyn don't yet support a common request type when it comes to semantic highlights: https://github.com/neovim/neovim/pull/26500 https://github.com/dotnet/roslyn/issues/70536
Here's a little hack you can put in your on_attach to get semantic tokens:
on_attach = function(client)
-- make sure this happens once per client, not per buffer
if not client.is_hacked then
client.is_hacked = true
-- let the runtime know the server can do semanticTokens/full now
client.server_capabilities = vim.tbl_deep_extend("force", client.server_capabilities, {
semanticTokensProvider = {
full = true,
},
})
-- monkey patch the request proxy
local request_inner = client.request
client.request = function(method, params, handler)
if method ~= vim.lsp.protocol.Methods.textDocument_semanticTokens_full then
return request_inner(method, params, handler)
end
local function find_buf_by_uri(search_uri)
local bufs = vim.api.nvim_list_bufs()
for _, buf in ipairs(bufs) do
local name = vim.api.nvim_buf_get_name(buf)
local uri = "file://" .. name
if uri == search_uri then
return buf
end
end
end
local doc_uri = params.textDocument.uri
local target_bufnr = find_buf_by_uri(doc_uri)
local line_count = vim.api.nvim_buf_line_count(target_bufnr)
local last_line = vim.api.nvim_buf_get_lines(target_bufnr, line_count - 1, line_count, true)[1]
return request_inner("textDocument/semanticTokens/range", {
textDocument = params.textDocument,
range = {
["start"] = {
line = 0,
character = 0,
},
["end"] = {
line = line_count - 1,
character = string.len(last_line) - 1,
},
},
}, handler)
end
end
end
It translates textDocument/semanticTokens/full
to textDocument/semanticTokens/range
and back. I can put it in a PR later if wanted.
Thank you a lot for your reply and for the workaround. Unfortunatley I can't get it to work, maybe i'm missing something
I did it like this inside lsp config:
require("roslyn").setup({
dotnet_cmd = "dotnet",
roslyn_version = "4.11.0-1.24209.10",
on_attach = function(client)
-- make sure this happens once per client, not per buffer
if not client.is_hacked then
client.is_hacked = true
-- let the runtime know the server can do semanticTokens/full now
client.server_capabilities = vim.tbl_deep_extend("force", client.server_capabilities, {
semanticTokensProvider = {
full = true,
},
})
-- monkey patch the request proxy
local request_inner = client.request
client.request = function(method, params, handler)
if method ~= vim.lsp.protocol.Methods.textDocument_semanticTokens_full then
return request_inner(method, params, handler)
end
local function find_buf_by_uri(search_uri)
local bufs = vim.api.nvim_list_bufs()
for _, buf in ipairs(bufs) do
local name = vim.api.nvim_buf_get_name(buf)
local uri = "file://" .. name
if uri == search_uri then
return buf
end
end
end
local doc_uri = params.textDocument.uri
local target_bufnr = find_buf_by_uri(doc_uri)
local line_count = vim.api.nvim_buf_line_count(target_bufnr)
local last_line =
vim.api.nvim_buf_get_lines(target_bufnr, line_count - 1, line_count, true)[1]
return request_inner("textDocument/semanticTokens/range", {
textDocument = params.textDocument,
range = {
["start"] = {
line = 0,
character = 0,
},
["end"] = {
line = line_count - 1,
character = string.len(last_line) - 1,
},
},
}, handler)
end
end
end,
capabilities = capabilities,
settings = {
["csharp|inlay_hints"] = {
csharp_enable_inlay_hints_for_lambda_parameter_types = true,
csharp_enable_inlay_hints_for_implicit_object_creation = true,
csharp_enable_inlay_hints_for_implicit_variable_types = true,
csharp_enable_inlay_hints_for_types = true,
dotnet_enable_inlay_hints_for_indexer_parameters = true,
dotnet_enable_inlay_hints_for_literal_parameters = true,
dotnet_enable_inlay_hints_for_object_creation_parameters = true,
dotnet_enable_inlay_hints_for_other_parameters = true,
dotnet_enable_inlay_hints_for_parameters = true,
dotnet_suppress_inlay_hints_for_parameters_that_differ_only_by_suffix = true,
dotnet_suppress_inlay_hints_for_parameters_that_match_argument_name = true,
dotnet_suppress_inlay_hints_for_parameters_that_match_method_intent = true,
},
},
})
Any update on this one ?
It used to work using that config for a while but now it suddenly stopped.
{
"seblj/roslyn.nvim",
event = "User csFile",
config = function()
require("roslyn").setup({
dotnet_cmd = "dotnet", -- this is the default
roslyn_version = "4.12.0-1.24329.2", -- this is the default
on_attach = function(client)
-- make sure this happens once per client, not per buffer
if not client.is_hacked then
client.is_hacked = true
-- let the runtime know the server can do semanticTokens/full now
client.server_capabilities = vim.tbl_deep_extend("force", client.server_capabilities, {
semanticTokensProvider = {
full = true,
},
})
-- monkey patch the request proxy
local request_inner = client.request
client.request = function(method, params, handler)
if method ~= vim.lsp.protocol.Methods.textDocument_semanticTokens_full then
return request_inner(method, params, handler)
end
local function find_buf_by_uri(search_uri)
local bufs = vim.api.nvim_list_bufs()
for _, buf in ipairs(bufs) do
local name = vim.api.nvim_buf_get_name(buf)
local uri = "file://" .. name
if uri == search_uri then
return buf
end
end
end
local doc_uri = params.textDocument.uri
local target_bufnr = find_buf_by_uri(doc_uri)
local line_count = vim.api.nvim_buf_line_count(target_bufnr)
local last_line = vim.api.nvim_buf_get_lines(target_bufnr, line_count - 1, line_count, true)[1]
return request_inner("textDocument/semanticTokens/range", {
textDocument = params.textDocument,
range = {
["start"] = {
line = 0,
character = 0,
},
["end"] = {
line = line_count - 1,
character = string.len(last_line) - 1,
},
},
}, handler)
end
end
end
})
end
},
EDIT: Okay it apppears like on_attach is not invoked anymore. So I guess once I get this done it'll start working again. EDIT2: The latest update fixes this issue :)
Here's a little hack you can put in your on_attach to get semantic tokens:
on_attach = function(client) -- make sure this happens once per client, not per buffer if not client.is_hacked then client.is_hacked = true -- let the runtime know the server can do semanticTokens/full now client.server_capabilities = vim.tbl_deep_extend("force", client.server_capabilities, { semanticTokensProvider = { full = true, }, }) -- monkey patch the request proxy local request_inner = client.request client.request = function(method, params, handler) if method ~= vim.lsp.protocol.Methods.textDocument_semanticTokens_full then return request_inner(method, params, handler) end local function find_buf_by_uri(search_uri) local bufs = vim.api.nvim_list_bufs() for _, buf in ipairs(bufs) do local name = vim.api.nvim_buf_get_name(buf) local uri = "file://" .. name if uri == search_uri then return buf end end end local doc_uri = params.textDocument.uri local target_bufnr = find_buf_by_uri(doc_uri) local line_count = vim.api.nvim_buf_line_count(target_bufnr) local last_line = vim.api.nvim_buf_get_lines(target_bufnr, line_count - 1, line_count, true)[1] return request_inner("textDocument/semanticTokens/range", { textDocument = params.textDocument, range = { ["start"] = { line = 0, character = 0, }, ["end"] = { line = line_count - 1, character = string.len(last_line) - 1, }, }, }, handler) end end end
It translates
textDocument/semanticTokens/full
totextDocument/semanticTokens/range
and back. I can put it in a PR later if wanted.
This monkeypatch appears to work in my case but I've got one weird problem. Whenever I open a file I need to toggle the syntax on and off for it to work.
Here's a little hack you can put in your on_attach to get semantic tokens:
on_attach = function(client) -- make sure this happens once per client, not per buffer if not client.is_hacked then client.is_hacked = true -- let the runtime know the server can do semanticTokens/full now client.server_capabilities = vim.tbl_deep_extend("force", client.server_capabilities, { semanticTokensProvider = { full = true, }, }) -- monkey patch the request proxy local request_inner = client.request client.request = function(method, params, handler) if method ~= vim.lsp.protocol.Methods.textDocument_semanticTokens_full then return request_inner(method, params, handler) end local function find_buf_by_uri(search_uri) local bufs = vim.api.nvim_list_bufs() for _, buf in ipairs(bufs) do local name = vim.api.nvim_buf_get_name(buf) local uri = "file://" .. name if uri == search_uri then return buf end end end local doc_uri = params.textDocument.uri local target_bufnr = find_buf_by_uri(doc_uri) local line_count = vim.api.nvim_buf_line_count(target_bufnr) local last_line = vim.api.nvim_buf_get_lines(target_bufnr, line_count - 1, line_count, true)[1] return request_inner("textDocument/semanticTokens/range", { textDocument = params.textDocument, range = { ["start"] = { line = 0, character = 0, }, ["end"] = { line = line_count - 1, character = string.len(last_line) - 1, }, }, }, handler) end end end
It translates
textDocument/semanticTokens/full
totextDocument/semanticTokens/range
and back. I can put it in a PR later if wanted.This monkeypatch appears to work in my case but I've got one weird problem. Whenever I open a file I need to toggle the syntax on and off for it to work.
Could it have something to do with the lazy events you load your LSP with?
No I started clean. Maybe it's something weird with my solution I dont konw.
Yaml files started having this issue as well. Theres something in this directories really messing up treesitter but I think I'll get it handled.
Btw I started uploading the lsp builds to a github repository once a day if that is of any interest to you
I know that this new LSP from Microsoft supports semantic tokens, but the usage of this library in neovim is not able to deliver them. Is there a way to enable them?
What I underlined with red should have been colored with red because they are parameters. What I underlined with yellow should have been yellow because they are Types.![image](https://github.com/jmederosalvarado/roslyn.nvim/assets/76454148/67a12551-a669-4687-9b38-361afbe8fd37)