Hey folks, I've noticed a few rough edges when trying to add some lsp features.
So I've asked cursor for a list of sensible small refactorings / bugfixes in the LSP.
textDocument/didClose) and give a PR?:robot: summary:
Did a read-only pass over src/lsp/. Biggest user pain today isn’t missing features so much as: sync full-check blocking the message loop (Helix close/shutdown timeout), UTF-16 advertised but query paths treating columns as bytes, and a few silent-wrong / silent-hang paths.
Proposed small, shippable refactors — each as a repro-first hand-off (pick one up as AI or human):
Do first (S):
didClose — sticky diags + buffer leak (openClose: true but no handler). Closing a tab never clears the store or publishes empty diagnostics, so squiggles and memory stick around for the session.id. Once we know the request id we should always best-effort sendError, otherwise the editor waits until timeout while the server is still alive.result: null. A real checker failure currently looks identical to “nothing under the cursor,” so you can’t tell broken analysis from an empty hover.Do next (M, biggest bang):
didChange already converts UTF-16 properly, but hover/goto/completion still treat character as a byte offset (and some handlers duplicate that math with a 4096-line cap).didOpen mustn’t block shutdown. The single-threaded loop runs a full buildResolvingMain inside open/change before it can read the next message, so close/quit times out even though shutdown itself is cheap.Also known (not separate docs): barefoot JSON walks are factorable in Zig (fromJson already exists in protocol.zig for some types); full coop-cancel is a later step after (6). Shared typed params would cut the copy-paste tax for every new caret feature without changing runtime UX.
Suggested order: 01 → 02/03 → 04 → 06 (parallel 05). After 04 + shared params parsing, new caret features get much cheaper — you mostly write the CIR query, not encoding/JSON plumbing again.
prompt (if anyone's interested)
Last updated: Aug 12 2026 at 12:35 UTC