omnisharp-roslyn: [LSP] languageserver not working with vim/neovim+lsp plugins

The version I use is the prebuilt binary package downloaded from github release page, v1.30.1 omnisharp-mono.tar.gz. linux-x86_64 package behaves exactly the same. Here is the relevant configurations in my .vimrc:

let g:LanguageClient_serverCommands = {
    \ 'cs': ['mono', '/opt/omnisharp-roslyn/OmniSharp.exe', '--languageserver', '--verbose'],
\ }

let g:LanguageClient_rootMarkers = {
    \ 'cs': ['.git', '*.csproj'],
\ }

let g:deoplete#enable_at_startup = 1
let g:LanguageClient_loggingLevel = 'DEBUG'
let g:LanguageClient_loadSettings = 0

And here is the relevant log when error occurs:

17:31:24 INFO reader-cs src/vim.rs:379 <= Some("cs") {"protocolVersion":"2.0","method":"window/logMessage","params":{"type":4,"message":"Starting server..."}}
17:31:24 ERROR reader-cs src/vim.rs:384 Failed to deserialize output: data did not match any variant of untagged enum RawMessage

 Message: {"protocolVersion":"2.0","method":"window/logMessage","params":{"type":4,"message":"Starting server..."}}

Error: ErrorImpl { code: Message("data did not match any variant of untagged enum RawMessage"), line: 0, column: 0 }
...
17:31:24 INFO main src/vim.rs:90 => Some("cs") {"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"textDocument":{"completion":{"completionItem":{"commitCharactersSupport":null,"documentationFormat":null,"snippetSupport":false},"dynamicRegistration":null}}},"initializationOptions":null,"processId":24814,"rootPath":"/home/shihira/Program/Unity/Vitruvius","rootUri":"file:///home/shihira/Program/Unity/Vitruvius","trace":"off"},"id":9}
Unhandled Exception:
Newtonsoft.Json.JsonSerializationException: Error converting value {null} to type 'System.Boolean'. Path 'params.capabilities.textDocument.completion.dynamicRegistration', line 1, position 221. ---> System.InvalidCastException: Null object cannot be converted to a value type.
  at System.Convert.ChangeType (System.Object value, System.Type conversionType, System.IFormatProvider provider) [0x00029] in <cae080c8689e4af39d0ab2b313d012f5>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType (Newtonsoft.Json.JsonReader reader, System.Object value, System.Globalization.CultureInfo culture, Newtonsoft.Json.Serialization.JsonContract contract, System.Type targetType) [0x000aa] in <dc86da7fc46c487ba6c7ab826da479cc>:0 
   --- End of inner exception stack trace ---
...
17:31:37 WARN main src/languageclient.rs:1910 Failed to start language server automatically. timed out waiting on channel

I noticed the key “protocolVersion”, which is usually “jsonrpc” in many other LSPs. Is it the reason why LanguageClient failed to deserialize it? Another problem causes the server crashing. I believe this is about what’s been mentioned and solved in https://github.com/OmniSharp/csharp-language-server-protocol/issues/75. If that’s true please merge them.

Thank you for your great work.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 26 (1 by maintainers)

Most upvoted comments

These directories exists: /home/iron-e/Programming/ACTIVE/reef/and ~/.omnisharp/Roslynator/src/Core/bin/Debug/netstandard2.0/Roslynator.Core.dll.

For some reason the paths are been merged in one. So the path isn’t valid.

Yeah. I notice that the first part of the path (/home/iron-e/…) is always equal to the root_dir, and I’ve tried this on a couple of other projects just to verify. It seems that now that the root_dir is being correctly resolved, it is being used as the context for all paths rather than just some of them.

I have a roslyn extension in the folder ~/.omnisharp/… as well.

Is this OmniSharp/omnisharp-vscode#2369 related?

I don’t think so… Roslynator has worked for me in VSCode and still works in coc.nvim. Seems to be something the nvim_lsp repo is mistakenly prepending.

If that’s true, it would also explain why it can’t find the netstandard or core .dll files— it’d be looking in root_dir instead of the root of the filesystem.


Edit: I discovered a workaround.

I discovered my error before was a red herring because omnisharp-vim also threw that error. I had to sift through it some more.

  1. dotnet clean && dotnet build from root_dir.
    • I remembered omnisharp-vim also had this problem sometimes, and I used to do this to fix it.
    • Some errors should disappear, not all.
  2. Before the LSP initializes, create at least one (but preferably just one) error in your code and save the file.
    • The virtual text will only show the diagnostics generated by the one that you created.
    • However, the diagnostics will be displayed until you clear them or a new problem is found.
      • This appears to be unrelated to nvim-lua/diagnostic-nvim.

I believe most of the problems mentioned in this issue are caused by the out-dated csharp-language-server-protocol on Nuget. Therefore I hope you to merge the latest LSP library to omnisharp-roslyn, or at least make a new branch to work on this. After half a year I am so sad to see the software still refuses to work just because of some stupid negligence.

I modified multiple places in the codebase to try to make the LSP mode work properly. So far the LSP mode just basically works with LanguageClient-neovim, launched, at least, and did some completion for me. This took me most of the spare time in the last week studying the code.

  • The latest version of stdio server just ignored -lsp. It is easy to get it to work by commenting out some if-conditions in OmniSharp.Stdio.Driver/Program.cs
  • jsonrpc, not protocolVersion: Just search all ProtocolVersion fields n the solution, and attach a [JsonProperty("jsonrpc") attribute to them.
  • {..., "insertTextFormat": 0}. This wouldn’t be a problem in most cases. But for LanguageClient-neovim, it uses rust, which is a strong-typed language, and it verifies this field very strictly. Only 1 and 2 is valid for InsertTextFormat according to the lsp spec.
            // CompletionListConverter.cs
            foreach (var item in v.Items)
            {
                if (item.InsertTextFormat != InsertTextFormat.Snippet)
                    item.InsertTextFormat = InsertTextFormat.PlainText;
                serializer.Serialize(writer, item);
            }
    

To build omnisharp-roslyn with csharp-language-server-protocol, clone the two repos into the same directory, and checkout v0.7.0 of csharp-lsp. Now (un)comment some lines in OmniSharp.LanguageServerProtocol.csproj:

    <ItemGroup>
        <!--<PackageReference Include="OmniSharp.Extensions.LanguageServerProtocol" Version="0.7.0" /> -->
        <ProjectReference Include="../../../csharp-language-server-protocol/src/Lsp/Lsp.csproj" />
        <ProjectReference Include="..\OmniSharp.Host\OmniSharp.Host.csproj" />
        ...
    </ItemGroup>

Then we are done.

I’ve been using omnisharp-node-client for awhile in order to get some form of LSP working with omnisharp. It’s buggy, slow, but atleast it works some of the time. Would be nice to get it working through the omnisharp server itself

I have some time today so I’ll give that a shot and report back.

Do you have any issues with the integration between omnisharp and nvim LSP or does it work perfectly?

On ale, I’ve been noticing that when I fix the last error on a file, omnisharp-roslyn doesn’t update the list of errors unless I do a :ALEReset. I’m wondering if this has happened for you on nvim LSP too.

I did find the reason. It’s a “bug” on the root_pattern function from the code. This method use the pattern to match the whole file name on the directory. So for a pattern like .csproj will try to find a file with name .csproj, not with a pattern like *.csproj.

For now my workaround is to use like that:

root_dir = util.root_pattern("Makefile");

Just put a Makefile there and life goes on.

A better approach is to make root_pattern accept patterns, but I still didn’t have time to create a solution.