auto_lsp_server/
main_loop.rs1use std::panic::RefUnwindSafe;
20
21use crate::{notification_registry::NotificationRegistry, request_registry::RequestRegistry};
22
23use super::Session;
24use anyhow::Error;
25use crossbeam_channel::select;
26use lsp_server::Message;
27
28#[derive(Debug)]
29pub(crate) enum Task {
30 Response(lsp_server::Response),
31 NotificationError(Error),
32}
33
34impl<Db: salsa::Database + Clone + Send + RefUnwindSafe> Session<Db> {
35 pub fn main_loop<'a>(
37 &'a mut self,
38 req_registry: &'a RequestRegistry<Db>,
39 not_registry: &'a NotificationRegistry<Db>,
40 ) -> anyhow::Result<()> {
41 loop {
42 select! {
43 recv(self.connection.receiver) -> msg => {
44 match msg? {
45 Message::Request(req) => {
46 if self.connection.handle_shutdown(&req)? {
47 return Ok(());
48 };
49
50 self.req_queue.incoming.register(req.id.clone(), req.method.clone());
51
52 if let Some(method) = req_registry.get(&req) {
53 RequestRegistry::exec(self, method, req);
54 } else if let Some(method) = req_registry.get_sync_mut(&req) {
55 RequestRegistry::exec_sync_mut(self, method, req)?;
56 } else {
57 RequestRegistry::complete(self,
58 RequestRegistry::<Db>::request_mismatch(req.id.clone(), anyhow::format_err!("Unknown request: {}", req.method))
59 )?
60 }
61 }
62 Message::Notification(not) => {
63 if let Some(method) = not_registry.get(¬) {
64 NotificationRegistry::exec(self, method, not);
65 } else if let Some(method) = not_registry.get_sync_mut(¬) {
66 NotificationRegistry::exec_sync_mut(self, method, not)?;
67 } else {
68 NotificationRegistry::handle_error(self, anyhow::format_err!("Unknown notification: {}", not.method))?
69 }
70 }
71 Message::Response(_) => {}
72 }
73 },
74 recv(self.task_rx) -> task => {
75 match task? {
76 Task::Response(resp) => RequestRegistry::complete(self, resp)?,
77 Task::NotificationError(err) => NotificationRegistry::handle_error(self, err)?,
78 }
79 }
80 }
81 }
82 }
83
84 pub fn send_notification<N: lsp_types::notification::Notification>(
86 &self,
87 params: N::Params,
88 ) -> anyhow::Result<()> {
89 let params = serde_json::to_value(¶ms)?;
90 let n = lsp_server::Notification {
91 method: N::METHOD.into(),
92 params,
93 };
94 self.connection.sender.send(Message::Notification(n))?;
95 Ok(())
96 }
97}