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 #[cfg(feature = "dap")]
414 Message::Dap(dap::Message::ResponseWithCommand(req)) => {
415 panic!("unexpected response to js world: {req:?}");
416 }
417 },
418 }
419 }
420}
421
422#[cfg(feature = "web")]
425fn to_js_value<T: serde::Serialize>(
426 value: &T,
427) -> Result<wasm_bindgen::JsValue, serde_wasm_bindgen::Error> {
428 value.serialize(&serde_wasm_bindgen::Serializer::new().serialize_maps_as_objects(true))
429}
430
431#[derive(Debug, Clone)]
433pub struct LspClient {
434 pub handle: tokio::runtime::Handle,
436
437 pub(crate) msg_kind: MessageKind,
438 pub sender: TransportHost,
440 pub(crate) req_queue: Arc<Mutex<ReqQueue>>,
441
442 pub(crate) hook: Arc<dyn LsHook>,
443}
444
445impl LspClient {
446 pub fn untyped(&self) -> &Self {
448 self
449 }
450
451 pub fn to_typed<S: Any>(&self) -> TypedLspClient<S> {
453 TypedLspClient {
454 client: self.clone(),
455 caster: Arc::new(|s| s.downcast_mut().expect("invalid cast")),
456 }
457 }
458
459 pub fn has_pending_requests(&self) -> bool {
461 self.req_queue.lock().incoming.has_pending()
462 }
463
464 pub fn begin_panic(&self) {
466 self.req_queue.lock().begin_panic();
467 }
468
469 pub fn send_event<T: std::any::Any + Send + 'static>(&self, event: T) {
471 self.sender.send_event(event);
472 }
473
474 #[cfg(feature = "lsp")]
476 pub fn complete_lsp_request<S: Any>(&self, service: &mut S, response: lsp::Response) {
477 let mut req_queue = self.req_queue.lock();
478 let Some(handler) = req_queue.outgoing.complete(response.id.clone()) else {
479 log::warn!("received response for unknown request");
480 return;
481 };
482 drop(req_queue);
483 handler(service, response.into())
484 }
485
486 #[cfg(feature = "dap")]
488 pub fn complete_dap_request<S: Any>(&self, service: &mut S, response: dap::Response) {
489 let mut req_queue = self.req_queue.lock();
490 let Some(handler) = req_queue
491 .outgoing
492 .complete((response.request_seq as i32).into())
494 else {
495 log::warn!("received response for unknown request");
496 return;
497 };
498 drop(req_queue);
499 handler(service, response.into())
500 }
501
502 pub fn register_request(&self, method: &str, id: &RequestId, received_at: Time) {
504 let mut req_queue = self.req_queue.lock();
505 self.hook.start_request(id, method);
506 req_queue
507 .incoming
508 .register(id.clone(), (method.to_owned(), received_at));
509 }
510
511 fn respond_result(&self, id: RequestId, result: LspResult<JsonValue>) {
512 let req_id = id.clone();
513 let msg: Message = match (self.msg_kind, result) {
514 #[cfg(feature = "lsp")]
515 (MessageKind::Lsp, res) => lsp::Response::new(id, res).into(),
516 #[cfg(feature = "dap")]
517 (MessageKind::Dap, Ok(resp)) => dap::Response::success(RequestId::dap(id), resp).into(),
518 #[cfg(feature = "dap")]
519 (MessageKind::Dap, Err(e)) => {
520 dap::Response::error(RequestId::dap(id), Some(e.message), None).into()
521 }
522 };
523
524 self.respond(req_id, msg);
525 }
526
527 pub fn respond(&self, id: RequestId, response: Message) {
529 let mut req_queue = self.req_queue.lock();
530 let Some((method, received_at)) = req_queue.incoming.complete(&id) else {
531 return;
532 };
533
534 self.hook.stop_request(&id, &method, received_at);
535
536 let delay = tinymist_std::time::now().duration_since(received_at);
537 match delay {
538 Ok(delay) => {
539 if delay.as_secs() > 10 {
540 let worst_outgoing =
541 req_queue.incoming.pending().max_by_key(|(_, data)| data.1);
542 let worst_case = if let Some((id, (method, since))) = worst_outgoing {
543 let duration = tinymist_std::time::now().duration_since(*since);
544 format!(", worst case: req({method:?}, {id:?}) - {duration:?}")
545 } else {
546 String::new()
547 };
548 log::warn!(
549 "request {id:?} is completed after {delay:?}, pending incoming requests: {:?}, pending outgoing requests: {:?}{worst_case}",
550 req_queue.incoming,
551 req_queue.outgoing
552 );
553 }
554 }
555 Err(err) => {
556 log::error!("failed to get delay for request {id:?}: {err:?}");
557 }
558 }
559
560 #[cfg(feature = "dap")]
561 let response = match response {
562 Message::Dap(dap::Message::Response(resp)) => Message::Dap(
563 dap::Message::ResponseWithCommand(dap::ResponseWithCommand::new(method, resp)),
564 ),
565 response => response,
566 };
567
568 self.sender.send_message(response);
569 }
570}
571
572impl LspClient {
573 pub async fn schedule_tail(self, req_id: RequestId, resp: ScheduleResult) {
576 match resp {
577 Ok(MaybeDone::Done(result)) => {
578 self.respond_result(req_id, result);
579 }
580 Ok(MaybeDone::Future(result)) => {
581 self.respond_result(req_id, result.await);
582 }
583 Ok(MaybeDone::Gone) => {
584 log::debug!("response for request({req_id:?}) was already sent");
585 }
586 Err(err) => {
587 self.respond_result(req_id, Err(err));
588 }
589 }
590 }
591}
592
593pub trait LsHook: fmt::Debug + Send + Sync {
595 fn start_request(&self, req_id: &RequestId, method: &str);
597 fn stop_request(&self, req_id: &RequestId, method: &str, received_at: Time);
599 fn start_notification(&self, track_id: i32, method: &str);
601 fn stop_notification(
603 &self,
604 track_id: i32,
605 method: &str,
606 received_at: Time,
607 result: LspResult<()>,
608 );
609}
610
611impl LsHook for () {
612 fn start_request(&self, req_id: &RequestId, method: &str) {
613 log::info!("handling {method} - ({req_id})");
614 }
615
616 fn stop_request(&self, req_id: &RequestId, method: &str, received_at: Time) {
617 let duration = received_at.elapsed();
618 log::info!("handled {method} - ({req_id}) in {duration:0.2?}");
619 }
620
621 fn start_notification(&self, track_id: i32, method: &str) {
622 log::info!("notifying ({track_id}) - {method}");
623 }
624
625 fn stop_notification(
626 &self,
627 track_id: i32,
628 method: &str,
629 received_at: Time,
630 result: LspResult<()>,
631 ) {
632 let request_duration = received_at.elapsed();
633 if let Err(err) = result {
634 log::error!(
635 "notify ({track_id}) - {method} failed in {request_duration:0.2?}: {err:?}"
636 );
637 } else {
638 log::info!("notify ({track_id}) - {method} succeeded in {request_duration:0.2?}");
639 }
640 }
641}
642
643type AsyncHandler<S, T, R> = fn(srv: &mut S, args: T) -> SchedulableResponse<R>;
644type RawHandler<S, T> = fn(srv: &mut S, args: T) -> ScheduleResult;
645type BoxPureHandler<S, T> = Box<dyn Fn(&mut S, T) -> LspResult<()>>;
646type BoxHandler<S, T> = Box<dyn Fn(&mut S, RequestId, T) -> SchedulableResponse<JsonValue>>;
647type ExecuteCmdMap<S> = HashMap<&'static str, BoxHandler<S, Vec<JsonValue>>>;
648type RegularCmdMap<S> = HashMap<&'static str, BoxHandler<S, JsonValue>>;
649type NotifyCmdMap<S> = HashMap<&'static str, BoxPureHandler<S, JsonValue>>;
650type ResourceMap<S> = HashMap<ImmutPath, BoxHandler<S, Vec<JsonValue>>>;
651type MayInitBoxHandler<A, S, T> =
652 Box<dyn for<'a> Fn(ServiceState<'a, A, S>, &LspClient, T) -> anyhow::Result<()>>;
653type EventMap<A, S> = HashMap<core::any::TypeId, MayInitBoxHandler<A, S, Event>>;
654
655pub trait Initializer {
657 type I: for<'de> serde::Deserialize<'de>;
659 type S;
661
662 fn initialize(self, req: Self::I) -> (Self::S, AnySchedulableResponse);
666}
667
668#[cfg(feature = "lsp")]
670pub type LspBuilder<Args> = LsBuilder<LspMessage, Args>;
671#[cfg(feature = "dap")]
673pub type DapBuilder<Args> = LsBuilder<DapMessage, Args>;
674
675pub struct LsBuilder<M, Args: Initializer> {
677 pub args: Args,
679 pub client: LspClient,
681 pub events: EventMap<Args, Args::S>,
683 pub command_handlers: ExecuteCmdMap<Args::S>,
685 pub notif_handlers: NotifyCmdMap<Args::S>,
687 pub req_handlers: RegularCmdMap<Args::S>,
689 pub resource_handlers: ResourceMap<Args::S>,
691 _marker: std::marker::PhantomData<M>,
692}
693
694impl<M, Args: Initializer> LsBuilder<M, Args>
695where
696 Args::S: 'static,
697{
698 pub fn new(args: Args, client: LspClient) -> Self {
700 Self {
701 args,
702 client,
703 events: EventMap::new(),
704 command_handlers: ExecuteCmdMap::new(),
705 notif_handlers: NotifyCmdMap::new(),
706 req_handlers: RegularCmdMap::new(),
707 resource_handlers: ResourceMap::new(),
708 _marker: std::marker::PhantomData,
709 }
710 }
711
712 pub fn with_event<T: std::any::Any>(
714 mut self,
715 ins: &T,
716 handler: impl for<'a> Fn(ServiceState<'a, Args, Args::S>, T) -> anyhow::Result<()> + 'static,
717 ) -> Self {
718 self.events.insert(
719 ins.type_id(),
720 Box::new(move |s, _client, req| handler(s, *req.downcast().unwrap())),
721 );
722 self
723 }
724
725 pub fn with_resource(
727 mut self,
728 path: &'static str,
729 handler: fn(&mut Args::S, Vec<JsonValue>) -> AnySchedulableResponse,
730 ) -> Self {
731 self.resource_handlers.insert(
732 Path::new(path).into(),
733 Box::new(move |s, _req_id, args| handler(s, args)),
734 );
735 self
736 }
737
738 pub fn build(self) -> LsDriver<M, Args> {
740 LsDriver {
741 state: State::Uninitialized(Some(Box::new(self.args))),
742 next_not_id: AtomicI32::new(1),
743 events: self.events,
744 client: self.client,
745 commands: self.command_handlers,
746 notifications: self.notif_handlers,
747 requests: self.req_handlers,
748 resources: self.resource_handlers,
749 _marker: std::marker::PhantomData,
750 }
751 }
752}
753
754pub enum ServiceState<'a, A, S> {
756 Uninitialized(Option<&'a mut A>),
758 Ready(&'a mut S),
760}
761
762impl<A, S> ServiceState<'_, A, S> {
763 pub fn ready(&mut self) -> Option<&mut S> {
765 match self {
766 ServiceState::Ready(s) => Some(s),
767 _ => None,
768 }
769 }
770}
771
772#[derive(Debug, Clone, PartialEq, Eq)]
773enum State<Args, S> {
774 Uninitialized(Option<Box<Args>>),
775 Initializing(S),
776 Ready(S),
777 ShuttingDown,
778}
779
780impl<Args, S> State<Args, S> {
781 fn opt(&self) -> Option<&S> {
782 match &self {
783 State::Ready(s) => Some(s),
784 _ => None,
785 }
786 }
787
788 fn opt_mut(&mut self) -> Option<&mut S> {
789 match self {
790 State::Ready(s) => Some(s),
791 _ => None,
792 }
793 }
794}
795
796pub struct LsDriver<M, Args: Initializer> {
798 state: State<Args, Args::S>,
800 pub client: LspClient,
802 pub next_not_id: AtomicI32,
804
805 pub events: EventMap<Args, Args::S>,
808 pub commands: ExecuteCmdMap<Args::S>,
810 pub notifications: NotifyCmdMap<Args::S>,
812 pub requests: RegularCmdMap<Args::S>,
814 pub resources: ResourceMap<Args::S>,
816 _marker: std::marker::PhantomData<M>,
817}
818
819impl<M, Args: Initializer> LsDriver<M, Args> {
820 pub fn state(&self) -> Option<&Args::S> {
822 self.state.opt()
823 }
824
825 pub fn state_mut(&mut self) -> Option<&mut Args::S> {
827 self.state.opt_mut()
828 }
829
830 pub fn ready(&mut self, params: Args::I) -> AnySchedulableResponse {
832 let args = match &mut self.state {
833 State::Uninitialized(args) => args,
834 _ => return just_result(Err(invalid_request("server is already initialized"))),
835 };
836
837 let args = args.take().expect("already initialized");
838 let (s, res) = args.initialize(params);
839 self.state = State::Ready(s);
840
841 res
842 }
843
844 pub fn get_resources(&mut self, req_id: RequestId, args: Vec<JsonValue>) -> ScheduleResult {
847 let s = self.state.opt_mut().ok_or_else(not_initialized)?;
848
849 let path =
850 from_value::<PathBuf>(args[0].clone()).map_err(|e| invalid_params(e.to_string()))?;
851
852 let Some(handler) = self.resources.get(path.as_path()) else {
853 log::error!("asked for unknown resource: {path:?}");
854 return Err(method_not_found());
855 };
856
857 handler(s, req_id, args)
859 }
860}
861
862pub fn just_ok<T, E>(res: T) -> Result<ResponseFuture<Result<T, E>>, E> {
864 Ok(futures::future::MaybeDone::Done(Ok(res)))
865}
866
867pub fn just_result<T, E>(res: Result<T, E>) -> Result<ResponseFuture<Result<T, E>>, E> {
869 Ok(futures::future::MaybeDone::Done(res))
870}
871
872pub fn just_future<T, E>(
874 fut: impl std::future::Future<Output = Result<T, E>> + Send + 'static,
875) -> Result<ResponseFuture<Result<T, E>>, E> {
876 Ok(futures::future::MaybeDone::Future(Box::pin(fut)))
877}
878
879pub fn invalid_params(msg: impl fmt::Display) -> ResponseError {
881 resp_err(ErrorCode::InvalidParams, msg)
882}
883
884pub fn internal_error(msg: impl fmt::Display) -> ResponseError {
886 resp_err(ErrorCode::InternalError, msg)
887}
888
889pub fn not_initialized() -> ResponseError {
891 resp_err(ErrorCode::ServerNotInitialized, "not initialized yet")
892}
893
894pub fn method_not_found() -> ResponseError {
896 resp_err(ErrorCode::MethodNotFound, "method not found")
897}
898
899pub fn invalid_request(msg: impl fmt::Display) -> ResponseError {
901 resp_err(ErrorCode::InvalidRequest, msg)
902}
903
904fn from_json<T: serde::de::DeserializeOwned>(json: JsonValue) -> LspResult<T> {
905 serde_json::from_value(json).map_err(invalid_request)
906}
907
908pub fn erased_response<T: Serialize + 'static>(resp: SchedulableResponse<T>) -> ScheduleResult {
910 fn map_respond_result<T: Serialize>(result: LspResult<T>) -> LspResult<JsonValue> {
912 result.and_then(|t| serde_json::to_value(t).map_err(internal_error))
913 }
914
915 let resp = resp?;
916
917 use futures::future::MaybeDone::*;
918 Ok(match resp {
919 Done(result) => MaybeDone::Done(map_respond_result(result)),
920 Future(fut) => MaybeDone::Future(Box::pin(async move { map_respond_result(fut.await) })),
921 Gone => {
922 log::warn!("response already taken");
923 MaybeDone::Done(Err(internal_error("response already taken")))
924 }
925 })
926}
927
928pub fn scheduled_response(resp: ScheduledResult) -> ScheduleResult {
930 match resp? {
931 Some(()) => Ok(MaybeDone::Gone),
932 None => just_ok(JsonValue::Null),
933 }
934}
935
936fn resp_err(code: ErrorCode, msg: impl fmt::Display) -> ResponseError {
937 ResponseError {
938 code: code as i32,
939 message: msg.to_string(),
940 data: None,
941 }
942}