Closed SchnozzleCat closed 4 days ago
Looking into this a bit more, it seems the roslyn
server already supports this, but setting the following:
["csharp|background_analysis"] = {
dotnet_compiler_diagnostics_scope = "fullSolution"
}
Doesn't seem to change anything.
Hmm I actually have no idea... I have spent an hour or two now trying to look through the source code for neovim, roslyn and c# dev-kit, but I can't see anything that indicates that this shouldn't work... Let me know if you manage to find something
Hmm I actually have no idea... I have spent an hour or two now trying to look through the source code for neovim, roslyn and c# dev-kit, but I can't see anything that indicates that this shouldn't work... Let me know if you manage to find something
Yeah it's strange. I even compiled the language server from source and set the default for that option to use FullSolution
, and it still doesn't work.
I have no idea how the event handlers for the LSP client work, maybe it's missing one for Workspace Diagnostics or something?
Maybe🤔 but I couldn't find anything that would suggest this. It is responding to a textDocument/diagnostic
, and I assumed that the server returns all diagnostics if the option is on. However, it clearly isn't... I have tried a couple of times to compile it myself to debug, but I havent't managed to do it. How did you do it? I think if we follow everything from when the server gets the request, we could figure out why. However, this is super difficult by just looking at the source code, and without actually debugging it
Maybe🤔 but I couldn't find anything that would suggest this. It is responding to a
textDocument/diagnostic
, and I assumed that the server returns all diagnostics if the option is on. However, it clearly isn't... I have tried a couple of times to compile it myself to debug, but I havent't managed to do it. How did you do it? I think if we follow everything from when the server gets the request, we could figure out why. However, this is super difficult by just looking at the source code, and without actually debugging it
I pulled the roslyn
main branch, installed dotnet9, and ran dotnet build ./src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Microsoft.CodeAnalysis.LanguageServer.csproj --configuration RELEASE
.
I assume running it in DEBUG should let you attach a debugger like netcoredbg
to it, but I haven't tested it yet.
Okay thanks! Will look at this more at a later time. Feel free the comment here about your findings if you keep debugging this!
No specific findings, but if you compile with DEBUG you can attach, and if you run the server with the --debug
flag, it will wait for a managed debugger to attach before continuing, which should make debugging easier.
I'll look into it a bit myself, but I don't really know how these language servers work, so unsure if I'll find anything useful in the time I have.
I am getting a bunch of these errors trying to compile
That's odd. It looks like it's trying to pull in dependencies from nuget instead of locally, maybe that's why its failing since the code does not match? Not a nuget expert though...
Actually, I don't think that's it, it looks like C# core stuff. Maybe a version mismatch? Check what's used in global.json on the commit you are on and make sure that's what you are using as well.
Yeah I have no idea. I was trying lots of different things for over an hour now, but no luck... I came across an issue on the repo which looked similar to my issue. However, it was closed as completed and didn't find any workaround or anything
In the meanwhile I am using a parserr to get the errors in a quick fix list
I got it working! (kind of)
Confirmed using dll: Microsoft.CodeAnalysis.LanguageServer.dll version: 4.12.0-1.24359.11+7e282662d51afa4923cdd0696ce26f4081faf706
return {
"seblj/roslyn.nvim",
commit = "5e36cac9371d014c52c4c1068a438bdb7d1c7987",
config = function()
require("roslyn").setup({
config = {
settings = {
["csharp|background_analysis"] = {
dotnet_compiler_diagnostics_scope = "fullSolution"
},
["csharp|inlay_hints"] = {
csharp_enable_inlay_hints_for_implicit_object_creation = true,
csharp_enable_inlay_hints_for_implicit_variable_types = true,
csharp_enable_inlay_hints_for_lambda_parameter_types = true,
csharp_enable_inlay_hints_for_types = true,
dotnet_enable_inlay_hints_for_indexer_parameters = true,
dotnet_enable_inlay_hints_for_literal_parameters = true,
dotnet_enable_inlay_hints_for_object_creation_parameters = true,
dotnet_enable_inlay_hints_for_other_parameters = true,
dotnet_enable_inlay_hints_for_parameters = true,
dotnet_suppress_inlay_hints_for_parameters_that_differ_only_by_suffix = true,
dotnet_suppress_inlay_hints_for_parameters_that_match_argument_name = true,
dotnet_suppress_inlay_hints_for_parameters_that_match_method_intent = true,
},
["csharp|code_lens"] = {
dotnet_enable_references_code_lens = true,
},
}
},
exe = {
"dotnet",
vim.fs.joinpath(vim.fn.stdpath("data"), "roslyn", "Microsoft.CodeAnalysis.LanguageServer.dll"),
},
filewatching = true,
})
vim.keymap.set("n", "<leader>p", function()
local clients = vim.lsp.get_clients()
for _, value in ipairs(clients) do
if value.name == "roslyn" then
vim.notify("roslyn client found")
value.rpc.request("workspace/diagnostic", { previousResultIds = {} }, function(err, result)
if err ~= nil then
print(vim.inspect(err))
end
if result ~= nil then
print(vim.inspect(result))
end
end)
end
end
end, { noremap = true, silent = true })
end
}
<leader>p
:messages
Im not sure if vim has some sort of inbuilt lsp support for workspace diagnostics but this should prove that the server itself behaves correctly
@seblj
Im working on another dotnet-plugin where I could make good use of the workspace/symbol
the only downside is that I would require the language server to be running independently of any buffer. If you are interested it would be cool to make a PR that exposes a way to start the lsp server when entering vim if it finds a solution/csproject file.
The benefits of this would be:
This would of course be exposed as opt-in functionality
@SchnozzleCat @franroa Here is a complete qf list keybinding for compiler errors
Cant be called multiple times. Might be necessary to send some textDocument/didOpen
, textDocument/didChange
before asking for diagnostics the second time
return {
"seblj/roslyn.nvim",
commit = "5e36cac9371d014c52c4c1068a438bdb7d1c7987",
config = function()
require("roslyn").setup({
config = {
settings = {
["csharp|background_analysis"] = {
dotnet_compiler_diagnostics_scope = "fullSolution"
},
["csharp|inlay_hints"] = {
csharp_enable_inlay_hints_for_implicit_object_creation = true,
csharp_enable_inlay_hints_for_implicit_variable_types = true,
csharp_enable_inlay_hints_for_lambda_parameter_types = true,
csharp_enable_inlay_hints_for_types = true,
dotnet_enable_inlay_hints_for_indexer_parameters = true,
dotnet_enable_inlay_hints_for_literal_parameters = true,
dotnet_enable_inlay_hints_for_object_creation_parameters = true,
dotnet_enable_inlay_hints_for_other_parameters = true,
dotnet_enable_inlay_hints_for_parameters = true,
dotnet_suppress_inlay_hints_for_parameters_that_differ_only_by_suffix = true,
dotnet_suppress_inlay_hints_for_parameters_that_match_argument_name = true,
dotnet_suppress_inlay_hints_for_parameters_that_match_method_intent = true,
},
["csharp|code_lens"] = {
dotnet_enable_references_code_lens = true,
},
}
},
exe = {
"dotnet",
vim.fs.joinpath(vim.fn.stdpath("data"), "roslyn", "Microsoft.CodeAnalysis.LanguageServer.dll"),
},
filewatching = true,
})
vim.keymap.set("n", "<leader>p", function()
local clients = vim.lsp.get_clients()
for _, value in ipairs(clients) do
if value.name == "roslyn" then
vim.notify("roslyn client found")
value.rpc.request("workspace/diagnostic", { previousResultIds = {} }, function(err, result)
if err ~= nil then
print(vim.inspect(err))
end
if result ~= nil then
local diags = {}
local seen = {}
for _, diag in ipairs(result.items) do
local filepath = diag.uri:gsub("file:///", "")
if #diag.items > 0 then
for _, diag_line in ipairs(diag.items) do
if diag_line.severity == 1 then
local hash = diag_line.message .. diag_line.range.start.line .. diag_line.range.start.character
if seen[hash] == nil then
local s = {
text = diag_line.message,
lnum = diag_line.range.start.line,
col = diag_line.range.start.character,
filename = filepath
}
table.insert(diags, s)
seen[hash] = true
end
end
end
end
end
vim.fn.setqflist(diags)
vim.cmd("copen")
end
end)
end
end
end, { noremap = true, silent = true })
end
}
@seblj Im working on another dotnet-plugin where I could make good use of the
workspace/symbol
the only downside is that I would require the language server to be running independently of any buffer. If you are interested it would be cool to make a PR that exposes a way to start the lsp server when entering vim if it finds a solution/csproject file.The benefits of this would be:
- Project initialization would start when entering vim instead of when entering a file(percieved perf boost)
- Reduced lag when entering a .cs file because the server is already running
- Enabling the development of things like workspace diagnostic windows/lualine indicators.
This would of course be exposed as opt-in functionality
Yes I would accept a PR for this! I have actually been thinking about this myself, but haven't decided if I want to use it myself, so I haven't looked into implementing it
I have also been wondering about changing a bit about how it starts, and what it should prefer from a sln or csproj.
As of now, it always finds the sln file and uses that over any csproj, even in subdirectories. As of now it is impossible to load a single project, even if mye cwd is inside that project.
I have been thinking if I should change this to stop searching at cwd or prefer to attach to a project in the cwd rather than a solution in the parent dir.
What do you think?
My personal experience from projects is one of these scenarios
In all the projects I have ever worked on in C# I would always prefer roslyn to pick the broadest scope for my project. So solution is always preferable. The only reason I see for picking a csproject directly instead of a sln file is performance in massive projects.
As of now it is impossible to load a single project, even if mye cwd is inside that project.
If there isnt a solution file then a csproject file is attached right?
TLDR; I think your current approach appeals to the broadest audience
If there isnt a solution file then a csproject file is attached right?
Yes
In all the projects I have ever worked on in C# I would always prefer roslyn to pick the broadest scope for my project. So solution is always preferable. The only reason I see for picking a csproject directly instead of a sln file is performance in massive projects.
Yeah I agree, but I was thinking that if neovim is opened inside one of the projects, then it could use the csproj file, but of course if neovim is opened in the root where the sln file lives, then it would of course use that.
It seems like this could be more consistent with how other editor that has a concept of workspaces do it. Because if I open a specific project in vscode, then it only uses that. But if I open the entire solution, then it used that
Oh now I understand, thats the way my plugin works, never looks up always looks down. Traversing upwards is nice if it doesnt find anything further down I guess.
Yeah that makes sense to prefer the .csproject if its in cwd or further down and no sln file is present in cwd or inbetween
Yes, I might change to this behaviour sometime in the future since I have wished for this a couple of times now. Maybe I will implement something (or ectend) CSTarget to be able to switch to csproj at runtime as well.
Need to think about this a little bit though, and especially the CSTarget thing
Maybe this will be useful - here's one that populates vim's diagnostics, so it works with things like Trouble.nvim and Telescope. All the functions except the last client.request are pasted from nvim runtime (vim/lsp/diagnostic.lua) because they're not public.
Looked into being able to preload the server and made a rough implementation but Im uncertain why its not behaving correctly
Doing the same thing with Roslyn starting normally from any buffer in the solution returns the build error.
Ill keep investigating maybe i need to do some diagnostic refresh request or something
Okay, so I see now that a handler for workspace/diagnostic
is just not implement in neovim core. I tried to search for an issue there or something to see if I could find some discussions about it or something, but I couldn't find it.
I am unfortunately not going to implement the handler in this plugin, as I believe efforts to support the handler should instead go into neovim core. I don't think I will look into sending a PR over there myself.
So with that said, I don't think there is anything to do for me right now for this, but feel free to paste snippets here if there are some improvements to the snippets already here or something, so that other users could take advantage of them😄
Is there a way to get workspace diagnostics to work? Not having to repeatedly run
dotnet build
to find errors while refactoring would be nice.