Expand description
Per-server actor (DESIGN.md §5.4 + §5.7). One tokio task owns the wire-side state for one (workspace, server-id) pair:
- The pending-request table (RequestId → oneshot to the editor-side caller).
- The negotiated
Capabilities. - A monotonic JSON-RPC request-id counter.
Two helper tasks fan I/O in and out:
- read_loop – reads
Messages fromLspReaderand pushes them into an inbound channel. - write_loop – receives
Messages on an outbound channel and writes them throughLspWriter.
§Why three tasks
A single-task design works for a typewriter-pace editor but
collapses under burst loads (a server emitting hundreds of
$/progress notifications during indexing while the editor
is also sending didChange per keystroke). Splitting reads
and writes onto separate tasks lets the OS schedule them
across cores; the actor task itself stays cheap (no I/O).
§Lifecycle
spawn runs the initialize handshake before returning a
ServerHandle. Failure during handshake yields
LspError::HandshakeFailed and tears the child process
down via kill_on_drop.
ServerHandle::shutdown runs the LSP shutdown protocol:
shutdown request → exit notification → wait for child
exit. The actor task exits cleanly and all pending
requests resolve with LspError::Cancelled.
Structs§
- Server
Handle - Editor-facing handle to one running language-server actor.
Functions§
- spawn
- Spawn a language server from a
ServerConfig. - spawn_
with_ io - Spawn the actor against pre-existing
LspReader/LspWriterhalves. Used by tests (mock server over a duplex pipe) and by future embedded transports (TCP, named pipe). - uri_
from_ path - uri_
to_ path - Convert a filesystem path to a
file://URI in the form LSP expects. lsp-types 0.97 dropped theurlcrate; we percent-encode manually for the small set of bytes that matter in a path (space →%20, etc.). Servers in practice tolerate plainfile:///<path>without aggressive encoding. Inverse ofuri_from_path. Strips thefile://scheme + percent-decodes the small set of bytes the encoder rewrites. Returns the path string (caller decides whether to coerce toPathBuf);Nonefor non-file://URIs.