Skip to content

Commit 99f459f

Browse files
committed
languages/csharp: add roslyn-ls support
It adds roslyn-ls configuration and roslyn-nvim plugin
1 parent 0eeb3f2 commit 99f459f

3 files changed

Lines changed: 101 additions & 58 deletions

File tree

docs/manual/release-notes/rl-0.8.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,3 +627,7 @@
627627
- Aligned `codelldb` adapter setup with [rustaceanvim]’s built-in logic.
628628
- Added `languages.rust.dap.backend` option to choose between `codelldb` and
629629
`lldb-dap` adapters.
630+
631+
[CaueAnjos](https://github.com/CaueAnjos)
632+
633+
- Add razor support for C# language

modules/plugins/languages/csharp.nix

Lines changed: 84 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@
2424
in
2525
optionalString (key != null) "vim.keymap.set('n', '${key}', ${action}, {buffer=bufnr, noremap=true, silent=true, desc='${desc}'})";
2626

27-
# Omnisharp doesn't have colors in popup docs for some reason, and I've also
28-
# seen mentions of it being way slower, so until someone finds missing
29-
# functionality, this will be the default.
30-
defaultServers = ["csharp_ls"];
27+
# roslyn is the official language server and the most feature-rich
28+
defaultServers = ["roslyn"];
3129
servers = {
3230
omnisharp = {
3331
cmd = mkLuaInline ''
@@ -43,19 +41,7 @@
4341
}
4442
'';
4543
filetypes = ["cs" "vb"];
46-
root_dir = mkLuaInline ''
47-
function(bufnr, on_dir)
48-
local function find_root_pattern(fname, lua_pattern)
49-
return vim.fs.root(0, function(name, path)
50-
return name:match(lua_pattern)
51-
end)
52-
end
53-
54-
local fname = vim.api.nvim_buf_get_name(bufnr)
55-
on_dir(find_root_pattern(fname, "%.sln$") or find_root_pattern(fname, "%.csproj$"))
56-
end
57-
'';
58-
init_options = {};
44+
root_marks = [".sln" ".csproj"];
5945
capabilities = {
6046
workspace = {
6147
workspaceFolders = false; # https://github.com/OmniSharp/omnisharp-roslyn/issues/909
@@ -120,65 +106,35 @@
120106
csharp_ls = {
121107
cmd = [(lib.getExe pkgs.csharp-ls)];
122108
filetypes = ["cs"];
123-
root_dir = mkLuaInline ''
124-
function(bufnr, on_dir)
125-
local function find_root_pattern(fname, lua_pattern)
126-
return vim.fs.root(0, function(name, path)
127-
return name:match(lua_pattern)
128-
end)
129-
end
130-
131-
local fname = vim.api.nvim_buf_get_name(bufnr)
132-
on_dir(find_root_pattern(fname, "%.sln$") or find_root_pattern(fname, "%.csproj$"))
133-
end
134-
'';
109+
root_marks = [".sln" ".csproj"];
135110
init_options = {
136111
AutomaticWorkspaceInit = true;
137112
};
138113
};
139114

140-
roslyn_ls = {
141-
cmd = mkLuaInline ''
142-
{
143-
${toLuaObject (getExe pkgs.roslyn-ls)},
144-
'--logLevel=Warning',
145-
'--extensionLogDirectory=' .. vim.fs.dirname(vim.lsp.get_log_path()),
146-
'--stdio',
147-
}
148-
'';
149-
150-
filetypes = ["cs"];
151-
root_dir = mkLuaInline ''
152-
function(bufnr, on_dir)
153-
local function find_root_pattern(fname, lua_pattern)
154-
return vim.fs.root(0, function(name, path)
155-
return name:match(lua_pattern)
156-
end)
157-
end
158-
159-
local fname = vim.api.nvim_buf_get_name(bufnr)
160-
on_dir(find_root_pattern(fname, "%.sln$") or find_root_pattern(fname, "%.csproj$"))
161-
end
162-
'';
163-
init_options = {};
115+
roslyn = {
116+
# NOTE: cmd is set by roslyn-nvim!
117+
filetypes = ["cs" "razor" "cshtml"];
118+
root_marks = [".sln" ".csproj"];
164119
};
165120
};
166121

167122
extraServerPlugins = {
168123
omnisharp = ["omnisharp-extended-lsp-nvim"];
169124
csharp_ls = ["csharpls-extended-lsp-nvim"];
170-
roslyn_ls = [];
125+
roslyn = ["roslyn-nvim"];
171126
};
172127

173128
cfg = config.vim.languages.csharp;
174129
in {
175130
options = {
176131
vim.languages.csharp = {
177-
enable = mkEnableOption "C# language support";
132+
enable = mkEnableOption "C# language support. It requires .NET sdk 10";
178133

179134
treesitter = {
180-
enable = mkEnableOption "C# treesitter" // {default = config.vim.languages.enableTreesitter;};
181-
package = mkGrammarOption pkgs "c-sharp";
135+
enable = mkEnableOption "C#/razor treesitter" // {default = config.vim.languages.enableTreesitter;};
136+
csPackage = mkGrammarOption pkgs "c-sharp";
137+
razorPackage = mkGrammarOption pkgs "razor";
182138
};
183139

184140
lsp = {
@@ -195,11 +151,81 @@ in {
195151
config = mkIf cfg.enable (mkMerge [
196152
(mkIf cfg.treesitter.enable {
197153
vim.treesitter.enable = true;
198-
vim.treesitter.grammars = [cfg.treesitter.package];
154+
vim.treesitter.grammars = [cfg.treesitter.csPackage cfg.treesitter.razorPackage];
155+
})
156+
157+
(mkIf (cfg.lsp.enable && lib.elem "roslyn" cfg.lsp.servers) {
158+
vim.luaConfigRC.roslyn-path = ''
159+
-- NOTE: this is required by roslyn-nvim to find roslyn
160+
vim.env.PATH = vim.env.PATH .. ":${pkgs.roslyn-ls}/bin"
161+
162+
-- NOTE: this is required by roslyn-nvim to find .razorExtension folder
163+
-- roslyn-nvim looks for .razorExtension folder using this logic!
164+
-- take a look at https://github.com/seblyng/roslyn.nvim/blob/main/lua/roslyn/health.lua
165+
local razor_extensions_path = "${pkgs.vscode-extensions.ms-dotnettools.csharp}/share/vscode/extensions/ms-dotnettools.csharp/.razorExtension"
166+
167+
-- Function to check if path exists (including symlinks)
168+
local function path_exists(path)
169+
local stat = vim.uv.fs_lstat(path)
170+
return stat ~= nil
171+
end
172+
173+
-- Function to create symlink
174+
local function create_razor_symlink()
175+
if not razor_extensions_path or razor_extensions_path == "" then
176+
vim.notify("razor_extensions_path is not set", vim.log.levels.WARN)
177+
return
178+
end
179+
180+
-- Check if source path exists
181+
if vim.fn.isdirectory(razor_extensions_path) == 0 then
182+
vim.notify("Source path does not exist: " .. razor_extensions_path, vim.log.levels.ERROR)
183+
return
184+
end
185+
186+
-- Get mason path
187+
vim.env.MASON = vim.fn.expand("~/.local/share/nvf/mason")
188+
local expanded_mason = vim.fn.expand("$MASON")
189+
local mason = expanded_mason == "$MASON"
190+
and vim.fs.joinpath(vim.fn.stdpath("data"), "mason")
191+
or expanded_mason
192+
local mason_packages = vim.fs.joinpath(mason, "packages")
193+
194+
-- Define target paths
195+
local targets = {
196+
vim.fs.joinpath(mason_packages, "roslyn", "libexec", ".razorExtension"),
197+
vim.fs.joinpath(mason_packages, "roslyn-unstable", "libexec", ".razorExtension"),
198+
}
199+
200+
-- Create symlinks for each target
201+
for _, target in ipairs(targets) do
202+
local parent_dir = vim.fn.fnamemodify(target, ":h")
203+
204+
-- Check if parent directory exists
205+
if vim.fn.isdirectory(parent_dir) == 1 then
206+
-- Remove existing symlink or directory
207+
if path_exists(target) then
208+
vim.fn.delete(target, "rf")
209+
end
210+
211+
-- Create symlink
212+
local success = vim.uv.fs_symlink(razor_extensions_path, target, { dir = true })
213+
214+
if not success then
215+
vim.notify("Failed to create symlink for .razorExtension: " .. target, vim.log.levels.ERROR)
216+
end
217+
end
218+
end
219+
end
220+
221+
-- Run the function
222+
create_razor_symlink()
223+
'';
199224
})
200225

201226
(mkIf cfg.lsp.enable {
202227
vim.startPlugins = concatMap (server: extraServerPlugins.${server}) cfg.lsp.servers;
228+
203229
vim.lsp.servers =
204230
mapListToAttrs (name: {
205231
inherit name;

npins/sources.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2373,6 +2373,19 @@
23732373
"url": "https://github.com/rose-pine/neovim/archive/72a04c4065345b51b56aed4859ea1d884f734097.tar.gz",
23742374
"hash": "144jffddwf727w4yqbikv2f46cny8r9z8mpkbc5ngzail5ldj0q8"
23752375
},
2376+
"roslyn-nvim": {
2377+
"type": "Git",
2378+
"repository": {
2379+
"type": "GitHub",
2380+
"owner": "seblyng",
2381+
"repo": "roslyn.nvim"
2382+
},
2383+
"branch": "main",
2384+
"submodules": false,
2385+
"revision": "1ebc9393d3e577d9f68102f14d98b2e4e7f15644",
2386+
"url": "https://github.com/seblyng/roslyn.nvim/archive/1ebc9393d3e577d9f68102f14d98b2e4e7f15644.tar.gz",
2387+
"hash": "0jbgxyrv59pf2n4xy821vcbwiahi4nal642nrpiwymzwya355adh"
2388+
},
23762389
"rtp-nvim": {
23772390
"type": "Git",
23782391
"repository": {

0 commit comments

Comments
 (0)