use std::backtrace::Backtrace; use std::fmt::Debug; use std::marker::PhantomData; use crossbeam::channel::SendError; use lsp_server::{Message, Response as Re}; use lsp_types::DiagnosticServerCancellationData; use lsp_types::request::Request; use serde::{Deserialize, Serialize}; use tokio::sync::oneshot; use tokio::task; use tokio_util::task::AbortOnDropHandle; #[derive(Serialize, Deserialize)] pub enum RequestError { Rx(PhantomData), Failure(Re, #[serde(skip)] Option), Cancelled(Re, DiagnosticServerCancellationData), Send(Message), } pub type AQErr = RequestError; impl Request for LSPError { type Params = (); type Result = (); const METHOD: &'static str = ""; } #[derive(Debug)] pub struct LSPError {} pub trait Anonymize { fn anonymize(self) -> Result>; } impl Anonymize for Result> { fn anonymize(self) -> Result> { self.map_err(|e| match e { RequestError::Send(x) => RequestError::Send(x), RequestError::Rx(_) => RequestError::Rx(PhantomData), RequestError::Failure(r, b) => RequestError::Failure(r, b), RequestError::Cancelled(r, d) => RequestError::Cancelled(r, d), }) } } // impl Debug for RequestError {} impl From for RequestError { fn from(_: oneshot::error::RecvError) -> Self { Self::Rx(PhantomData) } } impl std::error::Error for RequestError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } } impl From> for RequestError { fn from(x: SendError) -> Self { Self::Send(x.into_inner()) } } impl std::fmt::Display for RequestError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Send(x) => write!(f, "{} failed; couldnt send {x:?}", X::METHOD), Self::Rx(_) => write!(f, "{} failed; couldnt get from thingy", X::METHOD), Self::Failure(x, bt) => write!( f, "{} failed; returned badge :( {x:?} ({bt:?})", X::METHOD ), Self::Cancelled(x, y) => write!(f, "server cancelled {}. {x:?} {y:?}", X::METHOD), } } } impl Debug for RequestError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self, f) } } fn none() -> Option { None } impl Clone for Rq { fn clone(&self) -> Self { Self { result: self.result.clone(), request: None } } } #[derive(serde_derive::Serialize, serde_derive::Deserialize)] pub struct Rq> { #[serde(skip_serializing_if = "Option::is_none", default = "none")] pub result: Option, #[serde(skip, default = "none")] pub request: Option<(AbortOnDropHandle>, D)>, } impl Debug for Rq { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct(&format!("Rq<{}>", std::any::type_name::())) .field("result", &self.result) .field("request", &self.request) .finish() } } pub type RqS = Rq>; impl Default for Rq { fn default() -> Self { Self { result: None, request: None } } } impl Rq { pub fn new(f: task::JoinHandle>) -> Self { Self { request: Some((AbortOnDropHandle::new(f), ())), result: None, } } pub fn request(&mut self, f: task::JoinHandle>) { self.request = Some((AbortOnDropHandle::new(f), ())); } } impl Rq { pub fn running(&self) -> bool { matches!( self, Self { result: Some(_), .. } | Self { request: Some(_), .. }, ) } pub fn poll( &mut self, f: impl FnOnce(Result, (D, Option)) -> Option, ) -> bool { if self.request.as_mut().is_some_and(|(x, _)| x.is_finished()) && let Some((task, _)) = self.request.as_mut() && let Some(x) = futures::FutureExt::now_or_never(task) { let (_, d) = self.request.take().unwrap(); self.result = f( match x { Ok(x) => x, Err(e) => { log::error!( "unexpected join error from request poll: {e}" ); return false; } }, (d, self.result.take()), ); true } else { false } } }