gpui: Actually remove the Result from AsyncApp (#45809)

Depends on: https://github.com/zed-industries/zed/pull/45768

Refactor plan:
https://gist.github.com/mikayla-maki/6c4bf263fd80050715ba01f45478796e
Overall plan:
https://gist.github.com/mikayla-maki/7bb5078e4385a2e683e1e1eb40d17d38

This is the big one.

Release Notes:

- N/A

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikayla Maki 2026-01-07 12:48:24 -08:00 committed by GitHub
parent 4831e5cba9
commit 97c35c084b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
223 changed files with 2272 additions and 2822 deletions

View file

@ -375,18 +375,16 @@ impl ToolCall {
})
.ok()??;
let buffer = buffer.await.log_err()?;
let position = buffer
.update(cx, |buffer, _| {
let snapshot = buffer.snapshot();
if let Some(row) = location.line {
let column = snapshot.indent_size_for_line(row).len;
let point = snapshot.clip_point(Point::new(row, column), Bias::Left);
snapshot.anchor_before(point)
} else {
Anchor::min_for_buffer(snapshot.remote_id())
}
})
.ok()?;
let position = buffer.update(cx, |buffer, _| {
let snapshot = buffer.snapshot();
if let Some(row) = location.line {
let column = snapshot.indent_size_for_line(row).len;
let point = snapshot.clip_point(Point::new(row, column), Bias::Left);
snapshot.anchor_before(point)
} else {
Anchor::min_for_buffer(snapshot.remote_id())
}
});
Some(ResolvedLocation { buffer, position })
}
@ -1803,7 +1801,7 @@ impl AcpThread {
.ok();
let old_checkpoint = git_store
.update(cx, |git, cx| git.checkpoint(cx))?
.update(cx, |git, cx| git.checkpoint(cx))
.await
.context("failed to get old checkpoint")
.log_err();
@ -1983,7 +1981,7 @@ impl AcpThread {
rewind.await?;
if let Some(checkpoint) = checkpoint {
git_store
.update(cx, |git, cx| git.restore_checkpoint(checkpoint, cx))?
.update(cx, |git, cx| git.restore_checkpoint(checkpoint, cx))
.await?;
}
@ -2001,7 +1999,7 @@ impl AcpThread {
let telemetry = ActionLogTelemetry::from(&*self);
cx.spawn(async move |this, cx| {
cx.update(|cx| truncate.run(id.clone(), cx))?.await?;
cx.update(|cx| truncate.run(id.clone(), cx)).await?;
this.update(cx, |this, cx| {
if let Some((ix, _)) = this.user_message_mut(&id) {
// Collect all terminals from entries that will be removed
@ -2060,7 +2058,7 @@ impl AcpThread {
let equal = git_store
.update(cx, |git, cx| {
git.compare_checkpoints(old_checkpoint.clone(), new_checkpoint, cx)
})?
})
.await
.unwrap_or(true);
@ -2119,17 +2117,14 @@ impl AcpThread {
let project = self.project.clone();
let action_log = self.action_log.clone();
cx.spawn(async move |this, cx| {
let load = project
.update(cx, |project, cx| {
let path = project
.project_path_for_absolute_path(&path, cx)
.ok_or_else(|| {
acp::Error::resource_not_found(Some(path.display().to_string()))
})?;
Ok(project.open_buffer(path, cx))
})
.map_err(|e| acp::Error::internal_error().data(e.to_string()))
.flatten()?;
let load = project.update(cx, |project, cx| {
let path = project
.project_path_for_absolute_path(&path, cx)
.ok_or_else(|| {
acp::Error::resource_not_found(Some(path.display().to_string()))
})?;
Ok::<_, acp::Error>(project.open_buffer(path, cx))
})?;
let buffer = load.await?;
@ -2148,9 +2143,9 @@ impl AcpThread {
} else {
action_log.update(cx, |action_log, cx| {
action_log.buffer_read(buffer.clone(), cx);
})?;
});
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot())?;
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
this.update(cx, |this, _| {
this.shared_buffers.insert(buffer.clone(), snapshot.clone());
})?;
@ -2179,7 +2174,7 @@ impl AcpThread {
}),
cx,
);
})?;
});
Ok(snapshot.text_for_range(start..end).collect::<String>())
})
@ -2200,7 +2195,7 @@ impl AcpThread {
.context("invalid path")?;
anyhow::Ok(project.open_buffer(path, cx))
});
let buffer = load??.await?;
let buffer = load?.await?;
let snapshot = this.update(cx, |this, cx| {
this.shared_buffers
.get(&buffer)
@ -2235,7 +2230,7 @@ impl AcpThread {
}),
cx,
);
})?;
});
let format_on_save = cx.update(|cx| {
action_log.update(cx, |action_log, cx| {
@ -2257,7 +2252,7 @@ impl AcpThread {
action_log.buffer_edited(buffer.clone(), cx);
});
format_on_save
})?;
});
if format_on_save {
let format_task = project.update(cx, |project, cx| {
@ -2268,16 +2263,16 @@ impl AcpThread {
FormatTrigger::Save,
cx,
)
})?;
});
format_task.await.log_err();
action_log.update(cx, |action_log, cx| {
action_log.buffer_edited(buffer.clone(), cx);
})?;
});
}
project
.update(cx, |project, cx| project.save_buffer(buffer, cx))?
.update(cx, |project, cx| project.save_buffer(buffer, cx))
.await
})
}
@ -2323,7 +2318,7 @@ impl AcpThread {
project
.remote_client()
.and_then(|r| r.read(cx).default_system_shell())
})?
})
.unwrap_or_else(|| get_default_system_shell_preferring_bash());
let (task_command, task_args) =
ShellBuilder::new(&Shell::Program(shell), is_windows)
@ -2341,10 +2336,10 @@ impl AcpThread {
},
cx,
)
})?
})
.await?;
cx.new(|cx| {
anyhow::Ok(cx.new(|cx| {
Terminal::new(
terminal_id,
&format!("{} {}", command, args.join(" ")),
@ -2354,7 +2349,7 @@ impl AcpThread {
language_registry,
cx,
)
})
}))
}
});

View file

@ -35,7 +35,7 @@ impl Diff {
.await
.log_err();
buffer.update(cx, |buffer, cx| buffer.set_language(language.clone(), cx))?;
buffer.update(cx, |buffer, cx| buffer.set_language(language.clone(), cx));
let diff = build_buffer_diff(
old_text.unwrap_or("".into()).into(),
@ -45,31 +45,29 @@ impl Diff {
)
.await?;
multibuffer
.update(cx, |multibuffer, cx| {
let hunk_ranges = {
let buffer = buffer.read(cx);
diff.read(cx)
.snapshot(cx)
.hunks_intersecting_range(
Anchor::min_for_buffer(buffer.remote_id())
..Anchor::max_for_buffer(buffer.remote_id()),
buffer,
)
.map(|diff_hunk| diff_hunk.buffer_range.to_point(buffer))
.collect::<Vec<_>>()
};
multibuffer.update(cx, |multibuffer, cx| {
let hunk_ranges = {
let buffer = buffer.read(cx);
diff.read(cx)
.snapshot(cx)
.hunks_intersecting_range(
Anchor::min_for_buffer(buffer.remote_id())
..Anchor::max_for_buffer(buffer.remote_id()),
buffer,
)
.map(|diff_hunk| diff_hunk.buffer_range.to_point(buffer))
.collect::<Vec<_>>()
};
multibuffer.set_excerpts_for_path(
PathKey::for_buffer(&buffer, cx),
buffer.clone(),
hunk_ranges,
multibuffer_context_lines(cx),
cx,
);
multibuffer.add_diff(diff, cx);
})
.log_err();
multibuffer.set_excerpts_for_path(
PathKey::for_buffer(&buffer, cx),
buffer.clone(),
hunk_ranges,
multibuffer_context_lines(cx),
cx,
);
multibuffer.add_diff(diff, cx);
});
anyhow::Ok(())
}
@ -206,8 +204,8 @@ impl PendingDiff {
let buffer_diff = self.diff.clone();
let base_text = self.base_text.clone();
self.update_diff = cx.spawn(async move |diff, cx| {
let text_snapshot = buffer.read_with(cx, |buffer, _| buffer.text_snapshot())?;
let language = buffer.read_with(cx, |buffer, _| buffer.language().cloned())?;
let text_snapshot = buffer.read_with(cx, |buffer, _| buffer.text_snapshot());
let language = buffer.read_with(cx, |buffer, _| buffer.language().cloned());
let update = buffer_diff
.update(cx, |diff, cx| {
diff.update_diff(
@ -217,7 +215,7 @@ impl PendingDiff {
language,
cx,
)
})?
})
.await;
let (task1, task2) = buffer_diff.update(cx, |diff, cx| {
let task1 = diff.set_snapshot(update.clone(), &text_snapshot, cx);
@ -226,7 +224,7 @@ impl PendingDiff {
.unwrap()
.update(cx, |diff, cx| diff.set_snapshot(update, &text_snapshot, cx));
(task1, task2)
})?;
});
task1.await;
task2.await;
diff.update(cx, |diff, cx| {
@ -374,36 +372,37 @@ async fn build_buffer_diff(
language_registry: Option<Arc<LanguageRegistry>>,
cx: &mut AsyncApp,
) -> Result<Entity<BufferDiff>> {
let language = cx.update(|cx| buffer.read(cx).language().cloned())?;
let buffer = cx.update(|cx| buffer.read(cx).snapshot())?;
let language = cx.update(|cx| buffer.read(cx).language().cloned());
let text_snapshot = cx.update(|cx| buffer.read(cx).text_snapshot());
let buffer = cx.update(|cx| buffer.read(cx).snapshot());
let secondary_diff = cx.new(|cx| BufferDiff::new(&buffer, cx))?;
let secondary_diff = cx.new(|cx| BufferDiff::new(&buffer, cx));
let update = secondary_diff
.update(cx, |secondary_diff, cx| {
secondary_diff.update_diff(
buffer.text.clone(),
text_snapshot.clone(),
Some(old_text),
true,
language.clone(),
cx,
)
})?
})
.await;
secondary_diff
.update(cx, |secondary_diff, cx| {
secondary_diff.language_changed(language.clone(), language_registry.clone(), cx);
secondary_diff.set_snapshot(update.clone(), &buffer, cx)
})?
})
.await;
let diff = cx.new(|cx| BufferDiff::new(&buffer, cx))?;
let diff = cx.new(|cx| BufferDiff::new(&buffer, cx));
diff.update(cx, |diff, cx| {
diff.language_changed(language, language_registry, cx);
diff.set_secondary_diff(secondary_diff);
diff.set_snapshot(update.clone(), &buffer, cx)
})?
})
.await;
Ok(diff)
}

View file

@ -205,7 +205,7 @@ pub async fn create_terminal_entity(
project.environment().update(cx, |env, cx| {
env.directory_environment(dir.clone().into(), cx)
})
})?
})
.await
.unwrap_or_default()
} else {
@ -225,11 +225,9 @@ pub async fn create_terminal_entity(
.remote_client()
.and_then(|r| r.read(cx).default_system_shell())
.map(Shell::Program)
})?
})
.unwrap_or_else(|| Shell::Program(get_default_system_shell_preferring_bash()));
let is_windows = project
.read_with(cx, |project, cx| project.path_style(cx).is_windows())
.unwrap_or(cfg!(windows));
let is_windows = project.read_with(cx, |project, cx| project.path_style(cx).is_windows());
let (task_command, task_args) = task::ShellBuilder::new(&shell, is_windows)
.redirect_stdin_to_dev_null()
.build(Some(command.clone()), &args);
@ -246,6 +244,6 @@ pub async fn create_terminal_entity(
},
cx,
)
})?
})
.await
}

View file

@ -198,7 +198,7 @@ impl ActionLog {
.ok();
let buffer_repo = git_store.read_with(cx, |git_store, cx| {
git_store.repository_and_path_for_buffer_id(buffer.read(cx).remote_id(), cx)
})?;
});
let (mut git_diff_updates_tx, mut git_diff_updates_rx) = watch::channel(());
let _repo_subscription =
@ -214,7 +214,7 @@ impl ActionLog {
}
}
}))
})?
})
} else {
None
};
@ -394,54 +394,51 @@ impl ActionLog {
buffer.read(cx).language().cloned(),
))
})??;
let update = diff.update(cx, |diff, cx| {
diff.update_diff(
buffer_snapshot.clone(),
Some(new_base_text),
true,
language,
cx,
)
});
let mut unreviewed_edits = Patch::default();
if let Ok(update) = update {
let update = update.await;
diff.update(cx, |diff, cx| {
diff.set_snapshot(update.clone(), &buffer_snapshot, cx)
})?
let update = diff
.update(cx, |diff, cx| {
diff.update_diff(
buffer_snapshot.clone(),
Some(new_base_text),
true,
language,
cx,
)
})
.await;
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx))?;
diff.update(cx, |diff, cx| {
diff.set_snapshot(update.clone(), &buffer_snapshot, cx)
})
.await;
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx));
unreviewed_edits = cx
.background_spawn({
let buffer_snapshot = buffer_snapshot.clone();
let new_diff_base = new_diff_base.clone();
async move {
let mut unreviewed_edits = Patch::default();
for hunk in diff_snapshot.hunks_intersecting_range(
Anchor::min_for_buffer(buffer_snapshot.remote_id())
..Anchor::max_for_buffer(buffer_snapshot.remote_id()),
&buffer_snapshot,
) {
let old_range = new_diff_base
.offset_to_point(hunk.diff_base_byte_range.start)
..new_diff_base.offset_to_point(hunk.diff_base_byte_range.end);
let new_range = hunk.range.start..hunk.range.end;
unreviewed_edits.push(point_to_row_edit(
Edit {
old: old_range,
new: new_range,
},
&new_diff_base,
buffer_snapshot.as_rope(),
));
}
unreviewed_edits
let unreviewed_edits = cx
.background_spawn({
let buffer_snapshot = buffer_snapshot.clone();
let new_diff_base = new_diff_base.clone();
async move {
let mut unreviewed_edits = Patch::default();
for hunk in diff_snapshot.hunks_intersecting_range(
Anchor::min_for_buffer(buffer_snapshot.remote_id())
..Anchor::max_for_buffer(buffer_snapshot.remote_id()),
&buffer_snapshot,
) {
let old_range = new_diff_base
.offset_to_point(hunk.diff_base_byte_range.start)
..new_diff_base.offset_to_point(hunk.diff_base_byte_range.end);
let new_range = hunk.range.start..hunk.range.end;
unreviewed_edits.push(point_to_row_edit(
Edit {
old: old_range,
new: new_range,
},
&new_diff_base,
buffer_snapshot.as_rope(),
));
}
})
.await;
}
unreviewed_edits
}
})
.await;
this.update(cx, |this, cx| {
let tracked_buffer = this
.tracked_buffers

View file

@ -246,7 +246,7 @@ impl ActivityIndicator {
cx,
);
buffer.set_capability(language::Capability::ReadOnly, cx);
})?;
});
workspace.update_in(cx, |workspace, window, cx| {
workspace.add_item_to_active_pane(
Box::new(cx.new(|cx| {

View file

@ -250,10 +250,10 @@ impl NativeAgent {
log::debug!("Creating new NativeAgent");
let project_context = cx
.update(|cx| Self::build_project_context(&project, prompt_store.as_ref(), cx))?
.update(|cx| Self::build_project_context(&project, prompt_store.as_ref(), cx))
.await;
cx.new(|cx| {
Ok(cx.new(|cx| {
let context_server_store = project.read(cx).context_server_store();
let context_server_registry =
cx.new(|cx| ContextServerRegistry::new(context_server_store.clone(), cx));
@ -295,7 +295,7 @@ impl NativeAgent {
fs,
_subscriptions: subscriptions,
}
})
}))
}
fn register_session(
@ -512,10 +512,12 @@ impl NativeAgent {
let buffer_task =
project.update(cx, |project, cx| project.open_buffer(project_path, cx));
let rope_task = cx.spawn(async move |cx| {
buffer_task.await?.read_with(cx, |buffer, cx| {
let buffer = buffer_task.await?;
let (project_entry_id, rope) = buffer.read_with(cx, |buffer, cx| {
let project_entry_id = buffer.entry_id(cx).context("buffer has no file")?;
anyhow::Ok((project_entry_id, buffer.as_rope().clone()))
})?
})?;
anyhow::Ok((project_entry_id, rope))
});
// Build a string from the rope on a background thread.
cx.background_spawn(async move {
@ -761,10 +763,10 @@ impl NativeAgent {
let thread = task.await?;
let acp_thread =
this.update(cx, |this, cx| this.register_session(thread.clone(), cx))?;
let events = thread.update(cx, |thread, cx| thread.replay(cx))?;
let events = thread.update(cx, |thread, cx| thread.replay(cx));
cx.update(|cx| {
NativeAgentConnection::handle_thread_events(events, acp_thread.downgrade(), cx)
})?
})
.await?;
Ok(acp_thread)
})
@ -811,7 +813,7 @@ impl NativeAgent {
};
let db_thread = db_thread.await;
database.save_thread(id, db_thread).await.log_err();
history.update(cx, |history, cx| history.reload(cx)).ok();
history.update(cx, |history, cx| history.reload(cx));
});
}
@ -849,7 +851,7 @@ impl NativeAgent {
path_style,
cx,
);
})?;
});
for message in prompt.messages {
let context_server::types::PromptMessage { role, content } = message;
@ -866,13 +868,11 @@ impl NativeAgent {
true,
cx,
);
anyhow::Ok(())
})??;
})?;
thread.update(cx, |thread, cx| {
thread.push_acp_user_block(id, [block], path_style, cx);
anyhow::Ok(())
})??;
});
}
context_server::types::Role::Assistant => {
acp_thread.update(cx, |acp_thread, cx| {
@ -882,13 +882,11 @@ impl NativeAgent {
true,
cx,
);
anyhow::Ok(())
})??;
})?;
thread.update(cx, |thread, cx| {
thread.push_acp_agent_block(block, cx);
anyhow::Ok(())
})??;
});
}
}
@ -902,11 +900,11 @@ impl NativeAgent {
// Resume if MCP prompt did not end with a user message
thread.resume(cx)
}
})??;
})?;
cx.update(|cx| {
NativeAgentConnection::handle_thread_events(response_stream, acp_thread, cx)
})?
})
.await
})
}
@ -1187,33 +1185,30 @@ impl acp_thread::AgentConnection for NativeAgentConnection {
log::debug!("Starting thread creation in async context");
// Create Thread
let thread = agent.update(
cx,
|agent, cx: &mut gpui::Context<NativeAgent>| -> Result<_> {
// Fetch default model from registry settings
let registry = LanguageModelRegistry::read_global(cx);
// Log available models for debugging
let available_count = registry.available_models(cx).count();
log::debug!("Total available models: {}", available_count);
let thread = agent.update(cx, |agent, cx| {
// Fetch default model from registry settings
let registry = LanguageModelRegistry::read_global(cx);
// Log available models for debugging
let available_count = registry.available_models(cx).count();
log::debug!("Total available models: {}", available_count);
let default_model = registry.default_model().and_then(|default_model| {
agent
.models
.model_from_id(&LanguageModels::model_id(&default_model.model))
});
Ok(cx.new(|cx| {
Thread::new(
project.clone(),
agent.project_context.clone(),
agent.context_server_registry.clone(),
agent.templates.clone(),
default_model,
cx,
)
}))
},
)??;
agent.update(cx, |agent, cx| agent.register_session(thread, cx))
let default_model = registry.default_model().and_then(|default_model| {
agent
.models
.model_from_id(&LanguageModels::model_id(&default_model.model))
});
cx.new(|cx| {
Thread::new(
project.clone(),
agent.project_context.clone(),
agent.context_server_registry.clone(),
agent.templates.clone(),
default_model,
cx,
)
})
});
Ok(agent.update(cx, |agent, cx| agent.register_session(thread, cx)))
})
}
@ -1446,7 +1441,7 @@ impl ThreadEnvironment for AcpThreadEnvironment {
let terminal = task?.await?;
let (drop_tx, drop_rx) = oneshot::channel();
let terminal_id = terminal.read_with(cx, |terminal, _cx| terminal.id().clone())?;
let terminal_id = terminal.read_with(cx, |terminal, _cx| terminal.id().clone());
cx.spawn(async move |cx| {
drop_rx.await.ok();
@ -1471,17 +1466,19 @@ pub struct AcpTerminalHandle {
impl TerminalHandle for AcpTerminalHandle {
fn id(&self, cx: &AsyncApp) -> Result<acp::TerminalId> {
self.terminal.read_with(cx, |term, _cx| term.id().clone())
Ok(self.terminal.read_with(cx, |term, _cx| term.id().clone()))
}
fn wait_for_exit(&self, cx: &AsyncApp) -> Result<Shared<Task<acp::TerminalExitStatus>>> {
self.terminal
.read_with(cx, |term, _cx| term.wait_for_exit())
Ok(self
.terminal
.read_with(cx, |term, _cx| term.wait_for_exit()))
}
fn current_output(&self, cx: &AsyncApp) -> Result<acp::TerminalOutputResponse> {
self.terminal
.read_with(cx, |term, cx| term.current_output(cx))
Ok(self
.terminal
.read_with(cx, |term, cx| term.current_output(cx)))
}
fn kill(&self, cx: &AsyncApp) -> Result<()> {
@ -1489,13 +1486,14 @@ impl TerminalHandle for AcpTerminalHandle {
self.terminal.update(cx, |terminal, cx| {
terminal.kill(cx);
});
})?;
});
Ok(())
}
fn was_stopped_by_user(&self, cx: &AsyncApp) -> Result<bool> {
self.terminal
.read_with(cx, |term, _cx| term.was_stopped_by_user())
Ok(self
.terminal
.read_with(cx, |term, _cx| term.was_stopped_by_user()))
}
}

View file

@ -114,8 +114,8 @@ impl EditAgent {
let (events_tx, events_rx) = mpsc::unbounded();
let conversation = conversation.clone();
let output = cx.spawn(async move |cx| {
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
let path = cx.update(|cx| snapshot.resolve_file_path(true, cx))?;
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
let path = cx.update(|cx| snapshot.resolve_file_path(true, cx));
let prompt = CreateFilePromptTemplate {
path,
edit_description,
@ -148,7 +148,7 @@ impl EditAgent {
let this = self.clone();
let task = cx.spawn(async move |cx| {
this.action_log
.update(cx, |log, cx| log.buffer_created(buffer.clone(), cx))?;
.update(cx, |log, cx| log.buffer_created(buffer.clone(), cx));
this.overwrite_with_chunks_internal(buffer, parse_rx, output_events_tx, cx)
.await?;
parse_task.await
@ -182,7 +182,7 @@ impl EditAgent {
Anchor::min_max_range_for_buffer(buffer.read(cx).remote_id()),
))
.ok();
})?;
});
while let Some(event) = parse_rx.next().await {
match event? {
@ -203,7 +203,7 @@ impl EditAgent {
)
});
buffer.read(cx).remote_id()
})?;
});
output_events_tx
.unbounded_send(EditAgentOutputEvent::Edited(
Anchor::min_max_range_for_buffer(buffer_id),
@ -231,8 +231,8 @@ impl EditAgent {
let conversation = conversation.clone();
let edit_format = self.edit_format;
let output = cx.spawn(async move |cx| {
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
let path = cx.update(|cx| snapshot.resolve_file_path(true, cx))?;
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
let path = cx.update(|cx| snapshot.resolve_file_path(true, cx));
let prompt = match edit_format {
EditFormat::XmlTags => EditFileXmlPromptTemplate {
path,
@ -263,7 +263,7 @@ impl EditAgent {
cx: &mut AsyncApp,
) -> Result<EditAgentOutput> {
self.action_log
.update(cx, |log, cx| log.buffer_read(buffer.clone(), cx))?;
.update(cx, |log, cx| log.buffer_read(buffer.clone(), cx));
let (output, edit_events) = Self::parse_edit_chunks(edit_chunks, self.edit_format, cx);
let mut edit_events = edit_events.peekable();
@ -274,7 +274,7 @@ impl EditAgent {
continue;
};
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
// Resolve the old text in the background, updating the agent
// location as we keep refining which range it corresponds to.
@ -292,7 +292,7 @@ impl EditAgent {
}),
cx,
);
})?;
});
output_events
.unbounded_send(EditAgentOutputEvent::ResolvingEditRange(old_range))
.ok();
@ -375,7 +375,7 @@ impl EditAgent {
);
});
(min_edit_start, max_edit_end)
})?;
});
output_events
.unbounded_send(EditAgentOutputEvent::Edited(min_edit_start..max_edit_end))
.ok();

View file

@ -1473,9 +1473,9 @@ impl EditAgentTest {
.provider(&selected_model.provider)
.expect("Provider not found");
provider.authenticate(cx)
})?
})
.await?;
cx.update(|cx| {
Ok(cx.update(|cx| {
let models = LanguageModelRegistry::read_global(cx);
let model = models
.available_models(cx)
@ -1485,7 +1485,7 @@ impl EditAgentTest {
})
.unwrap_or_else(|| panic!("Model {} not found", selected_model.model.0));
model
})
}))
}
async fn eval(&self, mut eval: EvalInput, cx: &mut TestAppContext) -> Result<EditEvalOutput> {

View file

@ -43,7 +43,7 @@ pub fn load_agent_thread(
cx.spawn(async move |cx| {
let (agent, _) = connection.await?;
let agent = agent.downcast::<crate::NativeAgentConnection>().unwrap();
cx.update(|cx| agent.load_thread(session_id, cx))?.await
cx.update(|cx| agent.load_thread(session_id, cx)).await
})
}

View file

@ -25,13 +25,13 @@ pub async fn get_buffer_content_or_outline(
path: Option<&str>,
cx: &AsyncApp,
) -> Result<BufferContent> {
let file_size = buffer.read_with(cx, |buffer, _| buffer.text().len())?;
let file_size = buffer.read_with(cx, |buffer, _| buffer.text().len());
if file_size > AUTO_OUTLINE_SIZE {
// For large files, use outline instead of full content
// Wait until the buffer has been fully parsed, so we can read its outline
buffer
.read_with(cx, |buffer, _| buffer.parsing_idle())?
.read_with(cx, |buffer, _| buffer.parsing_idle())
.await;
let outline_items = buffer.read_with(cx, |buffer, _| {
@ -42,7 +42,7 @@ pub async fn get_buffer_content_or_outline(
.into_iter()
.map(|item| item.to_point(&snapshot))
.collect::<Vec<_>>()
})?;
});
// If no outline exists, fall back to first 1KB so the agent has some context
if outline_items.is_empty() {
@ -55,7 +55,7 @@ pub async fn get_buffer_content_or_outline(
} else {
format!("# First 1KB of file (file too large to show full content, and no outline available)\n\n{content}")
}
})?;
});
return Ok(BufferContent {
text,
@ -76,7 +76,7 @@ pub async fn get_buffer_content_or_outline(
})
} else {
// File is small enough, return full content
let text = buffer.read_with(cx, |buffer, _| buffer.text())?;
let text = buffer.read_with(cx, |buffer, _| buffer.text());
Ok(BufferContent {
text,
is_outline: false,

View file

@ -2413,7 +2413,7 @@ where
cx.spawn(async move |cx| {
let input = serde_json::from_value(input)?;
let output = cx
.update(|cx| self.0.clone().run(input, event_stream, cx))?
.update(|cx| self.0.clone().run(input, event_stream, cx))
.await?;
let raw_output = serde_json::to_value(&output)?;
Ok(AgentToolOutput {
@ -2650,7 +2650,7 @@ impl ToolCallEventStream {
.get_or_insert_default()
.set_always_allow_tool_actions(true);
});
})?;
});
}
Ok(())

View file

@ -403,10 +403,7 @@ pub fn get_prompt(
arguments: HashMap<String, String>,
cx: &mut AsyncApp,
) -> Task<Result<context_server::types::PromptsGetResponse>> {
let server = match cx.update(|cx| server_store.read(cx).get_running_server(server_id)) {
Ok(server) => server,
Err(error) => return Task::ready(Err(error)),
};
let server = cx.update(|cx| server_store.read(cx).get_running_server(server_id));
let Some(server) = server else {
return Task::ready(Err(anyhow::anyhow!("Context server not found")));
};

View file

@ -115,19 +115,19 @@ impl AgentTool for DeletePathTool {
cx.spawn(async move |cx| {
while let Some(path) = paths_rx.next().await {
if let Ok(buffer) = project
.update(cx, |project, cx| project.open_buffer(path, cx))?
.update(cx, |project, cx| project.open_buffer(path, cx))
.await
{
action_log.update(cx, |action_log, cx| {
action_log.will_delete_buffer(buffer.clone(), cx)
})?;
});
}
}
let deletion_task = project
.update(cx, |project, cx| {
project.delete_file(project_path, false, cx)
})?
})
.with_context(|| {
format!("Couldn't delete {path} because that path isn't in this project.")
})?;

View file

@ -105,7 +105,7 @@ impl AgentTool for DiagnosticsTool {
cx.spawn(async move |cx| {
let mut output = String::new();
let buffer = buffer.await?;
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
for (_, group) in snapshot.diagnostic_groups(None) {
let entry = &group.entries[group.primary_ix];

View file

@ -301,7 +301,7 @@ impl AgentTool for EditFileTool {
let buffer = project
.update(cx, |project, cx| {
project.open_buffer(project_path.clone(), cx)
})?
})
.await?;
// Check if the file has been modified since the agent last read it
@ -357,7 +357,7 @@ impl AgentTool for EditFileTool {
}
}
let diff = cx.new(|cx| Diff::new(buffer.clone(), cx))?;
let diff = cx.new(|cx| Diff::new(buffer.clone(), cx));
event_stream.update_diff(diff.clone());
let _finalize_diff = util::defer({
let diff = diff.downgrade();
@ -367,7 +367,7 @@ impl AgentTool for EditFileTool {
}
});
let old_snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
let old_snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
let old_text = cx
.background_spawn({
let old_snapshot = old_snapshot.clone();
@ -399,9 +399,9 @@ impl AgentTool for EditFileTool {
match event {
EditAgentOutputEvent::Edited(range) => {
if !emitted_location {
let line = buffer.update(cx, |buffer, _cx| {
let line = Some(buffer.update(cx, |buffer, _cx| {
range.start.to_point(&buffer.snapshot()).row
}).ok();
}));
if let Some(abs_path) = abs_path.clone() {
event_stream.update_fields(ToolCallUpdateFields::new().locations(vec![ToolCallLocation::new(abs_path).line(line)]));
}
@ -411,7 +411,7 @@ impl AgentTool for EditFileTool {
EditAgentOutputEvent::UnresolvedEditRange => hallucinated_old_text = true,
EditAgentOutputEvent::AmbiguousEditRange(ranges) => ambiguous_ranges = ranges,
EditAgentOutputEvent::ResolvingEditRange(range) => {
diff.update(cx, |card, cx| card.reveal_range(range.clone(), cx))?;
diff.update(cx, |card, cx| card.reveal_range(range.clone(), cx));
// if !emitted_location {
// let line = buffer.update(cx, |buffer, _cx| {
// range.start.to_point(&buffer.snapshot()).row
@ -428,23 +428,21 @@ impl AgentTool for EditFileTool {
}
// If format_on_save is enabled, format the buffer
let format_on_save_enabled = buffer
.read_with(cx, |buffer, cx| {
let settings = language_settings::language_settings(
buffer.language().map(|l| l.name()),
buffer.file(),
cx,
);
settings.format_on_save != FormatOnSave::Off
})
.unwrap_or(false);
let format_on_save_enabled = buffer.read_with(cx, |buffer, cx| {
let settings = language_settings::language_settings(
buffer.language().map(|l| l.name()),
buffer.file(),
cx,
);
settings.format_on_save != FormatOnSave::Off
});
let edit_agent_output = output.await?;
if format_on_save_enabled {
action_log.update(cx, |log, cx| {
log.buffer_edited(buffer.clone(), cx);
})?;
});
let format_task = project.update(cx, |project, cx| {
project.format(
@ -454,30 +452,30 @@ impl AgentTool for EditFileTool {
FormatTrigger::Save,
cx,
)
})?;
});
format_task.await.log_err();
}
project
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))?
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))
.await?;
action_log.update(cx, |log, cx| {
log.buffer_edited(buffer.clone(), cx);
})?;
});
// Update the recorded read time after a successful edit so consecutive edits work
if let Some(abs_path) = abs_path.as_ref() {
if let Some(new_mtime) = buffer.read_with(cx, |buffer, _| {
buffer.file().and_then(|file| file.disk_state().mtime())
})? {
}) {
self.thread.update(cx, |thread, _| {
thread.file_read_times.insert(abs_path.to_path_buf(), new_mtime);
})?;
}
}
let new_snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
let new_snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
let (new_text, unified_diff) = cx
.background_spawn({
let new_snapshot = new_snapshot.clone();

View file

@ -191,7 +191,7 @@ impl AgentTool for GrepTool {
continue;
}
let Ok((Some(path), mut parse_status)) = buffer.read_with(cx, |buffer, cx| {
let (Some(path), mut parse_status) = buffer.read_with(cx, |buffer, cx| {
(buffer.file().map(|file| file.full_path(cx)), buffer.parse_status())
}) else {
continue;
@ -200,20 +200,21 @@ impl AgentTool for GrepTool {
// Check if this file should be excluded based on its worktree settings
if let Ok(Some(project_path)) = project.read_with(cx, |project, cx| {
project.find_project_path(&path, cx)
})
&& cx.update(|cx| {
}) {
if cx.update(|cx| {
let worktree_settings = WorktreeSettings::get(Some((&project_path).into()), cx);
worktree_settings.is_path_excluded(&project_path.path)
|| worktree_settings.is_path_private(&project_path.path)
}).unwrap_or(false) {
}) {
continue;
}
}
while *parse_status.borrow() != ParseStatus::Idle {
parse_status.changed().await?;
}
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
let mut ranges = ranges
.into_iter()

View file

@ -167,14 +167,14 @@ impl AgentTool for ReadFileTool {
self.project.update(cx, |project, cx| {
project.open_image(project_path.clone(), cx)
})
})?
})
.await?;
let image =
image_entity.read_with(cx, |image_item, _| Arc::clone(&image_item.image))?;
image_entity.read_with(cx, |image_item, _| Arc::clone(&image_item.image));
let language_model_image = cx
.update(|cx| LanguageModelImage::from_image(image, cx))?
.update(|cx| LanguageModelImage::from_image(image, cx))
.await
.context("processing image")?;
@ -197,21 +197,21 @@ impl AgentTool for ReadFileTool {
project.update(cx, |project, cx| {
project.open_buffer(project_path.clone(), cx)
})
})?
})
.await?;
if buffer.read_with(cx, |buffer, _| {
buffer
.file()
.as_ref()
.is_none_or(|file| !file.disk_state().exists())
})? {
}) {
anyhow::bail!("{file_path} not found");
}
// Record the file read time and mtime
if let Some(mtime) = buffer.read_with(cx, |buffer, _| {
buffer.file().and_then(|file| file.disk_state().mtime())
})? {
}) {
self.thread
.update(cx, |thread, _| {
thread.file_read_times.insert(abs_path.to_path_buf(), mtime);
@ -239,11 +239,11 @@ impl AgentTool for ReadFileTool {
let start = buffer.anchor_before(Point::new(start_row, 0));
let end = buffer.anchor_before(Point::new(end_row, 0));
buffer.text_for_range(start..end).collect::<String>()
})?;
});
action_log.update(cx, |log, cx| {
log.buffer_read(buffer.clone(), cx);
})?;
});
Ok(result.into())
} else {
@ -257,7 +257,7 @@ impl AgentTool for ReadFileTool {
action_log.update(cx, |log, cx| {
log.buffer_read(buffer.clone(), cx);
})?;
});
if buffer_content.is_outline {
Ok(formatdoc! {"
@ -297,7 +297,7 @@ impl AgentTool for ReadFileTool {
acp::ToolCallContent::Content(acp::Content::new(markdown)),
]));
}
})?;
});
result
})

View file

@ -74,49 +74,29 @@ impl AgentTool for RestoreFileFromDiskTool {
let mut clean_paths: Vec<PathBuf> = Vec::new();
let mut not_found_paths: Vec<PathBuf> = Vec::new();
let mut open_errors: Vec<(PathBuf, String)> = Vec::new();
let mut dirty_check_errors: Vec<(PathBuf, String)> = Vec::new();
let dirty_check_errors: Vec<(PathBuf, String)> = Vec::new();
let mut reload_errors: Vec<String> = Vec::new();
for path in input_paths {
let project_path =
project.read_with(cx, |project, cx| project.find_project_path(&path, cx));
let project_path = match project_path {
Ok(Some(project_path)) => project_path,
Ok(None) => {
not_found_paths.push(path);
continue;
}
Err(error) => {
open_errors.push((path, error.to_string()));
continue;
}
let Some(project_path) =
project.read_with(cx, |project, cx| project.find_project_path(&path, cx))
else {
not_found_paths.push(path);
continue;
};
let open_buffer_task =
project.update(cx, |project, cx| project.open_buffer(project_path, cx));
let buffer = match open_buffer_task {
Ok(task) => match task.await {
Ok(buffer) => buffer,
Err(error) => {
open_errors.push((path, error.to_string()));
continue;
}
},
let buffer = match open_buffer_task.await {
Ok(buffer) => buffer,
Err(error) => {
open_errors.push((path, error.to_string()));
continue;
}
};
let is_dirty = match buffer.read_with(cx, |buffer, _| buffer.is_dirty()) {
Ok(is_dirty) => is_dirty,
Err(error) => {
dirty_check_errors.push((path, error.to_string()));
continue;
}
};
let is_dirty = buffer.read_with(cx, |buffer, _| buffer.is_dirty());
if is_dirty {
buffers_to_reload.insert(buffer);
@ -131,15 +111,8 @@ impl AgentTool for RestoreFileFromDiskTool {
project.reload_buffers(buffers_to_reload, true, cx)
});
match reload_task {
Ok(task) => {
if let Err(error) = task.await {
reload_errors.push(error.to_string());
}
}
Err(error) => {
reload_errors.push(error.to_string());
}
if let Err(error) = reload_task.await {
reload_errors.push(error.to_string());
}
}

View file

@ -71,49 +71,29 @@ impl AgentTool for SaveFileTool {
let mut clean_paths: Vec<PathBuf> = Vec::new();
let mut not_found_paths: Vec<PathBuf> = Vec::new();
let mut open_errors: Vec<(PathBuf, String)> = Vec::new();
let mut dirty_check_errors: Vec<(PathBuf, String)> = Vec::new();
let dirty_check_errors: Vec<(PathBuf, String)> = Vec::new();
let mut save_errors: Vec<(String, String)> = Vec::new();
for path in input_paths {
let project_path =
project.read_with(cx, |project, cx| project.find_project_path(&path, cx));
let project_path = match project_path {
Ok(Some(project_path)) => project_path,
Ok(None) => {
not_found_paths.push(path);
continue;
}
Err(error) => {
open_errors.push((path, error.to_string()));
continue;
}
let Some(project_path) =
project.read_with(cx, |project, cx| project.find_project_path(&path, cx))
else {
not_found_paths.push(path);
continue;
};
let open_buffer_task =
project.update(cx, |project, cx| project.open_buffer(project_path, cx));
let buffer = match open_buffer_task {
Ok(task) => match task.await {
Ok(buffer) => buffer,
Err(error) => {
open_errors.push((path, error.to_string()));
continue;
}
},
let buffer = match open_buffer_task.await {
Ok(buffer) => buffer,
Err(error) => {
open_errors.push((path, error.to_string()));
continue;
}
};
let is_dirty = match buffer.read_with(cx, |buffer, _| buffer.is_dirty()) {
Ok(is_dirty) => is_dirty,
Err(error) => {
dirty_check_errors.push((path, error.to_string()));
continue;
}
};
let is_dirty = buffer.read_with(cx, |buffer, _| buffer.is_dirty());
if is_dirty {
buffers_to_save.insert(buffer);
@ -125,30 +105,19 @@ impl AgentTool for SaveFileTool {
// Save each buffer individually since there's no batch save API.
for buffer in buffers_to_save {
let path_for_buffer = match buffer.read_with(cx, |buffer, _| {
buffer
.file()
.map(|file| file.path().to_rel_path_buf())
.map(|path| path.as_rel_path().as_unix_str().to_owned())
}) {
Ok(path) => path.unwrap_or_else(|| "<unknown>".to_string()),
Err(error) => {
save_errors.push(("<unknown>".to_string(), error.to_string()));
continue;
}
};
let path_for_buffer = buffer
.read_with(cx, |buffer, _| {
buffer
.file()
.map(|file| file.path().to_rel_path_buf())
.map(|path| path.as_rel_path().as_unix_str().to_owned())
})
.unwrap_or_else(|| "<unknown>".to_string());
let save_task = project.update(cx, |project, cx| project.save_buffer(buffer, cx));
match save_task {
Ok(task) => {
if let Err(error) = task.await {
save_errors.push((path_for_buffer, error.to_string()));
}
}
Err(error) => {
save_errors.push((path_for_buffer, error.to_string()));
}
if let Err(error) = save_task.await {
save_errors.push((path_for_buffer, error.to_string()));
}
}

View file

@ -111,7 +111,7 @@ impl AcpConnection {
is_remote: bool,
cx: &mut AsyncApp,
) -> Result<Self> {
let shell = cx.update(|cx| TerminalSettings::get(None, cx).shell.clone())?;
let shell = cx.update(|cx| TerminalSettings::get(None, cx).shell.clone());
let builder = ShellBuilder::new(&shell, cfg!(windows)).non_interactive();
let mut child =
builder.build_std_command(Some(command.path.display().to_string()), &command.args);
@ -133,13 +133,13 @@ impl AcpConnection {
let sessions = Rc::new(RefCell::new(HashMap::default()));
let (release_channel, version) = cx.update(|cx| {
let (release_channel, version): (Option<&str>, String) = cx.update(|cx| {
(
release_channel::ReleaseChannel::try_global(cx)
.map(|release_channel| release_channel.display_name()),
release_channel::AppVersion::global(cx).to_string(),
)
})?;
});
let client = ClientDelegate {
sessions: sessions.clone(),
@ -191,7 +191,7 @@ impl AcpConnection {
AcpConnectionRegistry::default_global(cx).update(cx, |registry, cx| {
registry.set_active_connection(server_name.clone(), &connection, cx)
});
})?;
});
let response = connection
.initialize(
@ -343,7 +343,7 @@ impl AgentConnection for AcpConnection {
}
})?;
let use_config_options = cx.update(|cx| cx.has_flag::<AcpBetaFeatureFlag>())?;
let use_config_options = cx.update(|cx| cx.has_flag::<AcpBetaFeatureFlag>());
// Config options take precedence over legacy modes/models
let (modes, models, config_options) = if use_config_options && let Some(opts) = response.config_options {
@ -532,8 +532,8 @@ impl AgentConnection for AcpConnection {
}
let session_id = response.session_id;
let action_log = cx.new(|_| ActionLog::new(project.clone()))?;
let thread = cx.new(|cx| {
let action_log = cx.new(|_| ActionLog::new(project.clone()));
let thread: Entity<AcpThread> = cx.new(|cx| {
AcpThread::new(
self.server_name.clone(),
self.clone(),
@ -544,7 +544,7 @@ impl AgentConnection for AcpConnection {
watch::Receiver::constant(self.agent_capabilities.prompt_capabilities.clone()),
cx,
)
})?;
});
let session = AcpSession {
@ -1104,8 +1104,7 @@ impl acp::Client for ClientDelegate {
cx,
)
})?;
let terminal_id =
terminal_entity.read_with(&self.cx, |terminal, _| terminal.id().clone())?;
let terminal_id = terminal_entity.read_with(&self.cx, |terminal, _| terminal.id().clone());
Ok(acp::CreateTerminalResponse::new(terminal_id))
}

View file

@ -47,7 +47,7 @@ impl AgentServer for Gemini {
extra_env.insert("SURFACE".to_owned(), "zed".to_owned());
if let Some(api_key) = cx
.update(GoogleLanguageModelProvider::api_key_for_gemini_cli)?
.update(GoogleLanguageModelProvider::api_key_for_gemini_cli)
.await
.ok()
{

View file

@ -466,9 +466,9 @@ impl MessageEditor {
}
}
});
Ok((chunks, all_tracked_buffers))
anyhow::Ok((chunks, all_tracked_buffers))
})?;
result
Ok(result)
})
}
@ -678,28 +678,24 @@ impl MessageEditor {
.update(cx, |project, cx| {
project.project_path_for_absolute_path(&file_path, cx)
})
.map_err(|e| e.to_string())?
.ok_or_else(|| "project path not found".to_string())?;
let buffer = project
.update(cx, |project, cx| project.open_buffer(project_path, cx))
.map_err(|e| e.to_string())?
.await
.map_err(|e| e.to_string())?;
buffer
.update(cx, |buffer, cx| {
let start = Point::new(*line_range.start(), 0)
.min(buffer.max_point());
let end = Point::new(*line_range.end() + 1, 0)
.min(buffer.max_point());
let content = buffer.text_for_range(start..end).collect();
Mention::Text {
content,
tracked_buffers: vec![cx.entity()],
}
})
.map_err(|e| e.to_string())
Ok(buffer.update(cx, |buffer, cx| {
let start =
Point::new(*line_range.start(), 0).min(buffer.max_point());
let end = Point::new(*line_range.end() + 1, 0)
.min(buffer.max_point());
let content = buffer.text_for_range(start..end).collect();
Mention::Text {
content,
tracked_buffers: vec![cx.entity()],
}
}))
}
})
.shared();

View file

@ -985,7 +985,7 @@ impl AcpThreadView {
);
});
}
})?;
});
anyhow::Ok(())
})
@ -1019,7 +1019,7 @@ impl AcpThreadView {
history_store
.update(&mut cx.clone(), |store, cx| {
store.save_thread(session_id.clone(), db_thread, cx)
})?
})
.await?;
let thread_metadata = agent::DbThreadMetadata {
@ -1652,18 +1652,18 @@ impl AcpThreadView {
.iter()
.take(entry_ix)
.any(|entry| entry.diffs().next().is_some())
})?;
});
if has_earlier_edits {
thread.update(cx, |thread, cx| {
thread.action_log().update(cx, |action_log, cx| {
action_log.keep_all_edits(None, cx);
});
})?;
});
}
thread
.update(cx, |thread, cx| thread.rewind(user_message_id, cx))?
.update(cx, |thread, cx| thread.rewind(user_message_id, cx))
.await?;
this.update_in(cx, |this, window, cx| {
this.send_impl(message_editor, window, cx);
@ -2140,7 +2140,7 @@ impl AcpThreadView {
})
});
if let Ok(Some(resolve_task)) = resolved_node_runtime {
if let Some(resolve_task) = resolved_node_runtime {
if let Ok(node_path) = resolve_task.await {
task.command = Some(node_path.to_string_lossy().to_string());
}
@ -2159,11 +2159,11 @@ impl AcpThreadView {
task.allow_concurrent_runs = true;
task.hide = task::HideStrategy::Always;
let terminal = terminal_panel.update_in(cx, |terminal_panel, window, cx| {
terminal_panel.spawn_task(&task, window, cx)
})?;
let terminal = terminal.await?;
let terminal = terminal_panel
.update_in(cx, |terminal_panel, window, cx| {
terminal_panel.spawn_task(&task, window, cx)
})?
.await?;
if check_exit_code {
// For extension-based auth, wait for the process to exit and check exit code
@ -2214,7 +2214,7 @@ impl AcpThreadView {
}
}
_ = exit_status => {
if !previous_attempt && project.read_with(cx, |project, _| project.is_via_remote_server())? && login.label.contains("gemini") {
if !previous_attempt && project.read_with(cx, |project, _| project.is_via_remote_server()) && login.label.contains("gemini") {
return cx.update(|window, cx| Self::spawn_external_agent_login(login, workspace, project.clone(), true, false, window, cx))?.await
}
return Err(anyhow!("exited before logging in"));
@ -5667,14 +5667,14 @@ impl AcpThreadView {
let markdown_language = markdown_language_task.await?;
let buffer = project
.update(cx, |project, cx| project.create_buffer(false, cx))?
.update(cx, |project, cx| project.create_buffer(false, cx))
.await?;
buffer.update(cx, |buffer, cx| {
buffer.set_text(markdown, cx);
buffer.set_language(Some(markdown_language), cx);
buffer.set_capability(language::Capability::ReadWrite, cx);
})?;
});
workspace.update_in(cx, |workspace, window, cx| {
let buffer = cx

View file

@ -821,7 +821,8 @@ impl AgentConfiguration {
}
},
)
})
});
anyhow::Ok(())
}
})
.detach_and_log_err(cx);
@ -1304,7 +1305,7 @@ fn show_unable_to_uninstall_extension_with_context_server(
.context_servers
.remove(&context_server_id.0);
});
})?;
});
anyhow::Ok(())
}
})

View file

@ -262,7 +262,7 @@ fn save_provider_to_settings(
let task = cx.write_credentials(&api_url, "Bearer", api_key.as_bytes());
cx.spawn(async move |cx| {
task.await
.map_err(|_| "Failed to write API key to keychain")?;
.map_err(|_| SharedString::from("Failed to write API key to keychain"))?;
cx.update(|cx| {
update_settings_file(fs, cx, |settings, _cx| {
settings
@ -278,8 +278,7 @@ fn save_provider_to_settings(
},
);
});
})
.ok();
});
Ok(())
})
}

View file

@ -1091,8 +1091,8 @@ impl<T: PromptCompletionProviderDelegate> CompletionProvider for PromptCompletio
)
}
})
.collect()
})?;
.collect::<Vec<_>>()
});
Ok(vec![CompletionResponse {
completions,
@ -1469,26 +1469,19 @@ pub(crate) fn search_symbols(
let Some(symbols) = symbols_task.await.log_err() else {
return Vec::new();
};
let Some((visible_match_candidates, external_match_candidates)): Option<(Vec<_>, Vec<_>)> =
project
.update(cx, |project, cx| {
symbols
.iter()
.enumerate()
.map(|(id, symbol)| {
StringMatchCandidate::new(id, symbol.label.filter_text())
})
.partition(|candidate| match &symbols[candidate.id].path {
SymbolLocation::InProject(project_path) => project
.entry_for_path(project_path, cx)
.is_some_and(|e| !e.is_ignored),
SymbolLocation::OutsideProject { .. } => false,
})
})
.log_err()
else {
return Vec::new();
};
let (visible_match_candidates, external_match_candidates): (Vec<_>, Vec<_>) = project
.update(cx, |project, cx| {
symbols
.iter()
.enumerate()
.map(|(id, symbol)| StringMatchCandidate::new(id, symbol.label.filter_text()))
.partition(|candidate| match &symbols[candidate.id].path {
SymbolLocation::InProject(project_path) => project
.entry_for_path(project_path, cx)
.is_some_and(|e| !e.is_ignored),
SymbolLocation::OutsideProject { .. } => false,
})
});
const MAX_MATCHES: usize = 100;
let mut visible_matches = cx.background_executor().block(fuzzy::match_strings(

View file

@ -300,7 +300,7 @@ impl InlineAssistant {
if let Some(error) = configuration_error() {
if let ConfigurationError::ProviderNotAuthenticated(provider) = error {
cx.spawn(async move |_, cx| {
cx.update(|cx| provider.authenticate(cx))?.await?;
cx.update(|cx| provider.authenticate(cx)).await?;
anyhow::Ok(())
})
.detach_and_log_err(cx);
@ -1633,7 +1633,7 @@ impl EditorInlineAssists {
let editor = editor.upgrade().context("editor was dropped")?;
cx.update_global(|assistant: &mut InlineAssistant, cx| {
assistant.update_editor_highlights(&editor, cx);
})?;
});
}
Ok(())
}
@ -1978,7 +1978,7 @@ impl CodeActionProvider for AssistantCodeActionProvider {
let multibuffer_snapshot = multibuffer.read(cx);
multibuffer_snapshot.anchor_range_in_excerpt(excerpt_id, action.range)
})
})?
})
.context("invalid range")?;
let prompt_store = prompt_store.await.ok();

View file

@ -94,7 +94,7 @@ impl MentionSet {
let content = if full_mention_content
&& let MentionUri::Directory { abs_path } = &mention_uri
{
cx.update(|cx| full_mention_for_directory(&project, abs_path, cx))?
cx.update(|cx| full_mention_for_directory(&project, abs_path, cx))
.await?
} else {
task.await.map_err(|e| anyhow!("{e}"))?
@ -180,9 +180,7 @@ impl MentionSet {
let image = cx
.spawn(async move |_, cx| {
let image = image_task.await.map_err(|e| e.to_string())?;
let image = image
.update(cx, |image, _| image.image.clone())
.map_err(|e| e.to_string())?;
let image = image.update(cx, |image, _| image.image.clone());
Ok(image)
})
.shared();
@ -291,10 +289,10 @@ impl MentionSet {
let task = project.update(cx, |project, cx| project.open_image(project_path, cx));
return cx.spawn(async move |_, cx| {
let image = task.await?;
let image = image.update(cx, |image, _| image.image.clone())?;
let image = image.update(cx, |image, _| image.image.clone());
let format = image.format;
let image = cx
.update(|cx| LanguageModelImage::from_image(image, cx))?
.update(|cx| LanguageModelImage::from_image(image, cx))
.await;
if let Some(image) = image {
Ok(Mention::Image(MentionImage {
@ -365,8 +363,8 @@ impl MentionSet {
content,
tracked_buffers: vec![cx.entity()],
}
})?;
anyhow::Ok(mention)
});
Ok(mention)
})
}
@ -493,9 +491,9 @@ impl MentionSet {
let agent = agent.downcast::<agent::NativeAgentConnection>().unwrap();
let summary = agent
.0
.update(cx, |agent, cx| agent.thread_summary(id, cx))?
.update(cx, |agent, cx| agent.thread_summary(id, cx))
.await?;
anyhow::Ok(Mention::Text {
Ok(Mention::Text {
content: summary.to_string(),
tracked_buffers: Vec::new(),
})
@ -512,7 +510,7 @@ impl MentionSet {
});
cx.spawn(async move |_, cx| {
let text_thread = text_thread_task.await?;
let xml = text_thread.update(cx, |text_thread, cx| text_thread.to_xml(cx))?;
let xml = text_thread.update(cx, |text_thread, cx| text_thread.to_xml(cx));
Ok(Mention::Text {
content: xml,
tracked_buffers: Vec::new(),
@ -580,8 +578,8 @@ pub(crate) fn paste_images_as_context(
})
.ok();
for image in images {
let Ok((excerpt_id, text_anchor, multibuffer_anchor)) =
editor.update_in(cx, |message_editor, window, cx| {
let Some((excerpt_id, text_anchor, multibuffer_anchor)) = editor
.update_in(cx, |message_editor, window, cx| {
let snapshot = message_editor.snapshot(window, cx);
let (excerpt_id, _, buffer_snapshot) =
snapshot.buffer_snapshot().as_singleton().unwrap();
@ -599,6 +597,7 @@ pub(crate) fn paste_images_as_context(
);
(*excerpt_id, text_anchor, multibuffer_anchor)
})
.ok()
else {
break;
};
@ -607,12 +606,10 @@ pub(crate) fn paste_images_as_context(
let Some(start_anchor) = multibuffer_anchor else {
continue;
};
let Ok(end_anchor) = editor.update(cx, |editor, cx| {
let end_anchor = editor.update(cx, |editor, cx| {
let snapshot = editor.buffer().read(cx).snapshot(cx);
snapshot.anchor_before(start_anchor.to_offset(&snapshot) + content_len)
}) else {
continue;
};
});
let image = Arc::new(image);
let Ok(Some((crease_id, tx))) = cx.update(|window, cx| {
insert_crease_for_mention(
@ -648,23 +645,17 @@ pub(crate) fn paste_images_as_context(
})
.shared();
mention_set
.update(cx, |mention_set, _cx| {
mention_set.insert_mention(crease_id, MentionUri::PastedImage, task.clone())
})
.ok();
mention_set.update(cx, |mention_set, _cx| {
mention_set.insert_mention(crease_id, MentionUri::PastedImage, task.clone())
});
if task.await.notify_async_err(cx).is_none() {
editor
.update(cx, |editor, cx| {
editor.edit([(start_anchor..end_anchor, "")], cx);
})
.ok();
mention_set
.update(cx, |mention_set, _cx| {
mention_set.remove_mention(&crease_id)
})
.ok();
editor.update(cx, |editor, cx| {
editor.edit([(start_anchor..end_anchor, "")], cx);
});
mention_set.update(cx, |mention_set, _cx| {
mention_set.remove_mention(&crease_id)
});
}
}
}))
@ -822,42 +813,44 @@ fn full_mention_for_directory(
cx.spawn(async move |cx| {
let file_paths = worktree.read_with(cx, |worktree, _cx| {
collect_files_in_path(worktree, &directory_path)
})?;
});
let descendants_future = cx.update(|cx| {
futures::future::join_all(file_paths.into_iter().map(|(worktree_path, full_path)| {
let rel_path = worktree_path
.strip_prefix(&directory_path)
.log_err()
.map_or_else(|| worktree_path.clone(), |rel_path| rel_path.into());
futures::future::join_all(file_paths.into_iter().map(
|(worktree_path, full_path): (Arc<RelPath>, String)| {
let rel_path = worktree_path
.strip_prefix(&directory_path)
.log_err()
.map_or_else(|| worktree_path.clone(), |rel_path| rel_path.into());
let open_task = project.update(cx, |project, cx| {
project.buffer_store().update(cx, |buffer_store, cx| {
let project_path = ProjectPath {
worktree_id,
path: worktree_path,
};
buffer_store.open_buffer(project_path, cx)
let open_task = project.update(cx, |project, cx| {
project.buffer_store().update(cx, |buffer_store, cx| {
let project_path = ProjectPath {
worktree_id,
path: worktree_path,
};
buffer_store.open_buffer(project_path, cx)
})
});
cx.spawn(async move |cx| {
let buffer = open_task.await.log_err()?;
let buffer_content = outline::get_buffer_content_or_outline(
buffer.clone(),
Some(&full_path),
&cx,
)
.await
.ok()?;
Some((rel_path, full_path, buffer_content.text, buffer))
})
});
cx.spawn(async move |cx| {
let buffer = open_task.await.log_err()?;
let buffer_content = outline::get_buffer_content_or_outline(
buffer.clone(),
Some(&full_path),
&cx,
)
.await
.ok()?;
Some((rel_path, full_path, buffer_content.text, buffer))
})
}))
})?;
},
))
});
let contents = cx
.background_spawn(async move {
let (contents, tracked_buffers) = descendants_future
let (contents, tracked_buffers): (Vec<_>, Vec<_>) = descendants_future
.await
.into_iter()
.flatten()

View file

@ -56,7 +56,7 @@ impl SlashCommand for DefaultSlashCommand {
let store = PromptStore::global(cx);
cx.spawn(async move |cx| {
let store = store.await?;
let prompts = store.read_with(cx, |store, _cx| store.default_prompt_metadata())?;
let prompts = store.read_with(cx, |store, _cx| store.default_prompt_metadata());
let mut text = String::new();
text.push('\n');

View file

@ -300,7 +300,7 @@ fn collect_diagnostics(
.await
.log_err()
{
let snapshot = cx.read_entity(&buffer, |buffer, _| buffer.snapshot())?;
let snapshot = cx.read_entity(&buffer, |buffer, _| buffer.snapshot());
collect_buffer_diagnostics(&mut output, &snapshot, options.include_warnings);
}

View file

@ -369,7 +369,7 @@ fn collect_files(
};
if let Some(buffer) = open_buffer_task.await.log_err() {
let mut output = SlashCommandOutput::default();
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
append_buffer_to_output(
&snapshot,
Some(path_including_worktree_name.display(path_style).as_ref()),

View file

@ -47,7 +47,7 @@ impl SlashCommand for PromptSlashCommand {
let cancellation_flag = Arc::new(AtomicBool::default());
let prompts: Vec<PromptMetadata> = store
.await?
.read_with(cx, |store, cx| store.search(query, cancellation_flag, cx))?
.read_with(cx, |store, cx| store.search(query, cancellation_flag, cx))
.await;
Ok(prompts
.into_iter()
@ -91,7 +91,7 @@ impl SlashCommand for PromptSlashCommand {
.id_for_title(&title)
.with_context(|| format!("no prompt found with title {:?}", title))?;
anyhow::Ok(store.load(prompt_id, cx))
})??
})?
.await?;
anyhow::Ok(body)
}

View file

@ -1263,7 +1263,7 @@ impl TextThread {
}
let token_count = cx
.update(|cx| model.model.count_tokens(request, cx))?
.update(|cx| model.model.count_tokens(request, cx))
.await?;
this.update(cx, |this, cx| {
this.token_count = Some(token_count);

View file

@ -124,7 +124,7 @@ impl TextThreadStore {
this.register_context_server_handlers(cx);
this.reload(cx).detach_and_log_err(cx);
this
})?;
});
Ok(this)
})
@ -166,7 +166,8 @@ impl TextThreadStore {
})
.collect();
cx.notify();
})
});
Ok(())
}
async fn handle_open_context(
@ -196,7 +197,7 @@ impl TextThreadStore {
.read(cx)
.serialize_ops(&TextThreadVersion::default(), cx),
)
})??;
})?;
let operations = operations.await;
Ok(proto::OpenContextResponse {
context: Some(proto::Context { operations }),
@ -224,7 +225,7 @@ impl TextThreadStore {
.read(cx)
.serialize_ops(&TextThreadVersion::default(), cx),
))
})??;
})?;
let operations = operations.await;
Ok(proto::CreateContextResponse {
context_id: context_id.to_proto(),
@ -245,7 +246,7 @@ impl TextThreadStore {
text_thread.update(cx, |text_thread, cx| text_thread.apply_ops([operation], cx));
}
Ok(())
})?
})
}
async fn handle_synchronize_contexts(
@ -290,7 +291,7 @@ impl TextThreadStore {
anyhow::Ok(proto::SynchronizeContextsResponse {
contexts: local_versions,
})
})?
})
}
fn handle_project_shared(&mut self, cx: &mut Context<Self>) {
@ -416,7 +417,7 @@ impl TextThreadStore {
Some(project),
cx,
)
})?;
});
let operations = cx
.background_spawn(async move {
context_proto
@ -426,7 +427,7 @@ impl TextThreadStore {
.collect::<Result<Vec<_>>>()
})
.await?;
text_thread.update(cx, |context, cx| context.apply_ops(operations, cx))?;
text_thread.update(cx, |context, cx| context.apply_ops(operations, cx));
this.update(cx, |this, cx| {
if let Some(existing_context) = this.loaded_text_thread_for_id(&context_id, cx) {
existing_context
@ -473,7 +474,7 @@ impl TextThreadStore {
Some(project),
cx,
)
})?;
});
this.update(cx, |this, cx| {
if let Some(existing_context) = this.loaded_text_thread_for_path(&path, cx) {
existing_context
@ -580,7 +581,7 @@ impl TextThreadStore {
Some(project),
cx,
)
})?;
});
let operations = cx
.background_spawn(async move {
context_proto
@ -590,7 +591,7 @@ impl TextThreadStore {
.collect::<Result<Vec<_>>>()
})
.await?;
text_thread.update(cx, |context, cx| context.apply_ops(operations, cx))?;
text_thread.update(cx, |context, cx| context.apply_ops(operations, cx));
this.update(cx, |this, cx| {
if let Some(existing_context) = this.loaded_text_thread_for_id(&text_thread_id, cx)
{

View file

@ -303,9 +303,9 @@ pub struct VoipParts {
#[cfg(not(any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd")))]
impl VoipParts {
pub fn new(cx: &AsyncApp) -> anyhow::Result<Self> {
let (apm, replays) = cx.try_read_default_global::<Audio, _>(|audio, _| {
let (apm, replays) = cx.read_default_global::<Audio, _>(|audio, _| {
(Arc::clone(&audio.echo_canceller), audio.replays.clone())
})?;
});
let legacy_audio_compatible =
AudioSettings::try_read_global(cx, |settings| settings.legacy_audio_compatible)
.unwrap_or(true);

View file

@ -436,7 +436,7 @@ impl AutoUpdater {
.0
.clone()
.context("auto-update not initialized")
})??;
})?;
set_status("Fetching remote server release", cx);
let release = Self::get_release_asset(
@ -456,7 +456,7 @@ impl AutoUpdater {
let version_path = platform_dir.join(format!("{}.gz", release.version));
smol::fs::create_dir_all(&platform_dir).await.ok();
let client = this.read_with(cx, |this, _| this.client.http_client())?;
let client = this.read_with(cx, |this, _| this.client.http_client());
if smol::fs::metadata(&version_path).await.is_err() {
log::info!(
@ -482,7 +482,7 @@ impl AutoUpdater {
.0
.clone()
.context("auto-update not initialized")
})??;
})?;
let release =
Self::get_release_asset(&this, channel, version, "zed-remote-server", os, arch, cx)
@ -500,7 +500,7 @@ impl AutoUpdater {
arch: &str,
cx: &mut AsyncApp,
) -> Result<ReleaseAsset> {
let client = this.read_with(cx, |this, _| this.client.clone())?;
let client = this.read_with(cx, |this, _| this.client.clone());
let (system_id, metrics_id, is_staff) = if client.telemetry().metrics_enabled() {
(
@ -563,7 +563,7 @@ impl AutoUpdater {
this.status.clone(),
ReleaseChannel::try_global(cx).unwrap_or(ReleaseChannel::Stable),
)
})?;
});
Self::check_dependencies()?;
@ -571,12 +571,12 @@ impl AutoUpdater {
this.status = AutoUpdateStatus::Checking;
log::info!("Auto Update: checking for updates");
cx.notify();
})?;
});
let fetched_release_data =
Self::get_release_asset(&this, release_channel, None, "zed", OS, ARCH, cx).await?;
let fetched_version = fetched_release_data.clone().version;
let app_commit_sha = cx.update(|cx| AppCommitSha::try_global(cx).map(|sha| sha.full()));
let app_commit_sha = Ok(cx.update(|cx| AppCommitSha::try_global(cx).map(|sha| sha.full())));
let newer_version = Self::check_if_fetched_version_is_newer(
release_channel,
app_commit_sha,
@ -586,7 +586,7 @@ impl AutoUpdater {
)?;
let Some(newer_version) = newer_version else {
return this.update(cx, |this, cx| {
this.update(cx, |this, cx| {
let status = match previous_status {
AutoUpdateStatus::Updated { .. } => previous_status,
_ => AutoUpdateStatus::Idle,
@ -594,6 +594,7 @@ impl AutoUpdater {
this.status = status;
cx.notify();
});
return Ok(());
};
this.update(cx, |this, cx| {
@ -601,7 +602,7 @@ impl AutoUpdater {
version: newer_version.clone(),
};
cx.notify();
})?;
});
let installer_dir = InstallerDir::new().await?;
let target_path = Self::target_path(&installer_dir).await?;
@ -612,11 +613,11 @@ impl AutoUpdater {
version: newer_version.clone(),
};
cx.notify();
})?;
});
let new_binary_path = Self::install_release(installer_dir, target_path, cx).await?;
if let Some(new_binary_path) = new_binary_path {
cx.update(|cx| cx.set_restart_path(new_binary_path))?;
cx.update(|cx| cx.set_restart_path(new_binary_path));
}
this.update(cx, |this, cx| {
@ -626,7 +627,8 @@ impl AutoUpdater {
version: newer_version,
};
cx.notify();
})
});
Ok(())
}
fn check_if_fetched_version_is_newer(
@ -807,9 +809,9 @@ async fn install_release_linux(
downloaded_tar_gz: PathBuf,
cx: &AsyncApp,
) -> Result<Option<PathBuf>> {
let channel = cx.update(|cx| ReleaseChannel::global(cx).dev_name())?;
let channel = cx.update(|cx| ReleaseChannel::global(cx).dev_name());
let home_dir = PathBuf::from(env::var("HOME").context("no HOME env var set")?);
let running_app_path = cx.update(|cx| cx.app_path())??;
let running_app_path = cx.update(|cx| cx.app_path())?;
let extracted = temp_dir.path().join("zed");
fs::create_dir_all(&extracted)
@ -874,7 +876,7 @@ async fn install_release_macos(
downloaded_dmg: PathBuf,
cx: &AsyncApp,
) -> Result<Option<PathBuf>> {
let running_app_path = cx.update(|cx| cx.app_path())??;
let running_app_path = cx.update(|cx| cx.app_path())?;
let running_app_filename = running_app_path
.file_name()
.with_context(|| format!("invalid running app path {running_app_path:?}"))?;

View file

@ -207,8 +207,8 @@ pub fn notify_if_app_was_updated(cx: &mut App) {
updater
.set_should_show_update_notification(false, cx)
.detach_and_log_err(cx);
})
})?;
});
});
}
anyhow::Ok(())
})

View file

@ -112,24 +112,24 @@ impl ActiveCall {
envelope: TypedEnvelope<proto::IncomingCall>,
mut cx: AsyncApp,
) -> Result<proto::Ack> {
let user_store = this.read_with(&cx, |this, _| this.user_store.clone())?;
let user_store = this.read_with(&cx, |this, _| this.user_store.clone());
let call = IncomingCall {
room_id: envelope.payload.room_id,
participants: user_store
.update(&mut cx, |user_store, cx| {
user_store.get_users(envelope.payload.participant_user_ids, cx)
})?
})
.await?,
calling_user: user_store
.update(&mut cx, |user_store, cx| {
user_store.get_user(envelope.payload.calling_user_id, cx)
})?
})
.await?,
initial_project: envelope.payload.initial_project,
};
this.update(&mut cx, |this, _| {
*this.incoming_call.0.borrow_mut() = Some(call);
})?;
});
Ok(proto::Ack {})
}
@ -147,7 +147,7 @@ impl ActiveCall {
{
incoming_call.take();
}
})?;
});
Ok(())
}
@ -187,7 +187,7 @@ impl ActiveCall {
let initial_project_id = if let Some(initial_project) = initial_project {
Some(
room.update(cx, |room, cx| room.share_project(initial_project, cx))?
room.update(cx, |room, cx| room.share_project(initial_project, cx))
.await?,
)
} else {
@ -196,7 +196,7 @@ impl ActiveCall {
room.update(cx, move |room, cx| {
room.call(called_user_id, initial_project_id, cx)
})?
})
.await?;
anyhow::Ok(())
@ -216,7 +216,7 @@ impl ActiveCall {
user_store,
cx,
)
})?
})
.await?;
this.update(cx, |this, cx| this.set_room(Some(room.clone()), cx))?

View file

@ -185,13 +185,13 @@ impl Room {
room.local_participant.role = participant.role()
}
room
})?;
});
let initial_project_id = if let Some(initial_project) = initial_project {
let initial_project_id = room
.update(cx, |room, cx| {
room.share_project(initial_project.clone(), cx)
})?
})
.await?;
Some(initial_project_id)
} else {
@ -202,7 +202,7 @@ impl Room {
.update(cx, |room, cx| {
room.leave_when_empty = true;
room.call(called_user_id, initial_project_id, cx)
})?
})
.await;
match did_join {
Ok(()) => Ok(room),
@ -286,12 +286,12 @@ impl Room {
user_store,
cx,
)
})?;
});
room.update(&mut cx, |room, cx| {
room.leave_when_empty = room.channel_id.is_none();
room.apply_room_update(room_proto, cx)?;
anyhow::Ok(())
})??;
})?;
Ok(room)
}
@ -379,7 +379,7 @@ impl Room {
.update(cx, |this, cx| {
this.status = RoomStatus::Rejoining;
cx.notify();
})?;
});
// Wait for client to re-establish a connection to the server.
let executor = cx.background_executor().clone();
@ -390,15 +390,11 @@ impl Room {
log::info!("client reconnected, attempting to rejoin room");
let Some(this) = this.upgrade() else { break };
match this.update(cx, |this, cx| this.rejoin(cx)) {
Ok(task) => {
if task.await.log_err().is_some() {
return true;
} else {
remaining_attempts -= 1;
}
}
Err(_app_dropped) => return false,
let task = this.update(cx, |this, cx| this.rejoin(cx));
if task.await.log_err().is_some() {
return true;
} else {
remaining_attempts -= 1;
}
} else if client_status.borrow().is_signed_out() {
return false;
@ -437,7 +433,7 @@ impl Room {
// we leave the room and return an error.
if let Some(this) = this.upgrade() {
log::info!("reconnection failed, leaving room");
this.update(cx, |this, cx| this.leave(cx))?.await?;
this.update(cx, |this, cx| this.leave(cx)).await?;
}
anyhow::bail!("can't reconnect to room: client failed to re-establish connection");
}
@ -665,7 +661,7 @@ impl Room {
mut cx: AsyncApp,
) -> Result<()> {
let room = envelope.payload.room.context("invalid room")?;
this.update(&mut cx, |this, cx| this.apply_room_update(room, cx))?
this.update(&mut cx, |this, cx| this.apply_room_update(room, cx))
}
fn apply_room_update(&mut self, room: proto::Room, cx: &mut Context<Self>) -> Result<()> {
@ -1203,7 +1199,7 @@ impl Room {
cx.spawn(async move |this, cx| {
let response = request.await?;
project.update(cx, |project, cx| project.shared(response.project_id, cx))??;
project.update(cx, |project, cx| project.shared(response.project_id, cx))?;
// If the user's location is in this project, it changes from UnsharedProject to SharedProject.
this.update(cx, |this, cx| {

View file

@ -71,8 +71,8 @@ impl ChannelBuffer {
capability,
base_text,
)
})?;
buffer.update(cx, |buffer, cx| buffer.apply_ops(operations, cx))?;
});
buffer.update(cx, |buffer, cx| buffer.apply_ops(operations, cx));
let subscription = client.subscribe_to_entity(channel.id.0)?;
@ -93,7 +93,7 @@ impl ChannelBuffer {
};
this.replace_collaborators(response.collaborators, cx);
this
})?)
}))
}
fn release(&mut self, _: &mut App) {
@ -168,7 +168,7 @@ impl ChannelBuffer {
cx.notify();
this.buffer
.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))
})?;
});
Ok(())
}
@ -182,7 +182,8 @@ impl ChannelBuffer {
this.replace_collaborators(message.payload.collaborators, cx);
cx.emit(ChannelBufferEvent::CollaboratorsChanged);
cx.notify();
})
});
Ok(())
}
fn on_buffer_update(

View file

@ -170,17 +170,14 @@ impl ChannelStore {
match status {
client::Status::Connected { .. } => {
this.update(cx, |this, cx| this.handle_connect(cx))
.ok()?
.await
.log_err()?;
}
client::Status::SignedOut | client::Status::UpgradeRequired => {
this.update(cx, |this, cx| this.handle_disconnect(false, cx))
.ok();
this.update(cx, |this, cx| this.handle_disconnect(false, cx));
}
_ => {
this.update(cx, |this, cx| this.handle_disconnect(true, cx))
.ok();
this.update(cx, |this, cx| this.handle_disconnect(true, cx));
}
}
}
@ -204,7 +201,7 @@ impl ChannelStore {
while let Some(update_channels) = update_channels_rx.next().await {
if let Some(this) = this.upgrade() {
let update_task = this
.update(cx, |this, cx| this.update_channels(update_channels, cx))?;
.update(cx, |this, cx| this.update_channels(update_channels, cx));
if let Some(update_task) = update_task {
update_task.await.log_err();
}
@ -814,7 +811,7 @@ impl ChannelStore {
this.update_channels_tx
.unbounded_send(message.payload)
.unwrap();
})?;
});
Ok(())
}
@ -841,7 +838,8 @@ impl ChannelStore {
.set_role(role)
}
}
})
});
Ok(())
}
fn handle_connect(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
@ -965,8 +963,7 @@ impl ChannelStore {
buffer.update(cx, |buffer, cx| buffer.disconnect(cx));
}
}
})
.ok();
});
}
})
});

View file

@ -343,7 +343,7 @@ impl ClientCredentialsProvider {
}
fn server_url(&self, cx: &AsyncApp) -> Result<String> {
cx.update(|cx| ClientSettings::get_global(cx).server_url.clone())
Ok(cx.update(|cx| ClientSettings::get_global(cx).server_url.clone()))
}
/// Reads the credentials from the provider.
@ -934,10 +934,10 @@ impl Client {
let connect_task = cx.update({
let cloud_client = self.cloud_client.clone();
move |cx| cloud_client.connect(cx)
})??;
})?;
let connection = connect_task.await?;
let (mut messages, task) = cx.update(|cx| connection.spawn(cx))?;
let (mut messages, task) = cx.update(|cx| connection.spawn(cx));
task.detach();
cx.spawn({
@ -977,8 +977,7 @@ impl Client {
}
})
.detach();
})
.log_err();
});
let credentials = self.sign_in(try_provider, cx).await?;
@ -1003,8 +1002,7 @@ impl Client {
}
})
.detach_and_log_err(cx);
})
.log_err();
});
Ok(())
}
@ -1249,14 +1247,8 @@ impl Client {
credentials: &Credentials,
cx: &AsyncApp,
) -> Task<Result<Connection, EstablishConnectionError>> {
let release_channel = cx
.update(|cx| ReleaseChannel::try_global(cx))
.ok()
.flatten();
let app_version = cx
.update(|cx| AppVersion::global(cx).to_string())
.ok()
.unwrap_or_default();
let release_channel = cx.update(|cx| ReleaseChannel::try_global(cx));
let app_version = cx.update(|cx| AppVersion::global(cx).to_string());
let http = self.http.clone();
let proxy = http.proxy().cloned();
@ -1293,7 +1285,7 @@ impl Client {
None => Box::new(TcpStream::connect(rpc_host).await?),
})
}
})?
})
.await?;
log::info!("connected to rpc endpoint {}", rpc_url);
@ -1361,12 +1353,12 @@ impl Client {
let (open_url_tx, open_url_rx) = oneshot::channel::<String>();
cx.update(|cx| {
cx.spawn(async move |cx| {
let url = open_url_rx.await?;
cx.update(|cx| cx.open_url(&url))
if let Ok(url) = open_url_rx.await {
cx.update(|cx| cx.open_url(&url));
}
})
.detach_and_log_err(cx);
})
.log_err();
.detach();
});
let credentials = background
.clone()
@ -1468,7 +1460,7 @@ impl Client {
})
.await?;
cx.update(|cx| cx.activate(true))?;
cx.update(|cx| cx.activate(true));
Ok(credentials)
})
}
@ -1687,8 +1679,7 @@ impl Client {
for handler in self.message_to_client_handlers.lock().iter() {
handler(&message, cx);
}
})
.ok();
});
}
pub fn telemetry(&self) -> &Arc<Telemetry> {
@ -2101,7 +2092,7 @@ mod tests {
let (done_tx2, done_rx2) = smol::channel::unbounded();
AnyProtoClient::from(client.clone()).add_entity_message_handler(
move |entity: Entity<TestEntity>, _: TypedEnvelope<proto::JoinProject>, cx| {
match entity.read_with(&cx, |entity, _| entity.id).unwrap() {
match entity.read_with(&cx, |entity, _| entity.id) {
1 => done_tx1.try_send(()).unwrap(),
2 => done_tx2.try_send(()).unwrap(),
_ => unreachable!(),

View file

@ -256,7 +256,7 @@ impl UserStore {
} else {
anyhow::Ok(())
}
})??;
})?;
this.update(cx, |_, cx| cx.notify())?;
}
@ -299,7 +299,7 @@ impl UserStore {
_: TypedEnvelope<proto::ShowContacts>,
mut cx: AsyncApp,
) -> Result<()> {
this.update(&mut cx, |_, cx| cx.emit(Event::ShowContacts))?;
this.update(&mut cx, |_, cx| cx.emit(Event::ShowContacts));
Ok(())
}
@ -312,7 +312,7 @@ impl UserStore {
this.update_contacts_tx
.unbounded_send(UpdateContacts::Update(message.payload))
.unwrap();
})?;
});
Ok(())
}
@ -353,7 +353,7 @@ impl UserStore {
let mut incoming_requests = Vec::new();
for request in message.incoming_requests {
incoming_requests.push({
this.update(cx, |this, cx| this.get_user(request.requester_id, cx))?
this.update(cx, |this, cx| this.get_user(request.requester_id, cx))
.await?
});
}
@ -361,7 +361,7 @@ impl UserStore {
let mut outgoing_requests = Vec::new();
for requested_user_id in message.outgoing_requests {
outgoing_requests.push(
this.update(cx, |this, cx| this.get_user(requested_user_id, cx))?
this.update(cx, |this, cx| this.get_user(requested_user_id, cx))
.await?,
);
}
@ -428,7 +428,7 @@ impl UserStore {
}
cx.notify();
})?;
});
Ok(())
})
@ -798,7 +798,7 @@ impl UserStore {
this.read_with(cx, |this, _cx| {
this.client.upgrade().map(|client| client.cloud_client())
})
})??
})?
.ok_or(anyhow::anyhow!("Failed to get Cloud client"))?;
let response = cloud_client.get_authenticated_user().await?;
@ -806,7 +806,7 @@ impl UserStore {
this.update(cx, |this, cx| {
this.update_authenticated_user(response, cx);
})
})??;
})?;
}
}
@ -914,7 +914,7 @@ impl Contact {
let user = user_store
.update(cx, |user_store, cx| {
user_store.get_user(contact.user_id, cx)
})?
})
.await?;
Ok(Self {
user,

View file

@ -283,7 +283,7 @@ impl EditPredictionDelegate for CodestralEditPredictionDelegate {
let edits: Arc<[(Range<Anchor>, Arc<str>)]> =
vec![(cursor_position..cursor_position, completion_text.into())].into();
let edit_preview = buffer
.read_with(cx, |buffer, cx| buffer.preview_edits(edits.clone(), cx))?
.read_with(cx, |buffer, cx| buffer.preview_edits(edits.clone(), cx))
.await;
this.update(cx, |this, cx| {

View file

@ -800,7 +800,6 @@ impl RandomizedTest for ProjectCollaborationTest {
assert!(
buffer
.read_with(&cx, |buffer, _| { buffer.saved_version().to_owned() })
.expect("App should not be dropped")
.observed_all(&requested_version)
);
anyhow::Ok(())

View file

@ -173,7 +173,7 @@ impl ChannelView {
};
buffer.set_language(Some(markdown), cx);
})
})?;
});
cx.new_window_entity(|window, cx| {
let mut this = Self::new(

View file

@ -2179,7 +2179,7 @@ impl CollabPanel {
cx.spawn_in(window, async move |this, cx| {
if answer.await? == 0 {
channel_store
.update(cx, |channels, _| channels.remove_channel(channel_id))?
.update(cx, |channels, _| channels.remove_channel(channel_id))
.await
.notify_async_err(cx);
this.update_in(cx, |_, window, cx| cx.focus_self(window))
@ -2213,7 +2213,7 @@ impl CollabPanel {
cx.spawn_in(window, async move |_, cx| {
if answer.await? == 0 {
user_store
.update(cx, |store, cx| store.remove_contact(user_id, cx))?
.update(cx, |store, cx| store.remove_contact(user_id, cx))
.await
.notify_async_err(cx);
}

View file

@ -24,27 +24,20 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut App) {
}
if let Some(incoming_call) = incoming_call {
let unique_screens = cx.update(|cx| cx.displays()).unwrap();
let unique_screens = cx.update(|cx| cx.displays());
let window_size = gpui::Size {
width: px(400.),
height: px(72.),
};
for screen in unique_screens {
if let Some(options) = cx
.update(|cx| notification_window_options(screen, window_size, cx))
.log_err()
{
let window = cx
.open_window(options, |_, cx| {
cx.new(|_| {
IncomingCallNotification::new(
incoming_call.clone(),
app_state.clone(),
)
})
})
.unwrap();
let options =
cx.update(|cx| notification_window_options(screen, window_size, cx));
if let Ok(window) = cx.open_window(options, |_, cx| {
cx.new(|_| {
IncomingCallNotification::new(incoming_call.clone(), app_state.clone())
})
}) {
notification_windows.push(window);
}
}
@ -88,8 +81,7 @@ impl IncomingCallNotificationState {
)
.detach_and_log_err(cx);
}
})
.log_err();
});
}
anyhow::Ok(())
})

View file

@ -222,16 +222,12 @@ impl McpServer {
} else if let Some(handler) = handlers.borrow().get(&request.method.as_ref()) {
let outgoing_tx = outgoing_tx.clone();
if let Some(task) = cx
.update(|cx| handler(request_id, request.params, cx))
.log_err()
{
cx.spawn(async move |_| {
let response = task.await;
outgoing_tx.unbounded_send(response).ok();
})
.detach();
}
let task = cx.update(|cx| handler(request_id, request.params, cx));
cx.spawn(async move |_| {
let response = task.await;
outgoing_tx.unbounded_send(response).ok();
})
.detach();
} else {
Self::send_err(
request_id,

View file

@ -31,7 +31,7 @@ impl StdioTransport {
working_directory: &Option<PathBuf>,
cx: &AsyncApp,
) -> Result<Self> {
let shell = cx.update(|cx| TerminalSettings::get(None, cx).shell.clone())?;
let shell = cx.update(|cx| TerminalSettings::get(None, cx).shell.clone());
let builder = ShellBuilder::new(&shell, cfg!(windows)).non_interactive();
let mut command =
builder.build_smol_command(Some(binary.executable.display().to_string()), &binary.args);

View file

@ -546,7 +546,7 @@ impl Copilot {
let mut params = server.default_initialize_params(false, cx);
params.initialization_options = Some(editor_info_json);
server.initialize(params, configuration.into(), cx)
})?
})
.await?;
this.update(cx, |_, cx| notify_did_change_config_to_server(&server, cx))?

View file

@ -624,8 +624,6 @@ impl CopilotChat {
) -> Result<(Arc<dyn HttpClient>, ApiToken, CopilotChatConfiguration)> {
let this = cx
.update(|cx| Self::global(cx))
.ok()
.flatten()
.context("Copilot chat is not enabled")?;
let (oauth_token, api_token, client, configuration) = this.read_with(cx, |this, _| {
@ -635,7 +633,7 @@ impl CopilotChat {
this.client.clone(),
this.configuration.clone(),
)
})?;
});
let oauth_token = oauth_token.context("No OAuth token available")?;
@ -648,7 +646,7 @@ impl CopilotChat {
this.update(cx, |this, cx| {
this.api_token = Some(token.clone());
cx.notify();
})?;
});
token
}
};

View file

@ -75,14 +75,12 @@ impl EditPredictionDelegate for CopilotEditPredictionDelegate {
let completions = copilot
.update(cx, |copilot, cx| {
copilot.completions(&buffer, cursor_position, cx)
})?
})
.await?;
if let Some(mut completion) = completions.into_iter().next()
&& let Some((trimmed_range, trimmed_text, snapshot)) = cx
.update(|cx| trim_completion(&completion, cx))
.ok()
.flatten()
&& let Some((trimmed_range, trimmed_text, snapshot)) =
cx.update(|cx| trim_completion(&completion, cx))
{
let preview = buffer
.update(cx, |this, cx| {
@ -90,7 +88,7 @@ impl EditPredictionDelegate for CopilotEditPredictionDelegate {
Arc::from([(trimmed_range.clone(), trimmed_text.clone())].as_slice()),
cx,
)
})?
})
.await;
this.update(cx, |this, cx| {
this.pending_refresh = None;

View file

@ -92,7 +92,7 @@ impl CredentialsProvider for KeychainCredentialsProvider {
url: &'a str,
cx: &'a AsyncApp,
) -> Pin<Box<dyn Future<Output = Result<Option<(String, Vec<u8>)>>> + 'a>> {
async move { cx.update(|cx| cx.read_credentials(url))?.await }.boxed_local()
async move { cx.update(|cx| cx.read_credentials(url)).await }.boxed_local()
}
fn write_credentials<'a>(
@ -103,7 +103,7 @@ impl CredentialsProvider for KeychainCredentialsProvider {
cx: &'a AsyncApp,
) -> Pin<Box<dyn Future<Output = Result<()>> + 'a>> {
async move {
cx.update(move |cx| cx.write_credentials(url, username, password))?
cx.update(move |cx| cx.write_credentials(url, username, password))
.await
}
.boxed_local()
@ -114,7 +114,7 @@ impl CredentialsProvider for KeychainCredentialsProvider {
url: &'a str,
cx: &'a AsyncApp,
) -> Pin<Box<dyn Future<Output = Result<()>> + 'a>> {
async move { cx.update(move |cx| cx.delete_credentials(url))?.await }.boxed_local()
async move { cx.update(move |cx| cx.delete_credentials(url)).await }.boxed_local()
}
}

View file

@ -178,9 +178,7 @@ impl TransportDelegate {
self.tasks.lock().clear();
let log_dap_communications =
cx.update(|cx| DebuggerSettings::get_global(cx).log_dap_communications)
.with_context(|| "Failed to get Debugger Setting log dap communications error in transport::start_handlers. Defaulting to false")
.unwrap_or(false);
cx.update(|cx| DebuggerSettings::get_global(cx).log_dap_communications);
let connect = self.transport.lock().connect();
let (input, output) = connect.await?;
@ -550,10 +548,9 @@ impl TcpTransport {
process = Some(p);
};
let timeout = connection_args.timeout.unwrap_or_else(|| {
cx.update(|cx| DebuggerSettings::get_global(cx).timeout)
.unwrap_or(20000u64)
});
let timeout = connection_args
.timeout
.unwrap_or_else(|| cx.update(|cx| DebuggerSettings::get_global(cx).timeout));
log::info!(
"Debug adapter has connected to TCP server {}:{}",

View file

@ -155,7 +155,7 @@ impl LogStore {
if let Some(this) = this.upgrade() {
this.update(cx, |this, cx| {
this.add_debug_adapter_message(message, cx);
})?;
});
}
smol::future::yield_now().await;
@ -170,7 +170,7 @@ impl LogStore {
if let Some(this) = this.upgrade() {
this.update(cx, |this, cx| {
this.add_debug_adapter_log(message, cx);
})?;
});
}
smol::future::yield_now().await;
@ -902,10 +902,10 @@ impl DapLogView {
let language = language.await.ok();
buffer.update(cx, |buffer, cx| {
buffer.set_language(language, cx);
})
});
}
})
.detach_and_log_err(cx);
.detach();
});
self.editor = editor;

View file

@ -268,7 +268,7 @@ impl DebugPanel {
dap_store
.update(cx, |dap_store, cx| {
dap_store.boot_session(session.clone(), definition, worktree, cx)
})?
})
.await
}
});
@ -286,7 +286,7 @@ impl DebugPanel {
.unbounded_send(format!("error: {:#}", error))
.ok();
session.shutdown(cx)
})?
})
.await;
}
anyhow::Ok(())
@ -404,7 +404,7 @@ impl DebugPanel {
session.boot(binary, worktree, dap_store_handle.downgrade(), cx)
});
(session, task)
})?;
});
Self::register_session(this.clone(), session.clone(), true, cx).await?;
if let Err(error) = task.await {
@ -418,7 +418,7 @@ impl DebugPanel {
))
.ok();
session.shutdown(cx)
})?
})
.await;
return Err(error);
@ -466,11 +466,10 @@ impl DebugPanel {
session.boot(binary, worktree, dap_store_handle.downgrade(), cx)
});
(session, task)
})?;
});
// Focus child sessions if the parent has never emitted a stopped event;
// this improves our JavaScript experience, as it always spawns a "main" session that then spawns subsessions.
let parent_ever_stopped =
parent_session.update(cx, |this, _| this.has_ever_stopped())?;
let parent_ever_stopped = parent_session.update(cx, |this, _| this.has_ever_stopped());
Self::register_session(this, session, !parent_ever_stopped, cx).await?;
task.await
})
@ -517,7 +516,7 @@ impl DebugPanel {
return;
}
}
session.update(cx, |session, cx| session.shutdown(cx)).ok();
session.update(cx, |session, cx| session.shutdown(cx));
this.update(cx, |this, cx| {
this.retain_sessions(|other| entity_id != other.entity_id());
if let Some(active_session_id) = this
@ -1443,7 +1442,7 @@ async fn register_session_inner(
session: Entity<Session>,
cx: &mut AsyncWindowContext,
) -> Result<Entity<DebugSession>> {
let adapter_name = session.read_with(cx, |session, _| session.adapter())?;
let adapter_name = session.read_with(cx, |session, _| session.adapter());
this.update_in(cx, |_, window, cx| {
cx.subscribe_in(
&session,

View file

@ -185,7 +185,7 @@ impl NewProcessModal {
.collect::<Vec<_>>();
let Some(task_inventory) = task_store
.update(cx, |task_store, _| task_store.task_inventory().cloned())?
.update(cx, |task_store, _| task_store.task_inventory().cloned())
else {
return Ok(());
};
@ -194,7 +194,7 @@ impl NewProcessModal {
.update(cx, |task_inventory, cx| {
task_inventory
.used_and_current_resolved_tasks(task_contexts.clone(), cx)
})?
})
.await;
if let Ok(task) = debug_picker.update(cx, |picker, cx| {

View file

@ -1113,7 +1113,7 @@ impl RunningState {
task_with_shell.clone(),
cx,
)
})?.await?;
}).await?;
let terminal_view = cx.new_window_entity(|window, cx| {
TerminalView::new(
@ -1135,7 +1135,7 @@ impl RunningState {
})?;
let exit_status = terminal
.read_with(cx, |terminal, cx| terminal.wait_for_completed_task(cx))?
.read_with(cx, |terminal, cx| terminal.wait_for_completed_task(cx))
.await
.context("Failed to wait for completed task")?;
@ -1302,7 +1302,7 @@ impl RunningState {
.pid()
.map(|pid| pid.as_u32())
.context("Terminal was spawned but PID was not available")
})?
})
});
cx.background_spawn(async move { anyhow::Ok(sender.send(terminal_task.await).await?) })

View file

@ -151,7 +151,7 @@ impl BreakpointList {
.update(cx, |this, cx| this.find_or_create_worktree(path, false, cx));
cx.spawn_in(window, async move |this, cx| {
let (worktree, relative_path) = task.await?;
let worktree_id = worktree.read_with(cx, |this, _| this.id())?;
let worktree_id = worktree.read_with(cx, |this, _| this.id());
let item = this
.update_in(cx, |this, window, cx| {
this.workspace.update(cx, |this, cx| {

View file

@ -428,7 +428,7 @@ impl StackFrameList {
.await?;
let position = buffer.read_with(cx, |this, _| {
this.snapshot().anchor_after(PointUtf16::new(row, 0))
})?;
});
this.update_in(cx, |this, window, cx| {
this.workspace.update(cx, |workspace, cx| {
let project_path = buffer

View file

@ -183,13 +183,13 @@ impl StackTraceView {
.await?;
let project_path = ProjectPath {
worktree_id: worktree.read_with(cx, |tree, _| tree.id())?,
worktree_id: worktree.read_with(cx, |tree, _| tree.id()),
path: relative_path,
};
if let Some(buffer) = this
.read_with(cx, |this, _| this.project.clone())?
.update(cx, |project, cx| project.open_buffer(project_path, cx))?
.update(cx, |project, cx| project.open_buffer(project_path, cx))
.await
.log_err()
{

View file

@ -360,7 +360,7 @@ impl ProjectDiagnosticsEditor {
};
if let Some(buffer) = project_handle
.update(cx, |project, cx| project.open_buffer(path.clone(), cx))?
.update(cx, |project, cx| project.open_buffer(path.clone(), cx))
.await
.log_err()
{
@ -1088,9 +1088,8 @@ async fn heuristic_syntactic_expand(
return Some(node_row_range);
} else if node_name.ends_with("statement") || node_name.ends_with("declaration") {
// Expand to the nearest dedent or blank line for statements and declarations.
let tab_size = cx
.update(|cx| snapshot.settings_at(node_range.start, cx).tab_size.get())
.ok()?;
let tab_size =
cx.update(|cx| snapshot.settings_at(node_range.start, cx).tab_size.get());
let indent_level = snapshot
.line_indent_for_row(node_range.start.row)
.len(tab_size);

View file

@ -153,19 +153,19 @@ async fn collect_snapshots(
.filter(|path| path.worktree_id == worktree_id)?;
let relative_path: Arc<Path> = project_path.path.as_std_path().into();
Some((project_path, relative_path))
})? {
}) {
if let hash_map::Entry::Vacant(entry) = snapshots_by_path.entry(relative_path) {
let buffer = project
.update(cx, |project, cx| {
project.open_buffer(project_path.clone(), cx)
})?
})
.await?;
let diff = git_store
.update(cx, |git_store, cx| {
git_store.open_uncommitted_diff(buffer.clone(), cx)
})?
})
.await?;
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx))?;
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx));
entry.insert((stored_event.old_snapshot.clone(), diff_snapshot));
}
}

View file

@ -1841,7 +1841,7 @@ impl EditPredictionStore {
worktree_id: file.worktree_id(cx),
path: file.path().clone(),
})
})?;
});
let buffer_task = project.update(cx, |project, cx| {
let (path, _, _) = project
@ -1862,7 +1862,7 @@ impl EditPredictionStore {
})?;
Some(project.open_buffer(path, cx))
})?;
});
if let Some(buffer_task) = buffer_task {
let closest_buffer = buffer_task.await?;
@ -1874,7 +1874,7 @@ impl EditPredictionStore {
.into_iter()
.min_by_key(|entry| entry.diagnostic.severity)
.map(|entry| entry.range.start)
})?
})
.map(|position| (closest_buffer, position));
}
}
@ -1973,8 +1973,7 @@ impl EditPredictionStore {
})
},
);
})
.ok();
});
}
Err(err)
}

View file

@ -49,16 +49,14 @@ impl EditPredictionResult {
};
}
let Some((edits, snapshot, edit_preview_task)) = edited_buffer
.read_with(cx, |buffer, cx| {
let Some((edits, snapshot, edit_preview_task)) =
edited_buffer.read_with(cx, |buffer, cx| {
let new_snapshot = buffer.snapshot();
let edits: Arc<[_]> =
interpolate_edits(&edited_buffer_snapshot, &new_snapshot, &edits)?.into();
Some((edits.clone(), new_snapshot, buffer.preview_edits(edits, cx)))
})
.ok()
.flatten()
else {
return Self {
id,

View file

@ -32,7 +32,7 @@ pub async fn apply_diff(
cx: &mut AsyncApp,
) -> Result<OpenedBuffers> {
let worktree = project
.read_with(cx, |project, cx| project.visible_worktrees(cx).next())?
.read_with(cx, |project, cx| project.visible_worktrees(cx).next())
.context("project has no worktree")?;
let paths: Vec<_> = diff_str
@ -65,7 +65,7 @@ pub async fn apply_diff(
} else {
None
}
})?;
});
if let Some(delete_task) = delete_task {
delete_task.await?;
@ -79,20 +79,20 @@ pub async fn apply_diff(
let buffer = match included_files.entry(path.to_string()) {
Entry::Occupied(entry) => entry.get().clone(),
Entry::Vacant(entry) => {
let buffer = if status == FileStatus::Created {
let buffer: Entity<Buffer> = if status == FileStatus::Created {
project
.update(cx, |project, cx| project.create_buffer(true, cx))?
.update(cx, |project, cx| project.create_buffer(true, cx))
.await?
} else {
let project_path = project
.update(cx, |project, cx| {
project.find_project_path(path.as_ref(), cx)
})?
})
.with_context(|| format!("no such path: {}", path))?;
project
.update(cx, |project, cx| {
project.open_buffer(project_path, cx)
})?
})
.await?
};
entry.insert(buffer.clone());
@ -111,7 +111,7 @@ pub async fn apply_diff(
.with_context(|| format!("Diff:\n{diff_str}"))?,
);
anyhow::Ok(())
})??;
})?;
}
DiffEvent::FileEnd { renamed_to } => {
let buffer = current_file
@ -135,14 +135,14 @@ pub async fn apply_diff(
new_project_path,
cx,
))
})??
})?
.await?;
}
let edits = mem::take(&mut edits);
buffer.update(cx, |buffer, cx| {
buffer.edit(edits, None, cx);
})?;
});
}
}
}
@ -174,7 +174,7 @@ pub async fn refresh_worktree_entries(
.as_local()
.unwrap()
.refresh_entries_for_paths(rel_paths)
})?
})
.recv()
.await;
}

View file

@ -177,8 +177,7 @@ pub(crate) fn request_prediction_with_zeta1(
})
},
);
})
.ok();
});
}
return Err(err);

View file

@ -11,7 +11,7 @@ use edit_prediction::{
EditPredictionStore,
zeta2::{zeta2_output_for_patch, zeta2_prompt_input},
};
use gpui::AsyncApp;
use gpui::{AsyncApp, Entity};
use std::sync::Arc;
use zeta_prompt::format_zeta_prompt;
@ -46,36 +46,37 @@ pub async fn run_format_prompt(
step_progress.set_substatus("formatting zeta2 prompt");
let ep_store = cx.update(|cx| {
let ep_store: Entity<EditPredictionStore> = cx.update(|cx| {
EditPredictionStore::try_global(cx).context("EditPredictionStore not initialized")
})??;
})?;
let state = example.state.as_ref().context("state must be set")?;
let snapshot = state.buffer.read_with(&cx, |buffer, _| buffer.snapshot())?;
let snapshot = state.buffer.read_with(&cx, |buffer, _| buffer.snapshot());
let project = state.project.clone();
let (_, input) = ep_store.update(&mut cx, |ep_store, cx| {
let events = ep_store
.edit_history_for_project(&project, cx)
.into_iter()
.map(|e| e.event)
.collect();
anyhow::Ok(zeta2_prompt_input(
&snapshot,
example
.context
.as_ref()
.context("context must be set")?
.files
.clone(),
events,
example.spec.cursor_path.clone(),
example
.buffer
.as_ref()
.context("buffer must be set")?
.cursor_offset,
))
})??;
let (_, input) =
ep_store.update(&mut cx, |ep_store: &mut EditPredictionStore, cx| {
let events = ep_store
.edit_history_for_project(&project, cx)
.into_iter()
.map(|e| e.event)
.collect();
anyhow::Ok(zeta2_prompt_input(
&snapshot,
example
.context
.as_ref()
.context("context must be set")?
.files
.clone(),
events,
example.spec.cursor_path.clone(),
example
.buffer
.as_ref()
.context("buffer must be set")?
.cursor_offset,
))
})?;
let prompt = format_zeta_prompt(&input);
let expected_output = zeta2_output_for_patch(
&input,

View file

@ -36,7 +36,7 @@ pub async fn run_load_project(
let (buffer, cursor_position) =
cursor_position(example, &project, &open_buffers, &mut cx).await?;
buffer
.read_with(&cx, |buffer, _| buffer.parsing_idle())?
.read_with(&cx, |buffer, _| buffer.parsing_idle())
.await;
let (example_buffer, language_name) = buffer.read_with(&cx, |buffer, _cx| {
let cursor_point = cursor_position.to_point(&buffer);
@ -64,7 +64,7 @@ pub async fn run_load_project(
},
language_name,
)
})?;
});
progress.set_info(language_name, InfoStyle::Normal);
@ -84,7 +84,7 @@ async fn cursor_position(
open_buffers: &OpenedBuffers,
cx: &mut AsyncApp,
) -> Result<(Entity<Buffer>, Anchor)> {
let language_registry = project.read_with(cx, |project, _| project.languages().clone())?;
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
let result = language_registry
.load_language_for_file_path(&example.spec.cursor_path)
.await;
@ -101,14 +101,14 @@ async fn cursor_position(
buffer.clone()
} else {
// Since the worktree scanner is disabled, manually refresh entries for the cursor path.
if let Some(worktree) = project.read_with(cx, |project, cx| project.worktrees(cx).next())? {
if let Some(worktree) = project.read_with(cx, |project, cx| project.worktrees(cx).next()) {
refresh_worktree_entries(&worktree, [&*example.spec.cursor_path], cx).await?;
}
let cursor_path = project
.read_with(cx, |project, cx| {
project.find_project_path(&example.spec.cursor_path, cx)
})?
})
.with_context(|| {
format!(
"failed to find cursor path {}",
@ -117,13 +117,13 @@ async fn cursor_position(
})?;
project
.update(cx, |project, cx| project.open_buffer(cursor_path, cx))?
.update(cx, |project, cx| project.open_buffer(cursor_path, cx))
.await?
};
let (cursor_excerpt, cursor_offset_within_excerpt) = example.spec.cursor_excerpt()?;
let excerpt_offset = cursor_buffer.read_with(cx, |buffer, _cx| {
let excerpt_offset = cursor_buffer.read_with(&*cx, |buffer, _cx| {
let text = buffer.text();
let mut matches = text.match_indices(&cursor_excerpt);
@ -139,11 +139,11 @@ async fn cursor_position(
&example.spec.name
);
Ok(excerpt_offset)
})??;
})?;
let cursor_offset = excerpt_offset + cursor_offset_within_excerpt;
let cursor_anchor =
cursor_buffer.read_with(cx, |buffer, _| buffer.anchor_after(cursor_offset))?;
cursor_buffer.read_with(&*cx, |buffer, _| buffer.anchor_after(cursor_offset));
Ok((cursor_buffer, cursor_anchor))
}
@ -155,7 +155,7 @@ async fn setup_project(
cx: &mut AsyncApp,
) -> Result<Entity<Project>> {
let ep_store = cx
.update(|cx| EditPredictionStore::try_global(cx))?
.update(|cx| EditPredictionStore::try_global(cx))
.context("Store should be initialized at init")?;
let worktree_path = setup_worktree(example, step_progress).await?;
@ -163,16 +163,13 @@ async fn setup_project(
if let Some(project) = app_state.project_cache.get(&example.spec.repository_url) {
ep_store.update(cx, |ep_store, _| {
ep_store.clear_history_for_project(&project);
})?;
let buffer_store = project.read_with(cx, |project, _| project.buffer_store().clone())?;
});
let buffer_store = project.read_with(cx, |project, _| project.buffer_store().clone());
let buffers = buffer_store.read_with(cx, |buffer_store, _| {
buffer_store.buffers().collect::<Vec<_>>()
})?;
});
for buffer in buffers {
buffer
.update(cx, |buffer, cx| buffer.reload(cx))?
.await
.ok();
buffer.update(cx, |buffer, cx| buffer.reload(cx)).await.ok();
}
return Ok(project);
}
@ -188,20 +185,20 @@ async fn setup_project(
false,
cx,
)
})?;
});
project
.update(cx, |project, cx| {
project.disable_worktree_scanner(cx);
project.create_worktree(&worktree_path, true, cx)
})?
})
.await?;
app_state
.project_cache
.insert(example.spec.repository_url.clone(), project.clone());
let buffer_store = project.read_with(cx, |project, _| project.buffer_store().clone())?;
let buffer_store = project.read_with(cx, |project, _| project.buffer_store().clone());
cx.subscribe(&buffer_store, {
let project = project.clone();
move |_, event, cx| match event {
@ -210,7 +207,7 @@ async fn setup_project(
}
_ => {}
}
})?
})
.detach();
Ok(project)

View file

@ -78,9 +78,9 @@ pub async fn run_prediction(
.await;
}
let ep_store = cx.update(|cx| {
EditPredictionStore::try_global(cx).context("EditPredictionStore not initialized")
})??;
let ep_store = cx
.update(|cx| EditPredictionStore::try_global(cx))
.context("EditPredictionStore not initialized")?;
ep_store.update(&mut cx, |store, _cx| {
let model = match provider {
@ -93,7 +93,7 @@ pub async fn run_prediction(
}
};
store.set_edit_prediction_model(model);
})?;
});
step_progress.set_substatus("configuring model");
let state = example.state.as_ref().context("state must be set")?;
let run_dir = RUN_DIR.join(&example.spec.name);
@ -101,8 +101,7 @@ pub async fn run_prediction(
let updated_example = Arc::new(Mutex::new(example.clone()));
let current_run_ix = Arc::new(AtomicUsize::new(0));
let mut debug_rx =
ep_store.update(&mut cx, |store, cx| store.debug_info(&state.project, cx))?;
let mut debug_rx = ep_store.update(&mut cx, |store, cx| store.debug_info(&state.project, cx));
let debug_task = cx.background_spawn({
let updated_example = updated_example.clone();
let current_run_ix = current_run_ix.clone();
@ -185,7 +184,7 @@ pub async fn run_prediction(
cloud_llm_client::PredictEditsRequestTrigger::Cli,
cx,
)
})?
})
.await?;
let actual_patch = prediction
@ -219,7 +218,7 @@ pub async fn run_prediction(
ep_store.update(&mut cx, |store, _| {
store.remove_project(&state.project);
})?;
});
debug_task.await?;
*example = Arc::into_inner(updated_example)

View file

@ -34,19 +34,19 @@ pub async fn run_context_retrieval(
let _lsp_handle = project.update(&mut cx, |project, cx| {
project.register_buffer_with_language_servers(&state.buffer, cx)
})?;
});
wait_for_language_servers_to_start(&project, &state.buffer, &step_progress, &mut cx).await?;
let ep_store = cx.update(|cx| {
EditPredictionStore::try_global(cx).context("EditPredictionStore not initialized")
})??;
let ep_store = cx
.update(|cx| EditPredictionStore::try_global(cx))
.context("EditPredictionStore not initialized")?;
let mut events = ep_store.update(&mut cx, |store, cx| {
store.register_buffer(&state.buffer, &project, cx);
store.set_use_context(true);
store.refresh_context(&project, &state.buffer, state.cursor_position, cx);
store.debug_info(&project, cx)
})?;
});
while let Some(event) = events.next().await {
match event {
@ -58,7 +58,7 @@ pub async fn run_context_retrieval(
}
let context_files =
ep_store.update(&mut cx, |store, cx| store.context_for_project(&project, cx))?;
ep_store.update(&mut cx, |store, cx| store.context_for_project(&project, cx));
let excerpt_count: usize = context_files.iter().map(|f| f.excerpts.len()).sum();
step_progress.set_info(format!("{} excerpts", excerpt_count), InfoStyle::Normal);
@ -75,10 +75,10 @@ async fn wait_for_language_servers_to_start(
step_progress: &Arc<StepProgress>,
cx: &mut AsyncApp,
) -> anyhow::Result<()> {
let lsp_store = project.read_with(cx, |project, _| project.lsp_store())?;
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
let (language_server_ids, mut starting_language_server_ids) = buffer
.update(cx, |buffer, cx| {
let (language_server_ids, mut starting_language_server_ids) =
buffer.update(cx, |buffer, cx| {
lsp_store.update(cx, |lsp_store, cx| {
let ids = lsp_store.language_servers_for_local_buffer(buffer, cx);
let starting_ids = ids
@ -88,8 +88,7 @@ async fn wait_for_language_servers_to_start(
.collect::<HashSet<_>>();
(ids, starting_ids)
})
})
.unwrap_or_default();
});
step_progress.set_substatus(format!("waiting for {} LSPs", language_server_ids.len()));
@ -164,7 +163,7 @@ async fn wait_for_language_servers_to_start(
];
project
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))?
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))
.await?;
let mut pending_language_server_ids = lsp_store.read_with(cx, |lsp_store, _| {
@ -178,7 +177,7 @@ async fn wait_for_language_servers_to_start(
.is_some_and(|status| status.has_pending_diagnostic_updates)
})
.collect::<HashSet<_>>()
})?;
});
while !pending_language_server_ids.is_empty() {
futures::select! {
language_server_id = rx.next() => {

View file

@ -197,7 +197,7 @@ impl RelatedExcerptStore {
DefinitionTask::CacheMiss(task) => {
let locations = task.await.log_err()??;
let duration = start_time.elapsed();
cx.update(|cx| {
Some(cx.update(|cx| {
(
identifier,
Arc::new(CacheEntry {
@ -210,8 +210,7 @@ impl RelatedExcerptStore {
}),
Some(duration),
)
})
.ok()
}))
}
}
})
@ -280,12 +279,12 @@ async fn rebuild_related_files(
if let hash_map::Entry::Vacant(e) = snapshots.entry(definition.buffer.entity_id()) {
definition
.buffer
.read_with(cx, |buffer, _| buffer.parsing_idle())?
.read_with(cx, |buffer, _| buffer.parsing_idle())
.await;
e.insert(
definition
.buffer
.read_with(cx, |buffer, _| buffer.snapshot())?,
.read_with(cx, |buffer, _| buffer.snapshot()),
);
}
let worktree_id = definition.path.worktree_id;
@ -296,7 +295,7 @@ async fn rebuild_related_files(
if let Some(worktree) = project.worktree_for_id(worktree_id, cx) {
e.insert(worktree.read(cx).root_name().as_unix_str().to_string());
}
})?;
});
}
}
}

View file

@ -188,7 +188,7 @@ impl EditPredictionContextView {
for (path, buffer, ranges) in paths {
multibuffer.set_excerpts_for_path(path, buffer, ranges, 0, cx);
}
})?;
});
editor.update_in(cx, |editor, window, cx| {
editor.move_to_beginning(&Default::default(), window, cx);

View file

@ -168,16 +168,19 @@ fn capture_example_as_markdown(
fs.create_dir(&dir).await.ok();
let mut path = dir.join(&example_spec.name.replace(' ', "--").replace(':', "-"));
path.set_extension("md");
project.update(cx, |project, cx| project.open_local_buffer(&path, cx))
project
.update(cx, |project, cx| project.open_local_buffer(&path, cx))
.await?
} else {
project.update(cx, |project, cx| project.create_buffer(false, cx))
}?
.await?;
project
.update(cx, |project, cx| project.create_buffer(false, cx))
.await?
};
buffer.update(cx, |buffer, cx| {
buffer.set_text(example_spec.to_markdown(), cx);
buffer.set_language(Some(markdown_language), cx);
})?;
});
workspace_entity.update_in(cx, |workspace, window, cx| {
workspace.add_item_to_active_pane(
Box::new(

View file

@ -74,8 +74,7 @@ impl BlinkManager {
cx.spawn(async move |this, cx| {
Timer::after(interval).await;
if let Some(this) = this.upgrade() {
this.update(cx, |this, cx| this.blink_cursors(epoch, cx))
.ok();
this.update(cx, |this, cx| this.blink_cursors(epoch, cx));
}
})
.detach();

View file

@ -45,10 +45,10 @@ pub fn switch_source_header(
.map(|file| file.path())
.map(|path| path.display(PathStyle::local()).to_string())
.unwrap_or_else(|| "Unknown".to_string())
})?;
});
let switch_source_header = if let Some((client, project_id)) = upstream_client {
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id())?;
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id());
let request = proto::LspExtSwitchSourceHeader {
project_id,
buffer_id: buffer_id.to_proto(),
@ -67,7 +67,7 @@ pub fn switch_source_header(
project::lsp_store::lsp_ext_command::SwitchSourceHeader,
cx,
)
})?
})
.await
.with_context(|| {
format!("Switch source/header LSP request for path \"{source_file}\" failed")

View file

@ -5512,12 +5512,10 @@ impl Editor {
Some(cx.spawn_in(window, async move |editor, cx| {
if let Some(transaction) = on_type_formatting.await? {
if push_to_client_history {
buffer
.update(cx, |buffer, _| {
buffer.push_transaction(transaction, Instant::now());
buffer.finalize_last_transaction();
})
.ok();
buffer.update(cx, |buffer, _| {
buffer.push_transaction(transaction, Instant::now());
buffer.finalize_last_transaction();
});
}
editor.update(cx, |editor, cx| {
editor.refresh_document_highlights(cx);
@ -6306,7 +6304,7 @@ impl Editor {
let project_transaction = lsp_store
.update(cx, |lsp_store, cx| {
lsp_store.apply_code_action(buffer_handle, command, false, cx)
})?
})
.await
.context("applying post-completion command")?;
if let Some(workspace) = editor.read_with(cx, |editor, _| editor.workspace())? {
@ -6713,7 +6711,7 @@ impl Editor {
.all(|range| {
excerpt_range.start <= range.start && excerpt_range.end >= range.end
})
})?;
});
if all_edits_within_excerpt {
return Ok(());
@ -6741,7 +6739,7 @@ impl Editor {
}
multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
multibuffer
})?;
});
workspace.update_in(cx, |workspace, window, cx| {
let project = workspace.project().clone();
@ -7101,13 +7099,9 @@ impl Editor {
.timer(Duration::from_millis(debounce))
.await;
let highlights = if let Some(highlights) = cx
.update(|cx| {
provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
})
.ok()
.flatten()
{
let highlights = if let Some(highlights) = cx.update(|cx| {
provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
}) {
highlights.await.log_err()
} else {
None
@ -16346,9 +16340,7 @@ impl Editor {
return;
};
let hide_runnables = project
.update(cx, |project, _| project.is_via_collab())
.unwrap_or(true);
let hide_runnables = project.update(cx, |project, _| project.is_via_collab());
if hide_runnables {
return;
}
@ -16531,11 +16523,9 @@ impl Editor {
let mut templates_with_tags = Vec::new();
if let Some(inventory) = inventory {
for RunnableTag(tag) in tags {
let Ok(new_tasks) = inventory.update(cx, |inventory, cx| {
let new_tasks = inventory.update(cx, |inventory, cx| {
inventory.list_tasks(file.clone(), Some(language.clone()), worktree_id, cx)
}) else {
return templates_with_tags;
};
});
templates_with_tags.extend(new_tasks.await.into_iter().filter(
move |(_, template)| {
template.tags.iter().any(|source_tag| source_tag == &tag)
@ -17621,7 +17611,7 @@ impl Editor {
.clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
target_buffer.anchor_after(target_start)
..target_buffer.anchor_before(target_end)
})?;
});
Location {
buffer: target_buffer_handle,
range,
@ -17720,7 +17710,7 @@ impl Editor {
});
(locations, current_location_index)
})?;
});
let Some(current_location_index) = current_location_index else {
// This indicates something has gone wrong, because we already
@ -18459,27 +18449,27 @@ impl Editor {
}
};
buffer
.update(cx, |buffer, cx| {
if let Some(transaction) = transaction
&& !buffer.is_singleton()
{
buffer.push_transaction(&transaction.0, cx);
}
cx.notify();
})
.ok();
buffer.update(cx, |buffer, cx| {
if let Some(transaction) = transaction
&& !buffer.is_singleton()
{
buffer.push_transaction(&transaction.0, cx);
}
cx.notify();
});
if let Some(transaction_id_now) =
buffer.read_with(cx, |b, cx| b.last_transaction_id(cx))?
buffer.read_with(cx, |b, cx| b.last_transaction_id(cx))
{
let has_new_transaction = transaction_id_prev != Some(transaction_id_now);
if has_new_transaction {
_ = editor.update(cx, |editor, _| {
editor
.selection_history
.insert_transaction(transaction_id_now, selections_prev);
});
editor
.update(cx, |editor, _| {
editor
.selection_history
.insert_transaction(transaction_id_now, selections_prev);
})
.ok();
}
}
@ -18527,17 +18517,15 @@ impl Editor {
}
transaction = apply_action.log_err().fuse() => transaction,
};
buffer
.update(cx, |buffer, cx| {
// check if we need this
if let Some(transaction) = transaction
&& !buffer.is_singleton()
{
buffer.push_transaction(&transaction.0, cx);
}
cx.notify();
})
.ok();
buffer.update(cx, |buffer, cx| {
// check if we need this
if let Some(transaction) = transaction
&& !buffer.is_singleton()
{
buffer.push_transaction(&transaction.0, cx);
}
cx.notify();
});
Ok(())
})
}
@ -18831,10 +18819,8 @@ impl Editor {
if let Some(debounce) = debounce {
cx.background_executor().timer(debounce).await;
}
let Some(snapshot) = editor.upgrade().and_then(|editor| {
editor
.update(cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
.ok()
let Some(snapshot) = editor.upgrade().map(|editor| {
editor.update(cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
}) else {
return;
};
@ -21217,19 +21203,14 @@ impl Editor {
anyhow::Result::<()>::Err(err).log_err();
if let Some(workspace) = workspace {
workspace
.update(cx, |workspace, cx| {
struct OpenPermalinkToLine;
workspace.update(cx, |workspace, cx| {
struct OpenPermalinkToLine;
workspace.show_toast(
Toast::new(
NotificationId::unique::<OpenPermalinkToLine>(),
message,
),
cx,
)
})
.ok();
workspace.show_toast(
Toast::new(NotificationId::unique::<OpenPermalinkToLine>(), message),
cx,
)
});
}
}
})
@ -24025,20 +24006,15 @@ fn update_uncommitted_diff_for_buffer(
});
cx.spawn(async move |cx| {
let diffs = future::join_all(tasks).await;
if editor
.read_with(cx, |editor, _cx| editor.temporary_diff_override)
.unwrap_or(false)
{
if editor.read_with(cx, |editor, _cx| editor.temporary_diff_override) {
return;
}
buffer
.update(cx, |buffer, cx| {
for diff in diffs.into_iter().flatten() {
buffer.add_diff(diff, cx);
}
})
.ok();
buffer.update(cx, |buffer, cx| {
for diff in diffs.into_iter().flatten() {
buffer.add_diff(diff, cx);
}
});
})
}
@ -25081,7 +25057,7 @@ impl SemanticsProvider for Entity<Project> {
snapshot.anchor_before(range.start)
..snapshot.anchor_after(range.end),
)
})?
})
}
})
})

View file

@ -18251,7 +18251,7 @@ async fn test_on_type_formatting_is_applied_after_autoindent(cx: &mut TestAppCon
"fn c() {\n d()\n .\n}\n",
"OnTypeFormatting should triggered after autoindent applied"
)
})?;
});
Ok(Some(vec![]))
}

View file

@ -533,9 +533,9 @@ impl GitBlame {
})
})
.collect::<Result<Vec<_>>>()
})??;
})?;
let provider_registry =
cx.update(|cx| GitHostingProviderRegistry::default_global(cx))?;
cx.update(|cx| GitHostingProviderRegistry::default_global(cx));
let (results, errors) = cx
.background_spawn({
async move {

View file

@ -475,7 +475,7 @@ pub(crate) fn find_url(
) -> Option<(Range<text::Anchor>, String)> {
const LIMIT: usize = 2048;
let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot()).ok()?;
let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
let offset = position.to_offset(&snapshot);
let mut token_start = offset;
@ -535,9 +535,7 @@ pub(crate) fn find_url_from_range(
) -> Option<String> {
const LIMIT: usize = 2048;
let Ok(snapshot) = buffer.read_with(&cx, |buffer, _| buffer.snapshot()) else {
return None;
};
let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
let start_offset = range.start.to_offset(&snapshot);
let end_offset = range.end.to_offset(&snapshot);
@ -595,7 +593,7 @@ pub(crate) async fn find_file(
cx: &mut AsyncWindowContext,
) -> Option<(Range<text::Anchor>, ResolvedPath)> {
let project = project?;
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot()).ok()?;
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
let scope = snapshot.language_scope_at(position);
let (range, candidate_file_path) = surrounding_filename(&snapshot, position)?;
let candidate_len = candidate_file_path.len();
@ -610,7 +608,6 @@ pub(crate) async fn find_file(
.update(cx, |project, cx| {
project.resolve_path_in_buffer(candidate_file_path, buffer, cx)
})
.ok()?
.await
.filter(|s| s.is_file())
}

View file

@ -165,7 +165,7 @@ pub fn hover_at_inlay(
this.hover_state.diagnostic_popover = None;
})?;
let language_registry = project.read_with(cx, |p, _| p.languages().clone())?;
let language_registry = project.read_with(cx, |p, _| p.languages().clone());
let blocks = vec![inlay_hover.tooltip];
let parsed_content =
parse_blocks(&blocks, Some(&language_registry), None, cx).await;

View file

@ -398,7 +398,7 @@ async fn update_editor_from_message(
.into_iter()
.map(|id| BufferId::new(id).map(|id| project.open_buffer_by_id(id, cx)))
.collect::<Result<Vec<_>>>()
})??;
})?;
let _inserted_excerpt_buffers = try_join_all(inserted_excerpt_buffers).await?;
// Update the editor's excerpts.
@ -892,7 +892,7 @@ impl Item for Editor {
project
.update(cx, |project, cx| {
project.save_buffers(buffers_to_save.clone(), cx)
})?
})
.await?;
}
@ -938,15 +938,13 @@ impl Item for Editor {
this.update(cx, |editor, cx| {
editor.request_autoscroll(Autoscroll::fit(), cx)
})?;
buffer
.update(cx, |buffer, cx| {
if let Some(transaction) = transaction
&& !buffer.is_singleton()
{
buffer.push_transaction(&transaction.0, cx);
}
})
.ok();
buffer.update(cx, |buffer, cx| {
if let Some(transaction) = transaction
&& !buffer.is_singleton()
{
buffer.push_transaction(&transaction.0, cx);
}
});
Ok(())
})
}
@ -1103,7 +1101,7 @@ impl SerializableItem for Editor {
let project = project.clone();
async move |cx| {
let language_registry =
project.read_with(cx, |project, _| project.languages().clone())?;
project.read_with(cx, |project, _| project.languages().clone());
let language = if let Some(language_name) = language {
// We don't fail here, because we'd rather not set the language if the name changed
@ -1118,7 +1116,7 @@ impl SerializableItem for Editor {
// First create the empty buffer
let buffer = project
.update(cx, |project, cx| project.create_buffer(true, cx))?
.update(cx, |project, cx| project.create_buffer(true, cx))
.await
.context("Failed to create buffer while deserializing editor")?;
@ -1132,7 +1130,7 @@ impl SerializableItem for Editor {
if let Some(entry) = buffer.peek_undo_stack() {
buffer.forget_transaction(entry.transaction_id());
}
})?;
});
cx.update(|window, cx| {
cx.new(|cx| {
@ -1187,7 +1185,7 @@ impl SerializableItem for Editor {
if let Some(entry) = buffer.peek_undo_stack() {
buffer.forget_transaction(entry.transaction_id());
}
})?;
});
}
cx.update(|window, cx| {
@ -1229,7 +1227,7 @@ impl SerializableItem for Editor {
..
} => window.spawn(cx, async move |cx| {
let buffer = project
.update(cx, |project, cx| project.create_buffer(true, cx))?
.update(cx, |project, cx| project.create_buffer(true, cx))
.await
.context("Failed to create buffer")?;

View file

@ -443,7 +443,7 @@ pub(crate) fn handle_from(
};
}
let buffer_snapshot = buffer.read_with(cx, |buf, _| buf.snapshot()).ok()?;
let buffer_snapshot = buffer.read_with(cx, |buf, _| buf.snapshot());
let Some(edit_behavior_state) =
should_auto_close(&buffer_snapshot, &edited_ranges, &jsx_tag_auto_close_config)
@ -567,11 +567,9 @@ pub(crate) fn handle_from(
}
}
buffer
.update(cx, |buffer, cx| {
buffer.edit(edits, None, cx);
})
.ok()?;
buffer.update(cx, |buffer, cx| {
buffer.edit(edits, None, cx);
});
if any_selections_need_update {
let multi_buffer_snapshot = this

View file

@ -99,9 +99,7 @@ pub(super) fn refresh_linked_ranges(
let cx = cx.to_async();
let highlights = async move {
let edits = linked_edits_task.await.log_err()?;
let snapshot = cx
.read_entity(&buffer, |buffer, _| buffer.snapshot())
.ok()?;
let snapshot = cx.read_entity(&buffer, |buffer, _| buffer.snapshot());
let buffer_id = snapshot.remote_id();
// Find the range containing our current selection.

View file

@ -60,27 +60,22 @@ async fn lsp_task_context(
buffer: &Entity<Buffer>,
cx: &mut AsyncApp,
) -> Option<TaskContext> {
let (worktree_store, environment) = project
.read_with(cx, |project, _| {
(project.worktree_store(), project.environment().clone())
})
.ok()?;
let (worktree_store, environment) = project.read_with(cx, |project, _| {
(project.worktree_store(), project.environment().clone())
});
let worktree_abs_path = cx
.update(|cx| {
let worktree_id = buffer.read(cx).file().map(|f| f.worktree_id(cx));
let worktree_abs_path = cx.update(|cx| {
let worktree_id = buffer.read(cx).file().map(|f| f.worktree_id(cx));
worktree_id
.and_then(|worktree_id| worktree_store.read(cx).worktree_for_id(worktree_id, cx))
.and_then(|worktree| worktree.read(cx).root_dir())
})
.ok()?;
worktree_id
.and_then(|worktree_id| worktree_store.read(cx).worktree_for_id(worktree_id, cx))
.and_then(|worktree| worktree.read(cx).root_dir())
});
let project_env = environment
.update(cx, |environment, cx| {
environment.buffer_environment(buffer, &worktree_store, cx)
})
.ok()?
.await;
Some(TaskContext {
@ -126,19 +121,18 @@ pub fn lsp_tasks(
let source_kind = match buffer.update(cx, |buffer, _| {
buffer.language().map(|language| language.name())
}) {
Ok(Some(language_name)) => TaskSourceKind::Lsp {
Some(language_name) => TaskSourceKind::Lsp {
server: server_id,
language_name: SharedString::from(language_name),
},
Ok(None) => continue,
Err(_) => return Vec::new(),
None => continue,
};
let id_base = source_kind.to_id_base();
let lsp_buffer_context = lsp_task_context(&project, &buffer, cx)
.await
.unwrap_or_default();
if let Ok(runnables_task) = project.update(cx, |project, cx| {
let runnables_task = project.update(cx, |project, cx| {
let buffer_id = buffer.read(cx).remote_id();
project.request_lsp(
buffer,
@ -149,8 +143,8 @@ pub fn lsp_tasks(
},
cx,
)
}) && let Some(new_runnables) = runnables_task.await.log_err()
{
});
if let Some(new_runnables) = runnables_task.await.log_err() {
new_lsp_tasks.extend(new_runnables.runnables.into_iter().filter_map(
|(location, runnable)| {
let resolved_task =

View file

@ -81,7 +81,7 @@ pub fn go_to_parent_module(
let upstream_client = lsp_store.read(cx).upstream_client();
cx.spawn_in(window, async move |editor, cx| {
let location_links = if let Some((client, project_id)) = upstream_client {
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id())?;
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id());
let request = proto::LspExtGoToParentModule {
project_id,
@ -103,7 +103,7 @@ pub fn go_to_parent_module(
.collect::<anyhow::Result<_>>()
.context("go to parent module via collab")?
} else {
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
let position = trigger_anchor.text_anchor.to_point_utf16(&buffer_snapshot);
project
.update(cx, |project, cx| {
@ -113,7 +113,7 @@ pub fn go_to_parent_module(
project::lsp_store::lsp_ext_command::GoToParentModule { position },
cx,
)
})?
})
.await
.context("go to parent module")?
};
@ -161,7 +161,7 @@ pub fn expand_macro_recursively(
let upstream_client = project.read(cx).lsp_store().read(cx).upstream_client();
cx.spawn_in(window, async move |_editor, cx| {
let macro_expansion = if let Some((client, project_id)) = upstream_client {
let buffer_id = buffer.update(cx, |buffer, _| buffer.remote_id())?;
let buffer_id = buffer.update(cx, |buffer, _| buffer.remote_id());
let request = proto::LspExtExpandMacro {
project_id,
buffer_id: buffer_id.to_proto(),
@ -176,7 +176,7 @@ pub fn expand_macro_recursively(
expansion: response.expansion,
}
} else {
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
let position = trigger_anchor.text_anchor.to_point_utf16(&buffer_snapshot);
project
.update(cx, |project, cx| {
@ -186,7 +186,7 @@ pub fn expand_macro_recursively(
ExpandMacro { position },
cx,
)
})?
})
.await
.context("expand macro")?
};
@ -200,7 +200,7 @@ pub fn expand_macro_recursively(
}
let buffer = project
.update(cx, |project, cx| project.create_buffer(false, cx))?
.update(cx, |project, cx| project.create_buffer(false, cx))
.await?;
workspace.update_in(cx, |workspace, window, cx| {
buffer.update(cx, |buffer, cx| {
@ -252,7 +252,7 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
let upstream_client = project.read(cx).lsp_store().read(cx).upstream_client();
cx.spawn_in(window, async move |_editor, cx| {
let docs_urls = if let Some((client, project_id)) = upstream_client {
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id())?;
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id());
let request = proto::LspExtOpenDocs {
project_id,
buffer_id: buffer_id.to_proto(),
@ -267,7 +267,7 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
local: response.local,
}
} else {
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
let position = trigger_anchor.text_anchor.to_point_utf16(&buffer_snapshot);
project
.update(cx, |project, cx| {
@ -277,7 +277,7 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
project::lsp_store::lsp_ext_command::OpenDocs { position },
cx,
)
})?
})
.await
.context("open docs")?
};
@ -303,7 +303,8 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
if let Some(web_url) = docs_urls.web {
cx.open_url(&web_url);
}
})
});
anyhow::Ok(())
})
.detach_and_log_err(cx);
}

View file

@ -150,7 +150,7 @@ fn main() {
registry.set_default_model(Some(agent_model.clone()), cx);
});
judge_model
})?;
});
let mut examples = Vec::new();
@ -210,7 +210,8 @@ fn main() {
if examples.is_empty() {
eprintln!("Filter matched no examples");
return cx.update(|cx| cx.quit());
cx.update(|cx| cx.quit());
return anyhow::Ok(());
}
let mut repo_urls = HashSet::default();
@ -294,7 +295,7 @@ fn main() {
let result = async {
example.setup().await?;
let run_output = cx
.update(|cx| example.run(app_state.clone(), cx))?
.update(|cx| example.run(app_state.clone(), cx))
.await?;
let judge_output = judge_example(
example.clone(),
@ -328,7 +329,8 @@ fn main() {
app_state.client.telemetry().flush_events().await;
cx.update(|cx| cx.quit())
cx.update(|cx| cx.quit());
anyhow::Ok(())
})
.detach_and_log_err(cx);
});

View file

@ -221,7 +221,7 @@ impl ExampleContext {
} else {
thread.proceed(cx)
}
})??;
})?;
let task = self.app.background_spawn(async move {
let mut messages = Vec::new();
@ -357,11 +357,13 @@ impl ExampleContext {
}
pub fn edits(&self) -> HashMap<Arc<RelPath>, FileEdits> {
self.agent_thread
.read_with(&self.app, |thread, cx| {
let action_log = thread.action_log().read(cx);
HashMap::from_iter(action_log.changed_buffers(cx).into_iter().map(
|(buffer, diff)| {
self.agent_thread.read_with(&self.app, |thread, cx| {
let action_log = thread.action_log().read(cx);
HashMap::from_iter(
action_log
.changed_buffers(cx)
.into_iter()
.map(|(buffer, diff)| {
let snapshot = buffer.read(cx).snapshot();
let file = snapshot.file().unwrap();
@ -381,10 +383,9 @@ impl ExampleContext {
.collect();
(file.path().clone(), FileEdits { hunks })
},
))
})
.unwrap()
}),
)
})
}
pub fn agent_thread(&self) -> Entity<Thread> {
@ -393,16 +394,14 @@ impl ExampleContext {
}
impl AppContext for ExampleContext {
type Result<T> = anyhow::Result<T>;
fn new<T: 'static>(
&mut self,
build_entity: impl FnOnce(&mut gpui::Context<T>) -> T,
) -> Self::Result<Entity<T>> {
) -> Entity<T> {
self.app.new(build_entity)
}
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<gpui::Reservation<T>> {
fn reserve_entity<T: 'static>(&mut self) -> gpui::Reservation<T> {
self.app.reserve_entity()
}
@ -410,7 +409,7 @@ impl AppContext for ExampleContext {
&mut self,
reservation: gpui::Reservation<T>,
build_entity: impl FnOnce(&mut gpui::Context<T>) -> T,
) -> Self::Result<Entity<T>> {
) -> Entity<T> {
self.app.insert_entity(reservation, build_entity)
}
@ -418,25 +417,21 @@ impl AppContext for ExampleContext {
&mut self,
handle: &Entity<T>,
update: impl FnOnce(&mut T, &mut gpui::Context<T>) -> R,
) -> Self::Result<R>
) -> R
where
T: 'static,
{
self.app.update_entity(handle, update)
}
fn as_mut<'a, T>(&'a mut self, handle: &Entity<T>) -> Self::Result<gpui::GpuiBorrow<'a, T>>
fn as_mut<'a, T>(&'a mut self, handle: &Entity<T>) -> gpui::GpuiBorrow<'a, T>
where
T: 'static,
{
self.app.as_mut(handle)
}
fn read_entity<T, R>(
&self,
handle: &Entity<T>,
read: impl FnOnce(&T, &App) -> R,
) -> Self::Result<R>
fn read_entity<T, R>(&self, handle: &Entity<T>, read: impl FnOnce(&T, &App) -> R) -> R
where
T: 'static,
{
@ -471,7 +466,7 @@ impl AppContext for ExampleContext {
self.app.background_spawn(future)
}
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> R
where
G: gpui::Global,
{

View file

@ -62,39 +62,29 @@ impl Example for CodeBlockCitations {
cx.assert(citation.contains("/"), format!("Slash in {citation:?}",))
{
let path_range = PathWithRange::new(citation);
let path = cx
.agent_thread()
.update(cx, |thread, cx| {
thread
.project()
.read(cx)
.find_project_path(path_range.path.as_ref(), cx)
})
.ok()
.flatten();
let path = cx.agent_thread().update(cx, |thread, cx| {
thread
.project()
.read(cx)
.find_project_path(path_range.path.as_ref(), cx)
});
if let Ok(path) = cx.assert_some(path, format!("Valid path: {citation:?}"))
{
let buffer_text = {
let buffer = match cx.agent_thread().update(cx, |thread, cx| {
thread
.project()
.update(cx, |project, cx| project.open_buffer(path, cx))
}) {
Ok(buffer_task) => buffer_task.await.ok(),
Err(err) => {
cx.assert(
false,
format!("Expected Ok(buffer), not {err:?}"),
)
.ok();
break;
}
};
let buffer = cx
.agent_thread()
.update(cx, |thread, cx| {
thread
.project()
.update(cx, |project, cx| project.open_buffer(path, cx))
})
.await
.ok();
let Ok(buffer_text) = cx.assert_some(
buffer.and_then(|buffer| {
buffer.read_with(cx, |buffer, _| buffer.text()).ok()
buffer.map(|buffer| {
buffer.read_with(cx, |buffer, _| buffer.text())
}),
"Reading buffer text succeeded",
) else {

View file

@ -29,7 +29,7 @@ impl Example for FileChangeNotificationExample {
.read(cx)
.find_project_path("README", cx)
.expect("README file should exist in this repo")
})?;
});
let buffer = {
cx.agent_thread()
@ -37,7 +37,7 @@ impl Example for FileChangeNotificationExample {
thread
.project()
.update(cx, |project, cx| project.open_buffer(project_path, cx))
})?
})
.await?
};
@ -45,7 +45,7 @@ impl Example for FileChangeNotificationExample {
thread.action_log().update(cx, |action_log, cx| {
action_log.buffer_read(buffer.clone(), cx);
});
})?;
});
// Start conversation (specific message is not important)
cx.prompt_with_max_turns("Find all files in this repo", 1)
@ -54,7 +54,7 @@ impl Example for FileChangeNotificationExample {
// Edit the README buffer - the model should get a notification on next turn
buffer.update(cx, |buffer, cx| {
buffer.edit([(0..buffer.len(), "Surprise!")], None, cx);
})?;
});
// Run for some more turns.
// The model shouldn't thank us for letting it know about the file change.

View file

@ -220,7 +220,7 @@ impl ExampleInstance {
worktree
.update(cx, |worktree, _cx| {
worktree.as_local().unwrap().scan_complete()
})?
})
.await;
struct LanguageServerState {
@ -233,39 +233,40 @@ impl ExampleInstance {
let lsp = if let Some(language_server) = &meta.language_server {
// Open a file that matches the language to cause LSP to start.
let language_file = worktree.read_with(cx, |worktree, _cx| {
worktree
.files(false, 0)
.find_map(|e| {
if e.path.clone().extension()
== Some(&language_server.file_extension)
{
Some(ProjectPath {
worktree_id: worktree.id(),
path: e.path.clone(),
})
} else {
None
}
})
.context("Failed to find a file for example language")
})??;
let language_file = worktree
.read_with(cx, |worktree, _cx| {
worktree
.files(false, 0)
.find_map(|e| {
if e.path.clone().extension()
== Some(&language_server.file_extension)
{
Some(ProjectPath {
worktree_id: worktree.id(),
path: e.path.clone(),
})
} else {
None
}
})
.context("Failed to find a file for example language")
})?;
let open_language_file_buffer_task = project.update(cx, |project, cx| {
project.open_buffer(language_file.clone(), cx)
})?;
});
let language_file_buffer = open_language_file_buffer_task.await?;
let lsp_open_handle = project.update(cx, |project, cx| {
project.register_buffer_with_language_servers(&language_file_buffer, cx)
})?;
});
wait_for_lang_server(&project, &language_file_buffer, this.log_prefix.clone(), cx).await?;
diagnostic_summary_before = project.read_with(cx, |project, cx| {
project.diagnostic_summary(false, cx)
})?;
project.diagnostic_summary(false, cx)
});
diagnostics_before = query_lsp_diagnostics(project.clone(), cx).await?;
if diagnostics_before.is_some() && language_server.allow_preexisting_diagnostics {
@ -337,7 +338,7 @@ impl ExampleInstance {
});
thread
}).unwrap();
});
let mut example_cx = ExampleContext::new(
meta.clone(),
@ -371,13 +372,13 @@ impl ExampleInstance {
.update(|cx| {
let project = project.clone();
cx.spawn(async move |cx| query_lsp_diagnostics(project, cx).await)
})?
})
.await?;
println!("{}Got diagnostics", this.log_prefix);
diagnostic_summary_after = project.read_with(cx, |project, cx| {
project.diagnostic_summary(false, cx)
})?;
project.diagnostic_summary(false, cx)
});
}
@ -389,7 +390,7 @@ impl ExampleInstance {
fs::write(this.run_directory.join("diagnostics_after.txt"), diagnostics_after)?;
}
thread.update(cx, |thread, _cx| {
Ok(thread.update(cx, |thread, _cx| {
RunOutput {
repository_diff,
diagnostic_summary_before,
@ -401,7 +402,7 @@ impl ExampleInstance {
thread_markdown: thread.to_markdown(),
programmatic_assertions: example_cx.assertions,
}
})
}))
})
}
@ -614,17 +615,19 @@ struct EvalTerminalHandle {
impl agent::TerminalHandle for EvalTerminalHandle {
fn id(&self, cx: &AsyncApp) -> Result<acp::TerminalId> {
self.terminal.read_with(cx, |term, _cx| term.id().clone())
Ok(self.terminal.read_with(cx, |term, _cx| term.id().clone()))
}
fn wait_for_exit(&self, cx: &AsyncApp) -> Result<Shared<Task<acp::TerminalExitStatus>>> {
self.terminal
.read_with(cx, |term, _cx| term.wait_for_exit())
Ok(self
.terminal
.read_with(cx, |term, _cx| term.wait_for_exit()))
}
fn current_output(&self, cx: &AsyncApp) -> Result<acp::TerminalOutputResponse> {
self.terminal
.read_with(cx, |term, cx| term.current_output(cx))
Ok(self
.terminal
.read_with(cx, |term, cx| term.current_output(cx)))
}
fn kill(&self, cx: &AsyncApp) -> Result<()> {
@ -632,13 +635,14 @@ impl agent::TerminalHandle for EvalTerminalHandle {
self.terminal.update(cx, |terminal, cx| {
terminal.kill(cx);
});
})?;
});
Ok(())
}
fn was_stopped_by_user(&self, cx: &AsyncApp) -> Result<bool> {
self.terminal
.read_with(cx, |term, _cx| term.was_stopped_by_user())
Ok(self
.terminal
.read_with(cx, |term, _cx| term.was_stopped_by_user()))
}
}
@ -653,7 +657,7 @@ impl agent::ThreadEnvironment for EvalThreadEnvironment {
let project = self.project.clone();
cx.spawn(async move |cx| {
let language_registry =
project.read_with(cx, |project, _cx| project.languages().clone())?;
project.read_with(cx, |project, _cx| project.languages().clone());
let id = acp::TerminalId::new(uuid::Uuid::new_v4().to_string());
let terminal =
acp_thread::create_terminal_entity(command, &[], vec![], cwd.clone(), &project, cx)
@ -668,7 +672,7 @@ impl agent::ThreadEnvironment for EvalThreadEnvironment {
language_registry,
cx,
)
})?;
});
Ok(Rc::new(EvalTerminalHandle { terminal }) as Rc<dyn agent::TerminalHandle>)
})
}
@ -899,25 +903,20 @@ pub fn wait_for_lang_server(
let (mut tx, mut rx) = mpsc::channel(1);
let lsp_store = project
.read_with(cx, |project, _| project.lsp_store())
.unwrap();
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
let has_lang_server = buffer
.update(cx, |buffer, cx| {
lsp_store.update(cx, |lsp_store, cx| {
lsp_store
.running_language_servers_for_local_buffer(buffer, cx)
.next()
.is_some()
})
let has_lang_server = buffer.update(cx, |buffer, cx| {
lsp_store.update(cx, |lsp_store, cx| {
lsp_store
.running_language_servers_for_local_buffer(buffer, cx)
.next()
.is_some()
})
.unwrap_or(false);
});
if has_lang_server {
project
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))
.unwrap()
.detach();
}
@ -984,7 +983,7 @@ pub async fn query_lsp_diagnostics(
.filter(|(_, _, summary)| summary.error_count > 0 || summary.warning_count > 0)
.map(|(project_path, _, _)| project_path)
.collect::<Vec<_>>()
})?;
});
if paths_with_diagnostics.is_empty() {
return Ok(None);
@ -993,9 +992,9 @@ pub async fn query_lsp_diagnostics(
let mut output = String::new();
for project_path in paths_with_diagnostics {
let buffer = project
.update(cx, |project, cx| project.open_buffer(project_path, cx))?
.update(cx, |project, cx| project.open_buffer(project_path, cx))
.await?;
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
for (_, group) in snapshot.diagnostic_groups(None) {
let entry = &group.entries[group.primary_ix];

View file

@ -245,8 +245,7 @@ impl HeadlessExtensionStore {
cx,
));
}
})
.ok();
});
let _ = join_all(removal_tasks).await;
fs.remove_dir(
@ -304,7 +303,7 @@ impl HeadlessExtensionStore {
let missing_extensions = extension_store
.update(&mut cx, |extension_store, cx| {
extension_store.sync_extensions(requested_extensions.collect(), cx)
})?
})
.await?;
Ok(proto::SyncExtensionsResponse {
@ -343,7 +342,7 @@ impl HeadlessExtensionStore {
PathBuf::from(envelope.payload.tmp_dir),
cx,
)
})?
})
.await?;
Ok(proto::Ack {})

View file

@ -681,11 +681,11 @@ impl WasmHost {
// Run wasi-dependent operations on tokio.
// wasmtime_wasi internally uses tokio for I/O operations.
let (extension_task, manifest, work_dir, tx, zed_api_version) =
gpui_tokio::Tokio::spawn(cx, load_extension(zed_api_version, component))?.await??;
gpui_tokio::Tokio::spawn(cx, load_extension(zed_api_version, component)).await??;
// Run the extension message loop on tokio since extension
// calls may invoke wasi functions that require a tokio runtime.
let task = Arc::new(gpui_tokio::Tokio::spawn(cx, extension_task)?);
let task = Arc::new(gpui_tokio::Tokio::spawn(cx, extension_task));
Ok(WasmExtension {
manifest,

View file

@ -471,7 +471,7 @@ impl ExtensionImports for WasmState {
}
.boxed_local()
})
.await?
.await
.to_wasmtime_result()
}

View file

@ -1004,7 +1004,7 @@ impl ExtensionImports for WasmState {
}
.boxed_local()
})
.await?
.await
.to_wasmtime_result()
}

View file

@ -13,7 +13,7 @@ use editor::{Editor, EditorElement, EditorStyle};
use extension_host::{ExtensionManifest, ExtensionOperation, ExtensionStore};
use fuzzy::{StringMatchCandidate, match_strings};
use gpui::{
Action, App, ClipboardItem, Context, Corner, Entity, EventEmitter, Flatten, Focusable,
Action, App, ClipboardItem, Context, Corner, Entity, EventEmitter, Focusable,
InteractiveElement, KeyContext, ParentElement, Point, Render, Styled, Task, TextStyle,
UniformListScrollHandle, WeakEntity, Window, actions, point, uniform_list,
};
@ -131,25 +131,22 @@ pub fn init(cx: &mut App) {
let workspace_handle = cx.entity().downgrade();
window
.spawn(cx, async move |cx| {
let extension_path =
match Flatten::flatten(prompt.await.map_err(|e| e.into())) {
Ok(Some(mut paths)) => paths.pop()?,
Ok(None) => return None,
Err(err) => {
workspace_handle
.update(cx, |workspace, cx| {
workspace.show_portal_error(err.to_string(), cx);
})
.ok();
return None;
}
};
let extension_path = match prompt.await.map_err(anyhow::Error::from) {
Ok(Some(mut paths)) => paths.pop()?,
Ok(None) => return None,
Err(err) => {
workspace_handle
.update(cx, |workspace, cx| {
workspace.show_portal_error(err.to_string(), cx);
})
.ok();
return None;
}
};
let install_task = store
.update(cx, |store, cx| {
store.install_dev_extension(extension_path, cx)
})
.ok()?;
let install_task = store.update(cx, |store, cx| {
store.install_dev_extension(extension_path, cx)
});
match install_task.await {
Ok(_) => {}

View file

@ -1225,35 +1225,27 @@ impl FileFinderDelegate {
let query_path = Path::new(query.path_query());
let mut path_matches = Vec::new();
let abs_file_exists = if let Ok(task) = project.update(cx, |this, cx| {
this.resolve_abs_file_path(query.path_query(), cx)
}) {
task.await.is_some()
} else {
false
};
let abs_file_exists = project
.update(cx, |this, cx| {
this.resolve_abs_file_path(query.path_query(), cx)
})
.await
.is_some();
if abs_file_exists {
let update_result = project
.update(cx, |project, cx| {
if let Some((worktree, relative_path)) =
project.find_worktree(query_path, cx)
{
path_matches.push(ProjectPanelOrdMatch(PathMatch {
score: 1.0,
positions: Vec::new(),
worktree_id: worktree.read(cx).id().to_usize(),
path: relative_path,
path_prefix: RelPath::empty().into(),
is_dir: false, // File finder doesn't support directories
distance_to_relative_ancestor: usize::MAX,
}));
}
})
.log_err();
if update_result.is_none() {
return abs_file_exists;
}
project.update(cx, |project, cx| {
if let Some((worktree, relative_path)) = project.find_worktree(query_path, cx) {
path_matches.push(ProjectPanelOrdMatch(PathMatch {
score: 1.0,
positions: Vec::new(),
worktree_id: worktree.read(cx).id().to_usize(),
path: relative_path,
path_prefix: RelPath::empty().into(),
is_dir: false, // File finder doesn't support directories
distance_to_relative_ancestor: usize::MAX,
}));
}
});
}
picker

View file

@ -744,8 +744,6 @@ pub async fn get_git_committer(cx: &AsyncApp) -> GitCommitter {
.context("could not find git binary path")
.log_err()
})
.ok()
.flatten()
} else {
None
};

View file

@ -397,7 +397,7 @@ impl BranchListDelegate {
cx.spawn(async move |_, cx| {
repo.update(cx, |repo, _| {
repo.create_branch(new_branch_name, base_branch)
})?
})
.await??;
Ok(())
@ -444,11 +444,11 @@ impl BranchListDelegate {
Entry::Branch { branch, .. } => match branch.remote_name() {
Some(remote_name) => {
is_remote = true;
repo.update(cx, |repo, _| repo.remove_remote(remote_name.to_string()))?
repo.update(cx, |repo, _| repo.remove_remote(remote_name.to_string()))
.await?
}
None => {
repo.update(cx, |repo, _| repo.delete_branch(branch.name().to_string()))?
repo.update(cx, |repo, _| repo.delete_branch(branch.name().to_string()))
.await?
}
},
@ -763,7 +763,7 @@ impl PickerDelegate for BranchListDelegate {
let branch = branch.clone();
cx.spawn(async move |_, cx| {
repo.update(cx, |repo, _| repo.change_branch(branch.name().to_string()))?
repo.update(cx, |repo, _| repo.change_branch(branch.name().to_string()))
.await??;
anyhow::Ok(())
@ -1433,7 +1433,6 @@ mod tests {
cx.spawn(async move |mut cx| {
for branch in branch_names {
repo.update(&mut cx, |repo, _| repo.create_branch(branch, None))
.unwrap()
.await
.unwrap()
.unwrap();
@ -1498,7 +1497,6 @@ mod tests {
repo.update(&mut cx, |repo, _| {
repo.create_remote(branch, String::from("test"))
})
.unwrap()
.await
.unwrap()
.unwrap();

Some files were not shown because too many files have changed in this diff Show more