Detailed changes
@@ -3,11 +3,13 @@ use gpui::{
};
use postage::watch;
use project::Project;
+use std::fmt::Write;
use workspace::{Settings, StatusItemView};
pub struct DiagnosticSummary {
settings: watch::Receiver<Settings>,
summary: project::DiagnosticSummary,
+ in_progress: bool,
}
impl DiagnosticSummary {
@@ -16,16 +18,26 @@ impl DiagnosticSummary {
settings: watch::Receiver<Settings>,
cx: &mut ViewContext<Self>,
) -> Self {
- cx.subscribe(project, |this, project, event, cx| {
- if let project::Event::DiskBasedDiagnosticsUpdated { .. } = event {
+ cx.subscribe(project, |this, project, event, cx| match event {
+ project::Event::DiskBasedDiagnosticsUpdated { .. } => {
this.summary = project.read(cx).diagnostic_summary(cx);
cx.notify();
}
+ project::Event::DiskBasedDiagnosticsStarted => {
+ this.in_progress = true;
+ cx.notify();
+ }
+ project::Event::DiskBasedDiagnosticsFinished => {
+ this.in_progress = false;
+ cx.notify();
+ }
+ _ => {}
})
.detach();
Self {
settings,
summary: project.read(cx).diagnostic_summary(cx),
+ in_progress: project.read(cx).is_running_disk_based_diagnostics(),
}
}
}
@@ -43,17 +55,21 @@ impl View for DiagnosticSummary {
enum Tag {}
let theme = &self.settings.borrow().theme.project_diagnostics;
+ let mut message = String::new();
+ if self.in_progress {
+ message.push_str("Checking... ");
+ }
+ write!(
+ message,
+ "Errors: {}, Warnings: {}",
+ self.summary.error_count, self.summary.warning_count
+ )
+ .unwrap();
MouseEventHandler::new::<Tag, _, _, _>(0, cx, |_, _| {
- Label::new(
- format!(
- "Errors: {}, Warnings: {}",
- self.summary.error_count, self.summary.warning_count
- ),
- theme.status_bar_item.text.clone(),
- )
- .contained()
- .with_style(theme.status_bar_item.container)
- .boxed()
+ Label::new(message, theme.status_bar_item.text.clone())
+ .contained()
+ .with_style(theme.status_bar_item.container)
+ .boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(|cx| cx.dispatch_action(crate::Deploy))
@@ -33,6 +33,7 @@ pub struct Project {
client_state: ProjectClientState,
collaborators: HashMap<PeerId, Collaborator>,
subscriptions: Vec<client::Subscription>,
+ pending_disk_based_diagnostics: isize,
}
enum ProjectClientState {
@@ -60,7 +61,9 @@ pub struct Collaborator {
pub enum Event {
ActiveEntryChanged(Option<ProjectEntry>),
WorktreeRemoved(WorktreeId),
+ DiskBasedDiagnosticsStarted,
DiskBasedDiagnosticsUpdated { worktree_id: WorktreeId },
+ DiskBasedDiagnosticsFinished,
DiagnosticsUpdated(ProjectPath),
}
@@ -187,6 +190,7 @@ impl Project {
client,
user_store,
fs,
+ pending_disk_based_diagnostics: 0,
}
})
}
@@ -259,6 +263,11 @@ impl Project {
cx,
Self::handle_update_diagnostic_summary,
),
+ client.subscribe_to_entity(
+ remote_id,
+ cx,
+ Self::handle_disk_based_diagnostics_updating,
+ ),
client.subscribe_to_entity(
remote_id,
cx,
@@ -273,6 +282,7 @@ impl Project {
remote_id,
replica_id,
},
+ pending_disk_based_diagnostics: 0,
};
for worktree in worktrees {
this.add_worktree(worktree, cx);
@@ -506,17 +516,29 @@ impl Project {
fn add_worktree(&mut self, worktree: ModelHandle<Worktree>, cx: &mut ModelContext<Self>) {
cx.observe(&worktree, |_, _, cx| cx.notify()).detach();
- cx.subscribe(&worktree, |_, worktree, event, cx| match event {
+ cx.subscribe(&worktree, move |this, worktree, event, cx| match event {
worktree::Event::DiagnosticsUpdated(path) => {
cx.emit(Event::DiagnosticsUpdated(ProjectPath {
worktree_id: worktree.read(cx).id(),
path: path.clone(),
}));
}
+ worktree::Event::DiskBasedDiagnosticsUpdating => {
+ if this.pending_disk_based_diagnostics == 0 {
+ cx.emit(Event::DiskBasedDiagnosticsStarted);
+ }
+ this.pending_disk_based_diagnostics += 1;
+ }
worktree::Event::DiskBasedDiagnosticsUpdated => {
+ this.pending_disk_based_diagnostics -= 1;
cx.emit(Event::DiskBasedDiagnosticsUpdated {
worktree_id: worktree.read(cx).id(),
});
+ if this.pending_disk_based_diagnostics == 0 {
+ if this.pending_disk_based_diagnostics == 0 {
+ cx.emit(Event::DiskBasedDiagnosticsFinished);
+ }
+ }
}
})
.detach();
@@ -539,6 +561,10 @@ impl Project {
}
}
+ pub fn is_running_disk_based_diagnostics(&self) -> bool {
+ self.pending_disk_based_diagnostics > 0
+ }
+
pub fn diagnostic_summary(&self, cx: &AppContext) -> DiagnosticSummary {
let mut summary = DiagnosticSummary::default();
for (_, path_summary) in self.diagnostic_summaries(cx) {
@@ -716,6 +742,24 @@ impl Project {
Ok(())
}
+ fn handle_disk_based_diagnostics_updating(
+ &mut self,
+ envelope: TypedEnvelope<proto::DiskBasedDiagnosticsUpdating>,
+ _: Arc<Client>,
+ cx: &mut ModelContext<Self>,
+ ) -> Result<()> {
+ let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
+ if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
+ worktree.update(cx, |worktree, cx| {
+ worktree
+ .as_remote()
+ .unwrap()
+ .disk_based_diagnostics_updating(cx);
+ });
+ }
+ Ok(())
+ }
+
fn handle_disk_based_diagnostics_updated(
&mut self,
envelope: TypedEnvelope<proto::DiskBasedDiagnosticsUpdated>,
@@ -67,6 +67,7 @@ pub enum Worktree {
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Event {
+ DiskBasedDiagnosticsUpdating,
DiskBasedDiagnosticsUpdated,
DiagnosticsUpdated(Arc<Path>),
}
@@ -1133,6 +1134,11 @@ impl LocalWorktree {
.log_err()
.flatten()
{
+ enum DiagnosticProgress {
+ Updating,
+ Updated,
+ }
+
let disk_based_sources = language
.disk_based_diagnostic_sources()
.cloned()
@@ -1155,10 +1161,21 @@ impl LocalWorktree {
while let Ok(diagnostics) = diagnostics_rx.recv().await {
if let Some(handle) = cx.read(|cx| this.upgrade(cx)) {
handle.update(&mut cx, |this, cx| {
+ if !has_disk_based_diagnostic_progress_token {
+ smol::block_on(
+ disk_based_diagnostics_done_tx
+ .send(DiagnosticProgress::Updating),
+ )
+ .ok();
+ }
this.update_diagnostics(diagnostics, &disk_based_sources, cx)
.log_err();
if !has_disk_based_diagnostic_progress_token {
- smol::block_on(disk_based_diagnostics_done_tx.send(())).ok();
+ smol::block_on(
+ disk_based_diagnostics_done_tx
+ .send(DiagnosticProgress::Updated),
+ )
+ .ok();
}
})
} else {
@@ -1181,13 +1198,23 @@ impl LocalWorktree {
match params.value {
lsp::ProgressParamsValue::WorkDone(progress) => match progress {
lsp::WorkDoneProgress::Begin(_) => {
+ if pending_disk_based_diagnostics == 0 {
+ smol::block_on(
+ disk_based_diagnostics_done_tx
+ .send(DiagnosticProgress::Updating),
+ )
+ .ok();
+ }
pending_disk_based_diagnostics += 1;
}
lsp::WorkDoneProgress::End(_) => {
pending_disk_based_diagnostics -= 1;
if pending_disk_based_diagnostics == 0 {
- smol::block_on(disk_based_diagnostics_done_tx.send(()))
- .ok();
+ smol::block_on(
+ disk_based_diagnostics_done_tx
+ .send(DiagnosticProgress::Updated),
+ )
+ .ok();
}
}
_ => {}
@@ -1198,21 +1225,41 @@ impl LocalWorktree {
.detach();
let rpc = self.client.clone();
cx.spawn_weak(|this, mut cx| async move {
- while let Ok(()) = disk_based_diagnostics_done_rx.recv().await {
+ while let Ok(progress) = disk_based_diagnostics_done_rx.recv().await {
if let Some(handle) = cx.read(|cx| this.upgrade(cx)) {
- let message = handle.update(&mut cx, |this, cx| {
- cx.emit(Event::DiskBasedDiagnosticsUpdated);
- let this = this.as_local().unwrap();
- this.share
- .as_ref()
- .map(|share| proto::DiskBasedDiagnosticsUpdated {
- project_id: share.project_id,
- worktree_id: this.id().to_proto(),
- })
- });
-
- if let Some(message) = message {
- rpc.send(message).await.log_err();
+ match progress {
+ DiagnosticProgress::Updating => {
+ let message = handle.update(&mut cx, |this, cx| {
+ cx.emit(Event::DiskBasedDiagnosticsUpdating);
+ let this = this.as_local().unwrap();
+ this.share.as_ref().map(|share| {
+ proto::DiskBasedDiagnosticsUpdating {
+ project_id: share.project_id,
+ worktree_id: this.id().to_proto(),
+ }
+ })
+ });
+
+ if let Some(message) = message {
+ rpc.send(message).await.log_err();
+ }
+ }
+ DiagnosticProgress::Updated => {
+ let message = handle.update(&mut cx, |this, cx| {
+ cx.emit(Event::DiskBasedDiagnosticsUpdated);
+ let this = this.as_local().unwrap();
+ this.share.as_ref().map(|share| {
+ proto::DiskBasedDiagnosticsUpdated {
+ project_id: share.project_id,
+ worktree_id: this.id().to_proto(),
+ }
+ })
+ });
+
+ if let Some(message) = message {
+ rpc.send(message).await.log_err();
+ }
+ }
}
} else {
break;
@@ -1691,6 +1738,10 @@ impl RemoteWorktree {
}
}
+ pub fn disk_based_diagnostics_updating(&self, cx: &mut ModelContext<Worktree>) {
+ cx.emit(Event::DiskBasedDiagnosticsUpdating);
+ }
+
pub fn disk_based_diagnostics_updated(&self, cx: &mut ModelContext<Worktree>) {
cx.emit(Event::DiskBasedDiagnosticsUpdated);
}
@@ -3848,6 +3899,11 @@ mod tests {
let mut events = subscribe(&tree, &mut cx);
fake_server.start_progress(&progress_token).await;
+ assert_eq!(
+ events.next().await.unwrap(),
+ Event::DiskBasedDiagnosticsUpdating
+ );
+
fake_server.start_progress(&progress_token).await;
fake_server.end_progress(&progress_token).await;
fake_server.start_progress(&progress_token).await;
@@ -3864,18 +3920,17 @@ mod tests {
}],
})
.await;
-
- let event = events.next().await.unwrap();
assert_eq!(
- event,
+ events.next().await.unwrap(),
Event::DiagnosticsUpdated(Arc::from(Path::new("a.rs")))
);
fake_server.end_progress(&progress_token).await;
fake_server.end_progress(&progress_token).await;
-
- let event = events.next().await.unwrap();
- assert_eq!(event, Event::DiskBasedDiagnosticsUpdated);
+ assert_eq!(
+ events.next().await.unwrap(),
+ Event::DiskBasedDiagnosticsUpdated
+ );
let buffer = tree
.update(&mut cx, |tree, cx| tree.open_buffer("a.rs", cx))
@@ -26,30 +26,31 @@ message Envelope {
ShareWorktree share_worktree = 19;
UpdateWorktree update_worktree = 20;
UpdateDiagnosticSummary update_diagnostic_summary = 21;
- DiskBasedDiagnosticsUpdated disk_based_diagnostics_updated = 22;
-
- OpenBuffer open_buffer = 23;
- OpenBufferResponse open_buffer_response = 24;
- CloseBuffer close_buffer = 25;
- UpdateBuffer update_buffer = 26;
- SaveBuffer save_buffer = 27;
- BufferSaved buffer_saved = 28;
-
- GetChannels get_channels = 29;
- GetChannelsResponse get_channels_response = 30;
- JoinChannel join_channel = 31;
- JoinChannelResponse join_channel_response = 32;
- LeaveChannel leave_channel = 33;
- SendChannelMessage send_channel_message = 34;
- SendChannelMessageResponse send_channel_message_response = 35;
- ChannelMessageSent channel_message_sent = 36;
- GetChannelMessages get_channel_messages = 37;
- GetChannelMessagesResponse get_channel_messages_response = 38;
-
- UpdateContacts update_contacts = 39;
-
- GetUsers get_users = 40;
- GetUsersResponse get_users_response = 41;
+ DiskBasedDiagnosticsUpdating disk_based_diagnostics_updating = 22;
+ DiskBasedDiagnosticsUpdated disk_based_diagnostics_updated = 23;
+
+ OpenBuffer open_buffer = 24;
+ OpenBufferResponse open_buffer_response = 25;
+ CloseBuffer close_buffer = 26;
+ UpdateBuffer update_buffer = 27;
+ SaveBuffer save_buffer = 28;
+ BufferSaved buffer_saved = 29;
+
+ GetChannels get_channels = 30;
+ GetChannelsResponse get_channels_response = 31;
+ JoinChannel join_channel = 32;
+ JoinChannelResponse join_channel_response = 33;
+ LeaveChannel leave_channel = 34;
+ SendChannelMessage send_channel_message = 35;
+ SendChannelMessageResponse send_channel_message_response = 36;
+ ChannelMessageSent channel_message_sent = 37;
+ GetChannelMessages get_channel_messages = 38;
+ GetChannelMessagesResponse get_channel_messages_response = 39;
+
+ UpdateContacts update_contacts = 40;
+
+ GetUsers get_users = 41;
+ GetUsersResponse get_users_response = 42;
}
}
@@ -181,6 +182,11 @@ message DiagnosticSummary {
uint32 hint_count = 7;
}
+message DiskBasedDiagnosticsUpdating {
+ uint64 project_id = 1;
+ uint64 worktree_id = 2;
+}
+
message DiskBasedDiagnosticsUpdated {
uint64 project_id = 1;
uint64 worktree_id = 2;
@@ -126,6 +126,7 @@ messages!(
ChannelMessageSent,
CloseBuffer,
DiskBasedDiagnosticsUpdated,
+ DiskBasedDiagnosticsUpdating,
Error,
GetChannelMessages,
GetChannelMessagesResponse,
@@ -183,6 +184,7 @@ entity_messages!(
BufferSaved,
CloseBuffer,
DiskBasedDiagnosticsUpdated,
+ DiskBasedDiagnosticsUpdating,
JoinProject,
LeaveProject,
OpenBuffer,
@@ -72,6 +72,7 @@ impl Server {
.add_handler(Server::share_worktree)
.add_handler(Server::update_worktree)
.add_handler(Server::update_diagnostic_summary)
+ .add_handler(Server::disk_based_diagnostics_updating)
.add_handler(Server::disk_based_diagnostics_updated)
.add_handler(Server::open_buffer)
.add_handler(Server::close_buffer)
@@ -556,6 +557,22 @@ impl Server {
Ok(())
}
+ async fn disk_based_diagnostics_updating(
+ self: Arc<Server>,
+ request: TypedEnvelope<proto::DiskBasedDiagnosticsUpdating>,
+ ) -> tide::Result<()> {
+ let receiver_ids = self
+ .state()
+ .project_connection_ids(request.payload.project_id, request.sender_id)
+ .ok_or_else(|| anyhow!(NO_SUCH_PROJECT))?;
+ broadcast(request.sender_id, receiver_ids, |connection_id| {
+ self.peer
+ .forward_send(request.sender_id, connection_id, request.payload.clone())
+ })
+ .await?;
+ Ok(())
+ }
+
async fn disk_based_diagnostics_updated(
self: Arc<Server>,
request: TypedEnvelope<proto::DiskBasedDiagnosticsUpdated>,