pub struct LspClient { /* private fields */ }Expand description
LSP client with async request/response handling.
This client manages communication with an LSP server, handling:
- Concurrent requests with unique ID tracking
- Background message loop for receiving responses
- Timeout support for all requests
- Graceful shutdown
Implementations§
Source§impl LspClient
impl LspClient
Sourcepub fn new(config: LspServerConfig) -> Self
pub fn new(config: LspServerConfig) -> Self
Create a new LSP client with the given configuration.
The client starts in an uninitialized state. Call initialize() to
start the server and complete the initialization handshake.
Sourcepub fn language_id(&self) -> &str
pub fn language_id(&self) -> &str
Get the language ID for this client.
Sourcepub async fn state(&self) -> ServerState
pub async fn state(&self) -> ServerState
Get the current server state.
Sourcepub fn request_timeout(&self) -> Duration
pub fn request_timeout(&self) -> Duration
The timeout applied to a single LSP request attempt, derived from
LspServerConfig::request_timeout_seconds.
This bounds one attempt, not a whole tool call: Self::request
retries up to SERVER_CANCELLED_MAX_RETRIES (3) additional times on a
-32802 (ServerCancelled) response, so the worst-case latency for a
single tool call is 4 * request_timeout() + 3.5s (the sum of the
retry backoff delays).
The configured value is clamped to the range from 1 second to
MAX_TIMEOUT_SECONDS. crate::serve/crate::serve_with now
validate the top-level ServerConfig (via ServerConfig::validate,
which rejects request_timeout_seconds that is 0 or greater than
MAX_TIMEOUT_SECONDS) regardless of whether it came from
ServerConfig::load_from or was built programmatically by the
caller. But Self::new, super::LspServer::spawn, and
super::LspServer::spawn_batch are all pub and take an
LspServerConfig (or super::ServerInitConfig wrapping one)
directly, bypassing that top-level validation entirely — it operates
on the top-level ServerConfig, not the per-server one. This clamp is
the last line of defense against a zero-duration timeout that would
fail every request instantly, or an astronomically large one that
tokio’s timeout/sleep would silently treat as unbounded (they fall
back to Instant::far_future() rather than panicking), for a caller
reaching either of these levels directly.
§Examples
use std::time::Duration;
use mcpls_core::config::LspServerConfig;
use mcpls_core::lsp::LspClient;
let mut config = LspServerConfig::rust_analyzer();
config.request_timeout_seconds = 45;
let client = LspClient::new(config);
assert_eq!(client.request_timeout(), Duration::from_secs(45));Sourcepub fn completion_timeout(&self) -> Duration
pub fn completion_timeout(&self) -> Duration
The timeout applied to completion (textDocument/completion) requests.
Equal to Self::request_timeout, capped at 10 seconds. Completions
cannot be configured above this cap by any
value of request_timeout_seconds — if that proves insufficient in
practice, the fix is a dedicated completion_timeout_seconds field,
not raising this cap.
§Examples
use std::time::Duration;
use mcpls_core::config::LspServerConfig;
use mcpls_core::lsp::LspClient;
let mut config = LspServerConfig::rust_analyzer();
config.request_timeout_seconds = 300;
let client = LspClient::new(config);
// Capped at 10s even though request_timeout_seconds is 300.
assert_eq!(client.completion_timeout(), Duration::from_secs(10));
assert!(client.completion_timeout() <= client.request_timeout());Sourcepub async fn request<P, R>(
&self,
method: &str,
params: P,
timeout_duration: Duration,
) -> Result<R>where
P: Serialize,
R: DeserializeOwned,
pub async fn request<P, R>(
&self,
method: &str,
params: P,
timeout_duration: Duration,
) -> Result<R>where
P: Serialize,
R: DeserializeOwned,
Send request and wait for response with timeout.
Automatically retries up to 3 times when the server returns error code
-32802 (ServerCancelled) with data.retriggerRequest == true, using
exponential backoff starting at 500 ms.
§Type Parameters
P- The type of the request parameters (must be serializable)R- The type of the response result (must be deserializable)
§Errors
Returns an error if:
- Server has shut down
- Request times out
- Response cannot be deserialized
- LSP server returns an error
Trait Implementations§
Source§impl Clone for LspClient
impl Clone for LspClient
Source§fn clone(&self) -> Self
fn clone(&self) -> Self
Creates a clone that shares the underlying connection.
The clone does not own the receiver task and cannot perform shutdown. All clones share the same command channel for sending requests.
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more