3 releases

0.1.2 Dec 16, 2024
0.1.1 Nov 5, 2024
0.1.0 Sep 25, 2024

#1210 in Development tools

Download history 150/week @ 2024-09-23 17/week @ 2024-09-30 5/week @ 2024-10-07 21/week @ 2024-10-14 147/week @ 2024-11-04 2/week @ 2024-11-11 12/week @ 2024-11-18 143/week @ 2024-12-16

144 downloads per month

MIT license

20KB
318 lines

async lsp client

The client used to connect to the LSP server.

It starts a new process as the LSP server and uses the standard input and output as a channel, connects and controls to send requests, responses, and notifications, and receives requests or notifications from the LSP server.

Based on tower-lsp, we have designed a series of concise APIs for accessing the LSP server. At the same time, it supports request cancellation for tower-lsp.

Usage

Create a lsp server

let (server, rx) = LspServer::new("deno", ["lsp"]);

Lifecycle Message

// initialize request
let initializeResult = server.initialize(initializeParams).await;
// initialized notification
server.initialized();
// shutdown request
server.shutdown();
// exit notification
server.exit();

Document Synchronization

// DidOpenTextDocument
server.send_notification::<DidOpenTextDocument>(DidOpenTextDocumentParams { ... }).await;
// DidChangeTextDocument
server.send_notification::<DidChangeTextDocument>(DidChangeTextDocumentParams { ... }).await;
// DidCloseTextDocument
server.send_notification::<DidCloseTextDocument>(DidCloseTextDocumentParams { ... }).await;
// other

Language Features

// hover
server.send_request::<HoverRequest>(HoverParams { ... }).await;
// completion
server.send_request::<Completion>(CompletionParams { ... }).await;
// goto definition
server.send_request::<GotoDefinition>(GotoDefinitionParams { ... }).await;
// other

Receive requests and notifications from the server

The rx is used to receive messages from the server. Usually, the message is received in another thread.

let server_ = server.clone(); // Clone the server is used to move.
tokio::spawn(async move {
    loop {
        if let Some(message) = rx.recv().await {
            // Process messages
            match message {
                ServerMessage::Notification(_) => {},
                // For requests, you need to send a response
                ServerMessage::Request(req) => {
                    let id = req.id().unwrap().clone();
                    match req.method() {
                        WorkspaceConfiguration::METHOD => {
                            server_.send_response::<WorkspaceConfiguration>(id, vec![])
                                .await
                        }
                        WorkDoneProgressCreate::METHOD => {
                            server_
                                .send_response::<WorkDoneProgressCreate>(id, ())
                                .await;
                        }
                        _ => {
                            server_
                                .send_error_response(
                                    id,
                                    jsonrpc::Error {
                                        code: jsonrpc::ErrorCode::MethodNotFound,
                                        message: std::borrow::Cow::Borrowed("Method Not Found"),
                                        data: req.params().cloned(),
                                    },
                                )
                                .await;
                        }
                    }
                }
            }
        } else {
            break;
        }
    }
});

rust features

  • tracing enable this feature uses the debug! macro of the tracing package to output messages between the server and the client.

Dependencies

~8–18MB
~224K SLoC