joaotavora / eglot

A client for Language Server Protocol servers
GNU General Public License v3.0
2.25k stars 200 forks source link

Not working with typst-lsp: completion request always time out #1363

Closed Zjl37 closed 7 months ago

Zjl37 commented 7 months ago

Hello, I can't get eglot working with typst-lsp. The server starts and initializes with no error messages, but does not give any completions. Here's an formatted event log, generated by typing a single '#' character in an empty Typst file: (In Typst markup a hash is needed before variables and functions, so a '#' is expected to trigger completion.)

https://gist.github.com/Zjl37/d506c225bce175e584a78d47e0dbecab

(There are many "timed-out request" message near the bottom of the log.)

Reproduce steps

  1. Install Emacs, Typst and typst-lsp.
  2. start emacs -Q -l init-min-240216.el ~/path/to/an/empty/or/new/test-file.typ, where the init file is:
(package-initialize)

(require 'eglot)
(add-to-list 'eglot-server-programs '((typst-ts-mode typst-mode) . ("typst-lsp")))

;; though there is a typst-ts-mode package in the wild, let's do this to keep things minimal
(define-derived-mode typst-mode text-mode "Typst" "Test Major mode for editing Typst.")

;; completion frontend
(require 'corfu)
(setq corfu-auto t)
(global-corfu-mode)
  1. M-x typst-mode
  2. M-x eglot
  3. Type a # character

Expected behavior

A completion list would show up.

Extra information

- `emacs-version`: GNU Emacs 29.2 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.40, cairo version 1.18.0) - eglot version: 1.17 - `typst-lsp --version`: Version: 0.12.1, commit 1928d88ff8bc3e178ad098146bec252751383a48 (Typst version 0.10.0) - `typst --version`: typst 0.10.0 (70ca0d25) - OS: Arch Linux - corfu version: 20240122.2327 (melpa)
Zjl37 commented 7 months ago

As I have little knowledge in LSP and Typst is a relatively new language, I'm not sure whether this is eglot's or typst-lsp's fault. However since I can configure and make this server work properly with lsp-mode, I decided to ask here first. If something has to be done with the lsp server, I could report there.

Thanks in advance!

joaotavora commented 7 months ago

This is most likely a server problem. To know exactly where the problem lies, please get rid of corfu in your recipe, and just use C-M-i in the place where you want the completion to happen.

Zjl37 commented 7 months ago

It's not corfu. Removing the last three lines,

the init file becomes... ```elisp (package-initialize) (require 'eglot) (add-to-list 'eglot-server-programs '((typst-ts-mode typst-mode) . ("typst-lsp"))) (define-derived-mode typst-mode text-mode "Typst" "Test Major mode for editing Typst.") ```

and still, the completion requests triggered by M-x completion-at-point time out, now with this error:

completion--some: jsonrpc-error: "request id=4 failed:", (jsonrpc-error-message . "Timed out")


What I expect is sth like:

图片

That is made with a minimal lsp-mode config. And its corresponding event log is here for comparison if you find it useful.

Note that the server works well with VSCodium, Nvim's lspconfig (as they documented) or Emacs's lsp-mode. Now I just wonder if you could tell me what makes the situation different in eglot, even though it may not be eglot's fault, I'd be very grateful.

joaotavora commented 7 months ago

Now I just wonder if you could tell me what makes the situation different in eglot, even though it may not be eglot's fault, I'd be very grateful.

I can't do that comparison right now. As far as I can tell Eglot didn't send any wrong outputs. A server shouldn't just timeout on a textDocument/completion or textDocument/hover request. Likely VScode or lsp-mode spoonfeed some server specific things to the server that Eglot doesn't know about. Eglot assumes LSP is enough and this is indeed enough to work with the vast majority of servers. Besides completion, have you gotten other things to work? Say definition finding, diagnostics, documentation, etc?

Zjl37 commented 7 months ago

have you gotten other things to work? Say definition finding, diagnostics, documentation, etc?

joaotavora commented 7 months ago

So basically, nothing really works. This has nothing to do with completion. I think the server needs some special handholding, and it's not immediately obvious what that is.

joaotavora commented 7 months ago

Maybe the server doesn't like to get workspace/didChangeConfiguration in the beginning. It's empty anyway. The jdtls server for example overwrites any user settings instead of mergin them and that causes problems (not these problems though).

Try:

(setq eglot-connect-hook nil)
Zjl37 commented 7 months ago

Yes, adding this line makes the server work! :smile:

However, should this be considered a server bug? after all eglot sends the workspace/didChangeConfiguration before the server registers this capability (seen from the log). Maybe eglot could declare it supports workspace/didChangeConfiguration during initialization, but it just instead warns about Server tried to register unsupported capability `workspace/didChangeConfiguration' while actually sending it. 😕 (Sorry I neglected this warning line 2 days ago)

joaotavora commented 7 months ago

As far as I can read from https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeConfiguration, the workspace/didChangeConfigueration can always be sent by the client, the server doesn't need to declare support for it (no server capability).

The client capability refers to an additional"dynamic registration" of a client-side capability (absent from Eglot) to enable what they call the "pull model", which is something that I don't know very well what it is, but Eglot doesn't support it (I don't mind if the server folks explain what it is, maybe it can be supported).

So, yes, I'd say this is a server bug. The client notification has been there from very early on, even before version 3.0 which introduced this addtional "registration".

Zjl37 commented 7 months ago

I see. Thank you very much for your investigating and explaining. I'll then report an issue to the server.