diff --git a/lua/rzls/documentstore.lua b/lua/rzls/documentstore.lua index 6a83e0c..79b5ddd 100644 --- a/lua/rzls/documentstore.lua +++ b/lua/rzls/documentstore.lua @@ -76,6 +76,9 @@ function M.update_vbuf(result, language_kind) local buf_eol = utils.buffer_eol(virtual_document.buf) local lines = vim.fn.split(virtual_document.content, buf_eol, true) vim.api.nvim_buf_set_lines(virtual_document.buf, 0, -1, false, lines) + if language_kind == razor.language_kinds.csharp then + vim.lsp.util._refresh("textDocument/diagnostic", { bufnr = virtual_document.buf }) + end end ---Creates virtual buffers for the given source buffer diff --git a/lua/rzls/server/lsp.lua b/lua/rzls/server/lsp.lua index 65a6858..e5235d6 100644 --- a/lua/rzls/server/lsp.lua +++ b/lua/rzls/server/lsp.lua @@ -8,13 +8,22 @@ local requests = { hoverProvider = true, definitionProvider = true, referencesProvider = true, + diagnosticProvider = { identifier = "aftershave" }, + textDocumentSync = 1, -- this is just a hack to get the notication to force a diag refresh }, + name = "aftershave", + version = "69.420", } end, ["shutdown"] = function(_) end, ["textDocument/hover"] = require("rzls.server.methods.hover"), ["textDocument/definition"] = require("rzls.server.methods.definition"), ["textDocument/references"] = require("rzls.server.methods.references"), + ["textDocument/diagnostic"] = require("rzls.server.methods.diagnostics"), +} + +local noops = { + ["textDocument/didClose"] = true, } function M.server() @@ -31,13 +40,20 @@ function M.server() Log.aftershave = "Closing aftershave server" closing = true else - Log.aftershave = "Unhandled method " .. method + Log.aftershave = "Unhandled request method " .. method end end - function srv.notify(method, _params) + function srv.notify(method, params) if method == "exit" then closing = true + elseif method == "textDocument/didOpen" or method == "textDocument/didChange" then + vim.defer_fn(function() + -- Defer to allow for roslyn to update + requests["textDocument/diagnostic"]({ textDocument = params.textDocument }) + end, 250) + elseif not noops[method] then + Log.aftershave = "Unhandled notify method " .. method end end diff --git a/lua/rzls/server/methods/diagnostics.lua b/lua/rzls/server/methods/diagnostics.lua new file mode 100644 index 0000000..fb402f6 --- /dev/null +++ b/lua/rzls/server/methods/diagnostics.lua @@ -0,0 +1,58 @@ +local documentstore = require("rzls.documentstore") +local razor = require("rzls.razor") +local Log = require("rzls.log") +local after_shave_diag_ns = vim.api.nvim_create_namespace("after_shave_diag_ns") + +---@param params lsp.DocumentDiagnosticParams +return function(params) + local razor_bufnr = vim.uri_to_bufnr(params.textDocument.uri) + local razor_docname = vim.api.nvim_buf_get_name(razor_bufnr) + + local vd = documentstore.get_virtual_document(razor_docname, 0, razor.language_kinds.csharp) + if not vd then + Log.rzlsnvim = "aftershave didnt find virtual document when publish diagnostics" + return + end + + local diags = vim.diagnostic.get(vd.buf, { severity = 1 }) + + local csharp_lines = vim.split(vd.content, "\n", { trimempty = false }) + + ---@type vim.Diagnostic[] + local mapped_diags = {} + + for _, diag in ipairs(diags) do + local orig_line = diag.lnum + local offset = -1 + -- walk up from the current line looking for the #line marker + -- if we find it, we can map the diagnostic to the razor file + + for i = orig_line, 1, -1 do + local cur_line = csharp_lines[i] + -- #line 58 "/home/tris/code/blazort/BlazorApp/Components/Pages/Movies.razor" + if cur_line:match("#line") then + local _, _, line, file = cur_line:find('#line (%d+) "(.+)"') + if line and file == razor_docname then + ---@type vim.Diagnostic + local new_diag = { + bufnr = razor_bufnr, + code = diag.code, + col = diag.col, + end_col = diag.end_col, + lnum = line + offset, + end_lnum = line + offset + (diag.lnum - diag.end_lnum), + message = diag.message, + severity = diag.severity, + namespace = after_shave_diag_ns, + _tags = diag._tags, + } + table.insert(mapped_diags, new_diag) + break + end + end + offset = offset + 1 + end + end + + vim.diagnostic.set(after_shave_diag_ns, razor_bufnr, mapped_diags, {}) +end