This is an actively maintained & upgraded fork that interacts with the improved & open-source C# Roslyn language server, meant to replace the old and discontinued OmniSharp. This language server is currently used in the Visual Studio Code C# Extension, which is shipped with the standard C# Dev Kit.
This plugin has recently added support for Razor/CSHTML files. This enabled razor support using co-hosting and superceeds the old rzls.nvim.
If you previoulsy used rzls.nvim, please uninstall it and the rzls language
server.
- Neovim >= 0.12.0
- Roslyn language server downloaded locally
- .NET SDK installed and
dotnetcommand available
roslyn is now a part of nvim-lspconfig, but it does not implement all things that are implemented here.
This plugin tries to keep things minimal but still implement some things that is not suited for nvim-lspconfig.
A couple of additional things this plugin implements
- Support for multiple solutions
- Broad root_dir detection support. Meaning it will search for solutions upward in parent directories if
broad_searchoption is set - Support for source generated files
Roslyn targetcommand to switch between multiple solutions
roslyn_demo.mp4
Mason (recommended)
You can install with MasonInstall roslyn-language-server. Note that this is installing it from nuget.org which is not necessarily up to date with the same version used in vscode.
For the time being, I would recommend using a custom registry to get a more up to date version. For this, you need to use a custom mason registry and set it up like this.
require("mason").setup({
registries = {
"github:mason-org/mason-registry",
"github:Crashdummyy/mason-registry",
},
})This registry provides two versions:
roslyn(same version as in vscode)roslyn-nightly(bleeding edge features with potentially breaking changes)
Manually
roslyn-language-server supports razor since version 5.8.0-1.26262.10.
This allows installation of the lsp as a dotnet tool.
This dotnet tool exists at two places:
- nuget.org, which is not updated that often.
- Azure Devops feed, where updates happen multiple times a day.
It is highly recommended to use the Azure DevOps feed.
[!IMPORTANT]
The version used in vscode can be extracted here.
The extension uses the Azure Devops feed as well.
# Installing the tool using the more recent Azure Devops feed
# This will take few seconds so please be patient
dotnet tool install -g roslyn-language-server --prerelease --source https://pkgs.dev.azure.com/azure-public/vside/_packaging/vs-impl/nuget/v3/index.json
You can invoke the tool using the following command: roslyn-language-server
Tool 'roslyn-language-server' (version '5.8.0-1.26263.4') was successfully installed.
# Installing the tool from nuget.org
# !! Any version before 5.8.0-1.26262.10 will not support razor/blazor !!
dotnet tool install -g roslyn-language-server --prerelease
You can invoke the tool using the following command: roslyn-language-server
Tool 'roslyn-language-server' (version '5.8.0-1.26262.10') was successfully installed.
# Updating works the same way as installing ( by replacing "install" with "update")
dotnet tool update -g roslyn-language-server --prerelease --source https://pkgs.dev.azure.com/azure-public/vside/_packaging/vs-impl/nuget/v3/index.jsonTip
For server compatibility check the roslyn repo
Install the plugin with your preferred package manager:
return {
"seblyng/roslyn.nvim",
---@module 'roslyn.config'
---@type RoslynNvimConfig
opts = {
-- your configuration comes here; leave empty for default settings
},
}The plugin comes with the following defaults:
opts = {
-- "auto" | "roslyn" | "off"
--
-- - "auto": Does nothing for filewatching, leaving everything as default
-- - "roslyn": Turns off neovim filewatching which will make roslyn do the filewatching
-- - "off": Hack to turn off all filewatching. (Can be used if you notice performance issues)
filewatching = "auto",
-- Optional function that takes an array of targets as the only argument. Return the target you
-- want to use. If it returns `nil`, then it falls back to guessing the target like normal
-- Example:
--
-- choose_target = function(target)
-- return vim.iter(target):find(function(item)
-- if string.match(item, "Foo.sln") then
-- return item
-- end
-- end)
-- end
choose_target = nil,
-- Optional function that takes the selected target as the only argument.
-- Returns a boolean of whether it should be ignored to attach to or not
--
-- I am for example using this to disable a solution with a lot of .NET Framework code on mac
-- Example:
--
-- ignore_target = function(target)
-- return string.match(target, "Foo.sln") ~= nil
-- end
ignore_target = nil,
-- Whether or not to look for solution files in the child of the (root).
-- Set this to true if you have some projects that are not a child of the
-- directory with the solution file
broad_search = false,
-- Whether or not to lock the solution target after the first attach.
-- This will always attach to the target in `vim.g.roslyn_nvim_selected_solution`.
-- NOTE: You can use `:Roslyn target` to change the target
lock_target = false,
-- If the plugin should silence notifications about initialization
silent = false,
}To configure language server specific settings sent to the server, you can use the vim.lsp.config interface with roslyn as the name of the server.
vim.lsp.config("roslyn", {
on_attach = function()
print("This will run when the server attaches!")
end,
settings = {
["csharp|inlay_hints"] = {
csharp_enable_inlay_hints_for_implicit_object_creation = true,
csharp_enable_inlay_hints_for_implicit_variable_types = true,
},
["csharp|code_lens"] = {
dotnet_enable_references_code_lens = true,
},
},
})To pass custom Roslyn extensions, override the server command and include one
--extension=/path/to/extension.dll argument per extension.
vim.lsp.config("roslyn", {
cmd = {
"roslyn-language-server",
"--stdio",
"--extension=/path/to/Roslynator.dll",
},
})Some tips and tricks that may be useful, but not in the scope of this plugin, are documented in the wiki.
Note
These settings are not guaranteed to be up-to-date and new ones can appear in the future. Aditionally, not all settings are shown here, but only the most relevant ones for Neovim. For a full list, visit this unit test from the vscode extension and look especially for the ones which don't have vsCodeConfiguration: null.
csharp|background_analysis
These settings control the scope of background diagnostics.
-
background_analysis.dotnet_analyzer_diagnostics_scope
Scope of the background analysis for .NET analyzer diagnostics.
Expected values:openFiles,fullSolution,none -
background_analysis.dotnet_compiler_diagnostics_scope
Scope of the background analysis for .NET compiler diagnostics.
Expected values:openFiles,fullSolution,none
csharp|code_lens
These settings control the LSP code lens.
-
dotnet_enable_references_code_lens
Enable code lens references.
Expected values:true,false -
dotnet_enable_tests_code_lens
Enable tests code lens.
Expected values:true,false
Tip
You must refresh the code lens yourself. Check :h vim.lsp.codelens.refresh() and the example autocmd.
csharp|completion
These settings control how the completions behave.
-
dotnet_provide_regex_completions
Show regular expressions in completion list.
Expected values:true,false -
dotnet_show_completion_items_from_unimported_namespaces
Enables support for showing unimported types and unimported extension methods in completion lists.
Expected values:true,false -
dotnet_show_name_completion_suggestions
Perform automatic object name completion for the members that you have recently selected.
Expected values:true,false
csharp|inlay_hints
These settings control what inlay hints should be displayed.
-
csharp_enable_inlay_hints_for_implicit_object_creation
Show hints for implicit object creation.
Expected values:true,false -
csharp_enable_inlay_hints_for_implicit_variable_types
Show hints for variables with inferred types.
Expected values:true,false -
csharp_enable_inlay_hints_for_lambda_parameter_types
Show hints for lambda parameter types.
Expected values:true,false -
csharp_enable_inlay_hints_for_types
Display inline type hints.
Expected values:true,false -
dotnet_enable_inlay_hints_for_indexer_parameters
Show hints for indexers.
Expected values:true,false -
dotnet_enable_inlay_hints_for_literal_parameters
Show hints for literals.
Expected values:true,false -
dotnet_enable_inlay_hints_for_object_creation_parameters
Show hints for 'new' expressions.
Expected values:true,false -
dotnet_enable_inlay_hints_for_other_parameters
Show hints for everything else.
Expected values:true,false -
dotnet_enable_inlay_hints_for_parameters
Display inline parameter name hints.
Expected values:true,false -
dotnet_suppress_inlay_hints_for_parameters_that_differ_only_by_suffix
Suppress hints when parameter names differ only by suffix.
Expected values:true,false -
dotnet_suppress_inlay_hints_for_parameters_that_match_argument_name
Suppress hints when argument matches parameter name.
Expected values:true,false -
dotnet_suppress_inlay_hints_for_parameters_that_match_method_intent
Suppress hints when parameter name matches the method's intent.
Expected values:true,false
Tip
These won't have any effect if you don't enable inlay hints in your config. Check :h vim.lsp.inlay_hint.enable().
csharp|symbol_search
This setting controls how the language server should search for symbols.
dotnet_search_reference_assemblies
Search symbols in reference assemblies.
Expected values:true,false
csharp|formatting
This setting controls how the language server should format code.
dotnet_organize_imports_on_format
Sort using directives on format alphabetically.
Expected values:true,false
:Roslyn targetchooses a solution if there are multiple to chose from
- If you have multiple solutions, this plugin tries to guess which one to use. You can change the target with the
:Roslyn targetcommand. - The current solution is always stored in
vim.g.roslyn_nvim_selected_solution. You can use this, for example, to display the current solution in your statusline.