Skip to main content

LspSupervisor

Struct LspSupervisor 

Source
pub struct LspSupervisor { /* private fields */ }
Expand description

One LSP subsystem per editor instance.

Implementations§

Source§

impl LspSupervisor

Source

pub fn new(logger: LspLogger) -> Self

Construct an empty supervisor with shared logger + diagnostics layer. Use add_config to populate the config registry.

Source

pub fn set_event_bus(&mut self, bus: Arc<EventBus>)

Install the editor event bus. Must be called once at startup before any buffer opens; after the call every actor spawned by the supervisor gets a per-actor fan-in task (see crate::fan_in) that turns Event::DocumentChanged into crate::actor::ServerHandle::record_edit without ever taking the supervisor’s mutex.

Calling twice replaces the bus reference; existing actors keep their original fan-in subscriptions (we don’t re-spawn them on bus swap because that would race with in-flight events).

Source

pub fn set_apply_edit_bus(&mut self, bus: ApplyEditBus)

Install the apply-edit bus (Phase 4.3). The App calls this once at startup with the sender side of the channel it created; every actor spawned after this point gets a clone and forwards inbound workspace/applyEdit requests through it. Calling twice replaces the bus; any actors already spawned keep their original clone (we don’t track them for retro-fitting in v1).

Source

pub fn set_configuration_bus(&mut self, bus: ConfigurationBus)

Install the configuration bus (Phase 4.1 follow-up). Same shape as Self::set_apply_edit_bus: cloned into every actor spawned after the call so server-initiated workspace/configuration requests reach the App’s drain. None falls back to per-item null replies.

Source

pub fn set_show_document_bus(&mut self, bus: ShowDocumentBus)

4.4.b: install the show-document bus. Cloned into every actor spawned (or restarted) after this call. The App calls this once at startup with the sender side of the channel whose receiver it holds.

Source

pub fn set_show_message_request_bus(&mut self, bus: ShowMessageRequestBus)

4.4.b: install the show-message-request bus.

Source

pub fn logger(&self) -> &LspLogger

Borrow the shared logger (so callers can register their own subsystem-level events).

Source

pub fn diagnostics(&self) -> &DiagnosticsLayer

Borrow the shared diagnostics layer.

Source

pub fn add_config(&mut self, config: ServerConfig)

Add a server config to the registry. The App calls this for every builtin + user-override config at startup.

Source

pub fn set_configs<I: IntoIterator<Item = ServerConfig>>(&mut self, configs: I)

Set the registry from an iterator (e.g. the curated builtins). Replaces any prior contents.

Source

pub fn configs(&self) -> &[Arc<ServerConfig>]

All registered configs (read-only; for :lsp-status).

Source

pub fn has_server_for_path(&self, path: &Path) -> bool

True iff at least one configured server’s file_patterns matches path. M.5.2 uses this from the App’s MajorEntered hook to decide whether to auto-activate lsp-mode on the buffer; if no server cares about the path, there’s nothing to gate on.

Source

pub fn running_actors(&self) -> Vec<(ActorKey, ServerHandle)>

Every actor currently running. Used by :lsp-status.

Source

pub fn all_running_handles(&self) -> Vec<ServerHandle>

Snapshot of every running actor’s ServerHandle. Used by workspace-scoped LSP requests (e.g. workspace/symbol) that fan out across every server, not just servers attached to one buffer.

Source

pub fn buffer_count_for(&self, key: &ActorKey) -> usize

Number of buffers currently attached to the actor at key. Cheap walk over attachments; used by :lsp-server-log to surface per-server buffer counts in the picker margin.

Source

pub async fn open_buffer( &mut self, path: PathBuf, text: String, ) -> LspResult<Vec<ServerHandle>>

Open a buffer. Walks the config registry, spawns matching actors as needed, attaches the buffer to each, and emits didOpen per server. Returns the list of attached ServerHandles – the App stores this so feature dispatch knows where to issue requests.

path is the buffer’s filesystem path; text is the initial buffer text.

Source

pub fn attach_handle( &mut self, uri: Uri, workspace_root: PathBuf, server_id: String, language_id: String, text: String, handle: ServerHandle, ) -> LspResult<()>

Attach a buffer to a pre-built ServerHandle. Used by:

  • Tests – the in-process MockServer returns a handle that the supervisor wouldn’t normally spawn.
  • Custom transports (future) – a TCP / named-pipe server that bypasses ChildTransport.

Identical effect to the actor-spawning branch of open_buffer: registers the actor under (workspace_root, server_id), builds a DocSync, emits didOpen, records the attachment, and starts the diagnostics pump if it isn’t already running.

Source

pub fn close_buffer(&mut self, uri: &Uri) -> LspResult<()>

Close a buffer. Flushes pending changes per attached server, sends didClose, and drops the URI from attachments + the diagnostics layer.

Source

pub fn record_edit(&mut self, uri: &Uri, edit: &Edit) -> LspResult<()>

Forward an edit to every attached actor’s mailbox.

Not on the editor’s hot path. Production edits flow through the editor event bus to a per-actor fan-in (see crate::fan_in), which means the UI thread never takes the supervisor mutex on a keystroke. This method remains for tests + admin tooling that drive the supervisor directly without standing up an event bus.

Source

pub fn flush(&mut self, uri: &Uri) -> LspResult<()>

Force-flush queued changes for uri across every attached server, bypassing the per-actor debounce. Used before synchronous requests that require the server to have seen the latest text – notably willSaveWaitUntil and :lsp-flush.

Source

pub fn flush_all(&mut self) -> LspResult<()>

Force-flush every open URI’s queued changes across every attached server. Used at editor shutdown so each server sees a coherent final state before didClose. Per-edit flushing is debounced inside each actor; this is the only “drain everything now” affordance.

Source

pub fn servers_for(&self, uri: &Uri) -> Vec<ServerHandle>

Every server attached to uri. The App walks this list to dispatch features (hover, goto-definition, …).

Source

pub fn attached_buffer_count(&self) -> usize

Number of currently-attached buffers.

Source

pub fn running_actor_count(&self) -> usize

Number of currently-running actors.

Source

pub async fn restart_server( &mut self, server_id: &str, ) -> LspResult<RestartReport>

4.4.d: force-restart every actor with id server_id.

Steps:

  1. Prune restart history outside the private RESTART_WINDOW.
  2. If history.len() >= MAX_RESTARTS, refuse (caller surfaces the cooldown to the user).
  3. Sleep compute_restart_backoff(history.len()).
  4. For every (workspace, server_id) actor pair: shut down the existing handle, drop the fan-in subscription, spawn a fresh actor with the same config, restart the diagnostics pump + fan-in.
  5. Replay didOpen for every URI that pointed at the old actor so the new actor sees the same workspace state.
  6. Push Instant::now() to history.

Replayed didOpen uses each tracked URI’s last-known text; today the supervisor doesn’t keep that text (each actor’s DocSync owns the mirror), so the replay uses the empty string and the App is expected to re-send the full buffer via the next didChange debounce. Future revision can snapshot text into RestartReport and let the App ferry it back via record_edit proactively.

Returns the list of (workspace, server_id) keys that were re-spawned and the URIs that need re-opening.

Source

pub async fn shutdown(&mut self) -> LspResult<()>

Detach every buffer + drop every actor. Used at editor exit. Each attached buffer’s didClose is fired.

Source§

impl LspSupervisor

Source

pub fn spawn(self, runtime_handle: &Handle) -> LspSupervisorHandle

Consume the configured supervisor and start the supervisor task on runtime_handle. Returns the LspSupervisorHandle App-side code uses for the rest of the editor’s lifetime.

After this call, all mutating operations route through the returned handle’s mailbox; reads come from the wait-free ArcSwap<SupervisorSnapshot>. The LspSupervisor itself is owned exclusively by the spawned task – no Arc, no Mutex, no contention possible with the UI thread.

Configuration calls (set_event_bus, set_apply_edit_bus, set_configuration_bus, add_config, set_configs) must happen before spawn – the post-spawn handle does not expose them. This matches the editor’s actual lifecycle: the App configures the supervisor at startup before any buffer opens.

runtime_handle is mandatory: the supervisor’s command- mailbox semantics only make sense against a live tokio task, and a missing runtime is a programming error. Production callers (App::new → build_lsp_subsystem) pass the editor’s shared LSP runtime handle (runtime::lsp_runtime()); tests that exercise the write path build an ad-hoc runtime via tokio::runtime::Builder and pass its handle. Earlier revisions used tokio::runtime::Handle::try_current() with a silent fallback that dropped cmd_rx; that path surfaced as LspError::ActorGone on every write whenever the caller didn’t happen to be inside a tokio context, which proved to be a real footgun (e.g. App::new runs before runtime::run has entered any context).

Trait Implementations§

Source§

impl Debug for LspSupervisor

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more