1#[cfg(feature = "dap")]
4mod dap_srv;
5
6#[cfg(feature = "lsp")]
7mod lsp_srv;
8
9use core::fmt;
10use std::any::Any;
11use std::collections::HashMap;
12use std::path::{Path, PathBuf};
13use std::pin::Pin;
14use std::sync::atomic::AtomicI32;
15#[cfg(feature = "web")]
16use std::sync::atomic::AtomicU32;
17use std::sync::{Arc, Weak};
18
19use futures::future::MaybeDone;
20use parking_lot::Mutex;
21use serde::Serialize;
22use serde_json::{Value as JsonValue, from_value};
23use tinymist_std::time::Time;
24
25use crate::msg::*;
26use crate::req_queue;
27use crate::*;
28
29type ImmutPath = Arc<Path>;
30
31pub type ResponseFuture<T> = MaybeDone<Pin<Box<dyn std::future::Future<Output = T> + Send>>>;
33pub type LspResponseFuture<T> = LspResult<ResponseFuture<T>>;
35pub type SchedulableResponse<T> = LspResponseFuture<LspResult<T>>;
37pub type AnySchedulableResponse = SchedulableResponse<JsonValue>;
39pub type ScheduleResult = AnySchedulableResponse;
41pub type ScheduledResult = LspResult<Option<()>>;
47
48pub type ConnectionTx = TConnectionTx<Message>;
50pub type ConnectionRx = TConnectionRx<Message>;
52
53#[derive(Debug, Clone)]
55pub struct TConnectionTx<M> {
56 pub event: crossbeam_channel::Sender<Event>,
58 pub lsp: crossbeam_channel::Sender<Message>,
60 pub(crate) marker: std::marker::PhantomData<M>,
61}
62
63#[derive(Debug, Clone)]
65pub struct TConnectionRx<M> {
66 pub event: crossbeam_channel::Receiver<Event>,
68 pub lsp: crossbeam_channel::Receiver<Message>,
70 pub(crate) marker: std::marker::PhantomData<M>,
71}
72
73impl<M: TryFrom<Message, Error = anyhow::Error>> TConnectionRx<M> {
74 pub fn recv(&self) -> anyhow::Result<EventOrMessage<M>> {
76 crossbeam_channel::select_biased! {
77 recv(self.lsp) -> msg => Ok(EventOrMessage::Msg(msg?.try_into()?)),
78 recv(self.event) -> event => Ok(event.map(EventOrMessage::Evt)?),
79 }
80 }
81}
82
83pub enum EventOrMessage<M> {
85 Evt(Event),
87 Msg(M),
89}
90
91pub struct Connection<M> {
93 pub sender: TConnectionTx<M>,
95 pub receiver: TConnectionRx<M>,
97}
98
99impl<M> Connection<M> {
100 pub fn channel() -> Self {
102 let (event_sender, event_receiver) = crossbeam_channel::unbounded::<crate::Event>();
103 let (lsp_sender, lsp_receiver) = crossbeam_channel::unbounded::<Message>();
104 Self {
105 sender: TConnectionTx {
106 event: event_sender,
107 lsp: lsp_sender,
108 marker: std::marker::PhantomData,
109 },
110 receiver: TConnectionRx {
111 event: event_receiver,
112 lsp: lsp_receiver,
113 marker: std::marker::PhantomData,
114 },
115 }
116 }
117}
118
119impl<M: TryFrom<Message, Error = anyhow::Error>> From<Connection<Message>> for Connection<M> {
120 fn from(conn: Connection<Message>) -> Self {
121 Self {
122 sender: TConnectionTx {
123 event: conn.sender.event,
124 lsp: conn.sender.lsp,
125 marker: std::marker::PhantomData,
126 },
127 receiver: TConnectionRx {
128 event: conn.receiver.event,
129 lsp: conn.receiver.lsp,
130 marker: std::marker::PhantomData,
131 },
132 }
133 }
134}
135
136impl<M: TryFrom<Message, Error = anyhow::Error>> From<TConnectionTx<M>> for ConnectionTx {
137 fn from(conn: TConnectionTx<M>) -> Self {
138 Self {
139 event: conn.event,
140 lsp: conn.lsp,
141 marker: std::marker::PhantomData,
142 }
143 }
144}
145
146type AnyCaster<S> = Arc<dyn Fn(&mut dyn Any) -> &mut S + Send + Sync>;
147
148pub struct TypedLspClient<S> {
150 client: LspClient,
151 caster: AnyCaster<S>,
152}
153
154impl<S> TypedLspClient<S> {
155 pub fn to_untyped(self) -> LspClient {
157 self.client
158 }
159}
160
161impl<S: 'static> TypedLspClient<S> {
162 pub fn untyped(&self) -> &LspClient {
164 &self.client
165 }
166
167 pub fn cast<T: 'static>(&self, f: fn(&mut S) -> &mut T) -> TypedLspClient<T> {
169 let caster = self.caster.clone();
170 TypedLspClient {
171 client: self.client.clone(),
172 caster: Arc::new(move |s| f(caster(s))),
173 }
174 }
175
176 pub fn send_event<T: std::any::Any + Send + 'static>(&self, event: T) {
178 self.sender.send_event(event);
179 }
180}
181
182impl<S> Clone for TypedLspClient<S> {
183 fn clone(&self) -> Self {
184 Self {
185 client: self.client.clone(),
186 caster: self.caster.clone(),
187 }
188 }
189}
190
191impl<S> std::ops::Deref for TypedLspClient<S> {
192 type Target = LspClient;
193
194 fn deref(&self) -> &Self::Target {
195 &self.client
196 }
197}
198
199#[derive(Debug, Clone)]
204pub struct LspClientRoot {
205 weak: LspClient,
206 _strong: Arc<ConnectionTx>,
207}
208
209impl LspClientRoot {
210 pub fn new<M: TryFrom<Message, Error = anyhow::Error> + GetMessageKind>(
212 handle: tokio::runtime::Handle,
213 sender: TConnectionTx<M>,
214 ) -> Self {
215 let _strong = Arc::new(sender.into());
216 let weak = LspClient {
217 handle,
218 msg_kind: M::MESSAGE_KIND,
219 sender: TransportHost::System(SystemTransportSender {
220 sender: Arc::downgrade(&_strong),
221 }),
222 req_queue: Arc::new(Mutex::new(ReqQueue::default())),
223
224 hook: Arc::new(()),
225 };
226 Self { weak, _strong }
227 }
228
229 #[cfg(feature = "web")]
231 pub fn new_js(handle: tokio::runtime::Handle, sender: JsTransportSender) -> Self {
232 let dummy = dummy_transport::<LspMessage>();
233
234 let _strong = Arc::new(dummy.sender.into());
235 let weak = LspClient {
236 handle,
237 msg_kind: LspMessage::MESSAGE_KIND,
238 sender: TransportHost::Js {
239 event_id: Arc::new(AtomicU32::new(0)),
240 events: Arc::new(Mutex::new(HashMap::new())),
241 sender,
242 },
243 req_queue: Arc::new(Mutex::new(ReqQueue::default())),
244
245 hook: Arc::new(()),
246 };
247 Self { weak, _strong }
248 }
249
250 pub fn with_hook(mut self, hook: Arc<dyn LsHook>) -> Self {
252 self.weak.hook = hook;
253 self
254 }
255
256 pub fn weak(&self) -> LspClient {
258 self.weak.clone()
259 }
260}
261
262type ReqHandler = Box<dyn for<'a> FnOnce(&'a mut dyn Any, LspOrDapResponse) + Send + Sync>;
263type ReqQueue = req_queue::ReqQueue<(String, Time), ReqHandler>;
264
265#[derive(Debug, Clone)]
267pub enum TransportHost {
268 System(SystemTransportSender),
270 #[cfg(feature = "web")]
272 Js {
273 event_id: Arc<AtomicU32>,
275 events: Arc<Mutex<HashMap<u32, Event>>>,
277 sender: JsTransportSender,
279 },
280}
281
282#[derive(Debug, Clone)]
284pub struct SystemTransportSender {
285 pub(crate) sender: Weak<ConnectionTx>,
287}
288
289#[cfg(feature = "web")]
291#[derive(Debug, Clone, serde::Deserialize)]
292#[serde(rename_all = "camelCase")]
293pub struct JsTransportSender {
294 #[serde(with = "serde_wasm_bindgen::preserve")]
295 pub(crate) send_event: js_sys::Function,
296 #[serde(with = "serde_wasm_bindgen::preserve")]
297 pub(crate) send_request: js_sys::Function,
298 #[serde(with = "serde_wasm_bindgen::preserve")]
299 pub(crate) send_notification: js_sys::Function,
300 #[serde(with = "serde_wasm_bindgen::preserve")]
302 pub resolve_fn: js_sys::Function,
303}
304
305#[cfg(feature = "web")]
306unsafe impl Send for TransportHost {}
309
310#[cfg(feature = "web")]
311unsafe impl Sync for TransportHost {}
314
315impl TransportHost {
316 pub fn send_event<T: std::any::Any + Send + 'static>(&self, event: T) {
318 match self {
319 TransportHost::System(host) => {
320 let Some(sender) = host.sender.upgrade() else {
321 log::warn!("failed to send request: connection closed");
322 return;
323 };
324
325 if let Err(res) = sender.event.send(Box::new(event)) {
326 log::warn!("failed to send event: {res:?}");
327 }
328 }
329 #[cfg(feature = "web")]
330 TransportHost::Js {
331 event_id,
332 sender,
333 events,
334 } => {
335 let event_id = {
336 let event_id = event_id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
337 let mut lg = events.lock();
338 lg.insert(event_id, Box::new(event));
339 js_sys::Number::from(event_id)
340 };
341 if let Err(err) = sender
342 .send_event
343 .call1(&wasm_bindgen::JsValue::UNDEFINED, &event_id.into())
344 {
345 log::error!("failed to send event: {err:?}");
346 }
347 }
348 }
349 }
350
351 pub fn send_message(&self, response: Message) {
353 match self {
354 TransportHost::System(host) => {
355 let Some(sender) = host.sender.upgrade() else {
356 log::warn!("failed to send response: connection closed");
357 return;
358 };
359 if let Err(res) = sender.lsp.send(response) {
360 log::warn!("failed to send response: {res:?}");
361 }
362 }
363 #[cfg(feature = "web")]
364 TransportHost::Js { sender, .. } => match response {
365 #[cfg(feature = "lsp")]
366 Message::Lsp(lsp::Message::Request(req)) => {
367 let msg = to_js_value(&req).expect("failed to serialize request to js value");
368 if let Err(err) = sender
369 .send_request
370 .call1(&wasm_bindgen::JsValue::UNDEFINED, &msg)
371 {
372 log::error!("failed to send request: {err:?}");
373 }
374 }
375 #[cfg(feature = "lsp")]
376 Message::Lsp(lsp::Message::Notification(req)) => {
377 let msg = to_js_value(&req).expect("failed to serialize request to js value");
378 if let Err(err) = sender
379 .send_notification
380 .call1(&wasm_bindgen::JsValue::UNDEFINED, &msg)
381 {
382 log::error!("failed to send request: {err:?}");
383 }
384 }
385 #[cfg(feature = "lsp")]
386 Message::Lsp(lsp::Message::Response(req)) => {
387 panic!("unexpected response to js world: {req:?}");
388 }
389 #[cfg(feature = "dap")]
390 Message::Dap(dap::Message::Request(req)) => {
391 let msg = to_js_value(&req).expect("failed to serialize request to js value");
392 if let Err(err) = sender
393 .send_request
394 .call1(&wasm_bindgen::JsValue::UNDEFINED, &msg)
395 {
396 log::error!("failed to send request: {err:?}");
397 }
398 }
399 #[cfg(feature = "dap")]
400 Message::Dap(dap::Message::Event(req)) => {
401 let msg = to_js_value(&req).expect("failed to serialize request to js value");
402 if let Err(err) = sender
403 .send_notification
404 .call1(&wasm_bindgen::JsValue::UNDEFINED, &msg)
405 {
406 log::error!("failed to send request: {err:?}");
407 }
408 }
409 #[cfg(feature = "dap")]
410 Message::Dap(dap::Message::Response(req)) => {
411 panic!("unexpected response to js world: {req:?}");
412 }
413 },
414 }
415 }
416}
417
418#[cfg(feature = "web")]
421fn to_js_value<T: serde::Serialize>(
422 value: &T,
423) -> Result<wasm_bindgen::JsValue, serde_wasm_bindgen::Error> {
424 value.serialize(&serde_wasm_bindgen::Serializer::new().serialize_maps_as_objects(true))
425}
426
427#[derive(Debug, Clone)]
429pub struct LspClient {
430 pub handle: tokio::runtime::Handle,
432
433 pub(crate) msg_kind: MessageKind,
434 pub sender: TransportHost,
436 pub(crate) req_queue: Arc<Mutex<ReqQueue>>,
437
438 pub(crate) hook: Arc<dyn LsHook>,
439}
440
441impl LspClient {
442 pub fn untyped(&self) -> &Self {
444 self
445 }
446
447 pub fn to_typed<S: Any>(&self) -> TypedLspClient<S> {
449 TypedLspClient {
450 client: self.clone(),
451 caster: Arc::new(|s| s.downcast_mut().expect("invalid cast")),
452 }
453 }
454
455 pub fn has_pending_requests(&self) -> bool {
457 self.req_queue.lock().incoming.has_pending()
458 }
459
460 pub fn begin_panic(&self) {
462 self.req_queue.lock().begin_panic();
463 }
464
465 pub fn send_event<T: std::any::Any + Send + 'static>(&self, event: T) {
467 self.sender.send_event(event);
468 }
469
470 #[cfg(feature = "lsp")]
472 pub fn complete_lsp_request<S: Any>(&self, service: &mut S, response: lsp::Response) {
473 let mut req_queue = self.req_queue.lock();
474 let Some(handler) = req_queue.outgoing.complete(response.id.clone()) else {
475 log::warn!("received response for unknown request");
476 return;
477 };
478 drop(req_queue);
479 handler(service, response.into())
480 }
481
482 #[cfg(feature = "dap")]
484 pub fn complete_dap_request<S: Any>(&self, service: &mut S, response: dap::Response) {
485 let mut req_queue = self.req_queue.lock();
486 let Some(handler) = req_queue
487 .outgoing
488 .complete((response.request_seq as i32).into())
490 else {
491 log::warn!("received response for unknown request");
492 return;
493 };
494 drop(req_queue);
495 handler(service, response.into())
496 }
497
498 pub fn register_request(&self, method: &str, id: &RequestId, received_at: Time) {
500 let mut req_queue = self.req_queue.lock();
501 self.hook.start_request(id, method);
502 req_queue
503 .incoming
504 .register(id.clone(), (method.to_owned(), received_at));
505 }
506
507 fn respond_result(&self, id: RequestId, result: LspResult<JsonValue>) {
508 let req_id = id.clone();
509 let msg: Message = match (self.msg_kind, result) {
510 #[cfg(feature = "lsp")]
511 (MessageKind::Lsp, res) => lsp::Response::new(id, res).into(),
512 #[cfg(feature = "dap")]
513 (MessageKind::Dap, Ok(resp)) => dap::Response::success(RequestId::dap(id), resp).into(),
514 #[cfg(feature = "dap")]
515 (MessageKind::Dap, Err(e)) => {
516 dap::Response::error(RequestId::dap(id), Some(e.message), None).into()
517 }
518 };
519
520 self.respond(req_id, msg);
521 }
522
523 pub fn respond(&self, id: RequestId, response: Message) {
525 let mut req_queue = self.req_queue.lock();
526 let Some((method, received_at)) = req_queue.incoming.complete(&id) else {
527 return;
528 };
529
530 self.hook.stop_request(&id, &method, received_at);
531
532 let delay = tinymist_std::time::now().duration_since(received_at);
533 match delay {
534 Ok(delay) => {
535 if delay.as_secs() > 10 {
536 let worst_outgoing =
537 req_queue.incoming.pending().max_by_key(|(_, data)| data.1);
538 let worst_case = if let Some((id, (method, since))) = worst_outgoing {
539 let duration = tinymist_std::time::now().duration_since(*since);
540 format!(", worst case: req({method:?}, {id:?}) - {duration:?}")
541 } else {
542 String::new()
543 };
544 log::warn!(
545 "request {id:?} is completed after {delay:?}, pending incoming requests: {:?}, pending outgoing requests: {:?}{worst_case}",
546 req_queue.incoming,
547 req_queue.outgoing
548 );
549 }
550 }
551 Err(err) => {
552 log::error!("failed to get delay for request {id:?}: {err:?}");
553 }
554 }
555
556 self.sender.send_message(response);
557 }
558}
559
560impl LspClient {
561 pub async fn schedule_tail(self, req_id: RequestId, resp: ScheduleResult) {
564 match resp {
565 Ok(MaybeDone::Done(result)) => {
566 self.respond_result(req_id, result);
567 }
568 Ok(MaybeDone::Future(result)) => {
569 self.respond_result(req_id, result.await);
570 }
571 Ok(MaybeDone::Gone) => {
572 log::warn!("response for request({req_id:?}) already taken");
573 self.respond_result(req_id, Err(internal_error("response already taken")));
574 }
575 Err(err) => {
576 self.respond_result(req_id, Err(err));
577 }
578 }
579 }
580}
581
582pub trait LsHook: fmt::Debug + Send + Sync {
584 fn start_request(&self, req_id: &RequestId, method: &str);
586 fn stop_request(&self, req_id: &RequestId, method: &str, received_at: Time);
588 fn start_notification(&self, track_id: i32, method: &str);
590 fn stop_notification(
592 &self,
593 track_id: i32,
594 method: &str,
595 received_at: Time,
596 result: LspResult<()>,
597 );
598}
599
600impl LsHook for () {
601 fn start_request(&self, req_id: &RequestId, method: &str) {
602 log::info!("handling {method} - ({req_id})");
603 }
604
605 fn stop_request(&self, req_id: &RequestId, method: &str, received_at: Time) {
606 let duration = received_at.elapsed();
607 log::info!("handled {method} - ({req_id}) in {duration:0.2?}");
608 }
609
610 fn start_notification(&self, track_id: i32, method: &str) {
611 log::info!("notifying ({track_id}) - {method}");
612 }
613
614 fn stop_notification(
615 &self,
616 track_id: i32,
617 method: &str,
618 received_at: Time,
619 result: LspResult<()>,
620 ) {
621 let request_duration = received_at.elapsed();
622 if let Err(err) = result {
623 log::error!(
624 "notify ({track_id}) - {method} failed in {request_duration:0.2?}: {err:?}"
625 );
626 } else {
627 log::info!("notify ({track_id}) - {method} succeeded in {request_duration:0.2?}");
628 }
629 }
630}
631
632type AsyncHandler<S, T, R> = fn(srv: &mut S, args: T) -> SchedulableResponse<R>;
633type RawHandler<S, T> = fn(srv: &mut S, args: T) -> ScheduleResult;
634type BoxPureHandler<S, T> = Box<dyn Fn(&mut S, T) -> LspResult<()>>;
635type BoxHandler<S, T> = Box<dyn Fn(&mut S, T) -> SchedulableResponse<JsonValue>>;
636type ExecuteCmdMap<S> = HashMap<&'static str, BoxHandler<S, Vec<JsonValue>>>;
637type RegularCmdMap<S> = HashMap<&'static str, BoxHandler<S, JsonValue>>;
638type NotifyCmdMap<S> = HashMap<&'static str, BoxPureHandler<S, JsonValue>>;
639type ResourceMap<S> = HashMap<ImmutPath, BoxHandler<S, Vec<JsonValue>>>;
640type MayInitBoxHandler<A, S, T> =
641 Box<dyn for<'a> Fn(ServiceState<'a, A, S>, &LspClient, T) -> anyhow::Result<()>>;
642type EventMap<A, S> = HashMap<core::any::TypeId, MayInitBoxHandler<A, S, Event>>;
643
644pub trait Initializer {
646 type I: for<'de> serde::Deserialize<'de>;
648 type S;
650
651 fn initialize(self, req: Self::I) -> (Self::S, AnySchedulableResponse);
655}
656
657#[cfg(feature = "lsp")]
659pub type LspBuilder<Args> = LsBuilder<LspMessage, Args>;
660#[cfg(feature = "dap")]
662pub type DapBuilder<Args> = LsBuilder<DapMessage, Args>;
663
664pub struct LsBuilder<M, Args: Initializer> {
666 pub args: Args,
668 pub client: LspClient,
670 pub events: EventMap<Args, Args::S>,
672 pub command_handlers: ExecuteCmdMap<Args::S>,
674 pub notif_handlers: NotifyCmdMap<Args::S>,
676 pub req_handlers: RegularCmdMap<Args::S>,
678 pub resource_handlers: ResourceMap<Args::S>,
680 _marker: std::marker::PhantomData<M>,
681}
682
683impl<M, Args: Initializer> LsBuilder<M, Args>
684where
685 Args::S: 'static,
686{
687 pub fn new(args: Args, client: LspClient) -> Self {
689 Self {
690 args,
691 client,
692 events: EventMap::new(),
693 command_handlers: ExecuteCmdMap::new(),
694 notif_handlers: NotifyCmdMap::new(),
695 req_handlers: RegularCmdMap::new(),
696 resource_handlers: ResourceMap::new(),
697 _marker: std::marker::PhantomData,
698 }
699 }
700
701 pub fn with_event<T: std::any::Any>(
703 mut self,
704 ins: &T,
705 handler: impl for<'a> Fn(ServiceState<'a, Args, Args::S>, T) -> anyhow::Result<()> + 'static,
706 ) -> Self {
707 self.events.insert(
708 ins.type_id(),
709 Box::new(move |s, _client, req| handler(s, *req.downcast().unwrap())),
710 );
711 self
712 }
713
714 pub fn with_resource(
716 mut self,
717 path: &'static str,
718 handler: fn(&mut Args::S, Vec<JsonValue>) -> AnySchedulableResponse,
719 ) -> Self {
720 self.resource_handlers
721 .insert(Path::new(path).into(), Box::new(handler));
722 self
723 }
724
725 pub fn build(self) -> LsDriver<M, Args> {
727 LsDriver {
728 state: State::Uninitialized(Some(Box::new(self.args))),
729 next_not_id: AtomicI32::new(1),
730 events: self.events,
731 client: self.client,
732 commands: self.command_handlers,
733 notifications: self.notif_handlers,
734 requests: self.req_handlers,
735 resources: self.resource_handlers,
736 _marker: std::marker::PhantomData,
737 }
738 }
739}
740
741pub enum ServiceState<'a, A, S> {
743 Uninitialized(Option<&'a mut A>),
745 Ready(&'a mut S),
747}
748
749impl<A, S> ServiceState<'_, A, S> {
750 pub fn ready(&mut self) -> Option<&mut S> {
752 match self {
753 ServiceState::Ready(s) => Some(s),
754 _ => None,
755 }
756 }
757}
758
759#[derive(Debug, Clone, PartialEq, Eq)]
760enum State<Args, S> {
761 Uninitialized(Option<Box<Args>>),
762 Initializing(S),
763 Ready(S),
764 ShuttingDown,
765}
766
767impl<Args, S> State<Args, S> {
768 fn opt(&self) -> Option<&S> {
769 match &self {
770 State::Ready(s) => Some(s),
771 _ => None,
772 }
773 }
774
775 fn opt_mut(&mut self) -> Option<&mut S> {
776 match self {
777 State::Ready(s) => Some(s),
778 _ => None,
779 }
780 }
781}
782
783pub struct LsDriver<M, Args: Initializer> {
785 state: State<Args, Args::S>,
787 pub client: LspClient,
789 pub next_not_id: AtomicI32,
791
792 pub events: EventMap<Args, Args::S>,
795 pub commands: ExecuteCmdMap<Args::S>,
797 pub notifications: NotifyCmdMap<Args::S>,
799 pub requests: RegularCmdMap<Args::S>,
801 pub resources: ResourceMap<Args::S>,
803 _marker: std::marker::PhantomData<M>,
804}
805
806impl<M, Args: Initializer> LsDriver<M, Args> {
807 pub fn state(&self) -> Option<&Args::S> {
809 self.state.opt()
810 }
811
812 pub fn state_mut(&mut self) -> Option<&mut Args::S> {
814 self.state.opt_mut()
815 }
816
817 pub fn ready(&mut self, params: Args::I) -> AnySchedulableResponse {
819 let args = match &mut self.state {
820 State::Uninitialized(args) => args,
821 _ => return just_result(Err(invalid_request("server is already initialized"))),
822 };
823
824 let args = args.take().expect("already initialized");
825 let (s, res) = args.initialize(params);
826 self.state = State::Ready(s);
827
828 res
829 }
830
831 pub fn get_resources(&mut self, args: Vec<JsonValue>) -> ScheduleResult {
834 let s = self.state.opt_mut().ok_or_else(not_initialized)?;
835
836 let path =
837 from_value::<PathBuf>(args[0].clone()).map_err(|e| invalid_params(e.to_string()))?;
838
839 let Some(handler) = self.resources.get(path.as_path()) else {
840 log::error!("asked for unknown resource: {path:?}");
841 return Err(method_not_found());
842 };
843
844 handler(s, args)
846 }
847}
848
849pub fn just_ok<T, E>(res: T) -> Result<ResponseFuture<Result<T, E>>, E> {
851 Ok(futures::future::MaybeDone::Done(Ok(res)))
852}
853
854pub fn just_result<T, E>(res: Result<T, E>) -> Result<ResponseFuture<Result<T, E>>, E> {
856 Ok(futures::future::MaybeDone::Done(res))
857}
858
859pub fn just_future<T, E>(
861 fut: impl std::future::Future<Output = Result<T, E>> + Send + 'static,
862) -> Result<ResponseFuture<Result<T, E>>, E> {
863 Ok(futures::future::MaybeDone::Future(Box::pin(fut)))
864}
865
866pub fn invalid_params(msg: impl fmt::Display) -> ResponseError {
868 resp_err(ErrorCode::InvalidParams, msg)
869}
870
871pub fn internal_error(msg: impl fmt::Display) -> ResponseError {
873 resp_err(ErrorCode::InternalError, msg)
874}
875
876pub fn not_initialized() -> ResponseError {
878 resp_err(ErrorCode::ServerNotInitialized, "not initialized yet")
879}
880
881pub fn method_not_found() -> ResponseError {
883 resp_err(ErrorCode::MethodNotFound, "method not found")
884}
885
886pub fn invalid_request(msg: impl fmt::Display) -> ResponseError {
888 resp_err(ErrorCode::InvalidRequest, msg)
889}
890
891fn from_json<T: serde::de::DeserializeOwned>(json: JsonValue) -> LspResult<T> {
892 serde_json::from_value(json).map_err(invalid_request)
893}
894
895pub fn erased_response<T: Serialize + 'static>(resp: SchedulableResponse<T>) -> ScheduleResult {
897 fn map_respond_result<T: Serialize>(result: LspResult<T>) -> LspResult<JsonValue> {
899 result.and_then(|t| serde_json::to_value(t).map_err(internal_error))
900 }
901
902 let resp = resp?;
903
904 use futures::future::MaybeDone::*;
905 Ok(match resp {
906 Done(result) => MaybeDone::Done(map_respond_result(result)),
907 Future(fut) => MaybeDone::Future(Box::pin(async move { map_respond_result(fut.await) })),
908 Gone => {
909 log::warn!("response already taken");
910 MaybeDone::Done(Err(internal_error("response already taken")))
911 }
912 })
913}
914
915fn resp_err(code: ErrorCode, msg: impl fmt::Display) -> ResponseError {
916 ResponseError {
917 code: code as i32,
918 message: msg.to_string(),
919 data: None,
920 }
921}