Introduce a new TryFutureExt::unwrap method

This commit is contained in:
Antonio Scandurra 2023-03-10 11:41:13 +01:00
parent 431e11a033
commit 221bb54e48
8 changed files with 151 additions and 92 deletions

1
Cargo.lock generated
View file

@ -3157,6 +3157,7 @@ dependencies = [
name = "journal"
version = "0.1.0"
dependencies = [
"anyhow",
"chrono",
"dirs 4.0.0",
"editor",

View file

@ -224,7 +224,7 @@ impl Telemetry {
.header("Content-Type", "application/json")
.body(json_bytes.into())?;
this.http_client.send(request).await?;
Ok(())
anyhow::Ok(())
}
.log_err(),
)
@ -320,7 +320,7 @@ impl Telemetry {
.header("Content-Type", "application/json")
.body(json_bytes.into())?;
this.http_client.send(request).await?;
Ok(())
anyhow::Ok(())
}
.log_err(),
)

View file

@ -68,7 +68,7 @@ impl PickerDelegate for ContactFinder {
this.potential_contacts = potential_contacts.into();
cx.notify();
});
Ok(())
anyhow::Ok(())
}
.log_err()
.await;

View file

@ -13,6 +13,7 @@ editor = { path = "../editor" }
gpui = { path = "../gpui" }
util = { path = "../util" }
workspace = { path = "../workspace" }
anyhow = "1.0"
chrono = "0.4"
dirs = "4.0"
log = { version = "0.4.16", features = ["kv_unstable_serde"] }

View file

@ -73,7 +73,7 @@ pub fn new_journal_entry(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
}
}
Ok(())
anyhow::Ok(())
}
.log_err()
})

View file

@ -160,15 +160,13 @@ impl LanguageServer {
server: Option<Child>,
root_path: &Path,
cx: AsyncAppContext,
mut on_unhandled_notification: F,
on_unhandled_notification: F,
) -> Self
where
Stdin: AsyncWrite + Unpin + Send + 'static,
Stdout: AsyncRead + Unpin + Send + 'static,
F: FnMut(AnyNotification) + 'static + Send,
{
let mut stdin = BufWriter::new(stdin);
let mut stdout = BufReader::new(stdout);
let (outbound_tx, outbound_rx) = channel::unbounded::<Vec<u8>>();
let notification_handlers =
Arc::new(Mutex::new(HashMap::<_, NotificationHandler>::default()));
@ -177,7 +175,49 @@ impl LanguageServer {
let input_task = cx.spawn(|cx| {
let notification_handlers = notification_handlers.clone();
let response_handlers = response_handlers.clone();
async move {
Self::handle_input(
stdout,
on_unhandled_notification,
notification_handlers,
response_handlers,
cx,
)
.log_err()
});
let (output_done_tx, output_done_rx) = barrier::channel();
let output_task = cx.background().spawn({
let response_handlers = response_handlers.clone();
Self::handle_output(stdin, outbound_rx, output_done_tx, response_handlers).log_err()
});
Self {
server_id,
notification_handlers,
response_handlers,
name: Default::default(),
capabilities: Default::default(),
next_id: Default::default(),
outbound_tx,
executor: cx.background(),
io_tasks: Mutex::new(Some((input_task, output_task))),
output_done_rx: Mutex::new(Some(output_done_rx)),
root_path: root_path.to_path_buf(),
_server: server,
}
}
async fn handle_input<Stdout, F>(
stdout: Stdout,
mut on_unhandled_notification: F,
notification_handlers: Arc<Mutex<HashMap<&'static str, NotificationHandler>>>,
response_handlers: Arc<Mutex<Option<HashMap<usize, ResponseHandler>>>>,
cx: AsyncAppContext,
) -> anyhow::Result<()>
where
Stdout: AsyncRead + Unpin + Send + 'static,
F: FnMut(AnyNotification) + 'static + Send,
{
let mut stdout = BufReader::new(stdout);
let _clear_response_handlers = util::defer({
let response_handlers = response_handlers.clone();
move || {
@ -233,12 +273,17 @@ impl LanguageServer {
smol::future::yield_now().await;
}
}
.log_err()
});
let (output_done_tx, output_done_rx) = barrier::channel();
let output_task = cx.background().spawn({
let response_handlers = response_handlers.clone();
async move {
async fn handle_output<Stdin>(
stdin: Stdin,
outbound_rx: channel::Receiver<Vec<u8>>,
output_done_tx: barrier::Sender,
response_handlers: Arc<Mutex<Option<HashMap<usize, ResponseHandler>>>>,
) -> anyhow::Result<()>
where
Stdin: AsyncWrite + Unpin + Send + 'static,
{
let mut stdin = BufWriter::new(stdin);
let _clear_response_handlers = util::defer({
let response_handlers = response_handlers.clone();
move || {
@ -259,24 +304,6 @@ impl LanguageServer {
drop(output_done_tx);
Ok(())
}
.log_err()
});
Self {
server_id,
notification_handlers,
response_handlers,
name: Default::default(),
capabilities: Default::default(),
next_id: Default::default(),
outbound_tx,
executor: cx.background(),
io_tasks: Mutex::new(Some((input_task, output_task))),
output_done_rx: Mutex::new(Some(output_done_rx)),
root_path: root_path.to_path_buf(),
_server: server,
}
}
/// Initializes a language server.
/// Note that `options` is used directly to construct [`InitializeParams`],
@ -389,7 +416,7 @@ impl LanguageServer {
output_done.recv().await;
log::debug!("language server shutdown finished");
drop(tasks);
Ok(())
anyhow::Ok(())
}
.log_err(),
)

View file

@ -5831,7 +5831,7 @@ impl Project {
})?;
}
Ok(())
anyhow::Ok(())
}
.log_err(),
)

View file

@ -124,11 +124,15 @@ pub trait TryFutureExt {
fn warn_on_err(self) -> LogErrorFuture<Self>
where
Self: Sized;
fn unwrap(self) -> UnwrapFuture<Self>
where
Self: Sized;
}
impl<F, T> TryFutureExt for F
impl<F, T, E> TryFutureExt for F
where
F: Future<Output = anyhow::Result<T>>,
F: Future<Output = Result<T, E>>,
E: std::fmt::Debug,
{
fn log_err(self) -> LogErrorFuture<Self>
where
@ -143,17 +147,25 @@ where
{
LogErrorFuture(self, log::Level::Warn)
}
fn unwrap(self) -> UnwrapFuture<Self>
where
Self: Sized,
{
UnwrapFuture(self)
}
}
pub struct LogErrorFuture<F>(F, log::Level);
impl<F, T> Future for LogErrorFuture<F>
impl<F, T, E> Future for LogErrorFuture<F>
where
F: Future<Output = anyhow::Result<T>>,
F: Future<Output = Result<T, E>>,
E: std::fmt::Debug,
{
type Output = Option<T>;
fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let level = self.1;
let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };
match inner.poll(cx) {
@ -169,6 +181,24 @@ where
}
}
pub struct UnwrapFuture<F>(F);
impl<F, T, E> Future for UnwrapFuture<F>
where
F: Future<Output = Result<T, E>>,
E: std::fmt::Debug,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };
match inner.poll(cx) {
Poll::Ready(result) => Poll::Ready(result.unwrap()),
Poll::Pending => Poll::Pending,
}
}
}
struct Defer<F: FnOnce()>(Option<F>);
impl<F: FnOnce()> Drop for Defer<F> {