Fix warnings/errors now that AsyncAppContext::update returns Result

This commit is contained in:
Antonio Scandurra 2023-04-18 14:58:57 +02:00
parent 31e6bb4fc1
commit d03c431f9a
33 changed files with 494 additions and 371 deletions

1
Cargo.lock generated
View file

@ -3366,6 +3366,7 @@ dependencies = [
"project", "project",
"settings", "settings",
"theme", "theme",
"util",
"workspace", "workspace",
] ]

View file

@ -2,7 +2,7 @@ use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage};
use editor::Editor; use editor::Editor;
use futures::StreamExt; use futures::StreamExt;
use gpui::{ use gpui::{
actions, actions, anyhow,
elements::*, elements::*,
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
Action, AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle, Action, AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle,
@ -73,11 +73,12 @@ impl ActivityIndicator {
status: event, status: event,
}); });
cx.notify(); cx.notify();
}); })?;
} else { } else {
break; break;
} }
} }
anyhow::Ok(())
}) })
.detach(); .detach();
cx.observe(&project, |_, _, cx| cx.notify()).detach(); cx.observe(&project, |_, _, cx| cx.notify()).detach();

View file

@ -113,7 +113,7 @@ pub fn notify_of_any_new_update(
.read(cx) .read(cx)
.set_should_show_update_notification(false, cx) .set_should_show_update_notification(false, cx)
.detach_and_log_err(cx); .detach_and_log_err(cx);
}); })?;
} }
} }
anyhow::Ok(()) anyhow::Ok(())

View file

@ -6115,7 +6115,8 @@ async fn test_basic_following(
.update(cx_a, |workspace, cx| { .update(cx_a, |workspace, cx| {
workspace::Pane::go_back(workspace, None, cx) workspace::Pane::go_back(workspace, None, cx)
}) })
.await; .await
.unwrap();
deterministic.run_until_parked(); deterministic.run_until_parked();
workspace_b.read_with(cx_b, |workspace, cx| { workspace_b.read_with(cx_b, |workspace, cx| {
assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b1.id()); assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b1.id());
@ -6125,7 +6126,8 @@ async fn test_basic_following(
.update(cx_a, |workspace, cx| { .update(cx_a, |workspace, cx| {
workspace::Pane::go_back(workspace, None, cx) workspace::Pane::go_back(workspace, None, cx)
}) })
.await; .await
.unwrap();
deterministic.run_until_parked(); deterministic.run_until_parked();
workspace_b.read_with(cx_b, |workspace, cx| { workspace_b.read_with(cx_b, |workspace, cx| {
assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b2.id()); assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b2.id());
@ -6135,7 +6137,8 @@ async fn test_basic_following(
.update(cx_a, |workspace, cx| { .update(cx_a, |workspace, cx| {
workspace::Pane::go_forward(workspace, None, cx) workspace::Pane::go_forward(workspace, None, cx)
}) })
.await; .await
.unwrap();
deterministic.run_until_parked(); deterministic.run_until_parked();
workspace_b.read_with(cx_b, |workspace, cx| { workspace_b.read_with(cx_b, |workspace, cx| {
assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b1.id()); assert_eq!(workspace.active_item(cx).unwrap().id(), editor_b1.id());

View file

@ -126,7 +126,7 @@ fn join_project(action: &JoinProject, app_state: Arc<AppState>, cx: &mut AppCont
} }
} }
} }
}); })?;
anyhow::Ok(()) anyhow::Ok(())
}) })

View file

@ -67,7 +67,7 @@ impl PickerDelegate for ContactFinder {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.potential_contacts = potential_contacts.into(); this.potential_contacts = potential_contacts.into();
cx.notify(); cx.notify();
}); })?;
anyhow::Ok(()) anyhow::Ok(())
} }
.log_err() .log_err()

View file

@ -7,6 +7,7 @@ use gpui::{
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use settings::Settings; use settings::Settings;
use std::cmp; use std::cmp;
use util::ResultExt;
use workspace::Workspace; use workspace::Workspace;
pub fn init(cx: &mut AppContext) { pub fn init(cx: &mut AppContext) {
@ -188,7 +189,8 @@ impl PickerDelegate for CommandPalette {
} else { } else {
this.selected_ix = cmp::min(this.selected_ix, this.matches.len() - 1); this.selected_ix = cmp::min(this.selected_ix, this.matches.len() - 1);
} }
}); })
.log_err();
}) })
} }

View file

@ -213,7 +213,7 @@ impl ProjectDiagnosticsEditor {
let buffer = project let buffer = project
.update(&mut cx, |project, cx| project.open_buffer(path.clone(), cx)) .update(&mut cx, |project, cx| project.open_buffer(path.clone(), cx))
.await?; .await?;
this.update(&mut cx, |this, cx| this.populate_excerpts(path, buffer, cx)) this.update(&mut cx, |this, cx| this.populate_excerpts(path, buffer, cx))?;
} }
Result::<_, anyhow::Error>::Ok(()) Result::<_, anyhow::Error>::Ok(())
} }

View file

@ -20,7 +20,7 @@ mod editor_tests;
pub mod test; pub mod test;
use aho_corasick::AhoCorasick; use aho_corasick::AhoCorasick;
use anyhow::Result; use anyhow::{anyhow, Result};
use blink_manager::BlinkManager; use blink_manager::BlinkManager;
use clock::ReplicaId; use clock::ReplicaId;
use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque}; use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
@ -2397,7 +2397,7 @@ impl Editor {
} else if this.hide_context_menu(cx).is_none() { } else if this.hide_context_menu(cx).is_none() {
this.update_visible_copilot_suggestion(cx); this.update_visible_copilot_suggestion(cx);
} }
}); })?;
} }
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
} }
@ -2534,11 +2534,13 @@ impl Editor {
prev_task.await; prev_task.await;
task = this task = this
.upgrade(&cx) .upgrade(&cx)
.and_then(|this| this.update(&mut cx, |this, _| this.code_actions_task.take())); .ok_or_else(|| anyhow!("editor dropped"))?
.update(&mut cx, |this, _| this.code_actions_task.take())?;
} }
if let Some(this) = this.upgrade(&cx) { this.upgrade(&cx)
this.update(&mut cx, |this, cx| { .ok_or_else(|| anyhow!("editor dropped"))?
.update(&mut cx, |this, cx| {
if this.focused { if this.focused {
if let Some((buffer, actions)) = this.available_code_actions.clone() { if let Some((buffer, actions)) = this.available_code_actions.clone() {
this.show_context_menu( this.show_context_menu(
@ -2553,8 +2555,8 @@ impl Editor {
); );
} }
} }
}) })?;
}
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
}) })
.detach_and_log_err(cx); .detach_and_log_err(cx);
@ -2666,7 +2668,7 @@ impl Editor {
cx, cx,
); );
}); });
}); })?;
Ok(()) Ok(())
} }
@ -2697,6 +2699,7 @@ impl Editor {
}); });
cx.notify(); cx.notify();
}) })
.log_err();
} }
})); }));
None None
@ -2786,7 +2789,8 @@ impl Editor {
cx, cx,
); );
cx.notify(); cx.notify();
}); })
.log_err();
} }
})); }));
None None
@ -2823,7 +2827,8 @@ impl Editor {
let mut completions = Vec::new(); let mut completions = Vec::new();
completions.extend(completion.log_err().into_iter().flatten()); completions.extend(completion.log_err().into_iter().flatten());
completions.extend(completions_cycling.log_err().into_iter().flatten()); completions.extend(completions_cycling.log_err().into_iter().flatten());
this.upgrade(&cx)?.update(&mut cx, |this, cx| { this.upgrade(&cx)?
.update(&mut cx, |this, cx| {
if !completions.is_empty() { if !completions.is_empty() {
this.copilot_state.completions.clear(); this.copilot_state.completions.clear();
this.copilot_state.active_completion_index = 0; this.copilot_state.active_completion_index = 0;
@ -2833,7 +2838,8 @@ impl Editor {
} }
this.update_visible_copilot_suggestion(cx); this.update_visible_copilot_suggestion(cx);
} }
}); })
.log_err()?;
Some(()) Some(())
}); });
@ -5416,7 +5422,7 @@ impl Editor {
let definitions = definitions.await?; let definitions = definitions.await?;
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx); Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
}); })?;
Ok::<(), anyhow::Error>(()) Ok::<(), anyhow::Error>(())
}) })
@ -5517,7 +5523,7 @@ impl Editor {
Self::open_locations_in_multibuffer( Self::open_locations_in_multibuffer(
workspace, locations, replica_id, title, cx, workspace, locations, replica_id, title, cx,
); );
}); })?;
Ok(()) Ok(())
}, },
@ -5705,7 +5711,7 @@ impl Editor {
editor: rename_editor, editor: rename_editor,
block_id, block_id,
}); });
}); })?;
} }
Ok(()) Ok(())
@ -5751,7 +5757,7 @@ impl Editor {
editor.update(&mut cx, |editor, cx| { editor.update(&mut cx, |editor, cx| {
editor.refresh_document_highlights(cx); editor.refresh_document_highlights(cx);
}); })?;
Ok(()) Ok(())
})) }))
} }
@ -6552,9 +6558,16 @@ impl Editor {
let position = action.position; let position = action.position;
let anchor = action.anchor; let anchor = action.anchor;
cx.spawn_weak(|_, mut cx| async move { cx.spawn_weak(|_, mut cx| async move {
let editor = editor.await.log_err()?.downcast::<Editor>()?; let editor = editor
.await?
.downcast::<Editor>()
.ok_or_else(|| anyhow!("opened item was not an editor"))?;
editor.update(&mut cx, |editor, cx| { editor.update(&mut cx, |editor, cx| {
let buffer = editor.buffer().read(cx).as_singleton()?; let buffer = editor
.buffer()
.read(cx)
.as_singleton()
.ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
let buffer = buffer.read(cx); let buffer = buffer.read(cx);
let cursor = if buffer.can_resolve(&anchor) { let cursor = if buffer.can_resolve(&anchor) {
language::ToPoint::to_point(&anchor, buffer) language::ToPoint::to_point(&anchor, buffer)
@ -6568,11 +6581,11 @@ impl Editor {
}); });
editor.nav_history = nav_history; editor.nav_history = nav_history;
Some(()) anyhow::Ok(())
})?; })??;
Some(()) anyhow::Ok(())
}) })
.detach() .detach_and_log_err(cx);
} }
fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> { fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {

View file

@ -208,7 +208,7 @@ fn show_hover(
local_diagnostic, local_diagnostic,
primary_diagnostic, primary_diagnostic,
}); });
}); })?;
} }
// Construct new hover popover from hover request // Construct new hover popover from hover request
@ -254,7 +254,7 @@ fn show_hover(
this.hover_state.info_popover = hover_popover; this.hover_state.info_popover = hover_popover;
cx.notify(); cx.notify();
}); })?;
} }
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
} }

View file

@ -80,7 +80,9 @@ impl FollowableItem for Editor {
}) })
}); });
let editor = editor.unwrap_or_else(|| { let editor = if let Some(editor) = editor {
editor
} else {
pane.update(&mut cx, |_, cx| { pane.update(&mut cx, |_, cx| {
let multibuffer = cx.add_model(|cx| { let multibuffer = cx.add_model(|cx| {
let mut multibuffer; let mut multibuffer;
@ -116,8 +118,8 @@ impl FollowableItem for Editor {
}); });
cx.add_view(|cx| Editor::for_multibuffer(multibuffer, Some(project), cx)) cx.add_view(|cx| Editor::for_multibuffer(multibuffer, Some(project), cx))
}) })?
}); };
editor.update(&mut cx, |editor, cx| { editor.update(&mut cx, |editor, cx| {
editor.remote_id = Some(remote_id); editor.remote_id = Some(remote_id);
@ -154,7 +156,7 @@ impl FollowableItem for Editor {
} }
anyhow::Ok(()) anyhow::Ok(())
})?; })??;
Ok(editor) Ok(editor)
})) }))
@ -387,7 +389,7 @@ impl FollowableItem for Editor {
offset: vec2f(message.scroll_x, message.scroll_y) offset: vec2f(message.scroll_x, message.scroll_y)
}, cx); }, cx);
} }
}); })?;
Ok(()) Ok(())
}) })
} }
@ -670,7 +672,7 @@ impl Item for Editor {
let transaction = reload_buffers.log_err().await; let transaction = reload_buffers.log_err().await;
this.update(&mut cx, |editor, cx| { this.update(&mut cx, |editor, cx| {
editor.request_autoscroll(Autoscroll::fit(), cx) editor.request_autoscroll(Autoscroll::fit(), cx)
}); })?;
buffer.update(&mut cx, |buffer, _| { buffer.update(&mut cx, |buffer, _| {
if let Some(transaction) = transaction { if let Some(transaction) = transaction {
if !buffer.is_singleton() { if !buffer.is_singleton() {

View file

@ -261,7 +261,7 @@ pub fn show_link_definition(
hide_link_definition(this, cx); hide_link_definition(this, cx);
} }
} }
}) })?;
} }
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())

View file

@ -248,10 +248,12 @@ impl ScrollManager {
self.hide_scrollbar_task = Some(cx.spawn_weak(|editor, mut cx| async move { self.hide_scrollbar_task = Some(cx.spawn_weak(|editor, mut cx| async move {
cx.background().timer(SCROLLBAR_SHOW_INTERVAL).await; cx.background().timer(SCROLLBAR_SHOW_INTERVAL).await;
if let Some(editor) = editor.upgrade(&cx) { if let Some(editor) = editor.upgrade(&cx) {
editor.update(&mut cx, |editor, cx| { editor
.update(&mut cx, |editor, cx| {
editor.scroll_manager.show_scrollbars = false; editor.scroll_manager.show_scrollbars = false;
cx.notify(); cx.notify();
}); })
.log_err();
} }
})); }));
} else { } else {

View file

@ -132,9 +132,12 @@ impl FeedbackEditor {
if answer == Some(0) { if answer == Some(0) {
match FeedbackEditor::submit_feedback(&feedback_text, client, specs).await { match FeedbackEditor::submit_feedback(&feedback_text, client, specs).await {
Ok(_) => this.update(&mut cx, |_, cx| { Ok(_) => {
this.update(&mut cx, |_, cx| {
cx.dispatch_action(workspace::CloseActiveItem); cx.dispatch_action(workspace::CloseActiveItem);
}), })
.log_err();
}
Err(error) => { Err(error) => {
log::error!("{}", error); log::error!("{}", error);
this.update(&mut cx, |_, cx| { this.update(&mut cx, |_, cx| {
@ -144,6 +147,7 @@ impl FeedbackEditor {
&["OK"], &["OK"],
); );
}) })
.log_err();
} }
} }
} }
@ -213,10 +217,10 @@ impl FeedbackEditor {
.add_view(|cx| FeedbackEditor::new(system_specs, project, buffer, cx)); .add_view(|cx| FeedbackEditor::new(system_specs, project, buffer, cx));
workspace.add_item(Box::new(feedback_editor), cx); workspace.add_item(Box::new(feedback_editor), cx);
}) })
})?
.await
}) })
.await; .detach_and_log_err(cx);
})
.detach();
} }
} }

View file

@ -13,7 +13,7 @@ use std::{
Arc, Arc,
}, },
}; };
use util::post_inc; use util::{post_inc, ResultExt};
use workspace::Workspace; use workspace::Workspace;
pub struct FileFinder { pub struct FileFinder {
@ -186,7 +186,8 @@ impl FileFinder {
let did_cancel = cancel_flag.load(atomic::Ordering::Relaxed); let did_cancel = cancel_flag.load(atomic::Ordering::Relaxed);
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.set_matches(search_id, did_cancel, query, matches, cx) this.set_matches(search_id, did_cancel, query, matches, cx)
}); })
.log_err();
}) })
} }

View file

@ -7,7 +7,6 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::Arc,
}; };
use util::TryFutureExt as _;
use workspace::AppState; use workspace::AppState;
actions!(journal, [NewJournalEntry]); actions!(journal, [NewJournalEntry]);
@ -44,17 +43,16 @@ pub fn new_journal_entry(app_state: Arc<AppState>, cx: &mut AppContext) {
Ok::<_, std::io::Error>((journal_dir, entry_path)) Ok::<_, std::io::Error>((journal_dir, entry_path))
}); });
cx.spawn(|mut cx| { cx.spawn(|mut cx| async move {
async move {
let (journal_dir, entry_path) = create_entry.await?; let (journal_dir, entry_path) = create_entry.await?;
let (workspace, _) = cx let (workspace, _) = cx
.update(|cx| workspace::open_paths(&[journal_dir], &app_state, cx)) .update(|cx| workspace::open_paths(&[journal_dir], &app_state, cx))
.await; .await?;
let opened = workspace let opened = workspace
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
workspace.open_paths(vec![entry_path], true, cx) workspace.open_paths(vec![entry_path], true, cx)
}) })?
.await; .await;
if let Some(Some(Ok(item))) = opened.first() { if let Some(Some(Ok(item))) = opened.first() {
@ -69,15 +67,13 @@ pub fn new_journal_entry(app_state: Arc<AppState>, cx: &mut AppContext) {
} }
editor.insert(&entry_heading, cx); editor.insert(&entry_heading, cx);
editor.insert("\n\n", cx); editor.insert("\n\n", cx);
}); })?;
} }
} }
anyhow::Ok(()) anyhow::Ok(())
}
.log_err()
}) })
.detach(); .detach_and_log_err(cx);
} }
fn journal_dir(settings: &Settings) -> Option<PathBuf> { fn journal_dir(settings: &Settings) -> Option<PathBuf> {

View file

@ -17,5 +17,6 @@ picker = { path = "../picker" }
project = { path = "../project" } project = { path = "../project" }
theme = { path = "../theme" } theme = { path = "../theme" }
settings = { path = "../settings" } settings = { path = "../settings" }
util = { path = "../util" }
workspace = { path = "../workspace" } workspace = { path = "../workspace" }
anyhow = "1.0" anyhow = "1.0"

View file

@ -1,6 +1,7 @@
mod active_buffer_language; mod active_buffer_language;
pub use active_buffer_language::ActiveBufferLanguage; pub use active_buffer_language::ActiveBufferLanguage;
use anyhow::anyhow;
use editor::Editor; use editor::Editor;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
@ -12,6 +13,7 @@ use picker::{Picker, PickerDelegate};
use project::Project; use project::Project;
use settings::Settings; use settings::Settings;
use std::sync::Arc; use std::sync::Arc;
use util::ResultExt;
use workspace::{AppState, Workspace}; use workspace::{AppState, Workspace};
actions!(language_selector, [Toggle]); actions!(language_selector, [Toggle]);
@ -140,12 +142,18 @@ impl PickerDelegate for LanguageSelector {
if let Some(mat) = self.matches.get(self.selected_index) { if let Some(mat) = self.matches.get(self.selected_index) {
let language_name = &self.candidates[mat.candidate_id].string; let language_name = &self.candidates[mat.candidate_id].string;
let language = self.language_registry.language_for_name(language_name); let language = self.language_registry.language_for_name(language_name);
cx.spawn(|this, mut cx| async move { let project = self.project.downgrade();
let buffer = self.buffer.downgrade();
cx.spawn_weak(|_, mut cx| async move {
let language = language.await?; let language = language.await?;
this.update(&mut cx, |this, cx| { let project = project
this.project.update(cx, |project, cx| { .upgrade(&cx)
project.set_language_for_buffer(&this.buffer, language, cx); .ok_or_else(|| anyhow!("project was dropped"))?;
}); let buffer = buffer
.upgrade(&cx)
.ok_or_else(|| anyhow!("buffer was dropped"))?;
project.update(&mut cx, |project, cx| {
project.set_language_for_buffer(&buffer, language, cx);
}); });
anyhow::Ok(()) anyhow::Ok(())
}) })
@ -170,7 +178,7 @@ impl PickerDelegate for LanguageSelector {
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) -> gpui::Task<()> { fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) -> gpui::Task<()> {
let background = cx.background().clone(); let background = cx.background().clone();
let candidates = self.candidates.clone(); let candidates = self.candidates.clone();
cx.spawn(|this, mut cx| async move { cx.spawn_weak(|this, mut cx| async move {
let matches = if query.is_empty() { let matches = if query.is_empty() {
candidates candidates
.into_iter() .into_iter()
@ -194,13 +202,16 @@ impl PickerDelegate for LanguageSelector {
.await .await
}; };
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.matches = matches; this.matches = matches;
this.selected_index = this this.selected_index = this
.selected_index .selected_index
.min(this.matches.len().saturating_sub(1)); .min(this.matches.len().saturating_sub(1));
cx.notify(); cx.notify();
}); })
.log_err();
}
}) })
} }

View file

@ -10,6 +10,7 @@ use gpui::{
use menu::{Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev}; use menu::{Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{cmp, sync::Arc}; use std::{cmp, sync::Arc};
use util::ResultExt;
pub struct Picker<D: PickerDelegate> { pub struct Picker<D: PickerDelegate> {
delegate: WeakViewHandle<D>, delegate: WeakViewHandle<D>,
@ -235,9 +236,10 @@ impl<D: PickerDelegate> Picker<D> {
pub fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) { pub fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) {
if let Some(delegate) = self.delegate.upgrade(cx) { if let Some(delegate) = self.delegate.upgrade(cx) {
let update = delegate.update(cx, |d, cx| d.update_matches(query, cx)); let update = delegate.update(cx, |d, cx| d.update_matches(query, cx));
cx.spawn(|this, mut cx| async move { cx.spawn_weak(|this, mut cx| async move {
update.await; update.await;
this.update(&mut cx, |this, cx| { this.upgrade(&cx)?
.update(&mut cx, |this, cx| {
if let Some(delegate) = this.delegate.upgrade(cx) { if let Some(delegate) = this.delegate.upgrade(cx) {
let delegate = delegate.read(cx); let delegate = delegate.read(cx);
let index = delegate.selected_index(); let index = delegate.selected_index();
@ -249,7 +251,8 @@ impl<D: PickerDelegate> Picker<D> {
this.list_state.scroll_to(target); this.list_state.scroll_to(target);
cx.notify(); cx.notify();
} }
}); })
.log_err()
}) })
.detach() .detach()
} }

View file

@ -498,7 +498,7 @@ impl ProjectPanel {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.edit_state.take(); this.edit_state.take();
cx.notify(); cx.notify();
}); })?;
let new_entry = new_entry?; let new_entry = new_entry?;
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
@ -519,7 +519,7 @@ impl ProjectPanel {
); );
} }
cx.notify(); cx.notify();
}); })?;
Ok(()) Ok(())
})) }))
} }
@ -655,7 +655,7 @@ impl ProjectPanel {
this.project this.project
.update(cx, |project, cx| project.delete_entry(entry_id, cx)) .update(cx, |project, cx| project.delete_entry(entry_id, cx))
.ok_or_else(|| anyhow!("no such entry")) .ok_or_else(|| anyhow!("no such entry"))
})? })??
.await .await
})) }))
} }

View file

@ -155,7 +155,7 @@ impl ProjectSymbolsView {
s.select_ranges([position..position]) s.select_ranges([position..position])
}); });
}); });
}); })?;
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
}) })
.detach_and_log_err(cx); .detach_and_log_err(cx);
@ -225,7 +225,8 @@ impl PickerDelegate for ProjectSymbolsView {
this.external_match_candidates = external_match_candidates; this.external_match_candidates = external_match_candidates;
this.symbols = symbols; this.symbols = symbols;
this.filter(&query, cx); this.filter(&query, cx);
}); })
.log_err();
} }
} }
}); });

View file

@ -10,6 +10,7 @@ use highlighted_workspace_location::HighlightedWorkspaceLocation;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use settings::Settings; use settings::Settings;
use util::ResultExt;
use workspace::{ use workspace::{
notifications::simple_message_notification::MessageNotification, OpenPaths, Workspace, notifications::simple_message_notification::MessageNotification, OpenPaths, Workspace,
WorkspaceLocation, WORKSPACE_DB, WorkspaceLocation, WORKSPACE_DB,
@ -57,7 +58,8 @@ impl RecentProjectsView {
}) })
.await; .await;
workspace.update(&mut cx, |workspace, cx| { workspace
.update(&mut cx, |workspace, cx| {
if !workspace_locations.is_empty() { if !workspace_locations.is_empty() {
workspace.toggle_modal(cx, |_, cx| { workspace.toggle_modal(cx, |_, cx| {
let view = cx.add_view(|cx| Self::new(workspace_locations, cx)); let view = cx.add_view(|cx| Self::new(workspace_locations, cx));
@ -71,7 +73,8 @@ impl RecentProjectsView {
}) })
}) })
} }
}); })
.log_err();
}) })
.detach(); .detach();
} }

View file

@ -15,6 +15,7 @@ use project::search::SearchQuery;
use serde::Deserialize; use serde::Deserialize;
use settings::Settings; use settings::Settings;
use std::{any::Any, sync::Arc}; use std::{any::Any, sync::Arc};
use util::ResultExt;
use workspace::{ use workspace::{
item::ItemHandle, item::ItemHandle,
searchable::{Direction, SearchEvent, SearchableItemHandle, WeakSearchableItemHandle}, searchable::{Direction, SearchEvent, SearchableItemHandle, WeakSearchableItemHandle},
@ -617,7 +618,8 @@ impl BufferSearchBar {
} }
cx.notify(); cx.notify();
} }
}); })
.log_err();
} }
})); }));
} }

View file

@ -279,7 +279,8 @@ impl TerminalView {
async move { async move {
Timer::after(CURSOR_BLINK_INTERVAL).await; Timer::after(CURSOR_BLINK_INTERVAL).await;
if let Some(this) = this.upgrade(&cx) { if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx)); this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx))
.log_err();
} }
} }
}) })
@ -298,6 +299,7 @@ impl TerminalView {
Timer::after(CURSOR_BLINK_INTERVAL).await; Timer::after(CURSOR_BLINK_INTERVAL).await;
if let Some(this) = this.upgrade(&cx) { if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx)) this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
.log_err();
} }
} }
}) })

View file

@ -8,6 +8,7 @@ use settings::{settings_file::SettingsFile, Settings};
use staff_mode::StaffMode; use staff_mode::StaffMode;
use std::sync::Arc; use std::sync::Arc;
use theme::{Theme, ThemeMeta, ThemeRegistry}; use theme::{Theme, ThemeMeta, ThemeRegistry};
use util::ResultExt;
use workspace::{AppState, Workspace}; use workspace::{AppState, Workspace};
pub struct ThemeSelector { pub struct ThemeSelector {
@ -185,7 +186,7 @@ impl PickerDelegate for ThemeSelector {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
cx.spawn(|this, mut cx| async move { cx.spawn_weak(|this, mut cx| async move {
let matches = if query.is_empty() { let matches = if query.is_empty() {
candidates candidates
.into_iter() .into_iter()
@ -209,6 +210,7 @@ impl PickerDelegate for ThemeSelector {
.await .await
}; };
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.matches = matches; this.matches = matches;
this.selected_index = this this.selected_index = this
@ -216,7 +218,9 @@ impl PickerDelegate for ThemeSelector {
.min(this.matches.len().saturating_sub(1)); .min(this.matches.len().saturating_sub(1));
this.show_selected_theme(cx); this.show_selected_theme(cx);
cx.notify(); cx.notify();
}); })
.log_err();
}
}) })
} }

View file

@ -6,6 +6,7 @@ use gpui::{
}; };
use picker::{Picker, PickerDelegate}; use picker::{Picker, PickerDelegate};
use settings::{settings_file::SettingsFile, BaseKeymap, Settings}; use settings::{settings_file::SettingsFile, BaseKeymap, Settings};
use util::ResultExt;
use workspace::Workspace; use workspace::Workspace;
pub struct BaseKeymapSelector { pub struct BaseKeymapSelector {
@ -109,7 +110,7 @@ impl PickerDelegate for BaseKeymapSelector {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
cx.spawn(|this, mut cx| async move { cx.spawn_weak(|this, mut cx| async move {
let matches = if query.is_empty() { let matches = if query.is_empty() {
candidates candidates
.into_iter() .into_iter()
@ -133,13 +134,16 @@ impl PickerDelegate for BaseKeymapSelector {
.await .await
}; };
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.matches = matches; this.matches = matches;
this.selected_index = this this.selected_index = this
.selected_index .selected_index
.min(this.matches.len().saturating_sub(1)); .min(this.matches.len().saturating_sub(1));
cx.notify(); cx.notify();
}); })
.log_err();
}
}) })
} }

View file

@ -1,3 +1,17 @@
use crate::{
pane, persistence::model::ItemId, searchable::SearchableItemHandle, DelayedDebouncedEditAction,
FollowableItemBuilders, ItemNavHistory, Pane, ToolbarItemLocation, ViewId, Workspace,
WorkspaceId,
};
use anyhow::{anyhow, Result};
use client::{proto, Client};
use gpui::{
fonts::HighlightStyle, AnyViewHandle, AppContext, Element, ModelHandle, Task, View,
ViewContext, ViewHandle, WeakViewHandle, WindowContext,
};
use project::{Project, ProjectEntryId, ProjectPath};
use settings::{Autosave, Settings};
use smallvec::SmallVec;
use std::{ use std::{
any::{Any, TypeId}, any::{Any, TypeId},
borrow::Cow, borrow::Cow,
@ -12,24 +26,7 @@ use std::{
}, },
time::Duration, time::Duration,
}; };
use anyhow::Result;
use client::{proto, Client};
use gpui::{
fonts::HighlightStyle, AnyViewHandle, AppContext, Element, ModelHandle, Task, View,
ViewContext, ViewHandle, WeakViewHandle, WindowContext,
};
use project::{Project, ProjectEntryId, ProjectPath};
use settings::{Autosave, Settings};
use smallvec::SmallVec;
use theme::Theme; use theme::Theme;
use util::ResultExt;
use crate::{
pane, persistence::model::ItemId, searchable::SearchableItemHandle, DelayedDebouncedEditAction,
FollowableItemBuilders, ItemNavHistory, Pane, ToolbarItemLocation, ViewId, Workspace,
WorkspaceId,
};
#[derive(Eq, PartialEq, Hash)] #[derive(Eq, PartialEq, Hash)]
pub enum ItemEvent { pub enum ItemEvent {
@ -461,18 +458,18 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
} else { } else {
cx.spawn_weak(|workspace, mut cx| async move { cx.spawn_weak(|workspace, mut cx| async move {
workspace workspace
.upgrade(&cx)? .upgrade(&cx)
.ok_or_else(|| anyhow!("workspace was dropped"))?
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
item.git_diff_recalc( item.git_diff_recalc(
workspace.project().clone(), workspace.project().clone(),
cx, cx,
) )
})? })?
.await .await?;
.log_err()?; anyhow::Ok(())
Some(())
}) })
.detach(); .detach_and_log_err(cx);
} }
} }

View file

@ -540,7 +540,7 @@ impl Pane {
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
Self::navigate_history(workspace, pane, mode, cx) Self::navigate_history(workspace, pane, mode, cx)
})? })?
.await; .await?;
} }
Ok(()) Ok(())
@ -1014,10 +1014,10 @@ impl Pane {
if let Some(item_ix) = pane.items.iter().position(|i| i.id() == item.id()) { if let Some(item_ix) = pane.items.iter().position(|i| i.id() == item.id()) {
pane.remove_item(item_ix, false, cx); pane.remove_item(item_ix, false, cx);
} }
}); })?;
} }
pane.update(&mut cx, |_, cx| cx.notify()); pane.update(&mut cx, |_, cx| cx.notify())?;
Ok(()) Ok(())
}) })
} }

View file

@ -131,16 +131,21 @@ impl SerializedPaneGroup {
)) ))
} }
SerializedPaneGroup::Pane(serialized_pane) => { SerializedPaneGroup::Pane(serialized_pane) => {
let pane = workspace.update(cx, |workspace, cx| workspace.add_pane(cx))?; let pane = workspace
.update(cx, |workspace, cx| workspace.add_pane(cx))
.log_err()?;
let active = serialized_pane.active; let active = serialized_pane.active;
serialized_pane serialized_pane
.deserialize_to(project, &pane, workspace_id, workspace, cx) .deserialize_to(project, &pane, workspace_id, workspace, cx)
.await; .await
.log_err()?;
if pane.read_with(cx, |pane, _| pane.items_len() != 0) { if pane.read_with(cx, |pane, _| pane.items_len() != 0) {
Some((Member::Pane(pane.clone()), active.then(|| pane))) Some((Member::Pane(pane.clone()), active.then(|| pane)))
} else { } else {
workspace.update(cx, |workspace, cx| workspace.remove_pane(pane, cx)); workspace
.update(cx, |workspace, cx| workspace.remove_pane(pane, cx))
.log_err()?;
None None
} }
} }
@ -166,7 +171,7 @@ impl SerializedPane {
workspace_id: WorkspaceId, workspace_id: WorkspaceId,
workspace: &ViewHandle<Workspace>, workspace: &ViewHandle<Workspace>,
cx: &mut AsyncAppContext, cx: &mut AsyncAppContext,
) -> Option<()> { ) -> Result<()> {
let mut active_item_index = None; let mut active_item_index = None;
for (index, item) in self.children.iter().enumerate() { for (index, item) in self.children.iter().enumerate() {
let project = project.clone(); let project = project.clone();
@ -193,7 +198,7 @@ impl SerializedPane {
if let Some(item_handle) = item_handle { if let Some(item_handle) = item_handle {
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
Pane::add_item(workspace, &pane_handle, item_handle, false, false, None, cx); Pane::add_item(workspace, &pane_handle, item_handle, false, false, None, cx);
}); })?;
} }
if item.active { if item.active {
@ -207,7 +212,7 @@ impl SerializedPane {
})?; })?;
} }
Some(()) anyhow::Ok(())
} }
} }

View file

@ -2,6 +2,7 @@ use crate::{
item::{Item, ItemEvent}, item::{Item, ItemEvent},
ItemNavHistory, Pane, WorkspaceId, ItemNavHistory, Pane, WorkspaceId,
}; };
use anyhow::Result;
use call::participant::{Frame, RemoteVideoTrack}; use call::participant::{Frame, RemoteVideoTrack};
use client::{proto::PeerId, User}; use client::{proto::PeerId, User};
use futures::StreamExt; use futures::StreamExt;
@ -25,7 +26,7 @@ pub struct SharedScreen {
pub peer_id: PeerId, pub peer_id: PeerId,
user: Arc<User>, user: Arc<User>,
nav_history: Option<ItemNavHistory>, nav_history: Option<ItemNavHistory>,
_maintain_frame: Task<()>, _maintain_frame: Task<Result<()>>,
} }
impl SharedScreen { impl SharedScreen {
@ -47,9 +48,10 @@ impl SharedScreen {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.frame = Some(frame); this.frame = Some(frame);
cx.notify(); cx.notify();
}) })?;
} }
this.update(&mut cx, |_, cx| cx.emit(Event::Close)); this.update(&mut cx, |_, cx| cx.emit(Event::Close))?;
Ok(())
}), }),
} }
} }

View file

@ -306,7 +306,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
let can_close = close.await?; let can_close = close.await?;
if can_close { if can_close {
cx.update(|cx| open_paths(&action.paths, &app_state, cx)) cx.update(|cx| open_paths(&action.paths, &app_state, cx))
.await; .await?;
} }
Ok(()) Ok(())
})) }))
@ -583,10 +583,12 @@ impl DelayedDebouncedEditAction {
} }
if let Some(workspace) = workspace.upgrade(&cx) { if let Some(workspace) = workspace.upgrade(&cx) {
workspace if let Some(result) = workspace
.update(&mut cx, |workspace, cx| (f)(workspace, cx)) .update(&mut cx, |workspace, cx| (f)(workspace, cx))
.await .log_err()
.log_err(); {
result.await.log_err();
}
} }
})); }));
} }
@ -627,7 +629,7 @@ pub struct Workspace {
background_actions: BackgroundActions, background_actions: BackgroundActions,
_window_subscriptions: [Subscription; 3], _window_subscriptions: [Subscription; 3],
_apply_leader_updates: Task<Result<()>>, _apply_leader_updates: Task<Result<()>>,
_observe_current_user: Task<()>, _observe_current_user: Task<Result<()>>,
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@ -723,9 +725,10 @@ impl Workspace {
while stream.recv().await.is_some() { while stream.recv().await.is_some() {
if let Some(this) = this.upgrade(&cx) { if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |_, cx| cx.notify()); this.update(&mut cx, |_, cx| cx.notify())?;
} }
} }
anyhow::Ok(())
}); });
let handle = cx.handle(); let handle = cx.handle();
@ -979,6 +982,7 @@ impl Workspace {
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
workspace.open_path(project_path, None, true, cx) workspace.open_path(project_path, None, true, cx)
}) })
.log_err()?
.await, .await,
) )
} else { } else {
@ -1040,13 +1044,13 @@ impl Workspace {
app_state: &Arc<AppState>, app_state: &Arc<AppState>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
callback: F, callback: F,
) -> Task<T> ) -> Task<Result<T>>
where where
T: 'static, T: 'static,
F: 'static + FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T, F: 'static + FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
{ {
if self.project.read(cx).is_local() { if self.project.read(cx).is_local() {
Task::Ready(Some(callback(self, cx))) Task::Ready(Some(Ok(callback(self, cx))))
} else { } else {
let task = Self::new_local(Vec::new(), app_state.clone(), cx); let task = Self::new_local(Vec::new(), app_state.clone(), cx);
cx.spawn(|_vh, mut cx| async move { cx.spawn(|_vh, mut cx| async move {
@ -1097,13 +1101,11 @@ impl Workspace {
_: &CloseWindow, _: &CloseWindow,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Option<Task<Result<()>>> { ) -> Option<Task<Result<()>>> {
let prepare = self.prepare_to_close(false, cx);
Some(cx.spawn(|this, mut cx| async move {
if prepare.await? {
this.update(&mut cx, |_, cx| {
let window_id = cx.window_id(); let window_id = cx.window_id();
let prepare = self.prepare_to_close(false, cx);
Some(cx.spawn_weak(|_, mut cx| async move {
if prepare.await? {
cx.remove_window(window_id); cx.remove_window(window_id);
});
} }
Ok(()) Ok(())
})) }))
@ -1155,7 +1157,7 @@ impl Workspace {
} }
Ok(this Ok(this
.update(&mut cx, |this, cx| this.save_all_internal(true, cx)) .update(&mut cx, |this, cx| this.save_all_internal(true, cx))?
.await?) .await?)
}) })
} }
@ -1233,13 +1235,16 @@ impl Workspace {
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
let mut project_paths = Vec::new(); let mut project_paths = Vec::new();
for path in &abs_paths { for path in &abs_paths {
project_paths.push( if let Some(project_path) = this
this.update(&mut cx, |this, cx| { .update(&mut cx, |this, cx| {
Workspace::project_path_for_path(this.project.clone(), path, visible, cx) Workspace::project_path_for_path(this.project.clone(), path, visible, cx)
}) })
.await .log_err()
.log_err(), {
); project_paths.push(project_path.await.log_err());
} else {
project_paths.push(None);
}
} }
let tasks = abs_paths let tasks = abs_paths
@ -1257,6 +1262,7 @@ impl Workspace {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.open_path(project_path, None, true, cx) this.open_path(project_path, None, true, cx)
}) })
.log_err()?
.await, .await,
) )
} else { } else {
@ -1280,14 +1286,15 @@ impl Workspace {
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
if let Some(paths) = paths.recv().await.flatten() { if let Some(paths) = paths.recv().await.flatten() {
let results = this let results = this
.update(&mut cx, |this, cx| this.open_paths(paths, true, cx)) .update(&mut cx, |this, cx| this.open_paths(paths, true, cx))?
.await; .await;
for result in results.into_iter().flatten() { for result in results.into_iter().flatten() {
result.log_err(); result.log_err();
} }
} }
anyhow::Ok(())
}) })
.detach(); .detach_and_log_err(cx);
} }
fn remove_folder_from_project( fn remove_folder_from_project(
@ -1406,7 +1413,7 @@ impl Workspace {
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
let answer = answer.recv().await; let answer = answer.recv().await;
if answer == Some(0) { if answer == Some(0) {
this.update(&mut cx, |this, cx| item.save(this.project.clone(), cx)) this.update(&mut cx, |this, cx| item.save(this.project.clone(), cx))?
.await?; .await?;
} }
Ok(()) Ok(())
@ -1423,7 +1430,7 @@ impl Workspace {
let mut abs_path = cx.prompt_for_new_path(&start_abs_path); let mut abs_path = cx.prompt_for_new_path(&start_abs_path);
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
if let Some(abs_path) = abs_path.recv().await.flatten() { if let Some(abs_path) = abs_path.recv().await.flatten() {
this.update(&mut cx, |_, cx| item.save_as(project, abs_path, cx)) this.update(&mut cx, |_, cx| item.save_as(project, abs_path, cx))?
.await?; .await?;
} }
Ok(()) Ok(())
@ -1588,14 +1595,7 @@ impl Workspace {
.upgrade(&cx) .upgrade(&cx)
.ok_or_else(|| anyhow!("pane was closed"))?; .ok_or_else(|| anyhow!("pane was closed"))?;
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
Ok(Pane::open_item( Pane::open_item(this, pane, project_entry_id, focus_item, cx, build_item)
this,
pane,
project_entry_id,
focus_item,
cx,
build_item,
))
}) })
}) })
} }
@ -1958,7 +1958,7 @@ impl Workspace {
None None
}; };
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
})?; })??;
Self::add_views_from_leader( Self::add_views_from_leader(
this.clone(), this.clone(),
leader_id, leader_id,
@ -1967,7 +1967,7 @@ impl Workspace {
&mut cx, &mut cx,
) )
.await?; .await?;
this.update(&mut cx, |this, cx| this.leader_updated(leader_id, cx)); this.update(&mut cx, |this, cx| this.leader_updated(leader_id, cx))?;
} }
Ok(()) Ok(())
})) }))
@ -2245,7 +2245,7 @@ impl Workspace {
}) })
.collect(), .collect(),
}) })
}) })?
} }
async fn handle_unfollow( async fn handle_unfollow(
@ -2260,7 +2260,7 @@ impl Workspace {
.remove(&envelope.original_sender_id()?); .remove(&envelope.original_sender_id()?);
cx.notify(); cx.notify();
Ok(()) Ok(())
}) })?
} }
async fn handle_update_followers( async fn handle_update_followers(
@ -2297,7 +2297,7 @@ impl Workspace {
} }
} }
anyhow::Ok(()) anyhow::Ok(())
})?; })??;
} }
proto::update_followers::Variant::UpdateView(update_view) => { proto::update_followers::Variant::UpdateView(update_view) => {
let variant = update_view let variant = update_view
@ -2318,7 +2318,7 @@ impl Workspace {
} }
} }
anyhow::Ok(()) anyhow::Ok(())
})?; })??;
try_join_all(tasks).await.log_err(); try_join_all(tasks).await.log_err();
} }
proto::update_followers::Variant::CreateView(view) => { proto::update_followers::Variant::CreateView(view) => {
@ -2333,7 +2333,7 @@ impl Workspace {
Self::add_views_from_leader(this.clone(), leader_id, panes, vec![view], cx).await?; Self::add_views_from_leader(this.clone(), leader_id, panes, vec![view], cx).await?;
} }
} }
this.update(cx, |this, cx| this.leader_updated(leader_id, cx)); this.update(cx, |this, cx| this.leader_updated(leader_id, cx))?;
Ok(()) Ok(())
} }
@ -2403,7 +2403,7 @@ impl Workspace {
} }
Some(()) Some(())
}); })?;
} }
Ok(()) Ok(())
} }
@ -2685,7 +2685,7 @@ impl Workspace {
&workspace, &workspace,
&mut cx, &mut cx,
) )
.await; .await?;
// Traverse the splits tree and add to things // Traverse the splits tree and add to things
let center_group = serialized_workspace let center_group = serialized_workspace
@ -2737,13 +2737,14 @@ impl Workspace {
}); });
cx.notify(); cx.notify();
}); })?;
// Serialize ourself to make sure our timestamps and any pane / item changes are replicated // Serialize ourself to make sure our timestamps and any pane / item changes are replicated
workspace.read_with(&cx, |workspace, cx| workspace.serialize_workspace(cx)) workspace.read_with(&cx, |workspace, cx| workspace.serialize_workspace(cx))
} }
anyhow::Ok(())
}) })
.detach(); .detach_and_log_err(cx);
} }
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
@ -2753,8 +2754,8 @@ impl Workspace {
} }
fn notify_if_database_failed(workspace: &ViewHandle<Workspace>, cx: &mut AsyncAppContext) { fn notify_if_database_failed(workspace: &ViewHandle<Workspace>, cx: &mut AsyncAppContext) {
if (*db::ALL_FILE_DB_FAILED).load(std::sync::atomic::Ordering::Acquire) {
workspace.update(cx, |workspace, cx| { workspace.update(cx, |workspace, cx| {
if (*db::ALL_FILE_DB_FAILED).load(std::sync::atomic::Ordering::Acquire) {
workspace.show_notification_once(0, cx, |cx| { workspace.show_notification_once(0, cx, |cx| {
cx.add_view(|_| { cx.add_view(|_| {
MessageNotification::new( MessageNotification::new(
@ -2766,11 +2767,9 @@ fn notify_if_database_failed(workspace: &ViewHandle<Workspace>, cx: &mut AsyncAp
) )
}) })
}); });
});
} else { } else {
let backup_path = (*db::BACKUP_DB_PATH).read(); let backup_path = (*db::BACKUP_DB_PATH).read();
if let Some(backup_path) = &*backup_path { if let Some(backup_path) = &*backup_path {
workspace.update(cx, |workspace, cx| {
workspace.show_notification_once(0, cx, |cx| { workspace.show_notification_once(0, cx, |cx| {
cx.add_view(|_| { cx.add_view(|_| {
let backup_path = backup_path.to_string_lossy(); let backup_path = backup_path.to_string_lossy();
@ -2788,9 +2787,9 @@ fn notify_if_database_failed(workspace: &ViewHandle<Workspace>, cx: &mut AsyncAp
) )
}) })
}); });
});
} }
} }
}).log_err();
} }
impl Entity for Workspace { impl Entity for Workspace {
@ -3017,10 +3016,12 @@ pub fn open_paths(
abs_paths: &[PathBuf], abs_paths: &[PathBuf],
app_state: &Arc<AppState>, app_state: &Arc<AppState>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Task<( ) -> Task<
Result<(
ViewHandle<Workspace>, ViewHandle<Workspace>,
Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>, Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>,
)> { )>,
> {
log::info!("open paths {:?}", abs_paths); log::info!("open paths {:?}", abs_paths);
// Open paths in existing workspace if possible // Open paths in existing workspace if possible
@ -3031,14 +3032,14 @@ pub fn open_paths(
let abs_paths = abs_paths.to_vec(); let abs_paths = abs_paths.to_vec();
cx.spawn(|mut cx| async move { cx.spawn(|mut cx| async move {
if let Some(existing) = existing { if let Some(existing) = existing {
( Ok((
existing.clone(), existing.clone(),
existing existing
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
workspace.open_paths(abs_paths, true, cx) workspace.open_paths(abs_paths, true, cx)
}) })?
.await, .await,
) ))
} else { } else {
let contains_directory = let contains_directory =
futures::future::join_all(abs_paths.iter().map(|path| app_state.fs.is_file(path))) futures::future::join_all(abs_paths.iter().map(|path| app_state.fs.is_file(path)))
@ -3055,9 +3056,9 @@ pub fn open_paths(
if contains_directory { if contains_directory {
workspace.toggle_sidebar(SidebarSide::Left, cx); workspace.toggle_sidebar(SidebarSide::Left, cx);
} }
}); })?;
(workspace, items) anyhow::Ok((workspace, items))
}) })
}) })
.await .await
@ -3074,11 +3075,13 @@ pub fn open_new(
cx.spawn(|mut cx| async move { cx.spawn(|mut cx| async move {
let (workspace, opened_paths) = task.await; let (workspace, opened_paths) = task.await;
workspace.update(&mut cx, |workspace, cx| { workspace
.update(&mut cx, |workspace, cx| {
if opened_paths.is_empty() { if opened_paths.is_empty() {
init(workspace, cx) init(workspace, cx)
} }
}) })
.log_err();
}) })
} }
@ -3702,7 +3705,8 @@ mod tests {
.update(cx, |workspace, cx| { .update(cx, |workspace, cx| {
Pane::go_back(workspace, Some(pane.clone()), cx) Pane::go_back(workspace, Some(pane.clone()), cx)
}) })
.await; .await
.unwrap();
assert_eq!(*toolbar_notify_count.borrow(), 3); assert_eq!(*toolbar_notify_count.borrow(), 3);
pane.read_with(cx, |pane, _| { pane.read_with(cx, |pane, _| {

View file

@ -606,11 +606,13 @@ async fn handle_cli_connection(
} else { } else {
paths paths
}; };
let (workspace, items) = cx
.update(|cx| workspace::open_paths(&paths, &app_state, cx))
.await;
let mut errored = false; let mut errored = false;
match cx
.update(|cx| workspace::open_paths(&paths, &app_state, cx))
.await
{
Ok((workspace, items)) => {
let mut item_release_futures = Vec::new(); let mut item_release_futures = Vec::new();
cx.update(|cx| { cx.update(|cx| {
for (item, path) in items.into_iter().zip(&paths) { for (item, path) in items.into_iter().zip(&paths) {
@ -629,7 +631,10 @@ async fn handle_cli_connection(
Some(Err(err)) => { Some(Err(err)) => {
responses responses
.send(CliResponse::Stderr { .send(CliResponse::Stderr {
message: format!("error opening {:?}: {}", path, err), message: format!(
"error opening {:?}: {}",
path, err
),
}) })
.log_err(); .log_err();
errored = true; errored = true;
@ -652,7 +657,8 @@ async fn handle_cli_connection(
drop(workspace); drop(workspace);
let _ = done_rx.await; let _ = done_rx.await;
} else { } else {
let _ = futures::future::try_join_all(item_release_futures).await; let _ =
futures::future::try_join_all(item_release_futures).await;
}; };
} }
.fuse(); .fuse();
@ -672,6 +678,16 @@ async fn handle_cli_connection(
} }
} }
} }
}
Err(error) => {
errored = true;
responses
.send(CliResponse::Stderr {
message: format!("error opening {:?}: {}", paths, error),
})
.log_err();
}
}
responses responses
.send(CliResponse::Exit { .send(CliResponse::Exit {

View file

@ -247,10 +247,10 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::AppContext) {
cx, cx,
); );
}) })
})?
.await
}) })
.await; .detach_and_log_err(cx);
})
.detach();
} }
}); });
cx.add_action( cx.add_action(
@ -399,7 +399,7 @@ fn restart(_: &Restart, cx: &mut gpui::AppContext) {
if !workspace if !workspace
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
workspace.prepare_to_close(true, cx) workspace.prepare_to_close(true, cx)
}) })?
.await? .await?
{ {
return Ok(()); return Ok(());
@ -444,7 +444,7 @@ fn quit(_: &Quit, cx: &mut gpui::AppContext) {
if !workspace if !workspace
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
workspace.prepare_to_close(true, cx) workspace.prepare_to_close(true, cx)
}) })?
.await? .await?
{ {
return Ok(()); return Ok(());
@ -481,8 +481,8 @@ fn open_config_file(
workspace.with_local_workspace(&app_state, cx, |workspace, cx| { workspace.with_local_workspace(&app_state, cx, |workspace, cx| {
workspace.open_paths(vec![path.to_path_buf()], false, cx) workspace.open_paths(vec![path.to_path_buf()], false, cx)
}) })
}) })?
.await .await?
.await; .await;
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
}) })
@ -521,7 +521,8 @@ fn open_log_file(
.flat_map(|line| [line, "\n"]) .flat_map(|line| [line, "\n"])
.collect::<String>(); .collect::<String>();
workspace.update(&mut cx, |workspace, cx| { workspace
.update(&mut cx, |workspace, cx| {
let project = workspace.project().clone(); let project = workspace.project().clone();
let buffer = project let buffer = project
.update(cx, |project, cx| project.create_buffer("", None, cx)) .update(cx, |project, cx| project.create_buffer("", None, cx))
@ -532,14 +533,13 @@ fn open_log_file(
MultiBuffer::singleton(buffer, cx).with_title("Log".into()) MultiBuffer::singleton(buffer, cx).with_title("Log".into())
}); });
workspace.add_item( workspace.add_item(
Box::new( Box::new(cx.add_view(|cx| {
cx.add_view(|cx| {
Editor::for_multibuffer(buffer, Some(project), cx) Editor::for_multibuffer(buffer, Some(project), cx)
}), })),
),
cx, cx,
); );
}); })
.log_err();
} }
}) })
.detach(); .detach();
@ -601,7 +601,7 @@ fn open_telemetry_log_file(
Box::new(cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))), Box::new(cx.add_view(|cx| Editor::for_multibuffer(buffer, Some(project), cx))),
cx, cx,
); );
}); }).log_err()?;
Some(()) Some(())
}) })
@ -642,10 +642,10 @@ fn open_bundled_file(
cx, cx,
); );
}) })
})?
.await
}) })
.await; .detach_and_log_err(cx);
})
.detach();
} }
#[cfg(test)] #[cfg(test)]
@ -705,11 +705,13 @@ mod tests {
cx, cx,
) )
}) })
.await; .await
.unwrap();
assert_eq!(cx.window_ids().len(), 1); assert_eq!(cx.window_ids().len(), 1);
cx.update(|cx| open_paths(&[PathBuf::from("/root/a")], &app_state, cx)) cx.update(|cx| open_paths(&[PathBuf::from("/root/a")], &app_state, cx))
.await; .await
.unwrap();
assert_eq!(cx.window_ids().len(), 1); assert_eq!(cx.window_ids().len(), 1);
let workspace_1 = cx let workspace_1 = cx
.read_window(cx.window_ids()[0], |cx| cx.root_view().clone()) .read_window(cx.window_ids()[0], |cx| cx.root_view().clone())
@ -729,7 +731,8 @@ mod tests {
cx, cx,
) )
}) })
.await; .await
.unwrap();
assert_eq!(cx.window_ids().len(), 2); assert_eq!(cx.window_ids().len(), 2);
// Replace existing windows // Replace existing windows
@ -741,7 +744,8 @@ mod tests {
cx, cx,
) )
}) })
.await; .await
.unwrap();
assert_eq!(cx.window_ids().len(), 2); assert_eq!(cx.window_ids().len(), 2);
cx.read_window(window_id, |cx| { cx.read_window(window_id, |cx| {
let workspace = cx.root_view().clone().downcast::<Workspace>().unwrap(); let workspace = cx.root_view().clone().downcast::<Workspace>().unwrap();
@ -768,7 +772,8 @@ mod tests {
.await; .await;
cx.update(|cx| open_paths(&[PathBuf::from("/root/a")], &app_state, cx)) cx.update(|cx| open_paths(&[PathBuf::from("/root/a")], &app_state, cx))
.await; .await
.unwrap();
assert_eq!(cx.window_ids().len(), 1); assert_eq!(cx.window_ids().len(), 1);
// When opening the workspace, the window is not in a edited state. // When opening the workspace, the window is not in a edited state.
@ -810,7 +815,8 @@ mod tests {
// Opening the buffer again doesn't impact the window's edited state. // Opening the buffer again doesn't impact the window's edited state.
cx.update(|cx| open_paths(&[PathBuf::from("/root/a")], &app_state, cx)) cx.update(|cx| open_paths(&[PathBuf::from("/root/a")], &app_state, cx))
.await; .await
.unwrap();
let editor = workspace.read_with(cx, |workspace, cx| { let editor = workspace.read_with(cx, |workspace, cx| {
workspace workspace
.active_item(cx) .active_item(cx)
@ -1475,7 +1481,8 @@ mod tests {
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file3.clone(), DisplayPoint::new(0, 0), 0.) (file3.clone(), DisplayPoint::new(0, 0), 0.)
@ -1483,7 +1490,8 @@ mod tests {
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file2.clone(), DisplayPoint::new(0, 0), 0.) (file2.clone(), DisplayPoint::new(0, 0), 0.)
@ -1491,7 +1499,8 @@ mod tests {
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file1.clone(), DisplayPoint::new(10, 0), 0.) (file1.clone(), DisplayPoint::new(10, 0), 0.)
@ -1499,7 +1508,8 @@ mod tests {
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file1.clone(), DisplayPoint::new(0, 0), 0.) (file1.clone(), DisplayPoint::new(0, 0), 0.)
@ -1508,7 +1518,8 @@ mod tests {
// Go back one more time and ensure we don't navigate past the first item in the history. // Go back one more time and ensure we don't navigate past the first item in the history.
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file1.clone(), DisplayPoint::new(0, 0), 0.) (file1.clone(), DisplayPoint::new(0, 0), 0.)
@ -1516,7 +1527,8 @@ mod tests {
workspace workspace
.update(cx, |w, cx| Pane::go_forward(w, None, cx)) .update(cx, |w, cx| Pane::go_forward(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file1.clone(), DisplayPoint::new(10, 0), 0.) (file1.clone(), DisplayPoint::new(10, 0), 0.)
@ -1524,7 +1536,8 @@ mod tests {
workspace workspace
.update(cx, |w, cx| Pane::go_forward(w, None, cx)) .update(cx, |w, cx| Pane::go_forward(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file2.clone(), DisplayPoint::new(0, 0), 0.) (file2.clone(), DisplayPoint::new(0, 0), 0.)
@ -1542,7 +1555,8 @@ mod tests {
.unwrap(); .unwrap();
workspace workspace
.update(cx, |w, cx| Pane::go_forward(w, None, cx)) .update(cx, |w, cx| Pane::go_forward(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file3.clone(), DisplayPoint::new(0, 0), 0.) (file3.clone(), DisplayPoint::new(0, 0), 0.)
@ -1550,7 +1564,8 @@ mod tests {
workspace workspace
.update(cx, |w, cx| Pane::go_forward(w, None, cx)) .update(cx, |w, cx| Pane::go_forward(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file3.clone(), DisplayPoint::new(16, 0), 12.5) (file3.clone(), DisplayPoint::new(16, 0), 12.5)
@ -1558,7 +1573,8 @@ mod tests {
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file3.clone(), DisplayPoint::new(0, 0), 0.) (file3.clone(), DisplayPoint::new(0, 0), 0.)
@ -1580,14 +1596,16 @@ mod tests {
.unwrap(); .unwrap();
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file1.clone(), DisplayPoint::new(10, 0), 0.) (file1.clone(), DisplayPoint::new(10, 0), 0.)
); );
workspace workspace
.update(cx, |w, cx| Pane::go_forward(w, None, cx)) .update(cx, |w, cx| Pane::go_forward(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file3.clone(), DisplayPoint::new(0, 0), 0.) (file3.clone(), DisplayPoint::new(0, 0), 0.)
@ -1630,14 +1648,16 @@ mod tests {
}); });
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file1.clone(), DisplayPoint::new(2, 0), 0.) (file1.clone(), DisplayPoint::new(2, 0), 0.)
); );
workspace workspace
.update(cx, |w, cx| Pane::go_back(w, None, cx)) .update(cx, |w, cx| Pane::go_back(w, None, cx))
.await; .await
.unwrap();
assert_eq!( assert_eq!(
active_location(&workspace, cx), active_location(&workspace, cx),
(file1.clone(), DisplayPoint::new(3, 0), 0.) (file1.clone(), DisplayPoint::new(3, 0), 0.)
@ -1751,61 +1771,84 @@ mod tests {
// Reopen all the closed items, ensuring they are reopened in the same order // Reopen all the closed items, ensuring they are reopened in the same order
// in which they were closed. // in which they were closed.
workspace.update(cx, Pane::reopen_closed_item).await; workspace
.update(cx, Pane::reopen_closed_item)
.await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file3.clone())); assert_eq!(active_path(&workspace, cx), Some(file3.clone()));
workspace.update(cx, Pane::reopen_closed_item).await; workspace
.update(cx, Pane::reopen_closed_item)
.await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file2.clone())); assert_eq!(active_path(&workspace, cx), Some(file2.clone()));
workspace.update(cx, Pane::reopen_closed_item).await; workspace
.update(cx, Pane::reopen_closed_item)
.await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file4.clone())); assert_eq!(active_path(&workspace, cx), Some(file4.clone()));
workspace.update(cx, Pane::reopen_closed_item).await; workspace
.update(cx, Pane::reopen_closed_item)
.await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file1.clone())); assert_eq!(active_path(&workspace, cx), Some(file1.clone()));
// Reopening past the last closed item is a no-op. // Reopening past the last closed item is a no-op.
workspace.update(cx, Pane::reopen_closed_item).await; workspace
.update(cx, Pane::reopen_closed_item)
.await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file1.clone())); assert_eq!(active_path(&workspace, cx), Some(file1.clone()));
// Reopening closed items doesn't interfere with navigation history. // Reopening closed items doesn't interfere with navigation history.
workspace workspace
.update(cx, |workspace, cx| Pane::go_back(workspace, None, cx)) .update(cx, |workspace, cx| Pane::go_back(workspace, None, cx))
.await; .await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file4.clone())); assert_eq!(active_path(&workspace, cx), Some(file4.clone()));
workspace workspace
.update(cx, |workspace, cx| Pane::go_back(workspace, None, cx)) .update(cx, |workspace, cx| Pane::go_back(workspace, None, cx))
.await; .await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file2.clone())); assert_eq!(active_path(&workspace, cx), Some(file2.clone()));
workspace workspace
.update(cx, |workspace, cx| Pane::go_back(workspace, None, cx)) .update(cx, |workspace, cx| Pane::go_back(workspace, None, cx))
.await; .await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file3.clone())); assert_eq!(active_path(&workspace, cx), Some(file3.clone()));
workspace workspace
.update(cx, |workspace, cx| Pane::go_back(workspace, None, cx)) .update(cx, |workspace, cx| Pane::go_back(workspace, None, cx))
.await; .await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file4.clone())); assert_eq!(active_path(&workspace, cx), Some(file4.clone()));
workspace workspace
.update(cx, |workspace, cx| Pane::go_back(workspace, None, cx)) .update(cx, |workspace, cx| Pane::go_back(workspace, None, cx))
.await; .await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file3.clone())); assert_eq!(active_path(&workspace, cx), Some(file3.clone()));
workspace workspace
.update(cx, |workspace, cx| Pane::go_back(workspace, None, cx)) .update(cx, |workspace, cx| Pane::go_back(workspace, None, cx))
.await; .await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file2.clone())); assert_eq!(active_path(&workspace, cx), Some(file2.clone()));
workspace workspace
.update(cx, |workspace, cx| Pane::go_back(workspace, None, cx)) .update(cx, |workspace, cx| Pane::go_back(workspace, None, cx))
.await; .await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file1.clone())); assert_eq!(active_path(&workspace, cx), Some(file1.clone()));
workspace workspace
.update(cx, |workspace, cx| Pane::go_back(workspace, None, cx)) .update(cx, |workspace, cx| Pane::go_back(workspace, None, cx))
.await; .await
.unwrap();
assert_eq!(active_path(&workspace, cx), Some(file1.clone())); assert_eq!(active_path(&workspace, cx), Some(file1.clone()));
fn active_path( fn active_path(