pub struct LspProcess { /* private fields */ }Expand description
Handle for managing an LSP server process and its communication.
LspProcess encapsulates the lifecycle of an external Language Server Protocol
process, handling stdin/stdout communication, message serialization/deserialization,
and process monitoring. It’s responsible for the low-level communication with
the language server executable.
§Communication Channels
The process uses two primary communication channels:
- stdin: For sending messages to the LSP server
- stdout: For receiving messages from the LSP server
§Examples
Creating a new process and sending a message:
use lsp_bridge::process::LspProcess;
use lsp_bridge::{LspMessage, LspRequest, protocol::RequestId};
use dashmap::DashMap;
use tokio::process::Command;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::new("rust-analyzer");
let child = cmd.spawn()?;
let pending_requests = Arc::new(DashMap::new());
let server_id = "rust-analyzer".to_string();
// Create the process handler
let process = LspProcess::new(child, pending_requests, server_id)?;
// Send an initialization message
let init_request = LspRequest::with_id(
RequestId::Number(1),
"initialize",
Some(serde_json::json!({})),
);
let init_message = LspMessage::Request(init_request);
process.send_message(init_message)?;
Ok(())
}Implementations§
Source§impl LspProcess
impl LspProcess
Sourcepub fn new(
process: Child,
pending_requests: Arc<DashMap<RequestId, Sender<Result<Value>>>>,
server_id: String,
) -> Result<Self>
pub fn new( process: Child, pending_requests: Arc<DashMap<RequestId, Sender<Result<Value>>>>, server_id: String, ) -> Result<Self>
Creates a new LSP process from a spawned child process.
This function takes ownership of a spawned child process and sets up the communication channels needed for LSP message exchange. It creates two asynchronous tasks:
- A writer task that sends messages to the server process
- A reader task that reads and processes responses from the server
§Arguments
process- The spawned child process for the LSP serverpending_requests- A thread-safe map to track pending requests and their response channelsserver_id- A unique identifier for the server, used in logs and error messages
§Returns
A Result containing the new LspProcess instance or an error if process initialization failed
§Errors
This function will return an error if:
- The child process stdin/stdout cannot be accessed
- The communication channels cannot be established
§Examples
use lsp_bridge::process::LspProcess;
use lsp_bridge::protocol::RequestId;
use dashmap::DashMap;
use serde_json::Value;
use std::sync::Arc;
use tokio::process::Command;
use tokio::sync::oneshot;
#[tokio::main]
async fn main() -> lsp_bridge::Result<()> {
let mut cmd = Command::new("rust-analyzer");
let child = cmd.spawn().expect("Failed to spawn process");
let pending_requests = Arc::new(DashMap::new());
let process = LspProcess::new(child, pending_requests, "rust".to_string())?;
// Process is now ready for communication
Ok(())
}Sourcepub fn send_message(&self, message: LspMessage) -> Result<()>
pub fn send_message(&self, message: LspMessage) -> Result<()>
Sends a message to the LSP server.
This method sends an LSP message to the server process through the message channel. The actual writing to the process stdin is handled by a dedicated writer task.
§Arguments
message- The LSP message to send to the server
§Returns
A Result indicating success or a communication error
§Errors
This function will return an error if the message channel has been closed, which typically means the process has terminated.
§Examples
// Create an initialize request
let initialize_request = LspRequest::with_id(
RequestId::Number(1),
"initialize",
Some(json!({
"capabilities": {
"textDocument": {
"completion": { "dynamicRegistration": true }
}
}
})),
);
let initialize = LspMessage::Request(initialize_request);
// Send the message
process.send_message(initialize)?;Sourcepub async fn kill(&mut self) -> Result<()>
pub async fn kill(&mut self) -> Result<()>
Forcibly terminates the LSP server process.
This method sends a kill signal to the LSP server process. It should be used as a last resort when the server does not respond to the standard shutdown request.
§Returns
A Result indicating success or an error with details
§Errors
This function will return an error if the operating system fails to kill the process. This might happen if the process has already exited or if the current user lacks permissions.
§Examples
// Attempt graceful shutdown first (not shown)
// ...
// If that fails, forcibly kill the process
process.kill().await?;Sourcepub async fn wait(&mut self) -> Result<ExitStatus>
pub async fn wait(&mut self) -> Result<ExitStatus>
Waits for the process to exit and returns its exit status.
This method is useful for monitoring the LSP server process and detecting when it has terminated, either normally or due to a crash.
§Returns
A Result containing the exit status or an error
§Errors
This function will return an error if there’s a problem waiting for the process, such as if the process was not started correctly.
§Examples
// Wait for the process to exit
let status = process.wait().await?;
println!("Process exited with status: {}", status);Sourcepub fn is_running(&mut self) -> bool
pub fn is_running(&mut self) -> bool
Check if the process is still running.
Sourcepub fn parse_content_length(header: &str) -> Option<usize>
pub fn parse_content_length(header: &str) -> Option<usize>
Parse Content-Length header.