]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/lib/lsp-server/examples/goto_def.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / src / tools / rust-analyzer / lib / lsp-server / examples / goto_def.rs
CommitLineData
064997fb
FG
1//! A minimal example LSP server that can only respond to the `gotoDefinition` request. To use
2//! this example, execute it and then send an `initialize` request.
3//!
4//! ```no_run
5//! Content-Length: 85
6//!
7//! {"jsonrpc": "2.0", "method": "initialize", "id": 1, "params": {"capabilities": {}}}
8//! ```
9//!
10//! This will respond with a server response. Then send it a `initialized` notification which will
11//! have no response.
12//!
13//! ```no_run
14//! Content-Length: 59
15//!
16//! {"jsonrpc": "2.0", "method": "initialized", "params": {}}
17//! ```
18//!
19//! Once these two are sent, then we enter the main loop of the server. The only request this
20//! example can handle is `gotoDefinition`:
21//!
22//! ```no_run
23//! Content-Length: 159
24//!
25//! {"jsonrpc": "2.0", "method": "textDocument/definition", "id": 2, "params": {"textDocument": {"uri": "file://temp"}, "position": {"line": 1, "character": 1}}}
26//! ```
27//!
28//! To finish up without errors, send a shutdown request:
29//!
30//! ```no_run
31//! Content-Length: 67
32//!
33//! {"jsonrpc": "2.0", "method": "shutdown", "id": 3, "params": null}
34//! ```
35//!
36//! The server will exit the main loop and finally we send a `shutdown` notification to stop
37//! the server.
38//!
39//! ```
40//! Content-Length: 54
41//!
42//! {"jsonrpc": "2.0", "method": "exit", "params": null}
43//! ```
44use std::error::Error;
45
46use lsp_types::OneOf;
47use lsp_types::{
48 request::GotoDefinition, GotoDefinitionResponse, InitializeParams, ServerCapabilities,
49};
50
51use lsp_server::{Connection, ExtractError, Message, Request, RequestId, Response};
52
53fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
54 // Note that we must have our logging only write out to stderr.
55 eprintln!("starting generic LSP server");
56
57 // Create the transport. Includes the stdio (stdin and stdout) versions but this could
58 // also be implemented to use sockets or HTTP.
59 let (connection, io_threads) = Connection::stdio();
60
61 // Run the server and wait for the two threads to end (typically by trigger LSP Exit event).
62 let server_capabilities = serde_json::to_value(&ServerCapabilities {
63 definition_provider: Some(OneOf::Left(true)),
64 ..Default::default()
65 })
66 .unwrap();
67 let initialization_params = connection.initialize(server_capabilities)?;
68 main_loop(connection, initialization_params)?;
69 io_threads.join()?;
70
71 // Shut down gracefully.
72 eprintln!("shutting down server");
73 Ok(())
74}
75
76fn main_loop(
77 connection: Connection,
78 params: serde_json::Value,
79) -> Result<(), Box<dyn Error + Sync + Send>> {
80 let _params: InitializeParams = serde_json::from_value(params).unwrap();
81 eprintln!("starting example main loop");
82 for msg in &connection.receiver {
6522a427 83 eprintln!("got msg: {msg:?}");
064997fb
FG
84 match msg {
85 Message::Request(req) => {
86 if connection.handle_shutdown(&req)? {
87 return Ok(());
88 }
6522a427 89 eprintln!("got request: {req:?}");
064997fb
FG
90 match cast::<GotoDefinition>(req) {
91 Ok((id, params)) => {
6522a427 92 eprintln!("got gotoDefinition request #{id}: {params:?}");
064997fb
FG
93 let result = Some(GotoDefinitionResponse::Array(Vec::new()));
94 let result = serde_json::to_value(&result).unwrap();
95 let resp = Response { id, result: Some(result), error: None };
96 connection.sender.send(Message::Response(resp))?;
97 continue;
98 }
6522a427 99 Err(err @ ExtractError::JsonError { .. }) => panic!("{err:?}"),
064997fb
FG
100 Err(ExtractError::MethodMismatch(req)) => req,
101 };
102 // ...
103 }
104 Message::Response(resp) => {
6522a427 105 eprintln!("got response: {resp:?}");
064997fb
FG
106 }
107 Message::Notification(not) => {
6522a427 108 eprintln!("got notification: {not:?}");
064997fb
FG
109 }
110 }
111 }
112 Ok(())
113}
114
115fn cast<R>(req: Request) -> Result<(RequestId, R::Params), ExtractError<Request>>
116where
117 R: lsp_types::request::Request,
118 R::Params: serde::de::DeserializeOwned,
119{
120 req.extract(R::METHOD)
121}