diff options
| author | Minh Khoi Do <107194093+khoido2003@users.noreply.github.com> | 2025-09-03 22:09:46 +0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-03 08:09:46 -0700 |
| commit | 5d785f0e9fd95124fa6332ebc30d66607ea3ca76 (patch) | |
| tree | 058a902972321afbe012738271233ea69701df2c | |
| parent | feat(biome,eslint,svelte,ts_ls,tsgo,vtsls): add deno.lock root marker #4051 (diff) | |
| download | nvim-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.lua | 69 |
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 = { |
