@@ -154,7 +154,7 @@ pub struct Project {
git_diff_debouncer: DelayedDebounced,
nonce: u128,
_maintain_buffer_languages: Task<()>,
- _maintain_workspace_config: Task<()>,
+ _maintain_workspace_config: Task<Result<()>>,
terminals: Terminals,
copilot_lsp_subscription: Option<gpui2::Subscription>,
copilot_log_subscription: Option<lsp2::Subscription>,
@@ -196,7 +196,7 @@ impl DelayedDebounced {
self.cancel_channel = Some(sender);
let previous_task = self.task.take();
- self.task = Some(cx.spawn(|project, mut cx| async move {
+ self.task = Some(cx.spawn(move |project, mut cx| async move {
let mut timer = cx.executor().timer(delay).fuse();
if let Some(previous_task) = previous_task {
previous_task.await;
@@ -623,9 +623,9 @@ impl Project {
fs: Arc<dyn Fs>,
cx: &mut AppContext,
) -> Handle<Self> {
- cx.add_model(|cx: &mut ModelContext<Self>| {
+ cx.entity(|cx: &mut ModelContext<Self>| {
let (tx, rx) = mpsc::unbounded();
- cx.spawn_weak(|this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
+ cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
.detach();
let copilot_lsp_subscription =
Copilot::global(cx).map(|copilot| subscribe_for_copilot_events(&copilot, cx));
@@ -708,7 +708,7 @@ impl Project {
}
let (tx, rx) = mpsc::unbounded();
- cx.spawn(|this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
+ cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
.detach();
let copilot_lsp_subscription =
Copilot::global(cx).map(|copilot| subscribe_for_copilot_events(&copilot, cx));
@@ -783,7 +783,7 @@ impl Project {
let _ = this.add_worktree(&worktree, cx);
}
this
- });
+ })?;
let subscription = subscription.set_model(&this, &mut cx);
let user_ids = response
@@ -822,7 +822,7 @@ impl Project {
fn shutdown_language_servers(
&mut self,
- cx: &mut ModelContext<Self>,
+ _cx: &mut ModelContext<Self>,
) -> impl Future<Output = ()> {
let shutdown_futures = self
.language_servers
@@ -988,7 +988,7 @@ impl Project {
cx.notify();
}
- pub fn buffer_for_id(&self, remote_id: u64, cx: &AppContext) -> Option<Handle<Buffer>> {
+ pub fn buffer_for_id(&self, remote_id: u64) -> Option<Handle<Buffer>> {
self.opened_buffers
.get(&remote_id)
.and_then(|buffer| buffer.upgrade())
@@ -1006,7 +1006,7 @@ impl Project {
self.user_store.clone()
}
- pub fn opened_buffers(&self, cx: &AppContext) -> Vec<Handle<Buffer>> {
+ pub fn opened_buffers(&self) -> Vec<Handle<Buffer>> {
self.opened_buffers
.values()
.filter_map(|b| b.upgrade())
@@ -1068,10 +1068,7 @@ impl Project {
}
/// Collect all worktrees, including ones that don't appear in the project panel
- pub fn worktrees<'a>(
- &'a self,
- cx: &'a AppContext,
- ) -> impl 'a + DoubleEndedIterator<Item = Handle<Worktree>> {
+ pub fn worktrees<'a>(&'a self) -> impl 'a + DoubleEndedIterator<Item = Handle<Worktree>> {
self.worktrees
.iter()
.filter_map(move |worktree| worktree.upgrade())
@@ -1099,7 +1096,7 @@ impl Project {
}
pub fn worktree_for_id(&self, id: WorktreeId, cx: &AppContext) -> Option<Handle<Worktree>> {
- self.worktrees(cx)
+ self.worktrees()
.find(|worktree| worktree.read(cx).id() == id)
}
@@ -1108,7 +1105,7 @@ impl Project {
entry_id: ProjectEntryId,
cx: &AppContext,
) -> Option<Handle<Worktree>> {
- self.worktrees(cx)
+ self.worktrees()
.find(|worktree| worktree.read(cx).contains_entry(entry_id))
}
@@ -1126,7 +1123,7 @@ impl Project {
}
pub fn contains_path(&self, path: &Path, cx: &AppContext) -> bool {
- for worktree in self.worktrees(cx) {
+ for worktree in self.worktrees() {
let worktree = worktree.read(cx).as_local();
if worktree.map_or(false, |w| w.contains_abs_path(path)) {
return true;
@@ -1153,7 +1150,7 @@ impl Project {
} else {
let client = self.client.clone();
let project_id = self.remote_id().unwrap();
- Some(cx.spawn(|_, mut cx| async move {
+ Some(cx.spawn(move |_, mut cx| async move {
let response = client
.request(proto::CreateProjectEntry {
worktree_id: project_path.worktree_id.to_proto(),
@@ -1172,7 +1169,7 @@ impl Project {
response.worktree_scan_id as usize,
cx,
)
- })
+ })?
.await
}))
}
@@ -1197,7 +1194,7 @@ impl Project {
let client = self.client.clone();
let project_id = self.remote_id().unwrap();
- Some(cx.spawn(|_, mut cx| async move {
+ Some(cx.spawn(move |_, mut cx| async move {
let response = client
.request(proto::CopyProjectEntry {
project_id,
@@ -1215,7 +1212,7 @@ impl Project {
response.worktree_scan_id as usize,
cx,
)
- })
+ })?
.await
}))
}
@@ -1240,7 +1237,7 @@ impl Project {
let client = self.client.clone();
let project_id = self.remote_id().unwrap();
- Some(cx.spawn(|_, mut cx| async move {
+ Some(cx.spawn(move |_, mut cx| async move {
let response = client
.request(proto::RenameProjectEntry {
project_id,
@@ -1280,7 +1277,7 @@ impl Project {
} else {
let client = self.client.clone();
let project_id = self.remote_id().unwrap();
- Some(cx.spawn(|_, mut cx| async move {
+ Some(cx.spawn(move |_, mut cx| async move {
let response = client
.request(proto::DeleteProjectEntry {
project_id,
@@ -1294,7 +1291,7 @@ impl Project {
response.worktree_scan_id as usize,
cx,
)
- })
+ })?
.await
}))
}
@@ -1317,7 +1314,7 @@ impl Project {
project_id: self.remote_id().unwrap(),
entry_id: entry_id.to_proto(),
});
- Some(cx.spawn(|_, mut cx| async move {
+ Some(cx.spawn(move |_, mut cx| async move {
let response = request.await?;
if let Some(worktree) = worktree.upgrade() {
worktree
@@ -1326,7 +1323,7 @@ impl Project {
.as_remote_mut()
.unwrap()
.wait_for_snapshot(response.worktree_scan_id as usize)
- })
+ })?
.await?;
}
Ok(())
@@ -1341,7 +1338,7 @@ impl Project {
self.client_subscriptions.push(
self.client
.subscribe_to_entity(project_id)?
- .set_model(&cx.handle().upgrade(), &mut cx.to_async()),
+ .set_model(&cx.handle(), &mut cx.to_async()),
);
for open_buffer in self.opened_buffers.values_mut() {
@@ -1380,7 +1377,7 @@ impl Project {
}
let store = cx.global::<SettingsStore>();
- for worktree in self.worktrees(cx) {
+ for worktree in self.worktrees() {
let worktree_id = worktree.read(cx).id().to_proto();
for (path, content) in store.local_settings(worktree.entity_id().as_u64() as usize) {
self.client
@@ -1403,8 +1400,8 @@ impl Project {
while let Some(update) = updates_rx.next().await {
match update {
LocalProjectUpdate::WorktreesChanged => {
- let worktrees = this.update(&mut cx, |this, cx| {
- this.worktrees(cx).collect::<Vec<_>>()
+ let worktrees = this.update(&mut cx, |this, _cx| {
+ this.worktrees().collect::<Vec<_>>()
})?;
let update_project = this
.update(&mut cx, |this, cx| {
@@ -1441,9 +1438,9 @@ impl Project {
let Some(buffer) = buffer else { continue };
let operations =
- buffer.read_with(&cx, |b, cx| b.serialize_ops(None, cx));
+ buffer.update(&mut cx, |b, cx| b.serialize_ops(None, cx))?;
let operations = operations.await;
- let state = buffer.read_with(&cx, |buffer, _| buffer.to_proto());
+ let state = buffer.update(&mut cx, |buffer, _| buffer.to_proto())?;
let initial_state = proto::CreateBufferForPeer {
project_id,
@@ -1452,7 +1449,7 @@ impl Project {
};
if client.send(initial_state).log_err().is_some() {
let client = client.clone();
- cx.background()
+ cx.executor()
.spawn(async move {
let mut chunks = split_operations(operations).peekable();
while let Some(chunk) = chunks.next() {
@@ -1683,12 +1680,12 @@ impl Project {
cx: &mut ModelContext<Self>,
) -> Task<Result<(ProjectEntryId, AnyHandle)>> {
let task = self.open_buffer(path, cx);
- cx.spawn_weak(|_, cx| async move {
+ cx.spawn(move |_, mut cx| async move {
let buffer = task.await?;
let project_entry_id = buffer
- .read(&cx, |buffer, cx| {
+ .update(&mut cx, |buffer, cx| {
File::from_dyn(buffer.file()).and_then(|file| file.project_entry_id(cx))
- })
+ })?
.ok_or_else(|| anyhow!("no project entry"))?;
let buffer: &AnyHandle = &buffer;
@@ -1749,14 +1746,15 @@ impl Project {
this.loading_buffers_by_path.remove(&project_path);
let buffer = load_result.map_err(Arc::new)?;
Ok(buffer)
- }));
+ })?);
+ anyhow::Ok(())
})
.detach();
rx
}
};
- cx.foreground().spawn(async move {
+ cx.executor().spawn(async move {
wait_for_loading_buffer(loading_watch)
.await
.map_err(|error| anyhow!("{}", error))
@@ -1774,9 +1772,9 @@ impl Project {
let worktree = worktree.as_local_mut().unwrap();
worktree.load_buffer(buffer_id, path, cx)
});
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let buffer = load_buffer.await?;
- this.update(&mut cx, |this, cx| this.register_buffer(&buffer, cx))?;
+ this.update(&mut cx, |this, cx| this.register_buffer(&buffer, cx))??;
Ok(buffer)
})
}
@@ -1792,7 +1790,7 @@ impl Project {
let remote_worktree_id = worktree.read(cx).id();
let path = path.clone();
let path_string = path.to_string_lossy().to_string();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let response = rpc
.request(proto::OpenBufferByPath {
project_id,
@@ -1802,7 +1800,7 @@ impl Project {
.await?;
this.update(&mut cx, |this, cx| {
this.wait_for_remote_buffer(response.buffer_id, cx)
- })
+ })?
.await
})
}
@@ -1815,19 +1813,19 @@ impl Project {
language_server_name: LanguageServerName,
cx: &mut ModelContext<Self>,
) -> Task<Result<Handle<Buffer>>> {
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let abs_path = abs_path
.to_file_path()
.map_err(|_| anyhow!("can't convert URI to path"))?;
let (worktree, relative_path) = if let Some(result) =
- this.read(&cx, |this, cx| this.find_local_worktree(&abs_path, cx))
+ this.update(&mut cx, |this, cx| this.find_local_worktree(&abs_path, cx))?
{
result
} else {
let worktree = this
.update(&mut cx, |this, cx| {
this.create_local_worktree(&abs_path, false, cx)
- })
+ })?
.await?;
this.update(&mut cx, |this, cx| {
this.language_server_ids.insert(
@@ -1839,10 +1837,10 @@ impl Project {
};
let project_path = ProjectPath {
- worktree_id: worktree.read_with(&cx, |worktree, _| worktree.id()),
+ worktree_id: worktree.update(&mut cx, |worktree, _| worktree.id())?,
path: relative_path.into(),
};
- this.update(&mut cx, |this, cx| this.open_buffer(project_path, cx))
+ this.update(&mut cx, |this, cx| this.open_buffer(project_path, cx))?
.await
})
}
@@ -1852,7 +1850,7 @@ impl Project {
id: u64,
cx: &mut ModelContext<Self>,
) -> Task<Result<Handle<Buffer>>> {
- if let Some(buffer) = self.buffer_for_id(id, cx) {
+ if let Some(buffer) = self.buffer_for_id(id) {
Task::ready(Ok(buffer))
} else if self.is_local() {
Task::ready(Err(anyhow!("buffer {} does not exist", id)))
@@ -1860,11 +1858,11 @@ impl Project {
let request = self
.client
.request(proto::OpenBufferById { project_id, id });
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let buffer_id = request.await?.buffer_id;
this.update(&mut cx, |this, cx| {
this.wait_for_remote_buffer(buffer_id, cx)
- })
+ })?
.await
})
} else {
@@ -1877,10 +1875,11 @@ impl Project {
buffers: HashSet<Handle<Buffer>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
- cx.spawn(|this, mut cx| async move {
- let save_tasks = buffers
- .into_iter()
- .map(|buffer| this.update(&mut cx, |this, cx| this.save_buffer(buffer, cx)));
+ cx.spawn(move |this, mut cx| async move {
+ let save_tasks = buffers.into_iter().filter_map(|buffer| {
+ this.update(&mut cx, |this, cx| this.save_buffer(buffer, cx))
+ .ok()
+ });
try_join_all(save_tasks).await?;
Ok(())
})
@@ -1912,7 +1911,7 @@ impl Project {
let old_file = File::from_dyn(buffer.read(cx).file())
.filter(|f| f.is_local())
.cloned();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
if let Some(old_file) = &old_file {
this.update(&mut cx, |this, cx| {
this.unregister_buffer_from_language_servers(&buffer, old_file, cx);
@@ -1925,7 +1924,7 @@ impl Project {
worktree.save_buffer(buffer.clone(), path.into(), true, cx)
}
Worktree::Remote(_) => panic!("cannot remote buffers as new files"),
- })
+ })?
.await?;
this.update(&mut cx, |this, cx| {
@@ -2431,9 +2430,9 @@ impl Project {
const DISK_BASED_DIAGNOSTICS_DEBOUNCE: Duration =
Duration::from_secs(1);
- let task = cx.spawn(|this, mut cx| async move {
+ let task = cx.spawn(move |this, mut cx| async move {
cx.executor().timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE).await;
- if let Some(this) = this.upgrade(&cx) {
+ if let Some(this) = this.upgrade() {
this.update(&mut cx, |this, cx| {
this.disk_based_diagnostics_finished(
language_server_id,
@@ -2521,20 +2520,18 @@ impl Project {
}
fn recalculate_buffer_diffs(&mut self, cx: &mut ModelContext<Self>) -> Task<()> {
- cx.spawn(|this, mut cx| async move {
- let buffers: Vec<_> = this.update(&mut cx, |this, _| {
- this.buffers_needing_diff.drain().collect()
- });
-
- let tasks: Vec<_> = this.update(&mut cx, |_, cx| {
- buffers
- .iter()
- .filter_map(|buffer| {
- let buffer = buffer.upgrade()?;
- buffer.update(cx, |buffer, cx| buffer.git_diff_recalc(cx))
- })
- .collect()
- });
+ let buffers = self.buffers_needing_diff.drain().collect::<Vec<_>>();
+ cx.spawn(move |this, mut cx| async move {
+ let tasks: Vec<_> = buffers
+ .iter()
+ .filter_map(|buffer| {
+ let buffer = buffer.upgrade()?;
+ buffer
+ .update(&mut cx, |buffer, cx| buffer.git_diff_recalc(cx))
+ .ok()
+ .flatten()
+ })
+ .collect();
futures::future::join_all(tasks).await;
@@ -2549,7 +2546,8 @@ impl Project {
}
}
}
- });
+ })
+ .ok();
})
}
@@ -2581,9 +2579,9 @@ impl Project {
) -> Task<()> {
let mut subscription = languages.subscribe();
let mut prev_reload_count = languages.reload_count();
- cx.spawn_weak(|project, mut cx| async move {
+ cx.spawn(move |project, mut cx| async move {
while let Some(()) = subscription.next().await {
- if let Some(project) = project.upgrade(&cx) {
+ if let Some(project) = project.upgrade() {
// If the language registry has been reloaded, then remove and
// re-assign the languages on all open buffers.
let reload_count = languages.reload_count();
@@ -2634,21 +2632,17 @@ impl Project {
})
}
- fn maintain_workspace_config(cx: &mut ModelContext<Project>) -> Task<()> {
+ fn maintain_workspace_config(cx: &mut ModelContext<Project>) -> Task<Result<()>> {
let (mut settings_changed_tx, mut settings_changed_rx) = watch::channel();
let _ = postage::stream::Stream::try_recv(&mut settings_changed_rx);
- let settings_observation = cx.observe_global::<SettingsStore, _>(move |_, _| {
+ let settings_observation = cx.observe_global::<SettingsStore>(move |_, _| {
*settings_changed_tx.borrow_mut() = ();
});
- cx.spawn_weak(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
while let Some(_) = settings_changed_rx.next().await {
- let Some(this) = this.upgrade(&cx) else {
- break;
- };
-
- let servers: Vec<_> = this.read_with(&cx, |this, _| {
+ let servers: Vec<_> = this.update(&mut cx, |this, _| {
this.language_servers
.values()
.filter_map(|state| match state {
@@ -2658,11 +2652,11 @@ impl Project {
} => Some((adapter.clone(), server.clone())),
})
.collect()
- });
+ })?;
for (adapter, server) in servers {
let workspace_config =
- cx.update(|cx| adapter.workspace_configuration(cx)).await;
+ cx.update(|cx| adapter.workspace_configuration(cx))?.await;
server
.notify::<lsp2::notification::DidChangeConfiguration>(
lsp2::DidChangeConfigurationParams {
@@ -2674,6 +2668,7 @@ impl Project {
}
drop(settings_observation);
+ anyhow::Ok(())
})
}
@@ -2717,12 +2712,12 @@ impl Project {
let task_buffer = buffer.clone();
let prettier_installation_task =
self.install_default_formatters(worktree, &new_language, &settings, cx);
- cx.spawn(|project, mut cx| async move {
+ cx.spawn(move |project, mut cx| async move {
prettier_installation_task.await?;
let _ = project
.update(&mut cx, |project, cx| {
project.prettier_instance_for_buffer(&task_buffer, cx)
- })
+ })?
.await;
anyhow::Ok(())
})
@@ -2806,9 +2801,9 @@ impl Project {
let language = language.clone();
let key = key.clone();
- cx.spawn_weak(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let result = Self::setup_and_insert_language_server(
- this,
+ this.clone(),
initialization_options,
pending_server,
adapter.clone(),
@@ -2883,10 +2878,15 @@ impl Project {
// TODO: This is race-safe with regards to preventing new instances from
// starting while deleting, but existing instances in other projects are going
// to be very confused and messed up
- this.update(&mut cx, |this, cx| {
- this.languages.delete_server_container(adapter.clone(), cx)
- })
- .await;
+ let Some(task) = this
+ .update(&mut cx, |this, cx| {
+ this.languages.delete_server_container(adapter.clone(), cx)
+ })
+ .log_err()
+ else {
+ return;
+ };
+ task.await;
this.update(&mut cx, |this, mut cx| {
let worktrees = this.worktrees.clone();
@@ -2907,6 +2907,7 @@ impl Project {
);
}
})
+ .ok();
}))
}
@@ -2921,7 +2922,7 @@ impl Project {
cx: &mut AsyncAppContext,
) -> Result<Option<Arc<LanguageServer>>> {
let setup = Self::setup_pending_language_server(
- this,
+ this.clone(),
initialization_options,
pending_server,
adapter.clone(),
@@ -2960,7 +2961,7 @@ impl Project {
server_id: LanguageServerId,
cx: &mut AsyncAppContext,
) -> Result<Option<Arc<LanguageServer>>> {
- let workspace_config = cx.update(|cx| adapter.workspace_configuration(cx)).await;
+ let workspace_config = cx.update(|cx| adapter.workspace_configuration(cx))?.await;
let language_server = match pending_server.task.await? {
Some(server) => server,
None => return Ok(None),
@@ -2969,8 +2970,8 @@ impl Project {
language_server
.on_notification::<lsp2::notification::PublishDiagnostics, _>({
let adapter = adapter.clone();
+ let this = this.clone();
move |mut params, mut cx| {
- let this = this;
let adapter = adapter.clone();
adapter.process_diagnostics(&mut params);
if let Some(this) = this.upgrade() {
@@ -2991,11 +2992,11 @@ impl Project {
language_server
.on_request::<lsp2::request::WorkspaceConfiguration, _, _>({
let adapter = adapter.clone();
- move |params, mut cx| {
+ move |params, cx| {
let adapter = adapter.clone();
async move {
let workspace_config =
- cx.update(|cx| adapter.workspace_configuration(cx)).await;
+ cx.update(|cx| adapter.workspace_configuration(cx))?.await;
Ok(params
.items
.into_iter()
@@ -3019,9 +3020,11 @@ impl Project {
// avoid stalling any language server like `gopls` which waits for a response
// to these requests when initializing.
language_server
- .on_request::<lsp2::request::WorkDoneProgressCreate, _, _>(
- move |params, mut cx| async move {
- if let Some(this) = this.upgrade() {
+ .on_request::<lsp2::request::WorkDoneProgressCreate, _, _>({
+ let this = this.clone();
+ move |params, mut cx| {
+ let this = this.clone();
+ async move {
this.update(&mut cx, |this, _| {
if let Some(status) = this.language_server_statuses.get_mut(&server_id)
{
@@ -3029,27 +3032,33 @@ impl Project {
status.progress_tokens.insert(token);
}
}
- });
+ })?;
+
+ Ok(())
}
- Ok(())
- },
- )
+ }
+ })
.detach();
language_server
.on_request::<lsp2::request::RegisterCapability, _, _>({
- move |params, mut cx| async move {
- let this = this.upgrade().ok_or_else(|| anyhow!("project dropped"))?;
- for reg in params.registrations {
- if reg.method == "workspace/didChangeWatchedFiles" {
- if let Some(options) = reg.register_options {
- let options = serde_json::from_value(options)?;
- this.update(&mut cx, |this, cx| {
- this.on_lsp_did_change_watched_files(server_id, options, cx);
- });
+ let this = this.clone();
+ move |params, mut cx| {
+ let this = this.clone();
+ async move {
+ for reg in params.registrations {
+ if reg.method == "workspace/didChangeWatchedFiles" {
+ if let Some(options) = reg.register_options {
+ let options = serde_json::from_value(options)?;
+ this.update(&mut cx, |this, cx| {
+ this.on_lsp_did_change_watched_files(
+ server_id, options, cx,
+ );
+ })?;
+ }
}
}
+ Ok(())
}
- Ok(())
}
})
.detach();
@@ -3057,24 +3066,34 @@ impl Project {
language_server
.on_request::<lsp2::request::ApplyWorkspaceEdit, _, _>({
let adapter = adapter.clone();
+ let this = this.clone();
move |params, cx| {
- Self::on_lsp_workspace_edit(this, params, server_id, adapter.clone(), cx)
+ Self::on_lsp_workspace_edit(
+ this.clone(),
+ params,
+ server_id,
+ adapter.clone(),
+ cx,
+ )
}
})
.detach();
language_server
.on_request::<lsp2::request::InlayHintRefreshRequest, _, _>({
- move |(), mut cx| async move {
- let this = this.upgrade().ok_or_else(|| anyhow!("project dropped"))?;
- this.update(&mut cx, |project, cx| {
- cx.emit(Event::RefreshInlayHints);
- project.remote_id().map(|project_id| {
- project.client.send(proto::RefreshInlayHints { project_id })
- })
- })
- .transpose()?;
- Ok(())
+ let this = this.clone();
+ move |(), mut cx| {
+ let this = this.clone();
+ async move {
+ this.update(&mut cx, |project, cx| {
+ cx.emit(Event::RefreshInlayHints);
+ project.remote_id().map(|project_id| {
+ project.client.send(proto::RefreshInlayHints { project_id })
+ })
+ })?
+ .transpose()?;
+ Ok(())
+ }
}
})
.detach();
@@ -3282,7 +3301,7 @@ impl Project {
let server_state = self.language_servers.remove(&server_id);
cx.emit(Event::LanguageServerRemoved(server_id));
- cx.spawn_weak(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let mut root_path = None;
let server = match server_state {
@@ -3298,7 +3317,7 @@ impl Project {
}
}
- if let Some(this) = this.upgrade(&cx) {
+ if let Some(this) = this.upgrade() {
this.update(&mut cx, |this, cx| {
this.language_server_statuses.remove(&server_id);
cx.notify();
@@ -3358,7 +3377,7 @@ impl Project {
}
let mut stops = stops.into_iter();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let (original_root_path, mut orphaned_worktrees) = stops.next().unwrap().await;
for stop in stops {
let (_, worktrees) = stop.await;
@@ -3412,7 +3431,7 @@ impl Project {
return;
}
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
log::info!("About to spawn test binary");
// A lack of test binary counts as a failure
@@ -3451,9 +3470,12 @@ impl Project {
if errored {
log::warn!("test binary check failed");
- let task = this.update(&mut cx, move |this, mut cx| {
- this.reinstall_language_server(language, adapter, server_id, &mut cx)
- });
+ let task = this
+ .update(&mut cx, move |this, mut cx| {
+ this.reinstall_language_server(language, adapter, server_id, &mut cx)
+ })
+ .ok()
+ .flatten();
if let Some(task) = task {
task.await;
@@ -3718,7 +3740,7 @@ impl Project {
.upgrade()
.ok_or_else(|| anyhow!("project project closed"))?;
let language_server = this
- .read(&cx, |this, _| this.language_server_for_id(server_id))
+ .update(&mut cx, |this, _| this.language_server_for_id(server_id))?
.ok_or_else(|| anyhow!("language server not found"))?;
let transaction = Self::deserialize_workspace_edit(
this.clone(),
@@ -4004,7 +4026,7 @@ impl Project {
let remote_buffers = self.remote_id().zip(remote_buffers);
let client = self.client.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let mut project_transaction = ProjectTransaction::default();
if let Some((project_id, remote_buffers)) = remote_buffers {
@@ -4013,7 +4035,9 @@ impl Project {
project_id,
buffer_ids: remote_buffers
.iter()
- .map(|buffer| buffer.update(&mut cx, |buffer, _| buffer.remote_id()))
+ .filter_map(|buffer| {
+ buffer.update(&mut cx, |buffer, _| buffer.remote_id()).ok()
+ })
.collect(),
})
.await?
@@ -4065,7 +4089,7 @@ impl Project {
})
.collect::<Vec<_>>();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
// Do not allow multiple concurrent formatting requests for the
// same buffer.
this.update(&mut cx, |this, cx| {
@@ -4121,7 +4145,7 @@ impl Project {
buffer.ensure_final_newline(cx);
}
buffer.end_transaction(cx)
- });
+ })?;
// Currently, formatting operations are represented differently depending on
// whether they come from a language server or an external command.
@@ -4191,7 +4215,7 @@ impl Project {
})?;
format_operation = Some(FormatOperation::Prettier(
prettier
- .format(buffer, buffer_path, &cx)
+ .format(buffer, buffer_path, &mut cx)
.await
.context("formatting via prettier")?,
));
@@ -4221,16 +4245,16 @@ impl Project {
if let Some(prettier_task) = this
.update(&mut cx, |project, cx| {
project.prettier_instance_for_buffer(buffer, cx)
- }).await {
+ })?.await {
match prettier_task.await
{
Ok(prettier) => {
let buffer_path = buffer.update(&mut cx, |buffer, cx| {
File::from_dyn(buffer.file()).map(|file| file.abs_path(cx))
- });
+ })?;
format_operation = Some(FormatOperation::Prettier(
prettier
- .format(buffer, buffer_path, &cx)
+ .format(buffer, buffer_path, &mut cx)
.await
.context("formatting via prettier")?,
));
@@ -4289,7 +4313,7 @@ impl Project {
} else {
let remote_id = self.remote_id();
let client = self.client.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let mut project_transaction = ProjectTransaction::default();
if let Some(project_id) = remote_id {
let response = client
@@ -4343,7 +4367,7 @@ impl Project {
.await?
} else if matches!(range_formatting_provider, Some(p) if *p != OneOf::Left(false)) {
let buffer_start = lsp2::Position::new(0, 0);
- let buffer_end = buffer.update(&mut cx, |b, _| point_to_lsp(b.max_point_utf16()))?;
+ let buffer_end = buffer.update(cx, |b, _| point_to_lsp(b.max_point_utf16()))?;
language_server
.request::<lsp2::request::RangeFormatting>(lsp2::DocumentRangeFormattingParams {
@@ -4374,7 +4398,7 @@ impl Project {
arguments: &[String],
cx: &mut AsyncAppContext,
) -> Result<Option<Diff>> {
- let working_dir_path = buffer.update(&mut cx, |buffer, cx| {
+ let working_dir_path = buffer.update(cx, |buffer, cx| {
let file = File::from_dyn(buffer.file())?;
let worktree = file.worktree.read(cx).as_local()?;
let mut worktree_path = worktree.abs_path().to_path_buf();
@@ -4382,7 +4406,7 @@ impl Project {
worktree_path.pop();
}
Some(worktree_path)
- });
+ })?;
if let Some(working_dir_path) = working_dir_path {
let mut child =
@@ -4399,7 +4423,7 @@ impl Project {
.stdin
.as_mut()
.ok_or_else(|| anyhow!("failed to acquire stdin"))?;
- let text = buffer.update(&mut cx, |buffer, _| buffer.as_rope().clone());
+ let text = buffer.update(cx, |buffer, _| buffer.as_rope().clone())?;
for chunk in text.chunks() {
stdin.write_all(chunk.as_bytes()).await?;
}
@@ -4417,7 +4441,9 @@ impl Project {
let stdout = String::from_utf8(output.stdout)?;
Ok(Some(
- buffer.read(cx, |buffer, cx| buffer.diff(stdout, cx)).await,
+ buffer
+ .update(cx, |buffer, cx| buffer.diff(stdout, cx))?
+ .await,
))
} else {
Ok(None)
@@ -4548,14 +4574,14 @@ impl Project {
);
}
- cx.spawn_weak(|this, cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let responses = futures::future::join_all(requests).await;
- let this = match this.upgrade(&cx) {
+ let this = match this.upgrade() {
Some(this) => this,
None => return Ok(Vec::new()),
};
- let symbols = this.read_with(&cx, |this, cx| {
+ let symbols = this.update(&mut cx, |this, cx| {
let mut symbols = Vec::new();
for (
adapter,
@@ -4613,7 +4639,7 @@ impl Project {
}
symbols
- });
+ })?;
Ok(futures::future::join_all(symbols).await)
})
@@ -4622,17 +4648,17 @@ impl Project {
project_id,
query: query.to_string(),
});
- cx.spawn_weak(|this, cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let response = request.await?;
let mut symbols = Vec::new();
- if let Some(this) = this.upgrade(&cx) {
- let new_symbols = this.read_with(&cx, |this, _| {
+ if let Some(this) = this.upgrade() {
+ let new_symbols = this.update(&mut cx, |this, _| {
response
.symbols
.into_iter()
.map(|symbol| this.deserialize_symbol(symbol))
.collect::<Vec<_>>()
- });
+ })?;
symbols = futures::future::join_all(new_symbols)
.await
.into_iter()
@@ -4690,11 +4716,11 @@ impl Project {
project_id,
symbol: Some(serialize_symbol(symbol)),
});
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let response = request.await?;
this.update(&mut cx, |this, cx| {
this.wait_for_remote_buffer(response.buffer_id, cx)
- })
+ })?
.await
})
} else {
@@ -4742,7 +4768,7 @@ impl Project {
.collect();
let buffer = buffer.clone();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let mut tasks = Vec::with_capacity(server_ids.len());
this.update(&mut cx, |this, cx| {
for server_id in server_ids {
@@ -4788,7 +4814,7 @@ impl Project {
_ => return Task::ready(Ok(Default::default())),
};
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let can_resolve = lang_server
.capabilities()
.completion_provider
@@ -4813,7 +4839,7 @@ impl Project {
None,
cx,
)
- })
+ })?
.await?;
buffer_handle.update(&mut cx, |buffer, cx| {
@@ -4851,7 +4877,7 @@ impl Project {
})
} else if let Some(project_id) = self.remote_id() {
let client = self.client.clone();
- cx.spawn(|_, mut cx| async move {
+ cx.spawn(move |_, mut cx| async move {
let response = client
.request(proto::ApplyCompletionAdditionalEdits {
project_id,