mod backend;
mod cancel;
mod code_action;
mod completion;
mod diagnostic;
mod execute;
mod folding_range;
pub(crate) mod formatting;
mod hover;
mod identification;
pub(crate) mod indent;
mod jump;
mod lifecycle;
mod misc;
mod on_type_formatting;
mod parse_tree;
pub(crate) mod semantic_tokens;
mod settings;
mod textdocument_synchronization;
mod workspace;
use std::rc::Rc;
use backend::{
handle_add_backend_notification, handle_list_backends_request, handle_ping_backend_request,
handle_update_backend_default_notification,
};
use code_action::handle_codeaction_request;
use completion::handle_completion_request;
use diagnostic::handle_diagnostic_request;
use futures::lock::Mutex;
use hover::handle_hover_request;
use jump::handle_jump_request;
use lifecycle::{
handle_exit_notification, handle_initialize_request, handle_initialized_notification,
handle_shutdown_request,
};
use textdocument_synchronization::{
handle_did_change_notification, handle_did_open_notification, handle_did_save_notification,
};
use workspace::handle_workspace_edit_response;
#[cfg(not(target_arch = "wasm32"))]
use tokio::task::spawn_local;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_futures::spawn_local;
use crate::server::{
handle_error,
lsp::errors::ErrorCode,
message_handler::{
backend::handle_get_backend_request,
cancel::handle_cancel_notification,
execute::handle_execute_request,
folding_range::handle_folding_range_request,
identification::handle_identify_request,
parse_tree::handle_parse_tree_request,
semantic_tokens::{
handle_semantic_tokens_full_request, handle_semantic_tokens_range_request,
},
settings::{handle_change_settings_notification, handle_default_settings_request},
},
};
use self::formatting::handle_format_request;
use self::on_type_formatting::handle_on_type_format_request;
use super::{
Server,
lsp::{errors::LSPError, rpc::deserialize_message},
};
pub(super) async fn dispatch(
server_rc: Rc<Mutex<Server>>,
message_string: &str,
) -> Result<(), LSPError> {
let message = deserialize_message(message_string)?;
let method = message.get_method().unwrap_or("response");
macro_rules! call {
($handler:ident) => {{
let message = message.parse()?;
$handler(server_rc, message).await
}};
}
macro_rules! call_async {
($handler:ident) => {{
let message_copy = message_string.to_string();
let _task = spawn_local(async move {
let message = message.parse().unwrap();
if let Err(err) = $handler(server_rc.clone(), message).await {
handle_error(server_rc, &message_copy, err).await;
}
});
#[cfg(not(target_arch = "wasm32"))]
_task.await.expect("local task should not crash");
Ok(())
}};
}
match method {
"initialize" => call!(handle_initialize_request),
"shutdown" => call!(handle_shutdown_request),
"textDocument/formatting" => call!(handle_format_request),
"textDocument/onTypeFormatting" => call!(handle_on_type_format_request),
"textDocument/diagnostic" => call!(handle_diagnostic_request),
"textDocument/codeAction" => call!(handle_codeaction_request),
"textDocument/hover" => call_async!(handle_hover_request),
"textDocument/completion" => call_async!(handle_completion_request),
"textDocument/foldingRange" => call!(handle_folding_range_request),
"textDocument/semanticTokens/full" => call!(handle_semantic_tokens_full_request),
"textDocument/semanticTokens/range" => call!(handle_semantic_tokens_range_request),
"qlueLs/addBackend" => call!(handle_add_backend_notification),
"qlueLs/getBackend" => call!(handle_get_backend_request),
"qlueLs/listBackends" => call!(handle_list_backends_request),
"qlueLs/updateDefaultBackend" => call!(handle_update_backend_default_notification),
"qlueLs/pingBackend" => call_async!(handle_ping_backend_request),
"qlueLs/jump" => call!(handle_jump_request),
"qlueLs/parseTree" => call!(handle_parse_tree_request),
"qlueLs/identifyOperationType" => call!(handle_identify_request),
"qlueLs/defaultSettings" => call!(handle_default_settings_request),
"qlueLs/executeOperation" => call_async!(handle_execute_request),
"initialized" => call!(handle_initialized_notification),
"exit" => call!(handle_exit_notification),
"textDocument/didOpen" => call!(handle_did_open_notification),
"textDocument/didChange" => call!(handle_did_change_notification),
"textDocument/didSave" => call!(handle_did_save_notification),
"qlueLs/changeSettings" => call!(handle_change_settings_notification),
"qlueLs/cancelQuery" => call_async!(handle_cancel_notification),
"response" => {
call!(handle_workspace_edit_response)
}
"$/cancelRequest" => {
tracing::warn!("Received cancel request (unsupported)");
Ok(())
}
"$/setTrace" => {
tracing::warn!("Received setTrace request (unsupported)");
Ok(())
}
unknown_method => {
tracing::warn!(
"Received message with unknown method \"{}\"",
unknown_method
);
Err(LSPError::new(
ErrorCode::MethodNotFound,
&format!("Method \"{}\" currently not supported", unknown_method),
))
}
}
}