Expand description
§lsp-server-tokio
An async-first Rust crate for building LSP (Language Server Protocol) servers using Tokio.
This crate provides transport-agnostic async LSP server infrastructure that handles protocol concerns so developers can focus on language-specific logic.
§Quick Start
use futures::StreamExt;
use lsp_server_tokio::{Connection, IncomingMessage, Response};
let mut conn = Connection::stdio();
let capabilities = serde_json::json!({
"documentFormattingProvider": true
});
let _client_params = conn.initialize(capabilities).await?;
let sender = conn.client_sender();
while let Some(result) = conn.receiver_mut().next().await {
let msg = result?;
match conn.route(msg) {
IncomingMessage::Request(req, _) if req.method == "shutdown" => {
conn.handle_shutdown(req.id)?;
}
IncomingMessage::Request(req, _) => {
sender.respond(Response::ok(req.id, serde_json::Value::Null))?;
}
IncomingMessage::Notification(notif) if notif.method == "exit" => {
break;
}
IncomingMessage::CancelHandled => {}
IncomingMessage::Notification(_) => {}
IncomingMessage::ResponseRouted | IncomingMessage::ResponseUnknown(_) => {}
_ => {}
}
}§Testing
Use duplex_transport() when you want connected in-memory transports for unit
and integration tests without stdio:
use futures::{SinkExt, StreamExt};
use lsp_server_tokio::{duplex_transport, Message, Request, Response};
let (mut client, mut server) = duplex_transport(4096);
client
.send(Message::Request(Request::new(1, "textDocument/hover", None)))
.await
.unwrap();
if let Some(Ok(Message::Request(req))) = server.next().await {
server
.send(Message::Response(Response::ok(
req.id,
serde_json::json!({"contents": "Hello"}),
)))
.await
.unwrap();
}§Core Types
RequestId- Identifies requests/responses (supports both integer and string IDs)ErrorCode- LSP specification error codesResponseError- Error responses with code, message, and optional dataMessage- Discriminated union of Request, Response, and NotificationRequest- JSON-RPC request with id and methodResponse- JSON-RPC response with result or errorNotification- JSON-RPC notification (no id, no response)
§Transport Layer
Transport- Type alias forFramed<T, LspCodec>providing Stream + Sinktransport()- Factory function wrapping anyAsyncRead+AsyncWriteduplex_transport()- Creates connected in-memory transports for testingLspCodec- Encoder/Decoder for Content-Length message framing
§Request Routing
The IncomingMessage enum classifies messages received from Connection::route():
IncomingMessage::Request- A request with automaticCancellationTokenfor cooperative cancellationIncomingMessage::Notification- A notification (no response expected)IncomingMessage::CancelHandled- A$/cancelRequestthat was applied automaticallyIncomingMessage::ResponseRouted- A response delivered to an awaiting receiverIncomingMessage::ResponseUnknown- A response for an unknown request ID
Structs§
- Cancellation
Token - A token which can be used to signal a cancellation request to one or more tasks.
- Client
Sender - A cloneable, non-blocking handle for server→client communication.
- Connection
- A bidirectional LSP connection with split sender/receiver and request tracking.
- Incoming
Requests - Tracks requests received from clients (incoming to the server).
- LspCodec
- LSP wire protocol codec implementing Content-Length framing.
- Message
Stream - The receiver half of an LSP connection.
- Notification
- A JSON-RPC 2.0 notification message.
- Outgoing
Requests - Tracks requests sent to clients (outgoing from the server).
- Request
- A JSON-RPC 2.0 request message.
- Request
Queue - Combined request queue tracking both incoming and outgoing requests.
- Response
- A JSON-RPC 2.0 response message.
- Response
Error - An error response in JSON-RPC format.
- Send
Error - Error returned when the connection is closed and messages can no longer be queued.
- Stdio
Transport - A combined stdin/stdout stream for LSP server communication.
Enums§
- Error
Code - LSP and JSON-RPC 2.0 error codes.
- Exit
Code - Exit code for the LSP server process.
- Incoming
Message - Represents a classified incoming message after routing.
- Lifecycle
State - Represents the lifecycle state of an LSP connection.
- Message
- A JSON-RPC 2.0 message that can be a Request, Response, or Notification.
- Protocol
Error - Errors that occur during LSP protocol lifecycle management.
- Request
Id - A request identifier that can be either an integer or a string.
- Response
Body - The payload of a JSON-RPC 2.0 response — either a success result or an error.
Constants§
- CANCEL_
REQUEST_ METHOD - The method name for cancel request notifications per LSP specification.
Functions§
- cancelled_
response - Creates a
RequestCancellederror response for a cancelled request. - duplex_
transport - Creates a pair of connected in-memory transports for testing.
- method_
not_ found_ response - Creates a
MethodNotFounderror response for an unhandled request. - parse_
cancel_ params - Parses the request ID from $/cancelRequest notification params.
- transport
- Creates an LSP transport from an async I/O stream.
Type Aliases§
- Stdio
Connection - A
Connectionbacked byStdioTransport. - Transport
- A bidirectional LSP transport over any async I/O stream.