use lsp_server::{Connection, ExtractError, Message, Request, RequestId, Response};
use lsp_types::{
request::{GotoDefinition, References},
GotoDefinitionResponse, InitializeParams, OneOf, ServerCapabilities,
};
use tracing::{info, trace};
use tracing_subscriber::util::SubscriberInitExt;
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)
}
fn run(connection: Connection, params: serde_json::Value) -> anyhow::Result<()> {
let _params: InitializeParams = serde_json::from_value(params).unwrap();
for msg in &connection.receiver {
trace!("got msg: {:?}", msg);
match msg {
Message::Request(req) => {
if connection.handle_shutdown(&req)? {
return Ok(());
}
trace!("got request: {:?}", req);
match cast::<GotoDefinition>(req.clone()) {
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,
};
match cast::<References>(req.clone()) {
Ok((id, params)) => {
eprintln!("got references request #{}: {:?}", id, params);
let result = Some(Vec::<String>::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) => {
trace!("got response: {:?}", resp);
}
Message::Notification(not) => {
trace!("got notification: {:?}", not);
}
}
}
Ok(())
}
fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_writer(std::io::stderr)
.finish()
.init();
info!("starting LSP server");
let (connection, io_threads) = Connection::stdio();
let server_capabilities = serde_json::to_value(&ServerCapabilities {
definition_provider: Some(OneOf::Left(true)),
references_provider: Some(OneOf::Left(true)),
..Default::default()
})
.unwrap();
let initialization_params = connection.initialize(server_capabilities)?;
run(connection, initialization_params)?;
io_threads.join()?;
info!("shutting down server");
Ok(())
}