-
Notifications
You must be signed in to change notification settings - Fork 44
Home
I ideally want this plugin to be pretty minimal, and mostly just a wrapper to start the roslyn server. I am not envisioning some big dev kit like vscode's plugin C# dev kit. I might add some custom handlers for the roslyn server, but I don't want to add everything.
This will be a wiki with some tips and tricks that I will probably update if there is some requests that I don't want to add to this plugin, but instead think the users can add to their config if they want this
As part of a handler that is implemented in this plugin, the roslyn server will try to restore projects that needs restoring. By default, there are no notifications for this displayed. The reason for this is that there are currently no good way to display progress notifications in neovim. Instead, there are two autocmds fired for each progress event, and also for when it is finished. This can be utilized to integrate with fidget.nvim for example to show progress notifications.
local handles = {}
vim.api.nvim_create_autocmd("User", {
pattern = "RoslynRestoreProgress",
callback = function(ev)
local token = ev.data.params[1]
local handle = handles[token]
if handle then
handle:report({
title = ev.data.params[2].state,
message = ev.data.params[2].message,
})
else
handles[token] = require("fidget.progress").handle.create({
title = ev.data.params[2].state,
message = ev.data.params[2].message,
lsp_client = {
name = "roslyn",
},
})
end
end,
})
vim.api.nvim_create_autocmd("User", {
pattern = "RoslynRestoreResult",
callback = function(ev)
local handle = handles[ev.data.token]
handles[ev.data.token] = nil
if handle then
handle.message = ev.data.err and ev.data.err.message or "Restore completed"
handle:finish()
end
end,
})
Currently, the diagnostics are a bit of a hack, and they might not always update correctly. However, it is possible to retrieve them as often as you would like with something like this:
vim.api.nvim_create_autocmd({ "InsertLeave" }, {
pattern = "*",
callback = function()
local clients = vim.lsp.get_clients({ name = "roslyn" })
if not clients or #clients == 0 then
return
end
local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
local buffers = vim.lsp.get_buffers_by_client_id(ctx.client_id)
for _, buf in ipairs(buffers) do
local params = { textDocument = vim.lsp.util.make_text_document_params(buf) }
client:request("textDocument/diagnostic", params, nil, buf)
end
end,
})
Just change the InsertLeave
event to whichever events you would like
This is already provided with the code actions if you have the cursor over the using statements. I therefore will not add a special command for this. If you however want this, you could do something like this:
vim.api.nvim_create_user_command("CSFixUsings", function()
local bufnr = vim.api.nvim_get_current_buf()
local clients = vim.lsp.get_clients({ name = "roslyn" })
if not clients or vim.tbl_isempty(clients) then
vim.notify("Couldn't find client", vim.log.levels.ERROR, { title = "Roslyn" })
return
end
local client = clients[1]
local action = {
kind = "quickfix",
data = {
CustomTags = { "RemoveUnnecessaryImports" },
TextDocument = { uri = vim.uri_from_bufnr(bufnr) },
CodeActionPath = { "Remove unnecessary usings" },
Range = {
["start"] = { line = 0, character = 0 },
["end"] = { line = 0, character = 0 },
},
UniqueIdentifier = "Remove unnecessary usings",
},
}
client:request("codeAction/resolve", action, function(err, resolved_action)
if err then
vim.notify("Fix using directives failed", vim.log.levels.ERROR, { title = "Roslyn" })
return
end
vim.lsp.util.apply_workspace_edit(resolved_action.edit, client.offset_encoding)
end)
end, { desc = "Remove unnecessary using directives" })
vim.api.nvim_create_autocmd("LspAttach", {
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
local bufnr = args.buf
if client and (client.name == "roslyn" or client.name == "roslyn_ls") then
vim.api.nvim_create_autocmd("InsertCharPre", {
desc = "Roslyn: Trigger an auto insert on '/'.",
buffer = bufnr,
callback = function()
local char = vim.v.char
if char ~= "/" then
return
end
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
row, col = row - 1, col + 1
local uri = vim.uri_from_bufnr(bufnr)
local params = {
_vs_textDocument = { uri = uri },
_vs_position = { line = row, character = col },
_vs_ch = char,
_vs_options = {
tabSize = vim.bo[bufnr].tabstop,
insertSpaces = vim.bo[bufnr].expandtab,
},
}
-- NOTE: We should send textDocument/_vs_onAutoInsert request only after
-- buffer has changed.
vim.defer_fn(function()
client:request(
---@diagnostic disable-next-line: param-type-mismatch
"textDocument/_vs_onAutoInsert",
params,
function(err, result, _)
if err or not result then
return
end
vim.snippet.expand(result._vs_textEdit.newText)
end,
bufnr
)
end, 1)
end,
})
end
end,
})