From 76c1160ffa626fc5f07b309420e6666eb79a3311 Mon Sep 17 00:00:00 2001 From: veetaha Date: Sun, 10 May 2020 18:35:33 +0300 Subject: Migrate flycheck to fully-lsp-compatible progress reports (introduce ra_progress crate) --- crates/ra_progress/Cargo.toml | 8 +++ crates/ra_progress/src/lib.rs | 129 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 crates/ra_progress/Cargo.toml create mode 100644 crates/ra_progress/src/lib.rs (limited to 'crates/ra_progress') diff --git a/crates/ra_progress/Cargo.toml b/crates/ra_progress/Cargo.toml new file mode 100644 index 000000000..c7f7c6dd3 --- /dev/null +++ b/crates/ra_progress/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "ra_progress" +version = "0.1.0" +authors = ["rust-analyzer developers"] +edition = "2018" + +[dependencies] +crossbeam-channel = { version = "0.4" } diff --git a/crates/ra_progress/src/lib.rs b/crates/ra_progress/src/lib.rs new file mode 100644 index 000000000..0ff1f846c --- /dev/null +++ b/crates/ra_progress/src/lib.rs @@ -0,0 +1,129 @@ +//! General-purpose instrumentation for progress reporting. +//! +//! Note: +//! Most of the methods accept `&mut self` just to be more restrictive (for forward compat) +//! even tho for some of them we can weaken this requirement to shared reference (`&self`). + +use crossbeam_channel::Receiver; +use std::fmt; + +#[derive(Debug)] +pub enum ProgressStatus { + Begin(B), + Progress(P), + End, +} + +pub struct Progress(Option>>); +impl Progress { + pub fn report(&mut self, payload: P) { + self.report_with(|| payload); + } + + pub fn report_with(&mut self, payload: impl FnOnce() -> P) { + self.send_status(|| ProgressStatus::Progress(payload())); + } + + fn send_status(&self, status: impl FnOnce() -> ProgressStatus) { + if let Some(sender) = &self.0 { + sender.try_send(status()).expect("progress report must not block"); + } + } +} + +impl Drop for Progress { + fn drop(&mut self) { + self.send_status(|| ProgressStatus::End); + } +} + +pub struct ProgressSource(Option>>); +impl ProgressSource { + pub fn real_if(real: bool) -> (Receiver>, Self) { + if real { + let (sender, receiver) = crossbeam_channel::unbounded(); + (receiver, Self(Some(sender))) + } else { + (crossbeam_channel::never(), Self(None)) + } + } + + pub fn begin(&mut self, payload: B) -> Progress { + self.begin_with(|| payload) + } + + pub fn begin_with(&mut self, payload: impl FnOnce() -> B) -> Progress { + let progress = Progress(self.0.clone()); + progress.send_status(|| ProgressStatus::Begin(payload())); + progress + } +} + +impl Clone for ProgressSource { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl fmt::Debug for ProgressSource { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("ProgressSource").field(&self.0).finish() + } +} + +pub type U32ProgressStatus = ProgressStatus; + +#[derive(Debug)] +pub struct U32ProgressReport { + pub processed: u32, + pub total: u32, +} +impl U32ProgressReport { + pub fn percentage(&self) -> f64 { + f64::from(100 * self.processed) / f64::from(self.total) + } + pub fn to_message(&self, prefix: &str, unit: &str) -> String { + format!("{} ({}/{} {})", prefix, self.processed, self.total, unit) + } +} + +pub struct U32Progress { + inner: Progress, + processed: u32, + total: u32, +} + +#[derive(Debug, Eq, PartialEq)] +pub struct IsDone(pub bool); + +impl U32Progress { + pub fn report(&mut self, new_processed: u32) -> IsDone { + if self.processed < new_processed { + self.processed = new_processed; + self.inner.report(U32ProgressReport { processed: new_processed, total: self.total }); + } + IsDone(self.processed >= self.total) + } +} + +#[derive(Clone)] +pub struct U32ProgressSource { + inner: ProgressSource, +} + +impl U32ProgressSource { + pub fn real_if( + real: bool, + ) -> (Receiver>, Self) { + let (recv, inner) = ProgressSource::real_if(real); + (recv, Self { inner }) + } + + pub fn begin(&mut self, initial: u32, total: u32) -> U32Progress { + U32Progress { + inner: self.inner.begin(U32ProgressReport { processed: initial, total }), + processed: initial, + total, + } + } +} -- cgit v1.2.3