aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMinh Khoi Do <107194093+khoido2003@users.noreply.github.com>2025-09-03 22:09:46 +0700
committerGitHub <noreply@github.com>2025-09-03 08:09:46 -0700
commit5d785f0e9fd95124fa6332ebc30d66607ea3ca76 (patch)
tree058a902972321afbe012738271233ea69701df2c
parentfeat(biome,eslint,svelte,ts_ls,tsgo,vtsls): add deno.lock root marker #4051 (diff)
downloadnvim-lspconfig-5d785f0e9fd95124fa6332ebc30d66607ea3ca76.tar
nvim-lspconfig-5d785f0e9fd95124fa6332ebc30d66607ea3ca76.tar.gz
nvim-lspconfig-5d785f0e9fd95124fa6332ebc30d66607ea3ca76.tar.bz2
nvim-lspconfig-5d785f0e9fd95124fa6332ebc30d66607ea3ca76.tar.lz
nvim-lspconfig-5d785f0e9fd95124fa6332ebc30d66607ea3ca76.tar.xz
nvim-lspconfig-5d785f0e9fd95124fa6332ebc30d66607ea3ca76.tar.zst
nvim-lspconfig-5d785f0e9fd95124fa6332ebc30d66607ea3ca76.zip
feat(roslyn_ls): support override completion and refresh diagnostics #4050
Problem: - Diagnostics were only refreshed for the current buffer, not all buffers managed by the client. In multi-file C# projects, this left diagnostics stale unless the user switched buffers. - Roslyn did not handle override method completion correctly. Solution: - Added `roslyn.client.completionComplexEdit` handler to apply edits for override completions. - Added `refresh_diagnostics` function, called on project initialization and on `BufWritePost` / `InsertLeave` events, to proactively pull diagnostics for all client buffers. Rationale: - Roslyn LSP primarily uses pull-based diagnostics. Neovim currently only triggers diagnostic pulls on text changes in the active buffer. This makes `debounce_text_changes` insufficient for Roslyn, as changes in one file can affect diagnostics across the entire solution. - The autocmds act as a server-specific workaround to mimic an “on-save/on-idle” pull model.
-rw-r--r--lsp/roslyn_ls.lua69
1 files changed, 62 insertions, 7 deletions
diff --git a/lsp/roslyn_ls.lua b/lsp/roslyn_ls.lua
index b7437da5..0469e1ad 100644
--- a/lsp/roslyn_ls.lua
+++ b/lsp/roslyn_ls.lua
@@ -22,6 +22,8 @@
local uv = vim.uv
local fs = vim.fs
+local group = vim.api.nvim_create_augroup('lspconfig.roslyn_ls', { clear = true })
+
---@param client vim.lsp.Client
---@param target string
local function on_init_sln(client, target)
@@ -44,19 +46,30 @@ local function on_init_project(client, project_files)
})
end
+---@param client vim.lsp.Client
+local function refresh_diagnostics(client)
+ local buffers = vim.lsp.get_buffers_by_client_id(client.id)
+ for _, buf in ipairs(buffers) do
+ if vim.api.nvim_buf_is_loaded(buf) then
+ client:request(
+ vim.lsp.protocol.Methods.textDocument_diagnostic,
+ { textDocument = vim.lsp.util.make_text_document_params(buf) },
+ nil,
+ buf
+ )
+ end
+ end
+end
+
local function roslyn_handlers()
return {
['workspace/projectInitializationComplete'] = function(_, _, ctx)
vim.notify('Roslyn project initialization complete', vim.log.levels.INFO, { title = 'roslyn_ls' })
-
- local buffers = vim.lsp.get_buffers_by_client_id(ctx.client_id)
local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
- for _, buf in ipairs(buffers) do
- client:request(vim.lsp.protocol.Methods.textDocument_diagnostic, {
- textDocument = vim.lsp.util.make_text_document_params(buf),
- }, nil, buf)
- end
+ refresh_diagnostics(client)
+ return vim.NIL
end,
+
['workspace/_roslyn_projectHasUnresolvedDependencies'] = function()
vim.notify('Detected missing dependencies. Run `dotnet restore` command.', vim.log.levels.ERROR, {
title = 'roslyn_ls',
@@ -105,6 +118,31 @@ return {
},
filetypes = { 'cs' },
handlers = roslyn_handlers(),
+
+ commands = {
+ ['roslyn.client.completionComplexEdit'] = function(command, ctx)
+ local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
+ local args = command.arguments or {}
+ local uri, edit = args[1], args[2]
+
+ if uri and edit and edit.newText and edit.range then
+ local workspace_edit = {
+ changes = {
+ [uri.uri] = {
+ {
+ range = edit.range,
+ newText = edit.newText,
+ },
+ },
+ },
+ }
+ vim.lsp.util.apply_workspace_edit(workspace_edit, client.offset_encoding)
+ else
+ vim.notify('roslyn_ls: completionComplexEdit args not understood: ' .. vim.inspect(args), vim.log.levels.WARN)
+ end
+ end,
+ },
+
root_dir = function(bufnr, cb)
local bufname = vim.api.nvim_buf_get_name(bufnr)
-- don't try to find sln or csproj for files from libraries
@@ -147,6 +185,23 @@ return {
end
end,
},
+
+ on_attach = function(client, bufnr)
+ -- avoid duplicate autocmds for same buffer
+ if vim.api.nvim_get_autocmds({ buffer = bufnr, group = group })[1] then
+ return
+ end
+
+ vim.api.nvim_create_autocmd({ 'BufWritePost', 'InsertLeave' }, {
+ group = group,
+ buffer = bufnr,
+ callback = function()
+ refresh_diagnostics(client)
+ end,
+ desc = 'roslyn_ls: refresh diagnostics',
+ })
+ end,
+
capabilities = {
-- HACK: Doesn't show any diagnostics if we do not set this to true
textDocument = {