mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-12-15 21:34:19 +00:00
internal: vendor lsp-server
This commit is contained in:
parent
06448c5548
commit
57cb65bb7a
18 changed files with 946 additions and 9 deletions
121
lib/lsp-server/examples/goto_def.rs
Normal file
121
lib/lsp-server/examples/goto_def.rs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
//! A minimal example LSP server that can only respond to the `gotoDefinition` request. To use
|
||||
//! this example, execute it and then send an `initialize` request.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! Content-Length: 85
|
||||
//!
|
||||
//! {"jsonrpc": "2.0", "method": "initialize", "id": 1, "params": {"capabilities": {}}}
|
||||
//! ```
|
||||
//!
|
||||
//! This will respond with a server response. Then send it a `initialized` notification which will
|
||||
//! have no response.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! Content-Length: 59
|
||||
//!
|
||||
//! {"jsonrpc": "2.0", "method": "initialized", "params": {}}
|
||||
//! ```
|
||||
//!
|
||||
//! Once these two are sent, then we enter the main loop of the server. The only request this
|
||||
//! example can handle is `gotoDefinition`:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! Content-Length: 159
|
||||
//!
|
||||
//! {"jsonrpc": "2.0", "method": "textDocument/definition", "id": 2, "params": {"textDocument": {"uri": "file://temp"}, "position": {"line": 1, "character": 1}}}
|
||||
//! ```
|
||||
//!
|
||||
//! To finish up without errors, send a shutdown request:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! Content-Length: 67
|
||||
//!
|
||||
//! {"jsonrpc": "2.0", "method": "shutdown", "id": 3, "params": null}
|
||||
//! ```
|
||||
//!
|
||||
//! The server will exit the main loop and finally we send a `shutdown` notification to stop
|
||||
//! the server.
|
||||
//!
|
||||
//! ```
|
||||
//! Content-Length: 54
|
||||
//!
|
||||
//! {"jsonrpc": "2.0", "method": "exit", "params": null}
|
||||
//! ```
|
||||
use std::error::Error;
|
||||
|
||||
use lsp_types::OneOf;
|
||||
use lsp_types::{
|
||||
request::GotoDefinition, GotoDefinitionResponse, InitializeParams, ServerCapabilities,
|
||||
};
|
||||
|
||||
use lsp_server::{Connection, ExtractError, Message, Request, RequestId, Response};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
|
||||
// Note that we must have our logging only write out to stderr.
|
||||
eprintln!("starting generic LSP server");
|
||||
|
||||
// Create the transport. Includes the stdio (stdin and stdout) versions but this could
|
||||
// also be implemented to use sockets or HTTP.
|
||||
let (connection, io_threads) = Connection::stdio();
|
||||
|
||||
// Run the server and wait for the two threads to end (typically by trigger LSP Exit event).
|
||||
let server_capabilities = serde_json::to_value(&ServerCapabilities {
|
||||
definition_provider: Some(OneOf::Left(true)),
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap();
|
||||
let initialization_params = connection.initialize(server_capabilities)?;
|
||||
main_loop(connection, initialization_params)?;
|
||||
io_threads.join()?;
|
||||
|
||||
// Shut down gracefully.
|
||||
eprintln!("shutting down server");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main_loop(
|
||||
connection: Connection,
|
||||
params: serde_json::Value,
|
||||
) -> Result<(), Box<dyn Error + Sync + Send>> {
|
||||
let _params: InitializeParams = serde_json::from_value(params).unwrap();
|
||||
eprintln!("starting example main loop");
|
||||
for msg in &connection.receiver {
|
||||
eprintln!("got msg: {:?}", msg);
|
||||
match msg {
|
||||
Message::Request(req) => {
|
||||
if connection.handle_shutdown(&req)? {
|
||||
return Ok(());
|
||||
}
|
||||
eprintln!("got request: {:?}", req);
|
||||
match cast::<GotoDefinition>(req) {
|
||||
Ok((id, params)) => {
|
||||
eprintln!("got gotoDefinition request #{}: {:?}", id, params);
|
||||
let result = Some(GotoDefinitionResponse::Array(Vec::new()));
|
||||
let result = serde_json::to_value(&result).unwrap();
|
||||
let resp = Response { id, result: Some(result), error: None };
|
||||
connection.sender.send(Message::Response(resp))?;
|
||||
continue;
|
||||
}
|
||||
Err(err @ ExtractError::JsonError { .. }) => panic!("{:?}", err),
|
||||
Err(ExtractError::MethodMismatch(req)) => req,
|
||||
};
|
||||
// ...
|
||||
}
|
||||
Message::Response(resp) => {
|
||||
eprintln!("got response: {:?}", resp);
|
||||
}
|
||||
Message::Notification(not) => {
|
||||
eprintln!("got notification: {:?}", not);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cast<R>(req: Request) -> Result<(RequestId, R::Params), ExtractError<Request>>
|
||||
where
|
||||
R: lsp_types::request::Request,
|
||||
R::Params: serde::de::DeserializeOwned,
|
||||
{
|
||||
req.extract(R::METHOD)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue