-
Notifications
You must be signed in to change notification settings - Fork 34
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
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 buffers = vim.lsp.get_buffers_by_client_id(clients[1].id)
for _, buf in ipairs(buffers) do
vim.lsp.util._refresh("textDocument/diagnostic", { bufnr = 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" })
{
'seblyng/roslyn.nvim',
---@module 'roslyn.config'
---@type RoslynNvimConfig
opts = {
config = {
capabilities = {
textDocument = {
_vs_onAutoInsert = { dynamicRegistration = false },
},
},
handlers = {
['textDocument/_vs_onAutoInsert'] = function(err, result, _)
if err or not result then
return
end
apply_vs_text_edit(result._vs_textEdit)
end,
},
},
},
},
---@class LineRange
---@field line integer
---@field character integer
---@class EditRange
---@field start LineRange
---@field end LineRange
---@class TextEdit
---@field newText string
---@field range EditRange
---@param edit TextEdit
local function apply_vs_text_edit(edit)
local bufnr = vim.api.nvim_get_current_buf()
local start_line = edit.range.start.line
local start_char = edit.range.start.character
local end_line = edit.range['end'].line
local end_char = edit.range['end'].character
local newText = string.gsub(edit.newText, "\r", "")
local lines = vim.split(newText, "\n")
local placeholder_row = -1
local placeholder_col = -1
-- placeholder handling
for i, line in ipairs(lines) do
local pos = string.find(line, '%$0')
if pos then
lines[i] = string.gsub(line, '%$0', '', 1)
placeholder_row = start_line + i - 1
placeholder_col = pos - 1
break
end
end
vim.api.nvim_buf_set_text(bufnr, start_line, start_char, end_line, end_char, lines)
if placeholder_row ~= -1 and placeholder_col ~= -1 then
local win = vim.api.nvim_get_current_win()
vim.api.nvim_win_set_cursor(win, { placeholder_row + 1, placeholder_col })
end
end
vim.api.nvim_create_autocmd('InsertCharPre', {
pattern = '*.cs',
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 bufnr = vim.api.nvim_get_current_buf()
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 = 4, insertSpaces = true },
}
-- NOTE: we should send textDocument/_vs_onAutoInsert request only after buffer has changed.
vim.defer_fn(function()
vim.lsp.buf_request(bufnr, 'textDocument/_vs_onAutoInsert', params)
end, 1)
end,
})