use std::error::Error;
use log::error;
use lsp_server::{Request, Response};
use lsp_types::request::{
CallHierarchyIncomingCalls, CallHierarchyOutgoingCalls, CallHierarchyPrepare,
CodeActionRequest, Completion, DocumentDiagnosticRequest, DocumentHighlightRequest,
DocumentLinkRequest, DocumentSymbolRequest, FoldingRangeRequest, Formatting, GotoDefinition,
GotoImplementation, GotoTypeDefinition, HoverRequest, InlayHintRequest, PrepareRenameRequest,
RangeFormatting, References, Rename, Request as LspRequest, ResolveCompletionItem,
SelectionRangeRequest, SemanticTokensFullRequest, SignatureHelpRequest, WillSaveWaitUntil,
WorkspaceSymbolRequest,
};
use crate::context::ServerContext;
use super::{
call_hierarchy::{on_incoming_calls, on_outgoing_calls, on_prepare_call_hierarchy},
code_action::on_code_action,
completion::{on_completion, on_completion_resolve},
definition::on_goto_definition_handler,
diagnostic::on_pull_document_diagnostic,
document_highlight::on_document_highlight,
document_link::on_document_link,
document_symbol::on_document_symbol,
folding_range::on_folding_range,
formatting::{on_formatting, on_range_formatting, on_will_save_wait_until},
hover::on_hover,
implementation::on_goto_implementation,
inlay_hint::on_inlay_hint,
references::on_references,
rename::{on_prepare_rename, on_rename},
selection_range::on_selection_range,
semantic_token::on_semantic_tokens,
signature_help::on_signature_help,
switch_source_header::{SwitchSourceHeader, on_switch_source_header},
type_definition::on_goto_type_definition,
workspace_symbol::on_workspace_symbol,
};
macro_rules! dispatch_request {
($request:expr, $context:expr, {
$($req_type:ty => $handler:expr),* $(,)?
}) => {
match $request.method.as_str() {
$(
<$req_type>::METHOD => {
let request_id = $request.id.clone();
match $request.extract::<<$req_type as LspRequest>::Params>(<$req_type>::METHOD) {
Ok((id, params)) => {
let snapshot = $context.snapshot();
let upto = snapshot.inbox().queued();
$context.task(id.clone(), move |cancel_token| {
let snapshot = snapshot.clone();
async move {
crate::context::catch_up_upto(&snapshot, upto).await;
$handler(snapshot, params, cancel_token).await
}
}).await;
return Ok(());
}
Err(error) => {
log::error!(
"the params of {} could not be read: {error}",
<$req_type>::METHOD
);
let response = Response::new_err(
request_id,
lsp_server::ErrorCode::InvalidParams as i32,
format!("{error}"),
);
$context.send(response);
return Ok(());
}
}
}
)*
method => {
error!("handler not found for request: {}", method);
let response = Response::new_err(
$request.id.clone(),
lsp_server::ErrorCode::MethodNotFound as i32,
"handler not found".to_string(),
);
$context.send(response);
}
}
};
}
pub async fn on_request_handler(
req: Request,
server_context: &mut ServerContext,
) -> Result<(), Box<dyn Error + Sync + Send>> {
log::debug!("dispatch: {} entering", req.method);
dispatch_request!(req, server_context, {
GotoDefinition => on_goto_definition_handler,
GotoImplementation => on_goto_implementation,
GotoTypeDefinition => on_goto_type_definition,
HoverRequest => on_hover,
CallHierarchyPrepare => on_prepare_call_hierarchy,
CallHierarchyIncomingCalls => on_incoming_calls,
CallHierarchyOutgoingCalls => on_outgoing_calls,
CodeActionRequest => on_code_action,
Completion => on_completion,
ResolveCompletionItem => on_completion_resolve,
DocumentHighlightRequest => on_document_highlight,
DocumentLinkRequest => on_document_link,
DocumentSymbolRequest => on_document_symbol,
Formatting => on_formatting,
RangeFormatting => on_range_formatting,
WillSaveWaitUntil => on_will_save_wait_until,
FoldingRangeRequest => on_folding_range,
InlayHintRequest => on_inlay_hint,
References => on_references,
SelectionRangeRequest => on_selection_range,
SemanticTokensFullRequest => on_semantic_tokens,
SignatureHelpRequest => on_signature_help,
SwitchSourceHeader => on_switch_source_header,
PrepareRenameRequest => on_prepare_rename,
Rename => on_rename,
WorkspaceSymbolRequest => on_workspace_symbol,
DocumentDiagnosticRequest => on_pull_document_diagnostic,
});
log::debug!("dispatch: returned");
Ok(())
}