Skip to main content

Module dynamic_registration

Module dynamic_registration 

Source
Expand description

Dynamic capability tracking (LSP §3.18.10.3 / 4.4.n).

After initialize, a server may send client/registerCapability to announce capabilities it didn’t list in the initial ServerCapabilities blob, or to attach method-specific options that the static shape can’t express (the canonical example is workspace/didChangeWatchedFiles – the glob patterns to watch depend on the active project and aren’t known at handshake). client/unregisterCapability reverses an earlier registration.

Before 4.4.n the actor accepted both requests with null and threw the payload away; feature dispatch saw only the static capability set. This module owns the “dynamic layer” the server adds on top – the Capabilities aggregate carries one of these and every supports_* probe that cares about dynamic-only registrations consults it alongside the static ServerCapabilities field.

§Indexing

The registry indexes registrations two ways:

  1. by_id (HashMap<String, DynamicRegistration>) – so unregisterCapability can find an entry by the id the server picked at register time and evict it in O(1).
  2. by_method (HashMap<String, Vec<String>>) – so feature dispatch can ask “is textDocument/completion registered dynamically?” without scanning the whole table. The vec holds registration ids; the registry stays a single source of truth (the actual DynamicRegistration lives only in by_id).

§Snapshot model

Capabilities is published through an arc_swap::ArcSwap cell on the ServerHandle; readers see the union of static + dynamic atomically. Mutations are per-actor (only the actor task issues the swap), so writes don’t race with each other. The cloning cost on update is the size of the registry’s two HashMaps – typically single-digit entries for the lifetime of a server, so the arithmetic is cheap.

Structs§

DynamicRegistration
One server-issued capability registration. The register_options blob’s interpretation is method-specific; the registry treats it as opaque JSON and hands it to the consumer when they fetch the entry. For methods we wire (e.g. workspace/didChangeWatchedFiles) the consumer parses it into the lsp_types shape on demand.
DynamicRegistry
In-memory index of every active dynamic registration for one server actor. Empty on a fresh server; mutated by the actor on client/(un)registerCapability and snapshotted into the published Capabilities on every change.