yegappan / lsp

Language Server Protocol (LSP) plugin for Vim9
MIT License
485 stars 59 forks source link

Multiple python LSP servers configured but only the first is running #384

Open newtonne opened 1 year ago

newtonne commented 1 year ago

When multiple LSP servers are configured for a filetype, only the first one seems to get loaded on vim startup.

Steps to reproduce

Minimal vimrc:

let lspServers = [
\   #{
\       name: 'pylsp',
\       filetype: 'python',
\       path: exepath('pylsp'),
\       debug: v:true,
\   },
\   #{
\       name: 'pyright',
\       filetype: 'python',
\       path: exepath('pyright-langserver'),
\       args: ['--stdio'],
\       debug: v:true,
\   },
\]
autocmd VimEnter * call LspAddServer(lspServers)

Then install both LSP servers:

python3 -m venv venv
. venv/bin/activate
pip install pyright python-lsp-server

Then open a python file in vim (vim test.py) and run :LspShowAllServers:

Filetype Information
====================
Filetype: 'python'
Server Name: 'pylsp'
Server Path: '/private/tmp/project/venv/bin/pylsp'
Status: Running

Filetype: 'python'
Server Name: 'pyright'
Server Path: '/private/tmp/project/venv/bin/pyright-langserver'
Status: Running

Buffer Information
==================
Buffer: 'test.py'
Server Path: '/private/tmp/project/venv/bin/pylsp'
Status: Running

Only the first configured LSP seems to get loaded. Running :LspServer restart fixes it:˚

Buffer Information
==================
Buffer: 'test.py'
Server Path: '/private/tmp/project/venv/bin/pylsp'
Status: Running
Server Path: '/private/tmp/project/venv/bin/pyright-langserver'
Status: Running

And both LSPs are there when I open another python file (:e test2.py):

Buffer: 'test2.py'
Server Path: '/private/tmp/project/venv/bin/pylsp'
Status: Running
Server Path: '/private/tmp/project/venv/bin/pyright-langserver'
Status: Running
maximyurevich commented 1 year ago

Why you use 2 servers for completion?

newtonne commented 1 year ago

They don't both get used for completion. See :h lsp-multiple-servers for more info on how this can work.

maximyurevich commented 1 year ago

They don't both get used for completion. See :h lsp-multiple-servers for more info on how this can work.

read about features in docs

andlrc commented 1 year ago

@newtonne I cannot reproduce this problem. I hunch is that it might be is caused by a timing issue in VimEnter and when a file is added with AddFile.

@maximyurevich OP isn't trying to use two servers for completion, only the first registered and supporting server will be used. In this case I would assume that pylsp supports completion, and therefore that would be used.

girishji commented 1 year ago

I can reproduce this.

@andlrc This is the problematic code in lsp.vim. It prevents the second LSP server from starting. Any reason why this check is in place?

export def AddFile(bnr: number): void
  if buf.BufHasLspServer(bnr)
    # LSP server for this buffer is already initialized and running
    return
  endif

There is a side effect if I remove that check. It reports first server (pylsp) twice (there is only one pylsp process)

Buffer Information
==================
Buffer: 'xx.py'
Server Path: '/usr/local/bin/pylsp'
Status: Running
Server Path: '/usr/local/bin/pylsp'
Status: Running
Server Path: '/Users/gp/Library/Python/3.11/bin/pyright-langserver'
Status: Running
andlrc commented 1 year ago

@girishji I don't think that's the problem.

I'm starting to think that the pyright-langserver is silently crashing on it's first setup.

There is a side effect if I remove that check. It reports first server (pylsp) twice (there is only one pylsp process)

Even though the server command is clever enough to keep only run one process, then this LSP plugin treats them as two individual servers for the most parts.

Any reason why this check is in place?

To avoid registering the same server to the same buffer over and over again with things like :e<Cr>.

girishji commented 1 year ago

I'm starting to think that the pyright-langserver is silently crashing on it's first setup.

@andlrc that is not true. AddFile() gets called twice. First time with only pylsp in server list (return value of LspGetServers() inside AddFile()), and second time with both pylsp and pyright. When AddFile() is called the second time (for the same buffer) it exits immediately because of the check I mentioned in my previous post. First time invocation has only one server in the list instead of two. This is why OP is seeing only pylsp initialized. This is clearly a bug.

00dani commented 1 year ago

There's a simple workaround for this bug, provided you don't need to add new LSP servers to your configuration at runtime. (You probably don't need to do that.) Rather than using an autocommand to add servers after Vim has loaded packages, like this:

autocmd VimEnter * ++once g:LspAddServer(lspServers)

You can intentionally autoload the necessary function ahead of time, like this:

g:lsp#lsp#AddServer(lspServers)

This syntax will configure all servers at launch, before AddFile() is ever invoked, so both servers for the same filetype will work correctly. This approach works fine if you installed yegappan/lsp with Vim's packages feature too.

In theory you should also be able to write import autoload 'lsp/lsp.vim' and then call lsp.AddServer(lspServers), but if you're using Vim packages then the new import autoload syntax doesn't work that way yet. 🤷‍♀️