Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple servers for a single language #57

Open
natebosch opened this issue Dec 23, 2017 · 3 comments
Open

Support multiple servers for a single language #57

natebosch opened this issue Dec 23, 2017 · 3 comments

Comments

@natebosch
Copy link
Owner

Could be nice to try multiple servers and, for example, jump to the definition from the first one that returns a location.

@kenshinji
Copy link

By multiple server, you mean like a cluster of language servers or different kind of servers ?

@natebosch
Copy link
Owner Author

A cluster of language servers for the same language.

natebosch added a commit that referenced this issue Mar 13, 2019
Towards #57
Towards #164

Add a capabilities library to filter down and parse out the options this
client cares about. Always store a dictionary of capabilities on the
server objects, and search those when checking for how other features
should behave.

This replaces the previous approach of storing a separate dictionary per
feature to track by filetype. Once we support multiple servers for a
given filetype the single config wouldn't make sense.
natebosch added a commit that referenced this issue Mar 13, 2019
Towards #57
Towards #164

Add a capabilities library to filter down and parse out the options this
client cares about. Always store a dictionary of capabilities on the
server objects, and search those when checking for how other features
should behave.

This replaces the previous approach of storing a separate dictionary per
feature to track by filetype. Once we support multiple servers for a
given filetype the single config wouldn't make sense.
natebosch added a commit that referenced this issue Jan 18, 2021
Towards #57

Change `lsc#server#start` to take a specific server instead of a
filetype. Return the server from `lsc#server#register` to allow
`RegisterLanguageServer` to pass it back to `lsc#server#start`. When
registering a server choose between starting it, or tracking buffers of
the newly registered filetype if the server is already running.

Start to separate the per-server pieces of file tracking. Still only
allows a single server per filetype in `server.vim`.

At server startup, track all files for the specific server rather than
all servers for the filetype. If multiple servers were allowed this
would prevent sending `didOpen` to already running server when a new one
starts. Pass the server instead of the filetype to `lsc#file#trackAll`.
Add `lsc#file#track` to track a specific buffer for the
`RegisterLanguageServer` case.

Remove the fallback to sending `didOpen` instead of `didChange` when
flushing file changes. Originally `s:DidOpen` could call
`lsc#file#flushChanges` because an `:edit` for an already open file
would call again, and the changes should be flushed instead of an
erroneous second `didOpen` for an already open file.
03eb193
Later this was reversed and `s:FlushChanges` was always the called
function, and it could instead call `s:DidOpen`.
3a37c0d

In the new design `s:DidOpen` is only called from the code paths which
should intentionally send the `didOpen` notification, instead of needing
to check at call time whether to send a `didOpen` or a `didChange`. The
`didOpen` notification is sent in the specific cases where the server
cannot have already received it - starting up a server and tracking all
relevant files, opening a new buffer which has not been handled at all,
or registering a language server for a new file type. For the latter 2
cases callers disambiguate between starting the server or sending
`didOpen` based on whether the server is already running. This fixes a
bug in `RegisterLanguageServer` which caused already open files to not
be tracked if an existing serve is configured to work for a new
filetype. Currently the new server and opened buffer paths both need to
check for a disabled server. The call to start servers is safe to make
repeatedly, even if the server is already starting up.

Calls to `lsc#file#flushChanges` triggered by the plugin before making
some other request like completion or references are ignored if the
buffer isn't already tracked. In those cases the call to the server
should not be made anyway, since the only way for a server to not track
an already open buffer is if it is not yet `'running'`, the call to
`lsc#file#trackAll` is done synchronously following the status change.

When calling `didOpen`, reuse buffer content from `s:file_contents` if
it exists instead of reading current buffer content. If a server starts
up after files are already tracked, the point at which `didOpen` is
called will match the point from which a diff is computed for the next
`didChange` call. The spec does not state the version must start at any
particular number, and allows for non-consecutive versions. Since the
version and content are always updated in the same method synchronously,
this should keep all sent messages sane for every server. Since
`didChange` are not sent for non-running servers and the `didOpen` calls
are sent synchronously when the server's status is changed to
`'running'`, it is safe to silently drop the `didChange` calls before a
server is running and know that they will pick back up from the correct
point when it is running.
natebosch added a commit that referenced this issue Jan 19, 2021
Towards #57

Change `lsc#server#start` to take a specific server instead of a
filetype. Return the server from `lsc#server#register` to allow
`RegisterLanguageServer` to pass it back to `lsc#server#start`. When
registering a server choose between starting it, or tracking buffers of
the newly registered filetype if the server is already running.

Start to separate the per-server pieces of file tracking. Still only
allows a single server per filetype in `server.vim`.

At server startup, track all files for the specific server rather than
all servers for the filetype. If multiple servers were allowed this
would prevent sending `didOpen` to already running server when a new one
starts. Pass the server instead of the filetype to `lsc#file#trackAll`.
Add `lsc#file#track` to track a specific buffer for the
`RegisterLanguageServer` case.

Remove the fallback to sending `didOpen` instead of `didChange` when
flushing file changes. Originally `s:DidOpen` could call
`lsc#file#flushChanges` because an `:edit` for an already open file
would call again, and the changes should be flushed instead of an
erroneous second `didOpen` for an already open file.
03eb193
Later this was reversed and `s:FlushChanges` was always the called
function, and it could instead call `s:DidOpen`.
3a37c0d

In the new design `s:DidOpen` is only called from the code paths which
should intentionally send the `didOpen` notification, instead of needing
to check at call time whether to send a `didOpen` or a `didChange`. The
`didOpen` notification is sent in the specific cases where the server
cannot have already received it - starting up a server and tracking all
relevant files, opening a new buffer which has not been handled at all,
or registering a language server for a new file type. For the latter 2
cases callers disambiguate between starting the server or sending
`didOpen` based on whether the server is already running. This fixes a
bug in `RegisterLanguageServer` which caused already open files to not
be tracked if an existing serve is configured to work for a new
filetype. Currently the new server and opened buffer paths both need to
check for a disabled server. The call to start servers is safe to make
repeatedly, even if the server is already starting up.

Calls to `lsc#file#flushChanges` triggered by the plugin before making
some other request like completion or references are ignored if the
buffer isn't already tracked. In those cases the call to the server
should not be made anyway, since the only way for a server to not track
an already open buffer is if it is not yet `'running'`, the call to
`lsc#file#trackAll` is done synchronously following the status change.

When calling `didOpen`, reuse buffer content from `s:file_contents` if
it exists instead of reading current buffer content. If a server starts
up after files are already tracked, the point at which `didOpen` is
called will match the point from which a diff is computed for the next
`didChange` call. The spec does not state the version must start at any
particular number, and allows for non-consecutive versions. Since the
version and content are always updated in the same method synchronously,
this should keep all sent messages sane for every server. The `didOpen`
calls are sent synchronously following the server's status change to
`'running'`, so it is safe to silently drop the `didChange` calls before a
server is running and know that they will pick back up from the correct
point when it is running.
@cwegener
Copy link

Is this still something that people are interested in?

I just had this requirement today:

  • Use one LSP for majority of functions (Definition, References, ShowHover ...)
  • Use second LSP for just for Diagnostics functions

Specifically for Python: pylsp for majority and sourcery-cli for Diagnostics

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants