Setting up omnisharp via nvim-lspconfig and nvim-lspinstall

I really like the idea of LSP support which would bring it closer to much more user friendly vscode which I am currently using.
I don’t want to trash talk neovim on neovim forum its amazing piece of software but I am always reluctant to use these power user text editors like neovim, emacs because it usually takes more than a day to set them up again on new system its not just backuping init.vim or vimrc but having correct folders, env vars, having correct plugin manager and what not.
Combination of LSP support, nvim-lspconfig and nvim-lspinstall is finally something I would like to use. My main languages are typescript and c#. I was able to setup typescript without problem but I am having problems with c#. I would appriacte any help.

My OS:

ProductName:	macOS
ProductVersion:	11.1
BuildVersion:	20C69

I have lattest everything

brew install --HEAD luajit
brew install --HEAD neovim
brew reinstall neovim
:PlugInstall
:PlugUpgrade
:PlugUpdate
:LspInstall csharp

My init.vim

if empty(glob('~/.local/share/nvim/site/autoload/plug.vim'))
    silent !curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs
        \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
    autocmd VimEnter * PlugInstall --sync | source ~/.config/nvim/init.vim
endif

call plug#begin('~/.config/nvim/plugged')

Plug 'neovim/nvim-lspconfig'
Plug 'kabouzeid/nvim-lspinstall'
Plug 'mhinz/vim-startify'
Plug 'ahmedkhalf/lsp-rooter.nvim'

call plug#end()

set nobackup
set nowritebackup
set number relativenumber

lua << EOF
local on_attach = function(client, bufnr)
  local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
  local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end

  buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')

  local opts = { noremap=true, silent=true }
  buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
  buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
  buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
  buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
  buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
  buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
  buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
  buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
  buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
  buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
  buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
  buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
  buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
  buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
  buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)

  if client.resolved_capabilities.document_formatting then
    buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
  elseif client.resolved_capabilities.document_range_formatting then
    buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.range_formatting()<CR>", opts)
  end

  if client.resolved_capabilities.document_highlight then
    vim.api.nvim_exec([[
    augroup lsp_document_highlight
    autocmd! * <buffer>
    autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
    autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
    augroup END
    ]], false)
  end
end

local function make_config()
  local capabilities = vim.lsp.protocol.make_client_capabilities()
  capabilities.textDocument.completion.completionItem.snippetSupport = true
  return {
    capabilities = capabilities,
    on_attach = on_attach,
  }
end

-- lsp-install
local function setup_servers()
  require'lspinstall'.setup()

  local servers = require'lspinstall'.installed_servers()

  for _, server in pairs(servers) do
    local config = make_config()
    require'lspconfig'[server].setup(config)
  end
end

setup_servers()

require'lspinstall'.post_install_hook = function ()
  setup_servers() -- reload installed servers
  vim.cmd("bufdo e") -- this triggers the FileType autocmd that starts the server
end

vim.lsp.set_log_level("debug")
EOF

:LspInfo

Configured servers: csharp
Neovim logs at: /Users/<redacted>/.cache/nvim/lsp.log

1 client(s) attached to this buffer: csharp

  Client: csharp (id 1)
        root:      /Users/<redacted>/Projects/NvimOmniTest
        filetypes: cs, vb
        cmd:       /Users/<redacted>/.local/share/nvim/lspinstall/csharp/./run --languag
eserver --hostPID 58744



1 active client(s):

  Client: csharp (id 1)
        root:      /Users/<redacted>/Projects/NvimOmniTest
        filetypes: cs, vb
        cmd:       /Users/<redacted>/.local/share/nvim/lspinstall/csharp/./run --languag
eserver --hostPID 58744



Clients that match the filetype cs:

  Config: csharp
        cmd:               /Users/<redacted>/.local/share/nvim/lspinstall/csharp/./run -
-languageserver --hostPID 58744
        cmd is executable: True
        identified root:   /Users/<redacted>/Projects/NvimOmniTest
        custom handlers:

Omnisharp file permissions

drwxr-xr-x 755 bin
drwxr-xr-x 755 etc
drwxr-xr-x 755 lib
-rw-r--r-- 644 license.md
drwxr-xr-x 755 omnisharp
-rwxr-xr-x 755 run

I created c# project with

dotnet new webapi --no-https -o NvimOmniTest
cd NvimTest
dotnet build

Logs when I try to use go to definition for user created type inside same file no other commands work either

Btw. I am able to make c# work with coc-omnisharp or omnisharp-vim but I want to specifically use lsp-install for reasons stated above.

Any help is appriciated if you need more info let me know.

If you’re wanting to setup Neovim 0.5.1 or newer with nvim-lspconfig, you’ll need to do the following on your Linux/MacOS system.

Ensure we have nvim-lspconfig plugin installed. I do the built-in Package Manager method. See the Neovim Docs usr_05

git clone \
  https://github.com/neovim/nvim-lspconfig.git \
  ~/.local/share/nvim/site/pack/neovim/start/nvim-lspconfig

Download and “install” or place the Omnisharp Roslyn Language Server on your system. I put mine under ~/.local/omnisharp

curl --verbose --location --remote-name https://github.com/OmniSharp/omnisharp-roslyn/releases/download/v1.37.17/omnisharp-linux-x64.tar.gz
mkdir -p ~/.local/omnisharp
mv omnisharp-linux-x64.tar.gz ~/.local/omnisharp
cd ~/.local/omnisharp
tar -xvf omnisharp-linux-x64.tar.gz

Then it should expand to show the contents with a ~/.local/omnisharp/run. This will be your executable for Omnisharp Roslyn. I use an init.lua but just use a lua block in your init.vim.

local pid = vim.fn.getpid()
local omnisharp_bin = "/var/home/dudleyp/.local/omnisharp/run"
require'lspconfig'.omnisharp.setup{
    cmd = { omnisharp_bin, "--languageserver" , "--hostPID", tostring(pid) };
}

The fun part you’ll notice is that you cannot use ~ or $HOME. You’ll need to specify this whole path, unless you figure out some lua magic to do it. This is all specified in the documentation as well.

I think from my experiences, you need to launch Neovim from the directory containing a .sln file, but you can then edit a .cs file and it’ll perform your autocomplete.

A difference from using coc.nvim and the omnisharp-vim plugin is that this won’t download and install it for you, nor are there any formatting commands using the omnisharp-roslyn. If someone knows something else, show me the way.

You may also need to install universal-ctags to your system. Universal-ctags is the more update version of Exuberant-ctags. If you use guttentag Vim plugin, ctags will automatically get ran when you save a file.

os.getenv(‘HOME’) … ‘/rest/of/my/path’ (you can use util.path.join from lspconfig if you want someting cross-platform)

I think from my experiences, you need to launch Neovim from the directory containing a .sln file, but you can then edit a .cs file and it’ll perform your autocomplete.

This shouldn’t be necessary see: https://github.com/neovim/nvim-lspconfig/blob/38eb8ea6bc669082d4709095c9563922e025debb/lua/lspconfig/omnisharp.lua#L11-L15

@mjlbach , do you know if the omnisharp-roslyn would be able too perform code formatting or is that a different plugin? I tried using OmniSharp-vim to get the :OmniSharpCodeFmt command, but I found that I have 2 instances of Roslyn running now.

No idea, I don’t use csharp or omnisharp

Please refer to the above, and also do not hijack threads to ask unrelated questions.

Did you solve this problem, I have the same need

This is kind of late, but in case anyone else is trying to figure out how to get their Omnisharp path in a non-OS specific way, here is how I pointed to the Omnisharp.dll file after installing Omnisharp-mono with mason:

NOTE: the concat operator is showing as three dots but it’s only two; not sure why that’s happening

local omniSharpPath = vim.fn.stdpath(“data”) … “/mason/packages/omnisharp-mono/omnisharp/Omnisharp.dll”