Fork me on GitHub
#lsp
<
2023-09-29
>
lassemaatta09:09:33

Every once in a while I have trouble getting completions from lsp-mode in emacs. I spent some time debugging this and it looks like sometimes when I try to active completions on some e.g. (some-alias/|) form (`|` is the cursor) LSP sends a textDocument/documentHighlight request instead of a textDocument/completion. Any idea what might cause this?

lassemaatta09:09:28

usually the buffer I'm working gets stuck in this state for a while and I can usually fix it by doing random stuff (clear the form and try again, save the file, etc) until the completions start working again.

lassemaatta09:09:03

It feels like there's a cache of previous completions somewhere in lsp-mode and when I run completion-at-point it will a) sometimes fetch completions from LSP with textDocument/completion, b) display the completion choices (in corfu) and c) also send a textDocument/documentHighlight. When everything is working I can observe all three a,b, and c happening or sometimes only b and c (I guess LSP is using the cache here). But sometimes it seems only c happens, as if the cache is empty but LSP still decides not to query for the completions, or something like that.

lassemaatta10:09:56

Or this could just as well be some configuration issue between corfu and lsp-mode, even though I've tried following https://github.com/minad/corfu/wiki#configuring-corfu-for-lsp-mode :man-shrugging:

ericdallo11:09:09

My guess is a misconfiguration with Corfu, I never used it, and my completions are 100% stable and I use it and trigger manually a lot as well

lassemaatta11:09:48

yeah, seems likely

mpenet18:09:36

I had the same issues with corfu + eglot. I am back on company mode and it works flawlessly now

ericdallo18:09:11

would be nice to open a issue on corfu

mpenet19:09:37

I did on eglot back then. I thought it was the culprit and corfu maintainer was involved in the discussion

lassemaatta15:09:12

I did some more testing by disabling corfu and/or starting a new session with lsp-start-plain and in both cases I could replicate the issue.

lassemaatta16:09:52

But when testing completions on some random java project with the eclipse jdtls LSP server I could not replicate the issue :thinking_face:

ericdallo16:09:09

Interesting, so it happens only with clojure-lsp? I can try repro the issue but never had that before

lassemaatta16:09:50

yeah, but on the other hand I've spent 99.9% of the time testing this with clojure-lsp. There's a few too many moving pieces here so I think I'll just try to bisect when and where this happens (or not happens).

lassemaatta17:09:26

I did find some tickets where lsp-mode + the typescript lsp server exhibited something a bit similar (https://github.com/emacs-lsp/lsp-mode/issues/3961 and the related https://github.com/typescript-language-server/typescript-language-server/issues/631) where, if I understood correctly, there was some issue in the language server. But most of the discussions about the internal details of the LSP completion protocols goes way over my head so no idea if these are in any way relevant to what I'm experiencing.

lassemaatta17:09:53

I think I'll try to test some other language servers and also setup calva so I can try another lsp client with clojure-lsp to see where I can replicate this.

ericdallo18:09:39

Yeah that would be helpful, vscode LSP client tends to be stable so it's good to prove if an issue is on server or not

lassemaatta06:10:23

I'm unable to replicate the exact issue in vscodium + calva, so I guess this rules out clojure-lsp. I'll see if I can setup eglot to check if this only occurs with lsp-mode I did notice one silly case where completions fail for both emacs and vscodium: writing multiple incomplete forms, e.g. something like

(ns some-ns
 (:require [some-lib :as a]
           [other-lib :as b]))

(a/) ;<- "Invalid symbol: a/."
(b/) ;<- "Invalid symbol: b/."
where moving the cursor after either a/ or b/ will fail to provide completions. But fix (or remove) one of them and then the other one works again. But I guess this is a rather silly example, not sure how often people would write incomplete forms like that.

ericdallo11:10:23

oh yeah, that slash corner case was pretty hard to support, probably it's not 100% yet (clojure-lsp under the hood, remove the / and consider it only when appending the result, that happens because rewrite-clj can't parse a invalid clojure code like that)