Skip to content

Commit b39376c

Browse files
committed
Add richer LSP server example (#20017)
1 parent 0ac6559 commit b39376c

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

crates/rust-analyzer/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,7 @@ in-rust-tree = [
106106

107107
[lints]
108108
workspace = true
109+
110+
[[example]]
111+
name = "rust_analyzer_lsp_example"
112+
path = "examples/rust_analyzer_lsp_example/main.rs"
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//! rust-analyzer LSP example
2+
//!
3+
//! A minimal Language Server Protocol server demonstrating how to embed
4+
//! `rust-analyzer` as a library. To run it:
5+
//! ```bash
6+
//! cargo run --example rust_analyzer_lsp_example
7+
//
8+
#![allow(clippy::print_stderr)]
9+
10+
use anyhow::Result;
11+
use lsp_server::{Connection, Message};
12+
use lsp_types::{
13+
CompletionParams, DidChangeTextDocumentParams, DocumentFormattingParams, OneOf,
14+
ServerCapabilities, TextDocumentSyncKind, TextDocumentSyncOptions,
15+
request::{Completion, Formatting, Request as LspRequest},
16+
};
17+
use serde_json::json;
18+
19+
fn main() -> Result<()> {
20+
// Set up a JSON-RPC connection over stdio
21+
let (connection, io_threads) = Connection::stdio();
22+
23+
// Perform the initialize handshake and advertise capabilities
24+
let (init_id, _init_params) = connection.initialize_start()?;
25+
let capabilities = ServerCapabilities {
26+
text_document_sync: Some(
27+
TextDocumentSyncOptions {
28+
change: Some(TextDocumentSyncKind::FULL),
29+
..Default::default()
30+
}
31+
.into(),
32+
),
33+
completion_provider: Some(Default::default()),
34+
document_formatting_provider: Some(OneOf::Left(true)),
35+
..Default::default()
36+
};
37+
connection.initialize_finish(init_id, json!({ "capabilities": capabilities }))?;
38+
39+
// Enter the main message loop
40+
for message in connection.receiver.iter() {
41+
match message {
42+
Message::Notification(notification)
43+
if notification.method == "textDocument/didChange" =>
44+
{
45+
let params: DidChangeTextDocumentParams =
46+
serde_json::from_value(notification.params).unwrap();
47+
eprintln!("Document changed: {}", params.text_document.uri);
48+
}
49+
Message::Request(request) if request.method == Completion::METHOD => {
50+
let _: CompletionParams = serde_json::from_value(request.params).unwrap();
51+
let response = lsp_server::Response::new_ok(
52+
request.id,
53+
json!({ "isIncomplete": false, "items": [] }),
54+
);
55+
connection.sender.send(Message::Response(response)).unwrap();
56+
}
57+
Message::Request(request) if request.method == Formatting::METHOD => {
58+
let _: DocumentFormattingParams = serde_json::from_value(request.params).unwrap();
59+
let response = lsp_server::Response::new_ok(request.id, json!([]));
60+
connection.sender.send(Message::Response(response)).unwrap();
61+
}
62+
Message::Request(request) if connection.handle_shutdown(&request)? => break,
63+
_ => {} // ignore all other messages
64+
}
65+
}
66+
67+
io_threads.join().unwrap();
68+
Ok(())
69+
}

0 commit comments

Comments
 (0)