Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
50bd8f5
feat!: start using vim.lsp.config
seblyng Mar 28, 2025
f3d8698
docs: update README to reflect breaking changes
seblyng Mar 28, 2025
48a6910
fix: warn users about using deprecated options
seblyng Mar 28, 2025
599a826
fix: update testrunner to use nvim 0.11
seblyng Mar 28, 2025
1371f2d
fix: warn about only supporting nvim 0.11 and greater
seblyng Mar 28, 2025
8ac5a90
ci: update runner in ci
seblyng Mar 28, 2025
43df107
fix: some refactoring and docs changes
seblyng Mar 29, 2025
e8ba5b0
fix: soft deprecate default install location for roslyn
seblyng Mar 29, 2025
9db0206
fix: refactor out some config to /lsp/roslyn.lua
seblyng Mar 29, 2025
8a9358b
fix: refactor
seblyng Mar 31, 2025
598b1f3
fix: check cmd and legacy path right before starting the server
seblyng Mar 31, 2025
35b4f0c
fix: only resolve users on_init and on_exit once
seblyng Apr 3, 2025
a0abb7d
fix: avoid multiple notifications about legacy path
seblyng Apr 5, 2025
6894103
feat: add some simple logging
seblyng Apr 5, 2025
f0bcbd5
docs: update readme
seblyng Apr 8, 2025
3346a56
chore: remove logging for now
seblyng Apr 8, 2025
d5b3590
fix: support table type for on_init and on_exit
seblyng Apr 8, 2025
38ef135
fix: defer creating commands until we are in a cs file
seblyng Apr 15, 2025
831caff
fix: move commands from on_init to rtp lsp file
seblyng Apr 17, 2025
d3c8262
refactor: move on_exit to rtp lsp config file
seblyng Apr 17, 2025
2b919f5
feat: use vim.lsp.enable
seblyng Apr 18, 2025
0095923
fix: set debug configuration by default
seblyng Apr 18, 2025
0fc691e
fix: source generated
seblyng Apr 18, 2025
7ef0236
fix: add filetypes and make `Roslyn restart` work again
seblyng Apr 18, 2025
f46d87a
docs: do not have docs with on_init
seblyng Apr 18, 2025
ae3868c
refactor
seblyng Apr 18, 2025
c1b5915
refactor: move out handlers and commands to separate file
seblyng Apr 18, 2025
8ae7afe
fix: roslyn target command
seblyng Apr 18, 2025
605cc6c
Merge remote-tracking branch 'origin/main' into vim.lsp.config
seblyng Apr 24, 2025
19734ee
fix: refactor root dir and solution finder methods
seblyng Apr 26, 2025
7ec3457
Merge remote-tracking branch 'origin/main' into vim.lsp.config
seblyng Apr 26, 2025
169665a
fix: change wording of initializing message
seblyng Apr 26, 2025
e83cff3
Merge remote-tracking branch 'origin/main' into vim.lsp.config
seblyng May 7, 2025
f22a037
fix: move handler from config file to file where all handlers are imp…
seblyng May 8, 2025
0dff8e3
Merge branch 'main' into vim.lsp.config
seblyng May 23, 2025
e9a519d
fix: remove restore handler
seblyng May 23, 2025
301c12d
fix: `Roslyn start` command with vim.lsp.config
seblyng May 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ jobs:

matrix:
neovim_branch:
- "v0.10.4"
- "v0.11.0"
- "nightly"

Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export NVIM_RUNNER_VERSION := v0.10.4
export NVIM_TEST_VERSION ?= v0.10.4
export NVIM_RUNNER_VERSION := v0.11.0
export NVIM_TEST_VERSION ?= v0.11.0

nvim-test:
git clone https://github.com/lewis6991/nvim-test
Expand Down
88 changes: 34 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

This is an actively maintained & upgraded [fork](https://github.com/jmederosalvarado/roslyn.nvim) that interacts with the improved & open-source C# [Roslyn](https://github.com/dotnet/roslyn) language server, meant to replace the old and discontinued OmniSharp. This language server is currently used in the [Visual Studio Code C# Extension](https://github.com/dotnet/vscode-csharp), which is shipped with the standard C# Dev Kit.

This standalone plugin was necessary because Roslyn uses a [non-standard](https://github.com/dotnet/roslyn/issues/72871) method of initializing communication with the client and requires additional custom integrations, unlike typical LSP setups in Neovim.

## IMPORTANT

This plugin does not provide Razor support.
Expand All @@ -12,7 +10,7 @@ Check out https://github.com/tris203/rzls.nvim if you are using Razor.

## ⚡️ Requirements

- Neovim >= 0.10.0
- Neovim >= 0.11.0
- Roslyn language server downloaded locally
- .NET SDK installed and `dotnet` command available

Expand Down Expand Up @@ -42,6 +40,7 @@ require("mason").setup({
```

You can then install it with `:MasonInstall roslyn` or through the popup menu by running `:Mason`. It is not available through [mason-lspconfig.nvim](https://github.com/williamboman/mason-lspconfig.nvim) and the `:LspInstall` interface
When installing the server through mason, the cmd is automatically added to the LSP config, so no need to add it manually

**NOTE**

Expand All @@ -58,16 +57,15 @@ There's currently an open [pull request](https://github.com/mason-org/mason-regi
3. Check if it's working by running `dotnet Microsoft.CodeAnalysis.LanguageServer.dll --version` in the `<target>` directory.
4. Configure it like this:
```lua
require("roslyn").setup({
config = {
cmd = {
"dotnet",
"<target>/Microsoft.CodeAnalysis.LanguageServer.dll",
"--logLevel=Information",
"--extensionLogDirectory=" .. vim.fs.dirname(vim.lsp.get_log_path()),
"--stdio",
},
vim.lsp.config("roslyn", {
cmd = {
"dotnet",
"<target>/Microsoft.CodeAnalysis.LanguageServer.dll",
"--logLevel=Information",
"--extensionLogDirectory=" .. vim.fs.dirname(vim.lsp.get_log_path()),
"--stdio",
},
-- Add other options here
})
```

Expand All @@ -81,15 +79,14 @@ require("roslyn").setup({
### [lazy.nvim](https://github.com/folke/lazy.nvim)

```lua
{
return {
"seblyng/roslyn.nvim",
ft = "cs",
---@module 'roslyn.config'
---@type RoslynNvimConfig
opts = {
-- your configuration comes here; leave empty for default settings
-- NOTE: You must configure `cmd` in `config.cmd` unless you have installed via mason
}
},
}
```

Expand All @@ -98,15 +95,7 @@ require("roslyn").setup({
The plugin comes with the following defaults:

```lua
{
---@type vim.lsp.ClientConfig
config = {
-- Here you can pass in any options that that you would like to pass to `vim.lsp.start`.
-- Use `:h vim.lsp.ClientConfig` to see all possible options.
-- The only options that are overwritten and won't have any effect by setting here:
-- - `name`
-- - `root_dir`
},
opts = {
-- "auto" | "roslyn" | "off"
--
-- - "auto": Does nothing for filewatching, leaving everything as default
Expand Down Expand Up @@ -147,10 +136,29 @@ The plugin comes with the following defaults:
-- 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,
})
}
```

To configure language server specific settings sent to the server, you can modify the `config.settings` map.
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.

## Example

```lua
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,
},
},
})
```

Some tips and tricks that may be useful, but not in the scope of this plugin,
are documented in the [wiki](https://github.com/seblyng/roslyn.nvim/wiki).
Expand Down Expand Up @@ -284,34 +292,6 @@ This setting controls how the language server should format code.
Sort using directives on format alphabetically.
Expected values: `true`, `false`

Example:

```lua
opts = {
config = {
settings = {
["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,
},
},
},
}
```

## 📚 Commands

- `:Roslyn restart` restarts the server
Expand Down
86 changes: 86 additions & 0 deletions lsp/roslyn.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
local utils = require("roslyn.sln.utils")

---@return string[]?
local function default_cmd()
local sysname = vim.uv.os_uname().sysname:lower()
local iswin = not not (sysname:find("windows") or sysname:find("mingw"))

local mason_path = vim.fs.joinpath(vim.fn.stdpath("data"), "mason", "bin", "roslyn")
local mason_cmd = iswin and string.format("%s.cmd", mason_path) or mason_path

if vim.uv.fs_stat(mason_cmd) == nil then
return nil
end

return {
mason_cmd,
"--logLevel=Information",
"--extensionLogDirectory=" .. vim.fs.dirname(vim.lsp.get_log_path()),
"--stdio",
}
end

---@type vim.lsp.Config
return {
name = "roslyn",
filetypes = { "cs" },
cmd = default_cmd(),
cmd_env = {
Configuration = vim.env.Configuration or "Debug",
},
capabilities = {
textDocument = {
-- HACK: Doesn't show any diagnostics if we do not set this to true
diagnostic = {
dynamicRegistration = true,
},
},
},
root_dir = function(bufnr, on_dir)
local config = require("roslyn.config")
local solutions = config.get().broad_search and utils.find_solutions_broad(bufnr) or utils.find_solutions(bufnr)
local root_dir = utils.root_dir(bufnr, solutions)
if root_dir then
on_dir(root_dir)
end
end,
on_init = {
function(client)
local on_init = require("roslyn.lsp.on_init")

local config = require("roslyn.config").get()
local selected_solution = vim.g.roslyn_nvim_selected_solution
if config.lock_target and selected_solution then
return on_init.sln(client, selected_solution)
end

local bufnr = vim.api.nvim_get_current_buf()
local files = utils.find_files_with_extensions(client.config.root_dir, { ".sln", ".slnx", ".slnf" })

local solution = utils.predict_target(bufnr, files)
if solution then
return on_init.sln(client, solution)
end

local csproj = utils.find_files_with_extensions(client.config.root_dir, { ".csproj" })
if #csproj > 0 then
return on_init.projects(client, csproj)
end

if selected_solution then
return on_init.sln(client, selected_solution)
end
end,
},
on_exit = {
function()
vim.g.roslyn_nvim_selected_solution = nil
vim.schedule(function()
require("roslyn.roslyn_emitter"):emit("stopped")
vim.notify("Roslyn server stopped", vim.log.levels.INFO, { title = "roslyn.nvim" })
end)
end,
},
commands = require("roslyn.lsp.commands"),
handlers = require("roslyn.lsp.handlers"),
}
Loading
Loading