pub struct ServerState {
pub documents: DashMap<Uri, DocumentState>,
pub cache: Arc<HttpCache>,
pub osv: Arc<OsvClient>,
pub deps_dev: Arc<DepsDevClient>,
pub lockfile_cache: Arc<LockFileCache>,
pub ecosystem_registry: Arc<EcosystemRegistry>,
pub registry_policy: Arc<RegistryAccessPolicy>,
pub nuget_user_profile_sources: Arc<AtomicBool>,
pub gitlab_instance_host: Arc<RwLock<Option<String>>>,
pub cold_start_limiter: ColdStartLimiter,
/* private fields */
}Expand description
Global LSP server state.
Manages all open documents, HTTP cache, lock file cache, and background
tasks for the server. This state is shared across all LSP handlers via
Arc and uses concurrent data structures (DashMap, RwLock) for
thread-safe access.
§Examples
use deps_lsp::document::ServerState;
use tower_lsp_server::ls_types::Uri;
let state = ServerState::new();
assert_eq!(state.document_count(), 0);Fields§
§documents: DashMap<Uri, DocumentState>Open documents by URI
cache: Arc<HttpCache>HTTP cache for registry requests
osv: Arc<OsvClient>OSV.dev vulnerability scan client, shared server-lifetime so every open document’s scan benefits from the same query/record cache.
deps_dev: Arc<DepsDevClient>deps.dev supply-chain trust signal client (spec 037), shared
server-lifetime so every hover benefits from the same TTL memo.
handlers/hover.rs is the only caller that hands this to
VersionData::with_trust — see that field’s docs for why this is
what makes the feature hover-only by construction (FR-010).
lockfile_cache: Arc<LockFileCache>Lock file cache for parsed lock files
ecosystem_registry: Arc<EcosystemRegistry>Ecosystem registry for trait-based architecture
registry_policy: Arc<RegistryAccessPolicy>Live-updatable workspace-registry reachability policy (spec #443,
registries.workspace_registries, widened from Cargo-only by
032-npm-npmrc-registry-support) — the same handle crate::register_ecosystems hands
to CargoEcosystem::with_context and NpmEcosystem::with_context alike, so
Backend::initialize/did_change_configuration updating this value here takes effect
on every parse from then on, with no need to reconstruct either ecosystem.
nuget_user_profile_sources: Arc<AtomicBool>Live-updatable registries.nuget_user_profile_sources setting (issue #561, FR-006) —
the same handle crate::register_ecosystems hands to NuGetEcosystem’s
NuGetParseContext, bundled inside EcosystemRuntime. See that struct’s docs.
gitlab_instance_host: Arc<RwLock<Option<String>>>Live-updatable registries.gitlab_instance_host setting (issue #466, spec
FR-005a/FR-011a) — the same raw-string handle crate::register_ecosystems hands to
GitlabCiEcosystem::with_context, bundled inside EcosystemRuntime. See that
struct’s docs for why this is a feature-agnostic Arc<RwLock<Option<String>>>
rather than a deps-gitlab-ci type.
cold_start_limiter: ColdStartLimiterCold start rate limiter
Implementations§
Source§impl ServerState
impl ServerState
Sourcepub fn supports_progress(&self) -> bool
pub fn supports_progress(&self) -> bool
Returns whether the client supports LSP work done progress notifications.
Sourcepub fn set_progress_supported(&self, supported: bool)
pub fn set_progress_supported(&self, supported: bool)
Records whether the client supports LSP work done progress notifications.
Called once from initialize with the result of negotiating
window.workDoneProgress from ClientCapabilities.
Sourcepub fn inlay_hint_refresh_supported(&self) -> bool
pub fn inlay_hint_refresh_supported(&self) -> bool
Returns whether the client supports workspace/inlayHint/refresh.
Sourcepub fn set_inlay_hint_refresh_supported(&self, supported: bool)
pub fn set_inlay_hint_refresh_supported(&self, supported: bool)
Records whether the client supports workspace/inlayHint/refresh.
Called once from initialize with the result of negotiating
workspace.inlayHint.refreshSupport from ClientCapabilities.
Sourcepub fn code_lens_refresh_supported(&self) -> bool
pub fn code_lens_refresh_supported(&self) -> bool
Returns whether the client supports workspace/codeLens/refresh.
Sourcepub fn set_code_lens_refresh_supported(&self, supported: bool)
pub fn set_code_lens_refresh_supported(&self, supported: bool)
Records whether the client supports workspace/codeLens/refresh.
Called once from initialize with the result of negotiating
workspace.codeLens.refreshSupport from ClientCapabilities.
Sourcepub fn diagnostic_refresh_supported(&self) -> bool
pub fn diagnostic_refresh_supported(&self) -> bool
Returns whether the client supports workspace/diagnostic/refresh.
Sourcepub fn set_diagnostic_refresh_supported(&self, supported: bool)
pub fn set_diagnostic_refresh_supported(&self, supported: bool)
Records whether the client supports workspace/diagnostic/refresh.
Called once from initialize with the result of negotiating
workspace.diagnostics.refreshSupport from ClientCapabilities.
Sourcepub fn spawn_refresh_requests(&self, client: &Client)
pub fn spawn_refresh_requests(&self, client: &Client)
Fires workspace/inlayHint/refresh and workspace/codeLens/refresh as
detached, capability-gated, timeout-bounded background requests (issue #493).
Neither refresh feeds anything downstream (hover/inlay-hint/code-lens handlers recompute on demand from already-committed document state), so a failure or timeout is only logged and never blocks the caller’s critical path — the OSV vulnerability commit and diagnostics publish this is called alongside. The capability gate skips clients that never declared support (and so may never reply); the timeout additionally bounds a client that declares support but stops replying, so detached tasks can’t accumulate without limit.
Sourcepub fn get_document(&self, uri: &Uri) -> Option<Ref<'_, Uri, DocumentState>>
pub fn get_document(&self, uri: &Uri) -> Option<Ref<'_, Uri, DocumentState>>
Retrieves document state by URI.
Returns a read-only reference to the document state if it exists.
The reference holds a lock on the internal map, so it should be
dropped as soon as possible. Prefer Self::with_document when the
caller needs to .await anything afterward — it makes dropping the
guard before the .await structural rather than a convention to remember.
Sourcepub fn with_document<T>(
&self,
uri: &Uri,
extract: impl FnOnce(&DocumentState) -> T,
) -> Option<T>
pub fn with_document<T>( &self, uri: &Uri, extract: impl FnOnce(&DocumentState) -> T, ) -> Option<T>
Extracts owned data from a document without exposing the DashMap shard Ref
to the caller.
extract runs synchronously while the shard lock is held and must return only
owned or Arc-cloned data (e.g. via DocumentState::parse_result_arc); the
Ref this method acquires is dropped before the call returns, so that
particular guard can never leak across an .await through T. This does not by
itself prevent extract from independently capturing and returning some other,
unrelated Ref (e.g. from a second get_document call on state) — extract’s
closure environment is not restricted to this method’s own guard. The
project-wide backstop against the DashMap Ref-across-await hazard (#333) in
general is the await-holding-invalid-types lint configured in the workspace
clippy.toml (#334), not this method’s type signature alone.
§Examples
let content_len = state.with_document(uri, |doc| doc.content.len());Sourcepub fn get_document_clone(&self, uri: &Uri) -> Option<DocumentState>
pub fn get_document_clone(&self, uri: &Uri) -> Option<DocumentState>
Retrieves a cloned copy of document state by URI.
This method clones the document state immediately and releases the DashMap lock, allowing concurrent access to the map while the document is being processed. Use this in hot paths where async operations are performed with the document data.
§Performance
Cloning DocumentState is relatively cheap: String/HashMap metadata is
deep-cloned, but the parse result is an Arc clone (a refcount bump), not a
deep copy of the underlying ecosystem-specific parse data.
§Examples
// Lock released immediately after clone
let doc = state.get_document_clone(uri);
if let Some(doc) = doc {
// Perform async operations without holding lock
let result = process_async(&doc).await;
}Sourcepub fn update_document(&self, uri: Uri, state: DocumentState)
pub fn update_document(&self, uri: Uri, state: DocumentState)
Updates or inserts document state.
If a document already exists at the given URI, it is replaced. Otherwise, a new entry is created.
Sourcepub fn remove_document(&self, uri: &Uri) -> Option<(Uri, DocumentState)>
pub fn remove_document(&self, uri: &Uri) -> Option<(Uri, DocumentState)>
Removes document state and returns the removed entry.
Returns None if no document exists at the given URI.
Sourcepub async fn spawn_background_task(&self, uri: Uri, task: JoinHandle<()>)
pub async fn spawn_background_task(&self, uri: Uri, task: JoinHandle<()>)
Spawns a background task for a document.
If a task already exists for the given URI, it is aborted before the new task is registered. This ensures only one background task runs per document.
Typical use case: fetching version data asynchronously after document open or change.
Sourcepub async fn cancel_background_task(&self, uri: &Uri)
pub async fn cancel_background_task(&self, uri: &Uri)
Cancels the background task for a document.
If no task exists, this is a no-op.
Sourcepub fn document_count(&self) -> usize
pub fn document_count(&self) -> usize
Returns the number of open documents.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for ServerState
impl !RefUnwindSafe for ServerState
impl !UnwindSafe for ServerState
impl Send for ServerState
impl Sync for ServerState
impl Unpin for ServerState
impl UnsafeUnpin for ServerState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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