microsoft / language-server-protocol

Defines a common protocol for language servers.
https://microsoft.github.io/language-server-protocol/
Creative Commons Attribution 4.0 International
11.16k stars 785 forks source link

Clarify how to implement polyglot language servers / cardinality for polyglot LSs #1964

Closed nthykier closed 2 months ago

nthykier commented 3 months ago

Hi

The situation

I am working on a polyglot language server for Debian packaging files. The packaging files are written in various different formats. The minimal set consists of at least 3 different file formats:

As a language server implementor, I cannot dictate a consolidation of the formats nor would any one of these formats be suitable to replace the remaining formats. Accordingly, it is premise for me to support multiple distinct formats. Additionally, changes in one file can have consequences for other files. As an example, certain changes in debian/control can influence completion items for debian/rules and certain content in debian/rules can trigger diagnostics in debian/control (in theory also vice versa here, but I have not coded any of them yet).

Therefore, as far as I can tell, I need a polyglot language server that should receive updates to multiple file formats (languages) at the same time. In particular, for these things to work reliably I want timely "did open" and "did change" across all registered formats in a project.

What I observe

I was using the emacs with the eglot plugin and that spawns a new instance of my language server per language (I think "major mode") even though it is the same language server with exactly the same arguments. In this setup, each instance of the language server only receives "did change" notifications for the concrete format they are associated with. As an example:

If I change debian/control, then instance 1 is notified of the unsaved changes but instance 2 is not. When I change debian/rules then the opposite happens. Only when I save the documents can the both instances see the same content (by virtue of them falling back to file system access for documents not "locked" by the editor).

Alternatives

I tried to register a workspace listener for changed files in the hopes that would also trigger a did open + did change notifications. Though the specs does not say it should and emacs did not provide them either. So that did not work for me.

The ask

I had hoped that the specification was clear on how to handle this situation. I see multiple solutions that would solve my problem.

1) Provide a way for a language server to declare that a single instance works with multiple formats at the same time. This is in a similar vein as #674 (or at least have some of the same challenges as #674) though the ask in #674 is that there is a single instance for the same format across all projects and here I want multiple file formats inside the same project.

2) Explicitly state that a language server should be notified of all open documents even those that is not the language the language server is an authority for (or provide a capability for a language server to request that). In this case, I would still have two instances but they would both be notified and therefore have full visibility.

Related issues

Issue #674 requests a feature to support one language server reused across multiple projects. A more generalized version of that could be a solution (as stated above). However, since it is not a given that a solution to #674 would also solve my request, I have decided to file this as a separate issue. If you decide to solve it by doing a more generalized version of #674, then feel free to move the relevant parts into #674 and close this as a duplicate.

dbaeumer commented 3 months ago

Although not stated explicitly, language server should be able to handle more than one file type. This is implicitly given by two things in the spec:

So my advice is to talk to the implementors of the Emacs client why they have decided to spawn a server per file type (which would not support the above features IMO). This is nothing the VS Code LSP client does.

Please let me know what the outcome of this discussion is.

nthykier commented 2 months ago

Turns out eglot does support reusing the same instance of the language server inside a project using a different configuration syntax than what I used. Apologies for the noise.