Move "async move" a few characters to the left in cx.spawn() (#26758)
This is the core change: https://github.com/zed-industries/zed/pull/26758/files#diff-044302c0d57147af17e68a0009fee3e8dcdfb4f32c27a915e70cfa80e987f765R1052 TODO: - [x] Use AsyncFn instead of Fn() -> Future in GPUI spawn methods - [x] Implement it in the whole app - [x] Implement it in the debugger - [x] Glance at the RPC crate, and see if those box future methods can be switched over. Answer: It can't directly, as you can't make an AsyncFn* into a trait object. There's ways around that, but they're all more complex than just keeping the code as is. - [ ] Fix platform specific code Release Notes: - N/A
This commit is contained in:
parent
7f2e3fb5bd
commit
1aefa5178b
256 changed files with 3110 additions and 3200 deletions
|
@ -63,9 +63,9 @@ impl ActivityIndicator {
|
|||
let auto_updater = AutoUpdater::get(cx);
|
||||
let this = cx.new(|cx| {
|
||||
let mut status_events = languages.language_server_binary_statuses();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
while let Some((name, status)) = status_events.next().await {
|
||||
this.update(&mut cx, |this: &mut ActivityIndicator, cx| {
|
||||
this.update(cx, |this: &mut ActivityIndicator, cx| {
|
||||
this.statuses.retain(|s| s.name != name);
|
||||
this.statuses.push(ServerStatus { name, status });
|
||||
cx.notify();
|
||||
|
@ -76,9 +76,9 @@ impl ActivityIndicator {
|
|||
.detach();
|
||||
|
||||
let mut status_events = languages.dap_server_binary_statuses();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
while let Some((name, status)) = status_events.next().await {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.statuses.retain(|s| s.name != name);
|
||||
this.statuses.push(ServerStatus { name, status });
|
||||
cx.notify();
|
||||
|
@ -123,9 +123,9 @@ impl ActivityIndicator {
|
|||
let project = project.clone();
|
||||
let error = error.clone();
|
||||
let server_name = server_name.clone();
|
||||
cx.spawn_in(window, |workspace, mut cx| async move {
|
||||
cx.spawn_in(window, async move |workspace, cx| {
|
||||
let buffer = create_buffer.await?;
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(
|
||||
[(
|
||||
0..0,
|
||||
|
@ -136,7 +136,7 @@ impl ActivityIndicator {
|
|||
);
|
||||
buffer.set_capability(language::Capability::ReadOnly, cx);
|
||||
})?;
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
workspace.add_item_to_active_pane(
|
||||
Box::new(cx.new(|cx| {
|
||||
Editor::for_buffer(buffer, Some(project.clone()), window, cx)
|
||||
|
|
|
@ -34,9 +34,9 @@ impl AskPassDelegate {
|
|||
password_prompt: impl Fn(String, oneshot::Sender<String>, &mut AsyncApp) + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
let (tx, mut rx) = mpsc::unbounded::<(String, oneshot::Sender<String>)>();
|
||||
let task = cx.spawn(|mut cx| async move {
|
||||
let task = cx.spawn(async move |cx: &mut AsyncApp| {
|
||||
while let Some((prompt, channel)) = rx.next().await {
|
||||
password_prompt(prompt, channel, &mut cx);
|
||||
password_prompt(prompt, channel, cx);
|
||||
}
|
||||
});
|
||||
Self { tx, _task: task }
|
||||
|
|
|
@ -98,9 +98,9 @@ pub fn init(
|
|||
AssistantSettings::register(cx);
|
||||
SlashCommandSettings::register(cx);
|
||||
|
||||
cx.spawn(|mut cx| {
|
||||
cx.spawn({
|
||||
let client = client.clone();
|
||||
async move {
|
||||
async move |cx| {
|
||||
let is_search_slash_command_enabled = cx
|
||||
.update(|cx| cx.wait_for_flag::<SearchSlashCommandFeatureFlag>())?
|
||||
.await;
|
||||
|
@ -116,7 +116,7 @@ pub fn init(
|
|||
let semantic_index = SemanticDb::new(
|
||||
paths::embeddings_dir().join("semantic-index-db.0.mdb"),
|
||||
Arc::new(embedding_provider),
|
||||
&mut cx,
|
||||
cx,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
|
|
@ -98,16 +98,16 @@ impl AssistantPanel {
|
|||
prompt_builder: Arc<PromptBuilder>,
|
||||
cx: AsyncWindowContext,
|
||||
) -> Task<Result<Entity<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let slash_commands = Arc::new(SlashCommandWorkingSet::default());
|
||||
let context_store = workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
.update(cx, |workspace, cx| {
|
||||
let project = workspace.project().clone();
|
||||
ContextStore::new(project, prompt_builder.clone(), slash_commands, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
// TODO: deserialize state.
|
||||
cx.new(|cx| Self::new(workspace, context_store, window, cx))
|
||||
})
|
||||
|
@ -357,9 +357,9 @@ impl AssistantPanel {
|
|||
) -> Task<()> {
|
||||
let mut status_rx = client.status();
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
while let Some(status) = status_rx.next().await {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if this.client_status.is_none()
|
||||
|| this
|
||||
.client_status
|
||||
|
@ -371,7 +371,7 @@ impl AssistantPanel {
|
|||
})
|
||||
.log_err();
|
||||
}
|
||||
this.update(&mut cx, |this, _cx| this.watch_client_status = None)
|
||||
this.update(cx, |this, _cx| this.watch_client_status = None)
|
||||
.log_err();
|
||||
})
|
||||
}
|
||||
|
@ -576,11 +576,11 @@ impl AssistantPanel {
|
|||
if self.authenticate_provider_task.is_none() {
|
||||
self.authenticate_provider_task = Some((
|
||||
provider.id(),
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if let Some(future) = load_credentials {
|
||||
let _ = future.await;
|
||||
}
|
||||
this.update(&mut cx, |this, _cx| {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.authenticate_provider_task = None;
|
||||
})
|
||||
.log_err();
|
||||
|
@ -641,9 +641,9 @@ impl AssistantPanel {
|
|||
}
|
||||
} else {
|
||||
let assistant_panel = assistant_panel.downgrade();
|
||||
cx.spawn_in(window, |workspace, mut cx| async move {
|
||||
cx.spawn_in(window, async move |workspace, cx| {
|
||||
let Some(task) =
|
||||
assistant_panel.update(&mut cx, |assistant, cx| assistant.authenticate(cx))?
|
||||
assistant_panel.update(cx, |assistant, cx| assistant.authenticate(cx))?
|
||||
else {
|
||||
let answer = cx
|
||||
.prompt(
|
||||
|
@ -665,7 +665,7 @@ impl AssistantPanel {
|
|||
return Ok(());
|
||||
};
|
||||
task.await?;
|
||||
if assistant_panel.update(&mut cx, |panel, cx| panel.is_authenticated(cx))? {
|
||||
if assistant_panel.update(cx, |panel, cx| panel.is_authenticated(cx))? {
|
||||
cx.update(|window, cx| match inline_assist_target {
|
||||
InlineAssistTarget::Editor(active_editor, include_context) => {
|
||||
let assistant_panel = if include_context {
|
||||
|
@ -698,7 +698,7 @@ impl AssistantPanel {
|
|||
}
|
||||
})?
|
||||
} else {
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
workspace.focus_panel::<AssistantPanel>(window, cx)
|
||||
})?;
|
||||
}
|
||||
|
@ -791,10 +791,10 @@ impl AssistantPanel {
|
|||
.context_store
|
||||
.update(cx, |store, cx| store.create_remote_context(cx));
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let context = task.await?;
|
||||
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let workspace = this.workspace.clone();
|
||||
let project = this.project.clone();
|
||||
let lsp_adapter_delegate =
|
||||
|
@ -847,9 +847,9 @@ impl AssistantPanel {
|
|||
|
||||
self.show_context(editor.clone(), window, cx);
|
||||
let workspace = self.workspace.clone();
|
||||
cx.spawn_in(window, move |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
workspace
|
||||
.update_in(&mut cx, |workspace, window, cx| {
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
workspace.focus_panel::<AssistantPanel>(window, cx);
|
||||
})
|
||||
.ok();
|
||||
|
@ -1069,8 +1069,8 @@ impl AssistantPanel {
|
|||
.filter(|editor| editor.read(cx).context().read(cx).path() == Some(&path))
|
||||
});
|
||||
if let Some(existing_context) = existing_context {
|
||||
return cx.spawn_in(window, |this, mut cx| async move {
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
return cx.spawn_in(window, async move |this, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.show_context(existing_context, window, cx)
|
||||
})
|
||||
});
|
||||
|
@ -1085,9 +1085,9 @@ impl AssistantPanel {
|
|||
|
||||
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project, cx).log_err().flatten();
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let context = context.await?;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let editor = cx.new(|cx| {
|
||||
ContextEditor::for_context(
|
||||
context,
|
||||
|
@ -1117,8 +1117,8 @@ impl AssistantPanel {
|
|||
.filter(|editor| *editor.read(cx).context().read(cx).id() == id)
|
||||
});
|
||||
if let Some(existing_context) = existing_context {
|
||||
return cx.spawn_in(window, |this, mut cx| async move {
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
return cx.spawn_in(window, async move |this, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.show_context(existing_context.clone(), window, cx)
|
||||
})?;
|
||||
Ok(existing_context)
|
||||
|
@ -1134,9 +1134,9 @@ impl AssistantPanel {
|
|||
.log_err()
|
||||
.flatten();
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let context = context.await?;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let editor = cx.new(|cx| {
|
||||
ContextEditor::for_context(
|
||||
context,
|
||||
|
|
|
@ -1311,9 +1311,9 @@ impl EditorInlineAssists {
|
|||
assist_ids: Vec::new(),
|
||||
scroll_lock: None,
|
||||
highlight_updates: highlight_updates_tx,
|
||||
_update_highlights: cx.spawn(|cx| {
|
||||
_update_highlights: cx.spawn({
|
||||
let editor = editor.downgrade();
|
||||
async move {
|
||||
async move |cx| {
|
||||
while let Ok(()) = highlight_updates_rx.changed().await {
|
||||
let editor = editor.upgrade().context("editor was dropped")?;
|
||||
cx.update_global(|assistant: &mut InlineAssistant, cx| {
|
||||
|
@ -1850,7 +1850,7 @@ impl PromptEditor {
|
|||
|
||||
fn count_tokens(&mut self, cx: &mut Context<Self>) {
|
||||
let assist_id = self.id;
|
||||
self.pending_token_count = cx.spawn(|this, mut cx| async move {
|
||||
self.pending_token_count = cx.spawn(async move |this, cx| {
|
||||
cx.background_executor().timer(Duration::from_secs(1)).await;
|
||||
let token_count = cx
|
||||
.update_global(|inline_assistant: &mut InlineAssistant, cx| {
|
||||
|
@ -1862,7 +1862,7 @@ impl PromptEditor {
|
|||
})??
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.token_counts = Some(token_count);
|
||||
cx.notify();
|
||||
})
|
||||
|
@ -2882,7 +2882,7 @@ impl CodegenAlternative {
|
|||
let request = self.build_request(user_prompt, assistant_panel_context, cx)?;
|
||||
self.request = Some(request.clone());
|
||||
|
||||
cx.spawn(|_, cx| async move { model.stream_completion_text(request, &cx).await })
|
||||
cx.spawn(async move |_, cx| model.stream_completion_text(request, &cx).await)
|
||||
.boxed_local()
|
||||
};
|
||||
self.handle_stream(telemetry_id, provider_id.to_string(), api_key, stream, cx);
|
||||
|
@ -2999,213 +2999,207 @@ impl CodegenAlternative {
|
|||
let completion = Arc::new(Mutex::new(String::new()));
|
||||
let completion_clone = completion.clone();
|
||||
|
||||
self.generation = cx.spawn(|codegen, mut cx| {
|
||||
async move {
|
||||
let stream = stream.await;
|
||||
let message_id = stream
|
||||
.as_ref()
|
||||
.ok()
|
||||
.and_then(|stream| stream.message_id.clone());
|
||||
let generate = async {
|
||||
let (mut diff_tx, mut diff_rx) = mpsc::channel(1);
|
||||
let executor = cx.background_executor().clone();
|
||||
let message_id = message_id.clone();
|
||||
let line_based_stream_diff: Task<anyhow::Result<()>> =
|
||||
cx.background_spawn(async move {
|
||||
let mut response_latency = None;
|
||||
let request_start = Instant::now();
|
||||
let diff = async {
|
||||
let chunks = StripInvalidSpans::new(stream?.stream);
|
||||
futures::pin_mut!(chunks);
|
||||
let mut diff = StreamingDiff::new(selected_text.to_string());
|
||||
let mut line_diff = LineDiff::default();
|
||||
self.generation = cx.spawn(async move |codegen, cx| {
|
||||
let stream = stream.await;
|
||||
let message_id = stream
|
||||
.as_ref()
|
||||
.ok()
|
||||
.and_then(|stream| stream.message_id.clone());
|
||||
let generate = async {
|
||||
let (mut diff_tx, mut diff_rx) = mpsc::channel(1);
|
||||
let executor = cx.background_executor().clone();
|
||||
let message_id = message_id.clone();
|
||||
let line_based_stream_diff: Task<anyhow::Result<()>> =
|
||||
cx.background_spawn(async move {
|
||||
let mut response_latency = None;
|
||||
let request_start = Instant::now();
|
||||
let diff = async {
|
||||
let chunks = StripInvalidSpans::new(stream?.stream);
|
||||
futures::pin_mut!(chunks);
|
||||
let mut diff = StreamingDiff::new(selected_text.to_string());
|
||||
let mut line_diff = LineDiff::default();
|
||||
|
||||
let mut new_text = String::new();
|
||||
let mut base_indent = None;
|
||||
let mut line_indent = None;
|
||||
let mut first_line = true;
|
||||
let mut new_text = String::new();
|
||||
let mut base_indent = None;
|
||||
let mut line_indent = None;
|
||||
let mut first_line = true;
|
||||
|
||||
while let Some(chunk) = chunks.next().await {
|
||||
if response_latency.is_none() {
|
||||
response_latency = Some(request_start.elapsed());
|
||||
}
|
||||
let chunk = chunk?;
|
||||
completion_clone.lock().push_str(&chunk);
|
||||
while let Some(chunk) = chunks.next().await {
|
||||
if response_latency.is_none() {
|
||||
response_latency = Some(request_start.elapsed());
|
||||
}
|
||||
let chunk = chunk?;
|
||||
completion_clone.lock().push_str(&chunk);
|
||||
|
||||
let mut lines = chunk.split('\n').peekable();
|
||||
while let Some(line) = lines.next() {
|
||||
new_text.push_str(line);
|
||||
if line_indent.is_none() {
|
||||
if let Some(non_whitespace_ch_ix) =
|
||||
new_text.find(|ch: char| !ch.is_whitespace())
|
||||
{
|
||||
line_indent = Some(non_whitespace_ch_ix);
|
||||
base_indent = base_indent.or(line_indent);
|
||||
let mut lines = chunk.split('\n').peekable();
|
||||
while let Some(line) = lines.next() {
|
||||
new_text.push_str(line);
|
||||
if line_indent.is_none() {
|
||||
if let Some(non_whitespace_ch_ix) =
|
||||
new_text.find(|ch: char| !ch.is_whitespace())
|
||||
{
|
||||
line_indent = Some(non_whitespace_ch_ix);
|
||||
base_indent = base_indent.or(line_indent);
|
||||
|
||||
let line_indent = line_indent.unwrap();
|
||||
let base_indent = base_indent.unwrap();
|
||||
let indent_delta =
|
||||
line_indent as i32 - base_indent as i32;
|
||||
let mut corrected_indent_len = cmp::max(
|
||||
0,
|
||||
suggested_line_indent.len as i32 + indent_delta,
|
||||
)
|
||||
as usize;
|
||||
if first_line {
|
||||
corrected_indent_len = corrected_indent_len
|
||||
.saturating_sub(
|
||||
selection_start.column as usize,
|
||||
);
|
||||
}
|
||||
|
||||
let indent_char = suggested_line_indent.char();
|
||||
let mut indent_buffer = [0; 4];
|
||||
let indent_str =
|
||||
indent_char.encode_utf8(&mut indent_buffer);
|
||||
new_text.replace_range(
|
||||
..line_indent,
|
||||
&indent_str.repeat(corrected_indent_len),
|
||||
);
|
||||
let line_indent = line_indent.unwrap();
|
||||
let base_indent = base_indent.unwrap();
|
||||
let indent_delta =
|
||||
line_indent as i32 - base_indent as i32;
|
||||
let mut corrected_indent_len = cmp::max(
|
||||
0,
|
||||
suggested_line_indent.len as i32 + indent_delta,
|
||||
)
|
||||
as usize;
|
||||
if first_line {
|
||||
corrected_indent_len = corrected_indent_len
|
||||
.saturating_sub(
|
||||
selection_start.column as usize,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if line_indent.is_some() {
|
||||
let char_ops = diff.push_new(&new_text);
|
||||
line_diff
|
||||
.push_char_operations(&char_ops, &selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
let indent_char = suggested_line_indent.char();
|
||||
let mut indent_buffer = [0; 4];
|
||||
let indent_str =
|
||||
indent_char.encode_utf8(&mut indent_buffer);
|
||||
new_text.replace_range(
|
||||
..line_indent,
|
||||
&indent_str.repeat(corrected_indent_len),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if line_indent.is_some() {
|
||||
let char_ops = diff.push_new(&new_text);
|
||||
line_diff.push_char_operations(&char_ops, &selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
new_text.clear();
|
||||
}
|
||||
|
||||
if lines.peek().is_some() {
|
||||
let char_ops = diff.push_new("\n");
|
||||
line_diff.push_char_operations(&char_ops, &selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
if line_indent.is_none() {
|
||||
// Don't write out the leading indentation in empty lines on the next line
|
||||
// This is the case where the above if statement didn't clear the buffer
|
||||
new_text.clear();
|
||||
}
|
||||
|
||||
if lines.peek().is_some() {
|
||||
let char_ops = diff.push_new("\n");
|
||||
line_diff
|
||||
.push_char_operations(&char_ops, &selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
if line_indent.is_none() {
|
||||
// Don't write out the leading indentation in empty lines on the next line
|
||||
// This is the case where the above if statement didn't clear the buffer
|
||||
new_text.clear();
|
||||
}
|
||||
line_indent = None;
|
||||
first_line = false;
|
||||
}
|
||||
line_indent = None;
|
||||
first_line = false;
|
||||
}
|
||||
}
|
||||
|
||||
let mut char_ops = diff.push_new(&new_text);
|
||||
char_ops.extend(diff.finish());
|
||||
line_diff.push_char_operations(&char_ops, &selected_text);
|
||||
line_diff.finish(&selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
|
||||
anyhow::Ok(())
|
||||
};
|
||||
|
||||
let result = diff.await;
|
||||
|
||||
let error_message =
|
||||
result.as_ref().err().map(|error| error.to_string());
|
||||
report_assistant_event(
|
||||
AssistantEvent {
|
||||
conversation_id: None,
|
||||
message_id,
|
||||
kind: AssistantKind::Inline,
|
||||
phase: AssistantPhase::Response,
|
||||
model: model_telemetry_id,
|
||||
model_provider: model_provider_id.to_string(),
|
||||
response_latency,
|
||||
error_message,
|
||||
language_name: language_name.map(|name| name.to_proto()),
|
||||
},
|
||||
telemetry,
|
||||
http_client,
|
||||
model_api_key,
|
||||
&executor,
|
||||
);
|
||||
|
||||
result?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
while let Some((char_ops, line_ops)) = diff_rx.next().await {
|
||||
codegen.update(&mut cx, |codegen, cx| {
|
||||
codegen.last_equal_ranges.clear();
|
||||
|
||||
let edits = char_ops
|
||||
.into_iter()
|
||||
.filter_map(|operation| match operation {
|
||||
CharOperation::Insert { text } => {
|
||||
let edit_start = snapshot.anchor_after(edit_start);
|
||||
Some((edit_start..edit_start, text))
|
||||
}
|
||||
CharOperation::Delete { bytes } => {
|
||||
let edit_end = edit_start + bytes;
|
||||
let edit_range = snapshot.anchor_after(edit_start)
|
||||
..snapshot.anchor_before(edit_end);
|
||||
edit_start = edit_end;
|
||||
Some((edit_range, String::new()))
|
||||
}
|
||||
CharOperation::Keep { bytes } => {
|
||||
let edit_end = edit_start + bytes;
|
||||
let edit_range = snapshot.anchor_after(edit_start)
|
||||
..snapshot.anchor_before(edit_end);
|
||||
edit_start = edit_end;
|
||||
codegen.last_equal_ranges.push(edit_range);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if codegen.active {
|
||||
codegen.apply_edits(edits.iter().cloned(), cx);
|
||||
codegen.reapply_line_based_diff(line_ops.iter().cloned(), cx);
|
||||
}
|
||||
codegen.edits.extend(edits);
|
||||
codegen.line_operations = line_ops;
|
||||
codegen.edit_position = Some(snapshot.anchor_after(edit_start));
|
||||
|
||||
cx.notify();
|
||||
})?;
|
||||
}
|
||||
let mut char_ops = diff.push_new(&new_text);
|
||||
char_ops.extend(diff.finish());
|
||||
line_diff.push_char_operations(&char_ops, &selected_text);
|
||||
line_diff.finish(&selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
|
||||
// Streaming stopped and we have the new text in the buffer, and a line-based diff applied for the whole new buffer.
|
||||
// That diff is not what a regular diff is and might look unexpected, ergo apply a regular diff.
|
||||
// It's fine to apply even if the rest of the line diffing fails, as no more hunks are coming through `diff_rx`.
|
||||
let batch_diff_task =
|
||||
codegen.update(&mut cx, |codegen, cx| codegen.reapply_batch_diff(cx))?;
|
||||
let (line_based_stream_diff, ()) =
|
||||
join!(line_based_stream_diff, batch_diff_task);
|
||||
line_based_stream_diff?;
|
||||
anyhow::Ok(())
|
||||
};
|
||||
|
||||
anyhow::Ok(())
|
||||
};
|
||||
let result = diff.await;
|
||||
|
||||
let result = generate.await;
|
||||
let elapsed_time = start_time.elapsed().as_secs_f64();
|
||||
let error_message = result.as_ref().err().map(|error| error.to_string());
|
||||
report_assistant_event(
|
||||
AssistantEvent {
|
||||
conversation_id: None,
|
||||
message_id,
|
||||
kind: AssistantKind::Inline,
|
||||
phase: AssistantPhase::Response,
|
||||
model: model_telemetry_id,
|
||||
model_provider: model_provider_id.to_string(),
|
||||
response_latency,
|
||||
error_message,
|
||||
language_name: language_name.map(|name| name.to_proto()),
|
||||
},
|
||||
telemetry,
|
||||
http_client,
|
||||
model_api_key,
|
||||
&executor,
|
||||
);
|
||||
|
||||
codegen
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.message_id = message_id;
|
||||
this.last_equal_ranges.clear();
|
||||
if let Err(error) = result {
|
||||
this.status = CodegenStatus::Error(error);
|
||||
} else {
|
||||
this.status = CodegenStatus::Done;
|
||||
result?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
while let Some((char_ops, line_ops)) = diff_rx.next().await {
|
||||
codegen.update(cx, |codegen, cx| {
|
||||
codegen.last_equal_ranges.clear();
|
||||
|
||||
let edits = char_ops
|
||||
.into_iter()
|
||||
.filter_map(|operation| match operation {
|
||||
CharOperation::Insert { text } => {
|
||||
let edit_start = snapshot.anchor_after(edit_start);
|
||||
Some((edit_start..edit_start, text))
|
||||
}
|
||||
CharOperation::Delete { bytes } => {
|
||||
let edit_end = edit_start + bytes;
|
||||
let edit_range = snapshot.anchor_after(edit_start)
|
||||
..snapshot.anchor_before(edit_end);
|
||||
edit_start = edit_end;
|
||||
Some((edit_range, String::new()))
|
||||
}
|
||||
CharOperation::Keep { bytes } => {
|
||||
let edit_end = edit_start + bytes;
|
||||
let edit_range = snapshot.anchor_after(edit_start)
|
||||
..snapshot.anchor_before(edit_end);
|
||||
edit_start = edit_end;
|
||||
codegen.last_equal_ranges.push(edit_range);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if codegen.active {
|
||||
codegen.apply_edits(edits.iter().cloned(), cx);
|
||||
codegen.reapply_line_based_diff(line_ops.iter().cloned(), cx);
|
||||
}
|
||||
this.elapsed_time = Some(elapsed_time);
|
||||
this.completion = Some(completion.lock().clone());
|
||||
cx.emit(CodegenEvent::Finished);
|
||||
codegen.edits.extend(edits);
|
||||
codegen.line_operations = line_ops;
|
||||
codegen.edit_position = Some(snapshot.anchor_after(edit_start));
|
||||
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})?;
|
||||
}
|
||||
|
||||
// Streaming stopped and we have the new text in the buffer, and a line-based diff applied for the whole new buffer.
|
||||
// That diff is not what a regular diff is and might look unexpected, ergo apply a regular diff.
|
||||
// It's fine to apply even if the rest of the line diffing fails, as no more hunks are coming through `diff_rx`.
|
||||
let batch_diff_task =
|
||||
codegen.update(cx, |codegen, cx| codegen.reapply_batch_diff(cx))?;
|
||||
let (line_based_stream_diff, ()) = join!(line_based_stream_diff, batch_diff_task);
|
||||
line_based_stream_diff?;
|
||||
|
||||
anyhow::Ok(())
|
||||
};
|
||||
|
||||
let result = generate.await;
|
||||
let elapsed_time = start_time.elapsed().as_secs_f64();
|
||||
|
||||
codegen
|
||||
.update(cx, |this, cx| {
|
||||
this.message_id = message_id;
|
||||
this.last_equal_ranges.clear();
|
||||
if let Err(error) = result {
|
||||
this.status = CodegenStatus::Error(error);
|
||||
} else {
|
||||
this.status = CodegenStatus::Done;
|
||||
}
|
||||
this.elapsed_time = Some(elapsed_time);
|
||||
this.completion = Some(completion.lock().clone());
|
||||
cx.emit(CodegenEvent::Finished);
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
cx.notify();
|
||||
}
|
||||
|
@ -3323,7 +3317,7 @@ impl CodegenAlternative {
|
|||
let new_snapshot = self.buffer.read(cx).snapshot(cx);
|
||||
let new_range = self.range.to_point(&new_snapshot);
|
||||
|
||||
cx.spawn(|codegen, mut cx| async move {
|
||||
cx.spawn(async move |codegen, cx| {
|
||||
let (deleted_row_ranges, inserted_row_ranges) = cx
|
||||
.background_spawn(async move {
|
||||
let old_text = old_snapshot
|
||||
|
@ -3373,7 +3367,7 @@ impl CodegenAlternative {
|
|||
.await;
|
||||
|
||||
codegen
|
||||
.update(&mut cx, |codegen, cx| {
|
||||
.update(cx, |codegen, cx| {
|
||||
codegen.diff.deleted_row_ranges = deleted_row_ranges;
|
||||
codegen.diff.inserted_row_ranges = inserted_row_ranges;
|
||||
cx.notify();
|
||||
|
@ -3587,10 +3581,10 @@ impl CodeActionProvider for AssistantCodeActionProvider {
|
|||
) -> Task<Result<ProjectTransaction>> {
|
||||
let editor = self.editor.clone();
|
||||
let workspace = self.workspace.clone();
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let editor = editor.upgrade().context("editor was released")?;
|
||||
let range = editor
|
||||
.update(&mut cx, |editor, cx| {
|
||||
.update(cx, |editor, cx| {
|
||||
editor.buffer().update(cx, |multibuffer, cx| {
|
||||
let buffer = buffer.read(cx);
|
||||
let multibuffer_snapshot = multibuffer.read(cx);
|
||||
|
@ -3625,7 +3619,7 @@ impl CodeActionProvider for AssistantCodeActionProvider {
|
|||
})
|
||||
})?
|
||||
.context("invalid range")?;
|
||||
let assistant_panel = workspace.update(&mut cx, |workspace, cx| {
|
||||
let assistant_panel = workspace.update(cx, |workspace, cx| {
|
||||
workspace
|
||||
.panel::<AssistantPanel>(cx)
|
||||
.context("assistant panel was released")
|
||||
|
|
|
@ -825,7 +825,7 @@ impl PromptEditor {
|
|||
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
|
||||
return;
|
||||
};
|
||||
self.pending_token_count = cx.spawn(|this, mut cx| async move {
|
||||
self.pending_token_count = cx.spawn(async move |this, cx| {
|
||||
cx.background_executor().timer(Duration::from_secs(1)).await;
|
||||
let request =
|
||||
cx.update_global(|inline_assistant: &mut TerminalInlineAssistant, cx| {
|
||||
|
@ -833,7 +833,7 @@ impl PromptEditor {
|
|||
})??;
|
||||
|
||||
let token_count = cx.update(|cx| model.count_tokens(request, cx))?.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.token_count = Some(token_count);
|
||||
cx.notify();
|
||||
})
|
||||
|
@ -1140,7 +1140,7 @@ impl Codegen {
|
|||
let telemetry = self.telemetry.clone();
|
||||
self.status = CodegenStatus::Pending;
|
||||
self.transaction = Some(TerminalTransaction::start(self.terminal.clone()));
|
||||
self.generation = cx.spawn(|this, mut cx| async move {
|
||||
self.generation = cx.spawn(async move |this, cx| {
|
||||
let model_telemetry_id = model.telemetry_id();
|
||||
let model_provider_id = model.provider_id();
|
||||
let response = model.stream_completion_text(prompt, &cx).await;
|
||||
|
@ -1197,12 +1197,12 @@ impl Codegen {
|
|||
}
|
||||
});
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.message_id = message_id;
|
||||
})?;
|
||||
|
||||
while let Some(hunk) = hunks_rx.next().await {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(transaction) = &mut this.transaction {
|
||||
transaction.push(hunk, cx);
|
||||
cx.notify();
|
||||
|
@ -1216,7 +1216,7 @@ impl Codegen {
|
|||
|
||||
let result = generate.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if let Err(error) = result {
|
||||
this.status = CodegenStatus::Error(error);
|
||||
} else {
|
||||
|
|
|
@ -372,10 +372,10 @@ impl ActiveThread {
|
|||
cx,
|
||||
);
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let updated_context_ids = refresh_task.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.context_store.read_with(cx, |context_store, cx| {
|
||||
context_store
|
||||
.context()
|
||||
|
@ -394,10 +394,10 @@ impl ActiveThread {
|
|||
|
||||
let model_registry = LanguageModelRegistry::read_global(cx);
|
||||
if let Some(model) = model_registry.active_model() {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let updated_context = context_update_task.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.thread.update(cx, |thread, cx| {
|
||||
thread.attach_tool_results(updated_context, cx);
|
||||
if !canceled {
|
||||
|
@ -418,9 +418,9 @@ impl ActiveThread {
|
|||
/// Only one task to save the thread will be in flight at a time.
|
||||
fn save_thread(&mut self, cx: &mut Context<Self>) {
|
||||
let thread = self.thread.clone();
|
||||
self.save_thread_task = Some(cx.spawn(|this, mut cx| async move {
|
||||
self.save_thread_task = Some(cx.spawn(async move |this, cx| {
|
||||
let task = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
this.thread_store
|
||||
.update(cx, |thread_store, cx| thread_store.save_thread(&thread, cx))
|
||||
})
|
||||
|
|
|
@ -110,16 +110,16 @@ impl AssistantPanel {
|
|||
prompt_builder: Arc<PromptBuilder>,
|
||||
cx: AsyncWindowContext,
|
||||
) -> Task<Result<Entity<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let tools = Arc::new(ToolWorkingSet::default());
|
||||
let thread_store = workspace.update(&mut cx, |workspace, cx| {
|
||||
let thread_store = workspace.update(cx, |workspace, cx| {
|
||||
let project = workspace.project().clone();
|
||||
ThreadStore::new(project, tools.clone(), prompt_builder.clone(), cx)
|
||||
})??;
|
||||
|
||||
let slash_commands = Arc::new(SlashCommandWorkingSet::default());
|
||||
let context_store = workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
.update(cx, |workspace, cx| {
|
||||
let project = workspace.project().clone();
|
||||
assistant_context_editor::ContextStore::new(
|
||||
project,
|
||||
|
@ -130,7 +130,7 @@ impl AssistantPanel {
|
|||
})?
|
||||
.await?;
|
||||
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
cx.new(|cx| Self::new(workspace, thread_store, context_store, window, cx))
|
||||
})
|
||||
})
|
||||
|
@ -344,9 +344,9 @@ impl AssistantPanel {
|
|||
|
||||
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project, cx).log_err().flatten();
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let context = context.await?;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let editor = cx.new(|cx| {
|
||||
ContextEditor::for_context(
|
||||
context,
|
||||
|
@ -377,9 +377,9 @@ impl AssistantPanel {
|
|||
.thread_store
|
||||
.update(cx, |this, cx| this.open_thread(thread_id, cx));
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let thread = open_thread_task.await?;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.active_view = ActiveView::Thread;
|
||||
let message_editor_context_store =
|
||||
cx.new(|_cx| crate::context_store::ContextStore::new(this.workspace.clone()));
|
||||
|
@ -450,10 +450,10 @@ impl AssistantPanel {
|
|||
.languages
|
||||
.language_for_name("Markdown");
|
||||
let thread = self.active_thread(cx);
|
||||
cx.spawn_in(window, |_this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_this, cx| {
|
||||
let markdown_language = markdown_language_task.await?;
|
||||
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let thread = thread.read(cx);
|
||||
let markdown = thread.to_markdown()?;
|
||||
let thread_summary = thread
|
||||
|
|
|
@ -367,7 +367,7 @@ impl CodegenAlternative {
|
|||
let request = self.build_request(user_prompt, cx)?;
|
||||
self.request = Some(request.clone());
|
||||
|
||||
cx.spawn(|_, cx| async move { model.stream_completion_text(request, &cx).await })
|
||||
cx.spawn(async move |_, cx| model.stream_completion_text(request, &cx).await)
|
||||
.boxed_local()
|
||||
};
|
||||
self.handle_stream(telemetry_id, provider_id.to_string(), api_key, stream, cx);
|
||||
|
@ -480,213 +480,207 @@ impl CodegenAlternative {
|
|||
let completion = Arc::new(Mutex::new(String::new()));
|
||||
let completion_clone = completion.clone();
|
||||
|
||||
self.generation = cx.spawn(|codegen, mut cx| {
|
||||
async move {
|
||||
let stream = stream.await;
|
||||
let message_id = stream
|
||||
.as_ref()
|
||||
.ok()
|
||||
.and_then(|stream| stream.message_id.clone());
|
||||
let generate = async {
|
||||
let (mut diff_tx, mut diff_rx) = mpsc::channel(1);
|
||||
let executor = cx.background_executor().clone();
|
||||
let message_id = message_id.clone();
|
||||
let line_based_stream_diff: Task<anyhow::Result<()>> =
|
||||
cx.background_spawn(async move {
|
||||
let mut response_latency = None;
|
||||
let request_start = Instant::now();
|
||||
let diff = async {
|
||||
let chunks = StripInvalidSpans::new(stream?.stream);
|
||||
futures::pin_mut!(chunks);
|
||||
let mut diff = StreamingDiff::new(selected_text.to_string());
|
||||
let mut line_diff = LineDiff::default();
|
||||
self.generation = cx.spawn(async move |codegen, cx| {
|
||||
let stream = stream.await;
|
||||
let message_id = stream
|
||||
.as_ref()
|
||||
.ok()
|
||||
.and_then(|stream| stream.message_id.clone());
|
||||
let generate = async {
|
||||
let (mut diff_tx, mut diff_rx) = mpsc::channel(1);
|
||||
let executor = cx.background_executor().clone();
|
||||
let message_id = message_id.clone();
|
||||
let line_based_stream_diff: Task<anyhow::Result<()>> =
|
||||
cx.background_spawn(async move {
|
||||
let mut response_latency = None;
|
||||
let request_start = Instant::now();
|
||||
let diff = async {
|
||||
let chunks = StripInvalidSpans::new(stream?.stream);
|
||||
futures::pin_mut!(chunks);
|
||||
let mut diff = StreamingDiff::new(selected_text.to_string());
|
||||
let mut line_diff = LineDiff::default();
|
||||
|
||||
let mut new_text = String::new();
|
||||
let mut base_indent = None;
|
||||
let mut line_indent = None;
|
||||
let mut first_line = true;
|
||||
let mut new_text = String::new();
|
||||
let mut base_indent = None;
|
||||
let mut line_indent = None;
|
||||
let mut first_line = true;
|
||||
|
||||
while let Some(chunk) = chunks.next().await {
|
||||
if response_latency.is_none() {
|
||||
response_latency = Some(request_start.elapsed());
|
||||
}
|
||||
let chunk = chunk?;
|
||||
completion_clone.lock().push_str(&chunk);
|
||||
while let Some(chunk) = chunks.next().await {
|
||||
if response_latency.is_none() {
|
||||
response_latency = Some(request_start.elapsed());
|
||||
}
|
||||
let chunk = chunk?;
|
||||
completion_clone.lock().push_str(&chunk);
|
||||
|
||||
let mut lines = chunk.split('\n').peekable();
|
||||
while let Some(line) = lines.next() {
|
||||
new_text.push_str(line);
|
||||
if line_indent.is_none() {
|
||||
if let Some(non_whitespace_ch_ix) =
|
||||
new_text.find(|ch: char| !ch.is_whitespace())
|
||||
{
|
||||
line_indent = Some(non_whitespace_ch_ix);
|
||||
base_indent = base_indent.or(line_indent);
|
||||
let mut lines = chunk.split('\n').peekable();
|
||||
while let Some(line) = lines.next() {
|
||||
new_text.push_str(line);
|
||||
if line_indent.is_none() {
|
||||
if let Some(non_whitespace_ch_ix) =
|
||||
new_text.find(|ch: char| !ch.is_whitespace())
|
||||
{
|
||||
line_indent = Some(non_whitespace_ch_ix);
|
||||
base_indent = base_indent.or(line_indent);
|
||||
|
||||
let line_indent = line_indent.unwrap();
|
||||
let base_indent = base_indent.unwrap();
|
||||
let indent_delta =
|
||||
line_indent as i32 - base_indent as i32;
|
||||
let mut corrected_indent_len = cmp::max(
|
||||
0,
|
||||
suggested_line_indent.len as i32 + indent_delta,
|
||||
)
|
||||
as usize;
|
||||
if first_line {
|
||||
corrected_indent_len = corrected_indent_len
|
||||
.saturating_sub(
|
||||
selection_start.column as usize,
|
||||
);
|
||||
}
|
||||
|
||||
let indent_char = suggested_line_indent.char();
|
||||
let mut indent_buffer = [0; 4];
|
||||
let indent_str =
|
||||
indent_char.encode_utf8(&mut indent_buffer);
|
||||
new_text.replace_range(
|
||||
..line_indent,
|
||||
&indent_str.repeat(corrected_indent_len),
|
||||
);
|
||||
let line_indent = line_indent.unwrap();
|
||||
let base_indent = base_indent.unwrap();
|
||||
let indent_delta =
|
||||
line_indent as i32 - base_indent as i32;
|
||||
let mut corrected_indent_len = cmp::max(
|
||||
0,
|
||||
suggested_line_indent.len as i32 + indent_delta,
|
||||
)
|
||||
as usize;
|
||||
if first_line {
|
||||
corrected_indent_len = corrected_indent_len
|
||||
.saturating_sub(
|
||||
selection_start.column as usize,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if line_indent.is_some() {
|
||||
let char_ops = diff.push_new(&new_text);
|
||||
line_diff
|
||||
.push_char_operations(&char_ops, &selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
let indent_char = suggested_line_indent.char();
|
||||
let mut indent_buffer = [0; 4];
|
||||
let indent_str =
|
||||
indent_char.encode_utf8(&mut indent_buffer);
|
||||
new_text.replace_range(
|
||||
..line_indent,
|
||||
&indent_str.repeat(corrected_indent_len),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if line_indent.is_some() {
|
||||
let char_ops = diff.push_new(&new_text);
|
||||
line_diff.push_char_operations(&char_ops, &selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
new_text.clear();
|
||||
}
|
||||
|
||||
if lines.peek().is_some() {
|
||||
let char_ops = diff.push_new("\n");
|
||||
line_diff.push_char_operations(&char_ops, &selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
if line_indent.is_none() {
|
||||
// Don't write out the leading indentation in empty lines on the next line
|
||||
// This is the case where the above if statement didn't clear the buffer
|
||||
new_text.clear();
|
||||
}
|
||||
|
||||
if lines.peek().is_some() {
|
||||
let char_ops = diff.push_new("\n");
|
||||
line_diff
|
||||
.push_char_operations(&char_ops, &selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
if line_indent.is_none() {
|
||||
// Don't write out the leading indentation in empty lines on the next line
|
||||
// This is the case where the above if statement didn't clear the buffer
|
||||
new_text.clear();
|
||||
}
|
||||
line_indent = None;
|
||||
first_line = false;
|
||||
}
|
||||
line_indent = None;
|
||||
first_line = false;
|
||||
}
|
||||
}
|
||||
|
||||
let mut char_ops = diff.push_new(&new_text);
|
||||
char_ops.extend(diff.finish());
|
||||
line_diff.push_char_operations(&char_ops, &selected_text);
|
||||
line_diff.finish(&selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
|
||||
anyhow::Ok(())
|
||||
};
|
||||
|
||||
let result = diff.await;
|
||||
|
||||
let error_message =
|
||||
result.as_ref().err().map(|error| error.to_string());
|
||||
report_assistant_event(
|
||||
AssistantEvent {
|
||||
conversation_id: None,
|
||||
message_id,
|
||||
kind: AssistantKind::Inline,
|
||||
phase: AssistantPhase::Response,
|
||||
model: model_telemetry_id,
|
||||
model_provider: model_provider_id.to_string(),
|
||||
response_latency,
|
||||
error_message,
|
||||
language_name: language_name.map(|name| name.to_proto()),
|
||||
},
|
||||
telemetry,
|
||||
http_client,
|
||||
model_api_key,
|
||||
&executor,
|
||||
);
|
||||
|
||||
result?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
while let Some((char_ops, line_ops)) = diff_rx.next().await {
|
||||
codegen.update(&mut cx, |codegen, cx| {
|
||||
codegen.last_equal_ranges.clear();
|
||||
|
||||
let edits = char_ops
|
||||
.into_iter()
|
||||
.filter_map(|operation| match operation {
|
||||
CharOperation::Insert { text } => {
|
||||
let edit_start = snapshot.anchor_after(edit_start);
|
||||
Some((edit_start..edit_start, text))
|
||||
}
|
||||
CharOperation::Delete { bytes } => {
|
||||
let edit_end = edit_start + bytes;
|
||||
let edit_range = snapshot.anchor_after(edit_start)
|
||||
..snapshot.anchor_before(edit_end);
|
||||
edit_start = edit_end;
|
||||
Some((edit_range, String::new()))
|
||||
}
|
||||
CharOperation::Keep { bytes } => {
|
||||
let edit_end = edit_start + bytes;
|
||||
let edit_range = snapshot.anchor_after(edit_start)
|
||||
..snapshot.anchor_before(edit_end);
|
||||
edit_start = edit_end;
|
||||
codegen.last_equal_ranges.push(edit_range);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if codegen.active {
|
||||
codegen.apply_edits(edits.iter().cloned(), cx);
|
||||
codegen.reapply_line_based_diff(line_ops.iter().cloned(), cx);
|
||||
}
|
||||
codegen.edits.extend(edits);
|
||||
codegen.line_operations = line_ops;
|
||||
codegen.edit_position = Some(snapshot.anchor_after(edit_start));
|
||||
|
||||
cx.notify();
|
||||
})?;
|
||||
}
|
||||
let mut char_ops = diff.push_new(&new_text);
|
||||
char_ops.extend(diff.finish());
|
||||
line_diff.push_char_operations(&char_ops, &selected_text);
|
||||
line_diff.finish(&selected_text);
|
||||
diff_tx
|
||||
.send((char_ops, line_diff.line_operations()))
|
||||
.await?;
|
||||
|
||||
// Streaming stopped and we have the new text in the buffer, and a line-based diff applied for the whole new buffer.
|
||||
// That diff is not what a regular diff is and might look unexpected, ergo apply a regular diff.
|
||||
// It's fine to apply even if the rest of the line diffing fails, as no more hunks are coming through `diff_rx`.
|
||||
let batch_diff_task =
|
||||
codegen.update(&mut cx, |codegen, cx| codegen.reapply_batch_diff(cx))?;
|
||||
let (line_based_stream_diff, ()) =
|
||||
join!(line_based_stream_diff, batch_diff_task);
|
||||
line_based_stream_diff?;
|
||||
anyhow::Ok(())
|
||||
};
|
||||
|
||||
anyhow::Ok(())
|
||||
};
|
||||
let result = diff.await;
|
||||
|
||||
let result = generate.await;
|
||||
let elapsed_time = start_time.elapsed().as_secs_f64();
|
||||
let error_message = result.as_ref().err().map(|error| error.to_string());
|
||||
report_assistant_event(
|
||||
AssistantEvent {
|
||||
conversation_id: None,
|
||||
message_id,
|
||||
kind: AssistantKind::Inline,
|
||||
phase: AssistantPhase::Response,
|
||||
model: model_telemetry_id,
|
||||
model_provider: model_provider_id.to_string(),
|
||||
response_latency,
|
||||
error_message,
|
||||
language_name: language_name.map(|name| name.to_proto()),
|
||||
},
|
||||
telemetry,
|
||||
http_client,
|
||||
model_api_key,
|
||||
&executor,
|
||||
);
|
||||
|
||||
codegen
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.message_id = message_id;
|
||||
this.last_equal_ranges.clear();
|
||||
if let Err(error) = result {
|
||||
this.status = CodegenStatus::Error(error);
|
||||
} else {
|
||||
this.status = CodegenStatus::Done;
|
||||
result?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
while let Some((char_ops, line_ops)) = diff_rx.next().await {
|
||||
codegen.update(cx, |codegen, cx| {
|
||||
codegen.last_equal_ranges.clear();
|
||||
|
||||
let edits = char_ops
|
||||
.into_iter()
|
||||
.filter_map(|operation| match operation {
|
||||
CharOperation::Insert { text } => {
|
||||
let edit_start = snapshot.anchor_after(edit_start);
|
||||
Some((edit_start..edit_start, text))
|
||||
}
|
||||
CharOperation::Delete { bytes } => {
|
||||
let edit_end = edit_start + bytes;
|
||||
let edit_range = snapshot.anchor_after(edit_start)
|
||||
..snapshot.anchor_before(edit_end);
|
||||
edit_start = edit_end;
|
||||
Some((edit_range, String::new()))
|
||||
}
|
||||
CharOperation::Keep { bytes } => {
|
||||
let edit_end = edit_start + bytes;
|
||||
let edit_range = snapshot.anchor_after(edit_start)
|
||||
..snapshot.anchor_before(edit_end);
|
||||
edit_start = edit_end;
|
||||
codegen.last_equal_ranges.push(edit_range);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if codegen.active {
|
||||
codegen.apply_edits(edits.iter().cloned(), cx);
|
||||
codegen.reapply_line_based_diff(line_ops.iter().cloned(), cx);
|
||||
}
|
||||
this.elapsed_time = Some(elapsed_time);
|
||||
this.completion = Some(completion.lock().clone());
|
||||
cx.emit(CodegenEvent::Finished);
|
||||
codegen.edits.extend(edits);
|
||||
codegen.line_operations = line_ops;
|
||||
codegen.edit_position = Some(snapshot.anchor_after(edit_start));
|
||||
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})?;
|
||||
}
|
||||
|
||||
// Streaming stopped and we have the new text in the buffer, and a line-based diff applied for the whole new buffer.
|
||||
// That diff is not what a regular diff is and might look unexpected, ergo apply a regular diff.
|
||||
// It's fine to apply even if the rest of the line diffing fails, as no more hunks are coming through `diff_rx`.
|
||||
let batch_diff_task =
|
||||
codegen.update(cx, |codegen, cx| codegen.reapply_batch_diff(cx))?;
|
||||
let (line_based_stream_diff, ()) = join!(line_based_stream_diff, batch_diff_task);
|
||||
line_based_stream_diff?;
|
||||
|
||||
anyhow::Ok(())
|
||||
};
|
||||
|
||||
let result = generate.await;
|
||||
let elapsed_time = start_time.elapsed().as_secs_f64();
|
||||
|
||||
codegen
|
||||
.update(cx, |this, cx| {
|
||||
this.message_id = message_id;
|
||||
this.last_equal_ranges.clear();
|
||||
if let Err(error) = result {
|
||||
this.status = CodegenStatus::Error(error);
|
||||
} else {
|
||||
this.status = CodegenStatus::Done;
|
||||
}
|
||||
this.elapsed_time = Some(elapsed_time);
|
||||
this.completion = Some(completion.lock().clone());
|
||||
cx.emit(CodegenEvent::Finished);
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
cx.notify();
|
||||
}
|
||||
|
@ -804,7 +798,7 @@ impl CodegenAlternative {
|
|||
let new_snapshot = self.buffer.read(cx).snapshot(cx);
|
||||
let new_range = self.range.to_point(&new_snapshot);
|
||||
|
||||
cx.spawn(|codegen, mut cx| async move {
|
||||
cx.spawn(async move |codegen, cx| {
|
||||
let (deleted_row_ranges, inserted_row_ranges) = cx
|
||||
.background_spawn(async move {
|
||||
let old_text = old_snapshot
|
||||
|
@ -854,7 +848,7 @@ impl CodegenAlternative {
|
|||
.await;
|
||||
|
||||
codegen
|
||||
.update(&mut cx, |codegen, cx| {
|
||||
.update(cx, |codegen, cx| {
|
||||
codegen.diff.deleted_row_ranges = deleted_row_ranges;
|
||||
codegen.diff.inserted_row_ranges = inserted_row_ranges;
|
||||
cx.notify();
|
||||
|
|
|
@ -281,10 +281,8 @@ impl ContextPicker {
|
|||
context_store.add_file_from_path(project_path.clone(), cx)
|
||||
});
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
task.await.notify_async_err(&mut cx)
|
||||
})
|
||||
.detach();
|
||||
cx.spawn_in(window, async move |_, cx| task.await.notify_async_err(cx))
|
||||
.detach();
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
@ -307,13 +305,13 @@ impl ContextPicker {
|
|||
};
|
||||
|
||||
let open_thread_task = thread_store.update(cx, |this, cx| this.open_thread(&thread.id, cx));
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let thread = open_thread_task.await?;
|
||||
context_store.update(&mut cx, |context_store, cx| {
|
||||
context_store.update(cx, |context_store, cx| {
|
||||
context_store.add_thread(thread, cx);
|
||||
})?;
|
||||
|
||||
this.update(&mut cx, |_this, cx| cx.notify())
|
||||
this.update(cx, |_this, cx| cx.notify())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -206,12 +206,12 @@ impl PickerDelegate for FetchContextPickerDelegate {
|
|||
let http_client = workspace.read(cx).client().http_client().clone();
|
||||
let url = self.url.clone();
|
||||
let confirm_behavior = self.confirm_behavior;
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let text = cx
|
||||
.background_spawn(Self::build_message(http_client, url.clone()))
|
||||
.await?;
|
||||
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.delegate
|
||||
.context_store
|
||||
.update(cx, |context_store, _cx| {
|
||||
|
|
|
@ -206,11 +206,11 @@ impl PickerDelegate for FileContextPickerDelegate {
|
|||
|
||||
let search_task = self.search(query, Arc::<AtomicBool>::default(), &workspace, cx);
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
// TODO: This should be probably be run in the background.
|
||||
let paths = search_task.await;
|
||||
|
||||
this.update(&mut cx, |this, _cx| {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.delegate.matches = paths;
|
||||
})
|
||||
.log_err();
|
||||
|
@ -345,10 +345,10 @@ impl PickerDelegate for FileContextPickerDelegate {
|
|||
};
|
||||
|
||||
let confirm_behavior = self.confirm_behavior;
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
match task.await.notify_async_err(&mut cx) {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
match task.await.notify_async_err(cx) {
|
||||
None => anyhow::Ok(()),
|
||||
Some(()) => this.update_in(&mut cx, |this, window, cx| match confirm_behavior {
|
||||
Some(()) => this.update_in(cx, |this, window, cx| match confirm_behavior {
|
||||
ConfirmBehavior::KeepOpen => {}
|
||||
ConfirmBehavior::Close => this.delegate.dismissed(window, cx),
|
||||
}),
|
||||
|
|
|
@ -149,9 +149,9 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
|||
}
|
||||
});
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let matches = search_task.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.delegate.matches = matches;
|
||||
this.delegate.selected_index = 0;
|
||||
cx.notify();
|
||||
|
@ -171,9 +171,9 @@ impl PickerDelegate for ThreadContextPickerDelegate {
|
|||
|
||||
let open_thread_task = thread_store.update(cx, |this, cx| this.open_thread(&entry.id, cx));
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let thread = open_thread_task.await?;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.delegate
|
||||
.context_store
|
||||
.update(cx, |context_store, cx| context_store.add_thread(thread, cx))
|
||||
|
|
|
@ -75,15 +75,15 @@ impl ContextStore {
|
|||
return Task::ready(Err(anyhow!("failed to read project")));
|
||||
};
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let open_buffer_task = project.update(&mut cx, |project, cx| {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let open_buffer_task = project.update(cx, |project, cx| {
|
||||
project.open_buffer(project_path.clone(), cx)
|
||||
})?;
|
||||
|
||||
let buffer_entity = open_buffer_task.await?;
|
||||
let buffer_id = this.update(&mut cx, |_, cx| buffer_entity.read(cx).remote_id())?;
|
||||
let buffer_id = this.update(cx, |_, cx| buffer_entity.read(cx).remote_id())?;
|
||||
|
||||
let already_included = this.update(&mut cx, |this, _cx| {
|
||||
let already_included = this.update(cx, |this, _cx| {
|
||||
match this.will_include_buffer(buffer_id, &project_path.path) {
|
||||
Some(FileInclusion::Direct(context_id)) => {
|
||||
this.remove_context(context_id);
|
||||
|
@ -98,7 +98,7 @@ impl ContextStore {
|
|||
return anyhow::Ok(());
|
||||
}
|
||||
|
||||
let (buffer_info, text_task) = this.update(&mut cx, |_, cx| {
|
||||
let (buffer_info, text_task) = this.update(cx, |_, cx| {
|
||||
let buffer = buffer_entity.read(cx);
|
||||
collect_buffer_info_and_text(
|
||||
project_path.path.clone(),
|
||||
|
@ -110,7 +110,7 @@ impl ContextStore {
|
|||
|
||||
let text = text_task.await;
|
||||
|
||||
this.update(&mut cx, |this, _cx| {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.insert_file(make_context_buffer(buffer_info, text));
|
||||
})?;
|
||||
|
||||
|
@ -123,8 +123,8 @@ impl ContextStore {
|
|||
buffer_entity: Entity<Buffer>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let (buffer_info, text_task) = this.update(&mut cx, |_, cx| {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let (buffer_info, text_task) = this.update(cx, |_, cx| {
|
||||
let buffer = buffer_entity.read(cx);
|
||||
let Some(file) = buffer.file() else {
|
||||
return Err(anyhow!("Buffer has no path."));
|
||||
|
@ -139,7 +139,7 @@ impl ContextStore {
|
|||
|
||||
let text = text_task.await;
|
||||
|
||||
this.update(&mut cx, |this, _cx| {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.insert_file(make_context_buffer(buffer_info, text))
|
||||
})?;
|
||||
|
||||
|
@ -179,18 +179,18 @@ impl ContextStore {
|
|||
}
|
||||
|
||||
let worktree_id = project_path.worktree_id;
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let worktree = project.update(&mut cx, |project, cx| {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let worktree = project.update(cx, |project, cx| {
|
||||
project
|
||||
.worktree_for_id(worktree_id, cx)
|
||||
.ok_or_else(|| anyhow!("no worktree found for {worktree_id:?}"))
|
||||
})??;
|
||||
|
||||
let files = worktree.update(&mut cx, |worktree, _cx| {
|
||||
let files = worktree.update(cx, |worktree, _cx| {
|
||||
collect_files_in_path(worktree, &project_path.path)
|
||||
})?;
|
||||
|
||||
let open_buffers_task = project.update(&mut cx, |project, cx| {
|
||||
let open_buffers_task = project.update(cx, |project, cx| {
|
||||
let tasks = files.iter().map(|file_path| {
|
||||
project.open_buffer(
|
||||
ProjectPath {
|
||||
|
@ -207,7 +207,7 @@ impl ContextStore {
|
|||
|
||||
let mut buffer_infos = Vec::new();
|
||||
let mut text_tasks = Vec::new();
|
||||
this.update(&mut cx, |_, cx| {
|
||||
this.update(cx, |_, cx| {
|
||||
for (path, buffer_entity) in files.into_iter().zip(buffers) {
|
||||
// Skip all binary files and other non-UTF8 files
|
||||
if let Ok(buffer_entity) = buffer_entity {
|
||||
|
@ -236,7 +236,7 @@ impl ContextStore {
|
|||
bail!("No text files found in {}", &project_path.path.display());
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.insert_directory(&project_path.path, context_buffers);
|
||||
})?;
|
||||
|
||||
|
@ -595,10 +595,10 @@ fn refresh_file_text(
|
|||
let id = file_context.id;
|
||||
let task = refresh_context_buffer(&file_context.context_buffer, cx);
|
||||
if let Some(task) = task {
|
||||
Some(cx.spawn(|mut cx| async move {
|
||||
Some(cx.spawn(async move |cx| {
|
||||
let context_buffer = task.await;
|
||||
context_store
|
||||
.update(&mut cx, |context_store, _| {
|
||||
.update(cx, |context_store, _| {
|
||||
let new_file_context = FileContext { id, context_buffer };
|
||||
context_store.replace_context(AssistantContext::File(new_file_context));
|
||||
})
|
||||
|
@ -636,10 +636,10 @@ fn refresh_directory_text(
|
|||
|
||||
let id = directory_context.snapshot.id;
|
||||
let path = directory_context.path.clone();
|
||||
Some(cx.spawn(|mut cx| async move {
|
||||
Some(cx.spawn(async move |cx| {
|
||||
let context_buffers = context_buffers.await;
|
||||
context_store
|
||||
.update(&mut cx, |context_store, _| {
|
||||
.update(cx, |context_store, _| {
|
||||
let new_directory_context = DirectoryContext::new(id, &path, context_buffers);
|
||||
context_store.replace_context(AssistantContext::Directory(new_directory_context));
|
||||
})
|
||||
|
@ -654,9 +654,9 @@ fn refresh_thread_text(
|
|||
) -> Task<()> {
|
||||
let id = thread_context.id;
|
||||
let thread = thread_context.thread.clone();
|
||||
cx.spawn(move |mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
context_store
|
||||
.update(&mut cx, |context_store, cx| {
|
||||
.update(cx, |context_store, cx| {
|
||||
let text = thread.read(cx).text().into();
|
||||
context_store.replace_context(AssistantContext::Thread(ThreadContext {
|
||||
id,
|
||||
|
|
|
@ -335,12 +335,12 @@ impl ContextStrip {
|
|||
context_store.accept_suggested_context(&suggested, cx)
|
||||
});
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
match task.await.notify_async_err(&mut cx) {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
match task.await.notify_async_err(cx) {
|
||||
None => {}
|
||||
Some(()) => {
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |_, cx| cx.notify())?;
|
||||
this.update(cx, |_, cx| cx.notify())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ impl InlineAssistant {
|
|||
if is_authenticated() {
|
||||
handle_assist(window, cx);
|
||||
} else {
|
||||
cx.spawn_in(window, |_workspace, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_workspace, cx| {
|
||||
let Some(task) = cx.update(|_, cx| {
|
||||
LanguageModelRegistry::read_global(cx)
|
||||
.active_provider()
|
||||
|
@ -1456,9 +1456,9 @@ impl EditorInlineAssists {
|
|||
assist_ids: Vec::new(),
|
||||
scroll_lock: None,
|
||||
highlight_updates: highlight_updates_tx,
|
||||
_update_highlights: cx.spawn(|cx| {
|
||||
_update_highlights: cx.spawn({
|
||||
let editor = editor.downgrade();
|
||||
async move {
|
||||
async move |cx| {
|
||||
while let Ok(()) = highlight_updates_rx.changed().await {
|
||||
let editor = editor.upgrade().context("editor was dropped")?;
|
||||
cx.update_global(|assistant: &mut InlineAssistant, cx| {
|
||||
|
@ -1748,10 +1748,10 @@ impl CodeActionProvider for AssistantCodeActionProvider {
|
|||
let editor = self.editor.clone();
|
||||
let workspace = self.workspace.clone();
|
||||
let thread_store = self.thread_store.clone();
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let editor = editor.upgrade().context("editor was released")?;
|
||||
let range = editor
|
||||
.update(&mut cx, |editor, cx| {
|
||||
.update(cx, |editor, cx| {
|
||||
editor.buffer().update(cx, |multibuffer, cx| {
|
||||
let buffer = buffer.read(cx);
|
||||
let multibuffer_snapshot = multibuffer.read(cx);
|
||||
|
|
|
@ -206,10 +206,10 @@ impl MessageEditor {
|
|||
|
||||
let thread = self.thread.clone();
|
||||
let context_store = self.context_store.clone();
|
||||
cx.spawn(move |_, mut cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
refresh_task.await;
|
||||
thread
|
||||
.update(&mut cx, |thread, cx| {
|
||||
.update(cx, |thread, cx| {
|
||||
let context = context_store.read(cx).snapshot(cx).collect::<Vec<_>>();
|
||||
thread.insert_user_message(user_message, context, cx);
|
||||
thread.send_to_model(model, request_kind, cx);
|
||||
|
@ -297,9 +297,9 @@ impl MessageEditor {
|
|||
.thread
|
||||
.update(cx, |thread, cx| thread.report_feedback(is_positive, cx));
|
||||
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
report.await?;
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
let message = if is_positive {
|
||||
"Positive feedback recorded. Thank you!"
|
||||
} else {
|
||||
|
|
|
@ -40,7 +40,7 @@ impl TerminalCodegen {
|
|||
let telemetry = self.telemetry.clone();
|
||||
self.status = CodegenStatus::Pending;
|
||||
self.transaction = Some(TerminalTransaction::start(self.terminal.clone()));
|
||||
self.generation = cx.spawn(|this, mut cx| async move {
|
||||
self.generation = cx.spawn(async move |this, cx| {
|
||||
let model_telemetry_id = model.telemetry_id();
|
||||
let model_provider_id = model.provider_id();
|
||||
let response = model.stream_completion_text(prompt, &cx).await;
|
||||
|
@ -97,12 +97,12 @@ impl TerminalCodegen {
|
|||
}
|
||||
});
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.message_id = message_id;
|
||||
})?;
|
||||
|
||||
while let Some(hunk) = hunks_rx.next().await {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(transaction) = &mut this.transaction {
|
||||
transaction.push(hunk, cx);
|
||||
cx.notify();
|
||||
|
@ -116,7 +116,7 @@ impl TerminalCodegen {
|
|||
|
||||
let result = generate.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if let Err(error) = result {
|
||||
this.status = CodegenStatus::Error(error);
|
||||
} else {
|
||||
|
|
|
@ -394,9 +394,9 @@ impl Thread {
|
|||
/// Serializes this thread into a format for storage or telemetry.
|
||||
pub fn serialize(&self, cx: &mut Context<Self>) -> Task<Result<SerializedThread>> {
|
||||
let initial_project_snapshot = self.initial_project_snapshot.clone();
|
||||
cx.spawn(|this, cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let initial_project_snapshot = initial_project_snapshot.await;
|
||||
this.read_with(&cx, |this, _| SerializedThread {
|
||||
this.read_with(cx, |this, _| SerializedThread {
|
||||
summary: this.summary_or_default(),
|
||||
updated_at: this.updated_at(),
|
||||
messages: this
|
||||
|
@ -602,7 +602,7 @@ impl Thread {
|
|||
) {
|
||||
let pending_completion_id = post_inc(&mut self.completion_count);
|
||||
|
||||
let task = cx.spawn(|thread, mut cx| async move {
|
||||
let task = cx.spawn(async move |thread, cx| {
|
||||
let stream = model.stream_completion(request, &cx);
|
||||
let stream_completion = async {
|
||||
let mut events = stream.await?;
|
||||
|
@ -612,7 +612,7 @@ impl Thread {
|
|||
while let Some(event) = events.next().await {
|
||||
let event = event?;
|
||||
|
||||
thread.update(&mut cx, |thread, cx| {
|
||||
thread.update(cx, |thread, cx| {
|
||||
match event {
|
||||
LanguageModelCompletionEvent::StartMessage { .. } => {
|
||||
thread.insert_message(Role::Assistant, String::new(), cx);
|
||||
|
@ -671,7 +671,7 @@ impl Thread {
|
|||
smol::future::yield_now().await;
|
||||
}
|
||||
|
||||
thread.update(&mut cx, |thread, cx| {
|
||||
thread.update(cx, |thread, cx| {
|
||||
thread
|
||||
.pending_completions
|
||||
.retain(|completion| completion.id != pending_completion_id);
|
||||
|
@ -687,7 +687,7 @@ impl Thread {
|
|||
let result = stream_completion.await;
|
||||
|
||||
thread
|
||||
.update(&mut cx, |thread, cx| {
|
||||
.update(cx, |thread, cx| {
|
||||
match result.as_ref() {
|
||||
Ok(stop_reason) => match stop_reason {
|
||||
StopReason::ToolUse => {
|
||||
|
@ -750,7 +750,7 @@ impl Thread {
|
|||
cache: false,
|
||||
});
|
||||
|
||||
self.pending_summary = cx.spawn(|this, mut cx| {
|
||||
self.pending_summary = cx.spawn(async move |this, cx| {
|
||||
async move {
|
||||
let stream = model.stream_completion_text(request, &cx);
|
||||
let mut messages = stream.await?;
|
||||
|
@ -767,7 +767,7 @@ impl Thread {
|
|||
}
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if !new_summary.is_empty() {
|
||||
this.summary = Some(new_summary.into());
|
||||
}
|
||||
|
@ -778,6 +778,7 @@ impl Thread {
|
|||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -823,10 +824,10 @@ impl Thread {
|
|||
});
|
||||
|
||||
let session = self.scripting_session.clone();
|
||||
cx.spawn(|_, cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
script_task.await;
|
||||
|
||||
let message = session.read_with(&cx, |session, _cx| {
|
||||
let message = session.read_with(cx, |session, _cx| {
|
||||
// Using a id to get the script output seems impractical.
|
||||
// Why not just include it in the Task result?
|
||||
// This is because we'll later report the script state as it runs,
|
||||
|
@ -851,12 +852,12 @@ impl Thread {
|
|||
output: Task<Result<String>>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let insert_output_task = cx.spawn(|thread, mut cx| {
|
||||
let insert_output_task = cx.spawn({
|
||||
let tool_use_id = tool_use_id.clone();
|
||||
async move {
|
||||
async move |thread, cx| {
|
||||
let output = output.await;
|
||||
thread
|
||||
.update(&mut cx, |thread, cx| {
|
||||
.update(cx, |thread, cx| {
|
||||
let pending_tool_use = thread
|
||||
.tool_use
|
||||
.insert_tool_output(tool_use_id.clone(), output);
|
||||
|
@ -881,12 +882,12 @@ impl Thread {
|
|||
output: Task<Result<String>>,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let insert_output_task = cx.spawn(|thread, mut cx| {
|
||||
let insert_output_task = cx.spawn({
|
||||
let tool_use_id = tool_use_id.clone();
|
||||
async move {
|
||||
async move |thread, cx| {
|
||||
let output = output.await;
|
||||
thread
|
||||
.update(&mut cx, |thread, cx| {
|
||||
.update(cx, |thread, cx| {
|
||||
let pending_tool_use = thread
|
||||
.scripting_tool_use
|
||||
.insert_tool_output(tool_use_id.clone(), output);
|
||||
|
@ -985,7 +986,7 @@ impl Thread {
|
|||
.map(|worktree| Self::worktree_snapshot(worktree, cx))
|
||||
.collect();
|
||||
|
||||
cx.spawn(move |_, cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
let worktree_snapshots = futures::future::join_all(worktree_snapshots).await;
|
||||
|
||||
let mut unsaved_buffers = Vec::new();
|
||||
|
@ -1012,7 +1013,7 @@ impl Thread {
|
|||
}
|
||||
|
||||
fn worktree_snapshot(worktree: Entity<project::Worktree>, cx: &App) -> Task<WorktreeSnapshot> {
|
||||
cx.spawn(move |cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
// Get worktree path and snapshot
|
||||
let worktree_info = cx.update(|app_cx| {
|
||||
let worktree = worktree.read(app_cx);
|
||||
|
@ -1036,7 +1037,7 @@ impl Thread {
|
|||
let current_branch = repo_entry.branch().map(|branch| branch.name.to_string());
|
||||
|
||||
// Get repository info
|
||||
let repo_result = worktree.read_with(&cx, |worktree, _cx| {
|
||||
let repo_result = worktree.read_with(cx, |worktree, _cx| {
|
||||
if let project::Worktree::Local(local_worktree) = &worktree {
|
||||
local_worktree.get_local_repo(repo_entry).map(|local_repo| {
|
||||
let repo = local_repo.repo();
|
||||
|
@ -1051,7 +1052,7 @@ impl Thread {
|
|||
Ok(Some((remote_url, head_sha, repository))) => {
|
||||
// Get diff asynchronously
|
||||
let diff = repository
|
||||
.diff(git::repository::DiffType::HeadToWorktree, cx)
|
||||
.diff(git::repository::DiffType::HeadToWorktree, cx.clone())
|
||||
.await
|
||||
.ok();
|
||||
|
||||
|
|
|
@ -106,14 +106,14 @@ impl ThreadStore {
|
|||
) -> Task<Result<Entity<Thread>>> {
|
||||
let id = id.clone();
|
||||
let database_future = ThreadsDatabase::global_future(cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let database = database_future.await.map_err(|err| anyhow!(err))?;
|
||||
let thread = database
|
||||
.try_find_thread(id.clone())
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("no thread found with ID: {id:?}"))?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
cx.new(|cx| {
|
||||
Thread::deserialize(
|
||||
id.clone(),
|
||||
|
@ -133,23 +133,23 @@ impl ThreadStore {
|
|||
thread.update(cx, |thread, cx| (thread.id().clone(), thread.serialize(cx)));
|
||||
|
||||
let database_future = ThreadsDatabase::global_future(cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let serialized_thread = serialized_thread.await?;
|
||||
let database = database_future.await.map_err(|err| anyhow!(err))?;
|
||||
database.save_thread(metadata, serialized_thread).await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| this.reload(cx))?.await
|
||||
this.update(cx, |this, cx| this.reload(cx))?.await
|
||||
})
|
||||
}
|
||||
|
||||
pub fn delete_thread(&mut self, id: &ThreadId, cx: &mut Context<Self>) -> Task<Result<()>> {
|
||||
let id = id.clone();
|
||||
let database_future = ThreadsDatabase::global_future(cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let database = database_future.await.map_err(|err| anyhow!(err))?;
|
||||
database.delete_thread(id.clone()).await?;
|
||||
|
||||
this.update(&mut cx, |this, _cx| {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.threads.retain(|thread| thread.id != id)
|
||||
})
|
||||
})
|
||||
|
@ -157,14 +157,14 @@ impl ThreadStore {
|
|||
|
||||
pub fn reload(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
|
||||
let database_future = ThreadsDatabase::global_future(cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let threads = database_future
|
||||
.await
|
||||
.map_err(|err| anyhow!(err))?
|
||||
.list_threads()
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.threads = threads;
|
||||
cx.notify();
|
||||
})
|
||||
|
@ -193,7 +193,7 @@ impl ThreadStore {
|
|||
cx.spawn({
|
||||
let server = server.clone();
|
||||
let server_id = server_id.clone();
|
||||
|this, mut cx| async move {
|
||||
async move |this, cx| {
|
||||
let Some(protocol) = server.client() else {
|
||||
return;
|
||||
};
|
||||
|
@ -218,7 +218,7 @@ impl ThreadStore {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
this.update(&mut cx, |this, _cx| {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.context_server_tool_ids.insert(server_id, tool_ids);
|
||||
})
|
||||
.log_err();
|
||||
|
|
|
@ -1144,9 +1144,9 @@ impl AssistantContext {
|
|||
|
||||
fn set_language(&mut self, cx: &mut Context<Self>) {
|
||||
let markdown = self.language_registry.language_for_name("Markdown");
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let markdown = markdown.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.buffer
|
||||
.update(cx, |buffer, cx| buffer.set_language(Some(markdown), cx));
|
||||
})
|
||||
|
@ -1188,7 +1188,7 @@ impl AssistantContext {
|
|||
return;
|
||||
};
|
||||
let debounce = self.token_count.is_some();
|
||||
self.pending_token_count = cx.spawn(|this, mut cx| {
|
||||
self.pending_token_count = cx.spawn(async move |this, cx| {
|
||||
async move {
|
||||
if debounce {
|
||||
cx.background_executor()
|
||||
|
@ -1197,13 +1197,14 @@ impl AssistantContext {
|
|||
}
|
||||
|
||||
let token_count = cx.update(|cx| model.count_tokens(request, cx))?.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.token_count = Some(token_count);
|
||||
this.start_cache_warming(&model, cx);
|
||||
cx.notify()
|
||||
})
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1342,7 +1343,7 @@ impl AssistantContext {
|
|||
};
|
||||
|
||||
let model = Arc::clone(model);
|
||||
self.pending_cache_warming_task = cx.spawn(|this, mut cx| {
|
||||
self.pending_cache_warming_task = cx.spawn(async move |this, cx| {
|
||||
async move {
|
||||
match model.stream_completion(request, &cx).await {
|
||||
Ok(mut stream) => {
|
||||
|
@ -1353,13 +1354,14 @@ impl AssistantContext {
|
|||
log::warn!("Cache warming failed: {}", e);
|
||||
}
|
||||
};
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.update_cache_status_for_completion(cx);
|
||||
})
|
||||
.ok();
|
||||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1916,7 +1918,7 @@ impl AssistantContext {
|
|||
});
|
||||
self.reparse(cx);
|
||||
|
||||
let insert_output_task = cx.spawn(|this, mut cx| async move {
|
||||
let insert_output_task = cx.spawn(async move |this, cx| {
|
||||
let run_command = async {
|
||||
let mut stream = output.await?;
|
||||
|
||||
|
@ -1933,7 +1935,7 @@ impl AssistantContext {
|
|||
|
||||
while let Some(event) = stream.next().await {
|
||||
let event = event?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.buffer.update(cx, |buffer, _cx| {
|
||||
buffer.finalize_last_transaction();
|
||||
buffer.start_transaction()
|
||||
|
@ -2034,7 +2036,7 @@ impl AssistantContext {
|
|||
})?;
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.buffer.update(cx, |buffer, cx| {
|
||||
buffer.finalize_last_transaction();
|
||||
buffer.start_transaction();
|
||||
|
@ -2080,7 +2082,7 @@ impl AssistantContext {
|
|||
|
||||
let command_result = run_command.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let version = this.version.clone();
|
||||
let timestamp = this.next_timestamp();
|
||||
let Some(invoked_slash_command) = this.invoked_slash_commands.get_mut(&command_id)
|
||||
|
@ -2210,7 +2212,7 @@ impl AssistantContext {
|
|||
let pending_completion_id = post_inc(&mut self.completion_count);
|
||||
|
||||
let task = cx.spawn({
|
||||
|this, mut cx| async move {
|
||||
async move |this, cx| {
|
||||
let stream = model.stream_completion(request, &cx);
|
||||
let assistant_message_id = assistant_message.id;
|
||||
let mut response_latency = None;
|
||||
|
@ -2225,7 +2227,7 @@ impl AssistantContext {
|
|||
}
|
||||
let event = event?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let message_ix = this
|
||||
.message_anchors
|
||||
.iter()
|
||||
|
@ -2264,7 +2266,7 @@ impl AssistantContext {
|
|||
})?;
|
||||
smol::future::yield_now().await;
|
||||
}
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.pending_completions
|
||||
.retain(|completion| completion.id != pending_completion_id);
|
||||
this.summarize(false, cx);
|
||||
|
@ -2276,7 +2278,7 @@ impl AssistantContext {
|
|||
|
||||
let result = stream_completion.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let error_message = if let Some(error) = result.as_ref().err() {
|
||||
if error.is::<PaymentRequiredError>() {
|
||||
cx.emit(ContextEvent::ShowPaymentRequiredError);
|
||||
|
@ -2786,7 +2788,7 @@ impl AssistantContext {
|
|||
cache: false,
|
||||
});
|
||||
|
||||
self.pending_summary = cx.spawn(|this, mut cx| {
|
||||
self.pending_summary = cx.spawn(async move |this, cx| {
|
||||
async move {
|
||||
let stream = model.stream_completion_text(request, &cx);
|
||||
let mut messages = stream.await?;
|
||||
|
@ -2795,7 +2797,7 @@ impl AssistantContext {
|
|||
while let Some(message) = messages.stream.next().await {
|
||||
let text = message?;
|
||||
let mut lines = text.lines();
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let version = this.version.clone();
|
||||
let timestamp = this.next_timestamp();
|
||||
let summary = this.summary.get_or_insert(ContextSummary::default());
|
||||
|
@ -2819,7 +2821,7 @@ impl AssistantContext {
|
|||
}
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let version = this.version.clone();
|
||||
let timestamp = this.next_timestamp();
|
||||
if let Some(summary) = this.summary.as_mut() {
|
||||
|
@ -2837,6 +2839,7 @@ impl AssistantContext {
|
|||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2943,12 +2946,12 @@ impl AssistantContext {
|
|||
return;
|
||||
}
|
||||
|
||||
self.pending_save = cx.spawn(|this, mut cx| async move {
|
||||
self.pending_save = cx.spawn(async move |this, cx| {
|
||||
if let Some(debounce) = debounce {
|
||||
cx.background_executor().timer(debounce).await;
|
||||
}
|
||||
|
||||
let (old_path, summary) = this.read_with(&cx, |this, _| {
|
||||
let (old_path, summary) = this.read_with(cx, |this, _| {
|
||||
let path = this.path.clone();
|
||||
let summary = if let Some(summary) = this.summary.as_ref() {
|
||||
if summary.done {
|
||||
|
@ -2963,7 +2966,7 @@ impl AssistantContext {
|
|||
})?;
|
||||
|
||||
if let Some(summary) = summary {
|
||||
let context = this.read_with(&cx, |this, cx| this.serialize(cx))?;
|
||||
let context = this.read_with(cx, |this, cx| this.serialize(cx))?;
|
||||
let mut discriminant = 1;
|
||||
let mut new_path;
|
||||
loop {
|
||||
|
@ -2995,7 +2998,7 @@ impl AssistantContext {
|
|||
}
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, _| this.path = Some(new_path))?;
|
||||
this.update(cx, |this, _| this.path = Some(new_path))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -907,7 +907,7 @@ impl ContextEditor {
|
|||
if editor_state.opened_patch != patch {
|
||||
state.update_task = Some({
|
||||
let this = this.clone();
|
||||
cx.spawn_in(window, |_, cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
Self::update_patch_editor(this.clone(), patch, cx)
|
||||
.await
|
||||
.log_err();
|
||||
|
@ -1070,10 +1070,9 @@ impl ContextEditor {
|
|||
})
|
||||
.ok();
|
||||
} else {
|
||||
patch_state.update_task =
|
||||
Some(cx.spawn_in(window, move |this, cx| async move {
|
||||
Self::open_patch_editor(this, new_patch, cx).await.log_err();
|
||||
}));
|
||||
patch_state.update_task = Some(cx.spawn_in(window, async move |this, cx| {
|
||||
Self::open_patch_editor(this, new_patch, cx).await.log_err();
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1103,10 +1102,10 @@ impl ContextEditor {
|
|||
async fn open_patch_editor(
|
||||
this: WeakEntity<Self>,
|
||||
patch: AssistantPatch,
|
||||
mut cx: AsyncWindowContext,
|
||||
cx: &mut AsyncWindowContext,
|
||||
) -> Result<()> {
|
||||
let project = this.read_with(&cx, |this, _| this.project.clone())?;
|
||||
let resolved_patch = patch.resolve(project.clone(), &mut cx).await;
|
||||
let project = this.read_with(cx, |this, _| this.project.clone())?;
|
||||
let resolved_patch = patch.resolve(project.clone(), cx).await;
|
||||
|
||||
let editor = cx.new_window_entity(|window, cx| {
|
||||
let editor = ProposedChangesEditor::new(
|
||||
|
@ -1130,7 +1129,7 @@ impl ContextEditor {
|
|||
editor
|
||||
})?;
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
if let Some(patch_state) = this.patches.get_mut(&patch.range) {
|
||||
patch_state.editor = Some(PatchEditorState {
|
||||
editor: editor.downgrade(),
|
||||
|
@ -1139,8 +1138,8 @@ impl ContextEditor {
|
|||
patch_state.update_task.take();
|
||||
}
|
||||
})?;
|
||||
this.read_with(&cx, |this, _| this.workspace.clone())?
|
||||
.update_in(&mut cx, |workspace, window, cx| {
|
||||
this.read_with(cx, |this, _| this.workspace.clone())?
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
workspace.add_item_to_active_pane(Box::new(editor.clone()), None, false, window, cx)
|
||||
})
|
||||
.log_err();
|
||||
|
@ -1151,11 +1150,11 @@ impl ContextEditor {
|
|||
async fn update_patch_editor(
|
||||
this: WeakEntity<Self>,
|
||||
patch: AssistantPatch,
|
||||
mut cx: AsyncWindowContext,
|
||||
cx: &mut AsyncWindowContext,
|
||||
) -> Result<()> {
|
||||
let project = this.update(&mut cx, |this, _| this.project.clone())?;
|
||||
let resolved_patch = patch.resolve(project.clone(), &mut cx).await;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
let project = this.update(cx, |this, _| this.project.clone())?;
|
||||
let resolved_patch = patch.resolve(project.clone(), cx).await;
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let patch_state = this.patches.get_mut(&patch.range)?;
|
||||
|
||||
let locations = resolved_patch
|
||||
|
@ -1625,14 +1624,14 @@ impl ContextEditor {
|
|||
.map(|path| Workspace::project_path_for_path(project.clone(), &path, false, cx))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
cx.spawn(move |_, cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
let mut paths = vec![];
|
||||
let mut worktrees = vec![];
|
||||
|
||||
let opened_paths = futures::future::join_all(tasks).await;
|
||||
for (worktree, project_path) in opened_paths.into_iter().flatten() {
|
||||
let Ok(worktree_root_name) =
|
||||
worktree.read_with(&cx, |worktree, _| worktree.root_name().to_string())
|
||||
worktree.read_with(cx, |worktree, _| worktree.root_name().to_string())
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
@ -1649,12 +1648,12 @@ impl ContextEditor {
|
|||
};
|
||||
|
||||
window
|
||||
.spawn(cx, |mut cx| async move {
|
||||
.spawn(cx, async move |cx| {
|
||||
let (paths, dragged_file_worktrees) = paths.await;
|
||||
let cmd_name = FileSlashCommand.name();
|
||||
|
||||
context_editor_view
|
||||
.update_in(&mut cx, |context_editor, window, cx| {
|
||||
.update_in(cx, |context_editor, window, cx| {
|
||||
let file_argument = paths
|
||||
.into_iter()
|
||||
.map(|path| path.to_string_lossy().to_string())
|
||||
|
@ -2200,9 +2199,9 @@ impl ContextEditor {
|
|||
.log_err();
|
||||
|
||||
if let Some(client) = client {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
client.authenticate_and_connect(true, &mut cx).await?;
|
||||
this.update(&mut cx, |_, cx| cx.notify())
|
||||
cx.spawn(async move |this, cx| {
|
||||
client.authenticate_and_connect(true, cx).await?;
|
||||
this.update(cx, |_, cx| cx.notify())
|
||||
})
|
||||
.detach_and_log_err(cx)
|
||||
}
|
||||
|
@ -3161,10 +3160,10 @@ impl FollowableItem for ContextEditor {
|
|||
assistant_panel_delegate.open_remote_context(workspace, context_id, window, cx)
|
||||
});
|
||||
|
||||
Some(window.spawn(cx, |mut cx| async move {
|
||||
Some(window.spawn(cx, async move |cx| {
|
||||
let context_editor = context_editor_task.await?;
|
||||
context_editor
|
||||
.update_in(&mut cx, |context_editor, window, cx| {
|
||||
.update_in(cx, |context_editor, window, cx| {
|
||||
context_editor.remote_id = Some(id);
|
||||
context_editor.editor.update(cx, |editor, cx| {
|
||||
editor.apply_update_proto(
|
||||
|
|
|
@ -164,9 +164,9 @@ impl PickerDelegate for SavedContextPickerDelegate {
|
|||
cx: &mut Context<Picker<Self>>,
|
||||
) -> Task<()> {
|
||||
let search = self.store.read(cx).search(query, cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let matches = search.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let host_contexts = this.delegate.store.read(cx).host_contexts();
|
||||
this.delegate.matches = host_contexts
|
||||
.iter()
|
||||
|
|
|
@ -100,7 +100,7 @@ impl ContextStore {
|
|||
let fs = project.read(cx).fs().clone();
|
||||
let languages = project.read(cx).languages().clone();
|
||||
let telemetry = project.read(cx).client().telemetry().clone();
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
const CONTEXT_WATCH_DURATION: Duration = Duration::from_millis(100);
|
||||
let (mut events, _) = fs.watch(contexts_dir(), CONTEXT_WATCH_DURATION).await;
|
||||
|
||||
|
@ -125,16 +125,15 @@ impl ContextStore {
|
|||
languages,
|
||||
slash_commands,
|
||||
telemetry,
|
||||
_watch_updates: cx.spawn(|this, mut cx| {
|
||||
_watch_updates: cx.spawn(async move |this, cx| {
|
||||
async move {
|
||||
while events.next().await.is_some() {
|
||||
this.update(&mut cx, |this, cx| this.reload(cx))?
|
||||
.await
|
||||
.log_err();
|
||||
this.update(cx, |this, cx| this.reload(cx))?.await.log_err();
|
||||
}
|
||||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
}),
|
||||
client_subscription: None,
|
||||
_project_subscriptions: vec![
|
||||
|
@ -395,7 +394,7 @@ impl ContextStore {
|
|||
let prompt_builder = self.prompt_builder.clone();
|
||||
let slash_commands = self.slash_commands.clone();
|
||||
let request = self.client.request(proto::CreateContext { project_id });
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = request.await?;
|
||||
let context_id = ContextId::from_proto(response.context_id);
|
||||
let context_proto = response.context.context("invalid context")?;
|
||||
|
@ -421,8 +420,8 @@ impl ContextStore {
|
|||
.collect::<Result<Vec<_>>>()
|
||||
})
|
||||
.await?;
|
||||
context.update(&mut cx, |context, cx| context.apply_ops(operations, cx))?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
context.update(cx, |context, cx| context.apply_ops(operations, cx))?;
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(existing_context) = this.loaded_context_for_id(&context_id, cx) {
|
||||
existing_context
|
||||
} else {
|
||||
|
@ -457,7 +456,7 @@ impl ContextStore {
|
|||
let prompt_builder = self.prompt_builder.clone();
|
||||
let slash_commands = self.slash_commands.clone();
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let saved_context = load.await?;
|
||||
let context = cx.new(|cx| {
|
||||
AssistantContext::deserialize(
|
||||
|
@ -471,7 +470,7 @@ impl ContextStore {
|
|||
cx,
|
||||
)
|
||||
})?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(existing_context) = this.loaded_context_for_path(&path, cx) {
|
||||
existing_context
|
||||
} else {
|
||||
|
@ -489,7 +488,7 @@ impl ContextStore {
|
|||
) -> Task<Result<()>> {
|
||||
let fs = self.fs.clone();
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
fs.remove_file(
|
||||
&path,
|
||||
RemoveOptions {
|
||||
|
@ -499,7 +498,7 @@ impl ContextStore {
|
|||
)
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.contexts.retain(|context| {
|
||||
context
|
||||
.upgrade()
|
||||
|
@ -565,7 +564,7 @@ impl ContextStore {
|
|||
});
|
||||
let prompt_builder = self.prompt_builder.clone();
|
||||
let slash_commands = self.slash_commands.clone();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = request.await?;
|
||||
let context_proto = response.context.context("invalid context")?;
|
||||
let context = cx.new(|cx| {
|
||||
|
@ -590,8 +589,8 @@ impl ContextStore {
|
|||
.collect::<Result<Vec<_>>>()
|
||||
})
|
||||
.await?;
|
||||
context.update(&mut cx, |context, cx| context.apply_ops(operations, cx))?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
context.update(cx, |context, cx| context.apply_ops(operations, cx))?;
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(existing_context) = this.loaded_context_for_id(&context_id, cx) {
|
||||
existing_context
|
||||
} else {
|
||||
|
@ -700,12 +699,12 @@ impl ContextStore {
|
|||
project_id,
|
||||
contexts,
|
||||
});
|
||||
cx.spawn(|this, cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = request.await?;
|
||||
|
||||
let mut context_ids = Vec::new();
|
||||
let mut operations = Vec::new();
|
||||
this.read_with(&cx, |this, cx| {
|
||||
this.read_with(cx, |this, cx| {
|
||||
for context_version_proto in response.contexts {
|
||||
let context_version = ContextVersion::from_proto(&context_version_proto);
|
||||
let context_id = ContextId::from_proto(context_version_proto.context_id);
|
||||
|
@ -768,7 +767,7 @@ impl ContextStore {
|
|||
|
||||
fn reload(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
|
||||
let fs = self.fs.clone();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
fs.create_dir(contexts_dir()).await?;
|
||||
|
||||
let mut paths = fs.read_dir(contexts_dir()).await?;
|
||||
|
@ -808,7 +807,7 @@ impl ContextStore {
|
|||
}
|
||||
contexts.sort_unstable_by_key(|context| Reverse(context.mtime));
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.contexts_metadata = contexts;
|
||||
cx.notify();
|
||||
})
|
||||
|
@ -850,7 +849,7 @@ impl ContextStore {
|
|||
cx.spawn({
|
||||
let server = server.clone();
|
||||
let server_id = server_id.clone();
|
||||
|this, mut cx| async move {
|
||||
async move |this, cx| {
|
||||
let Some(protocol) = server.client() else {
|
||||
return;
|
||||
};
|
||||
|
@ -875,7 +874,7 @@ impl ContextStore {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
this.update(&mut cx, |this, _cx| {
|
||||
this.update( cx, |this, _cx| {
|
||||
this.context_server_slash_command_ids
|
||||
.insert(server_id.clone(), slash_command_ids);
|
||||
})
|
||||
|
|
|
@ -59,7 +59,7 @@ impl SlashCommandCompletionProvider {
|
|||
let command_name = command_name.to_string();
|
||||
let editor = self.editor.clone();
|
||||
let workspace = self.workspace.clone();
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let matches = match_strings(
|
||||
&candidates,
|
||||
&command_name,
|
||||
|
|
|
@ -100,7 +100,7 @@ impl PickerDelegate for SlashCommandDelegate {
|
|||
cx: &mut Context<Picker<Self>>,
|
||||
) -> Task<()> {
|
||||
let all_commands = self.all_commands.clone();
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let filtered_commands = cx
|
||||
.background_spawn(async move {
|
||||
if query.is_empty() {
|
||||
|
@ -119,7 +119,7 @@ impl PickerDelegate for SlashCommandDelegate {
|
|||
})
|
||||
.await;
|
||||
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.delegate.filtered_commands = filtered_commands;
|
||||
this.delegate.set_selected_index(0, window, cx);
|
||||
cx.notify();
|
||||
|
|
|
@ -63,14 +63,14 @@ impl Eval {
|
|||
model: Arc<dyn LanguageModel>,
|
||||
cx: &mut App,
|
||||
) -> Task<anyhow::Result<EvalOutput>> {
|
||||
cx.spawn(move |mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
checkout_repo(&self.eval_setup, &self.repo_path).await?;
|
||||
|
||||
let (assistant, done_rx) =
|
||||
cx.update(|cx| HeadlessAssistant::new(app_state.clone(), cx))??;
|
||||
|
||||
let _worktree = assistant
|
||||
.update(&mut cx, |assistant, cx| {
|
||||
.update(cx, |assistant, cx| {
|
||||
assistant.project.update(cx, |project, cx| {
|
||||
project.create_worktree(&self.repo_path, true, cx)
|
||||
})
|
||||
|
@ -79,7 +79,7 @@ impl Eval {
|
|||
|
||||
let start_time = std::time::SystemTime::now();
|
||||
|
||||
assistant.update(&mut cx, |assistant, cx| {
|
||||
assistant.update(cx, |assistant, cx| {
|
||||
assistant.thread.update(cx, |thread, cx| {
|
||||
let context = vec![];
|
||||
thread.insert_user_message(self.user_prompt.clone(), context, cx);
|
||||
|
@ -93,7 +93,7 @@ impl Eval {
|
|||
|
||||
let diff = query_git(&self.repo_path, vec!["diff"]).await?;
|
||||
|
||||
assistant.update(&mut cx, |assistant, cx| {
|
||||
assistant.update(cx, |assistant, cx| {
|
||||
let thread = assistant.thread.read(cx);
|
||||
let last_message = thread.messages().last().unwrap();
|
||||
if last_message.role != language_model::Role::Assistant {
|
||||
|
|
|
@ -212,7 +212,7 @@ pub fn authenticate_model_provider(
|
|||
pub async fn send_language_model_request(
|
||||
model: Arc<dyn LanguageModel>,
|
||||
request: LanguageModelRequest,
|
||||
cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> anyhow::Result<String> {
|
||||
match model.stream_completion_text(request, &cx).await {
|
||||
Ok(mut stream) => {
|
||||
|
|
|
@ -61,7 +61,7 @@ impl Judge {
|
|||
};
|
||||
|
||||
let model = self.model.clone();
|
||||
cx.spawn(move |cx| send_language_model_request(model, request, cx))
|
||||
cx.spawn(async move |cx| send_language_model_request(model, request, cx).await)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ fn main() {
|
|||
let editor_model_provider_id = editor_model.provider_id();
|
||||
let judge_model_provider_id = judge_model.provider_id();
|
||||
|
||||
cx.spawn(move |cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
// Authenticate all model providers first
|
||||
cx.update(|cx| authenticate_model_provider(model_provider_id.clone(), cx))
|
||||
.unwrap()
|
||||
|
|
|
@ -77,8 +77,8 @@ impl SlashCommand for AutoCommand {
|
|||
|
||||
let cx: &mut App = cx;
|
||||
|
||||
cx.spawn(|cx: gpui::AsyncApp| async move {
|
||||
let task = project_index.read_with(&cx, |project_index, cx| {
|
||||
cx.spawn(async move |cx| {
|
||||
let task = project_index.read_with(cx, |project_index, cx| {
|
||||
project_index.flush_summary_backlogs(cx)
|
||||
})?;
|
||||
|
||||
|
@ -117,9 +117,9 @@ impl SlashCommand for AutoCommand {
|
|||
return Task::ready(Err(anyhow!("no project indexer")));
|
||||
};
|
||||
|
||||
let task = window.spawn(cx, |cx| async move {
|
||||
let task = window.spawn(cx, async move |cx| {
|
||||
let summaries = project_index
|
||||
.read_with(&cx, |project_index, cx| project_index.all_summaries(cx))?
|
||||
.read_with(cx, |project_index, cx| project_index.all_summaries(cx))?
|
||||
.await?;
|
||||
|
||||
commands_for_summaries(&summaries, &original_prompt, &cx).await
|
||||
|
|
|
@ -186,7 +186,7 @@ impl SlashCommand for DiagnosticsSlashCommand {
|
|||
|
||||
let task = collect_diagnostics(workspace.read(cx).project().clone(), options, cx);
|
||||
|
||||
window.spawn(cx, move |_| async move {
|
||||
window.spawn(cx, async move |_| {
|
||||
task.await?
|
||||
.map(|output| output.to_event_stream())
|
||||
.ok_or_else(|| anyhow!("No diagnostics found"))
|
||||
|
@ -268,7 +268,7 @@ fn collect_diagnostics(
|
|||
})
|
||||
.collect();
|
||||
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let mut output = SlashCommandOutput::default();
|
||||
|
||||
if let Some(error_source) = error_source.as_ref() {
|
||||
|
@ -299,7 +299,7 @@ fn collect_diagnostics(
|
|||
}
|
||||
|
||||
if let Some(buffer) = project_handle
|
||||
.update(&mut cx, |project, cx| project.open_buffer(project_path, cx))?
|
||||
.update(cx, |project, cx| project.open_buffer(project_path, cx))?
|
||||
.await
|
||||
.log_err()
|
||||
{
|
||||
|
|
|
@ -241,7 +241,7 @@ fn collect_files(
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let (events_tx, events_rx) = mpsc::unbounded();
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
for snapshot in snapshots {
|
||||
let worktree_id = snapshot.id();
|
||||
let mut directory_stack: Vec<Arc<Path>> = Vec::new();
|
||||
|
@ -352,7 +352,7 @@ fn collect_files(
|
|||
)))?;
|
||||
} else if entry.is_file() {
|
||||
let Some(open_buffer_task) = project_handle
|
||||
.update(&mut cx, |project, cx| {
|
||||
.update(cx, |project, cx| {
|
||||
project.open_buffer((worktree_id, &entry.path), cx)
|
||||
})
|
||||
.ok()
|
||||
|
@ -361,7 +361,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),
|
||||
|
|
|
@ -99,7 +99,7 @@ impl SlashCommand for ProjectSlashCommand {
|
|||
return Task::ready(Err(anyhow::anyhow!("no project indexer")));
|
||||
};
|
||||
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let current_model = current_model.ok_or_else(|| anyhow!("no model selected"))?;
|
||||
|
||||
let prompt =
|
||||
|
@ -123,7 +123,7 @@ impl SlashCommand for ProjectSlashCommand {
|
|||
.search_queries;
|
||||
|
||||
let results = project_index
|
||||
.read_with(&cx, |project_index, cx| {
|
||||
.read_with(cx, |project_index, cx| {
|
||||
project_index.search(search_queries.clone(), 25, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
|
|
@ -109,9 +109,9 @@ impl SlashCommand for SearchSlashCommand {
|
|||
return Task::ready(Err(anyhow::anyhow!("no project indexer")));
|
||||
};
|
||||
|
||||
window.spawn(cx, |cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let results = project_index
|
||||
.read_with(&cx, |project_index, cx| {
|
||||
.read_with(cx, |project_index, cx| {
|
||||
project_index.search(vec![query.clone()], limit.unwrap_or(5), cx)
|
||||
})?
|
||||
.await?;
|
||||
|
|
|
@ -86,7 +86,7 @@ impl SlashCommand for TabSlashCommand {
|
|||
tab_items_for_queries(workspace, &[current_query], cancel, false, window, cx);
|
||||
|
||||
let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId);
|
||||
window.spawn(cx, |_| async move {
|
||||
window.spawn(cx, async move |_| {
|
||||
let tab_items = tab_items_search.await?;
|
||||
let run_command = tab_items.len() == 1;
|
||||
let tab_completion_items = tab_items.into_iter().filter_map(|(path, ..)| {
|
||||
|
@ -172,11 +172,11 @@ fn tab_items_for_queries(
|
|||
) -> Task<anyhow::Result<Vec<(Option<PathBuf>, BufferSnapshot, usize)>>> {
|
||||
let empty_query = queries.is_empty() || queries.iter().all(|query| query.trim().is_empty());
|
||||
let queries = queries.to_owned();
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let mut open_buffers =
|
||||
workspace
|
||||
.context("no workspace")?
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
.update(cx, |workspace, cx| {
|
||||
if strict_match && empty_query {
|
||||
let snapshot = active_item_buffer(workspace, cx)?;
|
||||
let full_path = snapshot.resolve_file_path(cx, true);
|
||||
|
|
|
@ -50,7 +50,7 @@ impl Tool for BashTool {
|
|||
};
|
||||
let working_directory = worktree.read(cx).abs_path();
|
||||
|
||||
cx.spawn(|_| async move {
|
||||
cx.spawn(async move |_| {
|
||||
// Add 2>&1 to merge stderr into stdout for proper interleaving.
|
||||
let command = format!("({}) 2>&1", input.command);
|
||||
|
||||
|
|
|
@ -65,10 +65,10 @@ impl Tool for DiagnosticsTool {
|
|||
};
|
||||
let buffer = project.update(cx, |project, cx| project.open_buffer(project_path, cx));
|
||||
|
||||
cx.spawn(|cx| async move {
|
||||
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];
|
||||
|
|
|
@ -103,7 +103,7 @@ impl Tool for EditFilesTool {
|
|||
cx,
|
||||
);
|
||||
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let result = task.await;
|
||||
|
||||
let str_result = match &result {
|
||||
|
@ -111,10 +111,8 @@ impl Tool for EditFilesTool {
|
|||
Err(err) => Err(err.to_string()),
|
||||
};
|
||||
|
||||
log.update(&mut cx, |log, cx| {
|
||||
log.set_tool_output(req_id, str_result, cx)
|
||||
})
|
||||
.log_err();
|
||||
log.update(cx, |log, cx| log.set_tool_output(req_id, str_result, cx))
|
||||
.log_err();
|
||||
|
||||
result
|
||||
})
|
||||
|
@ -188,7 +186,7 @@ impl EditToolRequest {
|
|||
cache: false,
|
||||
});
|
||||
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let llm_request = LanguageModelRequest {
|
||||
messages,
|
||||
tools: vec![],
|
||||
|
@ -211,10 +209,10 @@ impl EditToolRequest {
|
|||
};
|
||||
|
||||
while let Some(chunk) = chunks.stream.next().await {
|
||||
request.process_response_chunk(&chunk?, &mut cx).await?;
|
||||
request.process_response_chunk(&chunk?, cx).await?;
|
||||
}
|
||||
|
||||
request.finalize(&mut cx).await
|
||||
request.finalize(cx).await
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -70,14 +70,14 @@ impl Tool for ReadFileTool {
|
|||
return Task::ready(Err(anyhow!("Path not found in project")));
|
||||
};
|
||||
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = cx
|
||||
.update(|cx| {
|
||||
project.update(cx, |project, cx| project.open_buffer(project_path, cx))
|
||||
})?
|
||||
.await?;
|
||||
|
||||
let result = buffer.read_with(&cx, |buffer, _cx| {
|
||||
let result = buffer.read_with(cx, |buffer, _cx| {
|
||||
if buffer
|
||||
.file()
|
||||
.map_or(false, |file| file.disk_state().exists())
|
||||
|
@ -102,7 +102,7 @@ impl Tool for ReadFileTool {
|
|||
}
|
||||
})??;
|
||||
|
||||
action_log.update(&mut cx, |log, cx| {
|
||||
action_log.update(cx, |log, cx| {
|
||||
log.buffer_read(buffer, cx);
|
||||
})?;
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ impl Tool for RegexSearchTool {
|
|||
|
||||
let results = project.update(cx, |project, cx| project.search(query, cx));
|
||||
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move|cx| {
|
||||
futures::pin_mut!(results);
|
||||
|
||||
let mut output = String::new();
|
||||
|
@ -86,7 +86,7 @@ impl Tool for RegexSearchTool {
|
|||
continue;
|
||||
}
|
||||
|
||||
buffer.read_with(&cx, |buffer, cx| -> Result<(), anyhow::Error> {
|
||||
buffer.read_with(cx, |buffer, cx| -> Result<(), anyhow::Error> {
|
||||
if let Some(path) = buffer.file().map(|file| file.full_path(cx)) {
|
||||
let mut file_header_written = false;
|
||||
let mut ranges = ranges
|
||||
|
|
|
@ -252,11 +252,9 @@ impl AutoUpdater {
|
|||
}
|
||||
|
||||
pub fn start_polling(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
loop {
|
||||
this.update(&mut cx, |this, cx| this.poll(cx))?;
|
||||
cx.background_executor().timer(POLL_INTERVAL).await;
|
||||
}
|
||||
cx.spawn(async move |this, cx| loop {
|
||||
this.update(cx, |this, cx| this.poll(cx))?;
|
||||
cx.background_executor().timer(POLL_INTERVAL).await;
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -267,9 +265,9 @@ impl AutoUpdater {
|
|||
|
||||
cx.notify();
|
||||
|
||||
self.pending_poll = Some(cx.spawn(|this, mut cx| async move {
|
||||
self.pending_poll = Some(cx.spawn(async move |this, cx| {
|
||||
let result = Self::update(this.upgrade()?, cx.clone()).await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.pending_poll = None;
|
||||
if let Err(error) = result {
|
||||
log::error!("auto-update failed: error:{:?}", error);
|
||||
|
|
|
@ -64,7 +64,7 @@ fn view_release_notes_locally(
|
|||
|
||||
workspace
|
||||
.with_local_workspace(window, cx, move |_, window, cx| {
|
||||
cx.spawn_in(window, |workspace, mut cx| async move {
|
||||
cx.spawn_in(window, async move |workspace, cx| {
|
||||
let markdown = markdown.await.log_err();
|
||||
let response = client.get(&url, Default::default(), true).await;
|
||||
let Some(mut response) = response.log_err() else {
|
||||
|
@ -79,7 +79,7 @@ fn view_release_notes_locally(
|
|||
|
||||
if let Ok(body) = body {
|
||||
workspace
|
||||
.update_in(&mut cx, |workspace, window, cx| {
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
let project = workspace.project().clone();
|
||||
let buffer = project.update(cx, |project, cx| {
|
||||
project.create_local_buffer("", markdown, cx)
|
||||
|
@ -130,7 +130,7 @@ pub fn notify_if_app_was_updated(cx: &mut App) {
|
|||
return;
|
||||
};
|
||||
let should_show_notification = updater.read(cx).should_show_update_notification(cx);
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let should_show_notification = should_show_notification.await?;
|
||||
if should_show_notification {
|
||||
cx.update(|cx| {
|
||||
|
|
|
@ -1080,12 +1080,12 @@ impl BufferDiff {
|
|||
let complete_on_drop = util::defer(|| {
|
||||
tx.send(()).ok();
|
||||
});
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
let snapshot = snapshot.await;
|
||||
let Some(this) = this.upgrade() else {
|
||||
return;
|
||||
};
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.set_state(snapshot, &buffer);
|
||||
})
|
||||
.log_err();
|
||||
|
|
|
@ -54,10 +54,10 @@ impl OneAtATime {
|
|||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.cancel.replace(tx);
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
futures::select_biased! {
|
||||
_ = rx.fuse() => Ok(None),
|
||||
result = f(cx).fuse() => result.map(Some),
|
||||
result = f(cx.clone()).fuse() => result.map(Some),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -192,19 +192,19 @@ impl ActiveCall {
|
|||
};
|
||||
|
||||
let invite = if let Some(room) = room {
|
||||
cx.spawn(move |_, mut cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
let room = room.await.map_err(|err| anyhow!("{:?}", err))?;
|
||||
|
||||
let initial_project_id = if let Some(initial_project) = initial_project {
|
||||
Some(
|
||||
room.update(&mut cx, |room, cx| room.share_project(initial_project, cx))?
|
||||
room.update(cx, |room, cx| room.share_project(initial_project, cx))?
|
||||
.await?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
room.update(&mut cx, move |room, cx| {
|
||||
room.update(cx, move |room, cx| {
|
||||
room.call(called_user_id, initial_project_id, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
@ -215,7 +215,7 @@ impl ActiveCall {
|
|||
let client = self.client.clone();
|
||||
let user_store = self.user_store.clone();
|
||||
let room = cx
|
||||
.spawn(move |this, mut cx| async move {
|
||||
.spawn(async move |this, cx| {
|
||||
let create_room = async {
|
||||
let room = cx
|
||||
.update(|cx| {
|
||||
|
@ -229,14 +229,14 @@ impl ActiveCall {
|
|||
})?
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| this.set_room(Some(room.clone()), cx))?
|
||||
this.update(cx, |this, cx| this.set_room(Some(room.clone()), cx))?
|
||||
.await?;
|
||||
|
||||
anyhow::Ok(room)
|
||||
};
|
||||
|
||||
let room = create_room.await;
|
||||
this.update(&mut cx, |this, _| this.pending_room_creation = None)?;
|
||||
this.update(cx, |this, _| this.pending_room_creation = None)?;
|
||||
room.map_err(Arc::new)
|
||||
})
|
||||
.shared();
|
||||
|
@ -247,10 +247,10 @@ impl ActiveCall {
|
|||
})
|
||||
};
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let result = invite.await;
|
||||
if result.is_ok() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.report_call_event("Participant Invited", cx)
|
||||
})?;
|
||||
} else {
|
||||
|
@ -258,7 +258,7 @@ impl ActiveCall {
|
|||
log::error!("invite failed: {:?}", result);
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.pending_invites.remove(&called_user_id);
|
||||
cx.notify();
|
||||
})?;
|
||||
|
@ -315,11 +315,11 @@ impl ActiveCall {
|
|||
._join_debouncer
|
||||
.spawn(cx, move |cx| Room::join(room_id, client, user_store, cx));
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let room = join.await?;
|
||||
this.update(&mut cx, |this, cx| this.set_room(room.clone(), cx))?
|
||||
this.update(cx, |this, cx| this.set_room(room.clone(), cx))?
|
||||
.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.report_call_event("Incoming Call Accepted", cx)
|
||||
})?;
|
||||
Ok(())
|
||||
|
@ -363,13 +363,11 @@ impl ActiveCall {
|
|||
Room::join_channel(channel_id, client, user_store, cx).await
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let room = join.await?;
|
||||
this.update(&mut cx, |this, cx| this.set_room(room.clone(), cx))?
|
||||
this.update(cx, |this, cx| this.set_room(room.clone(), cx))?
|
||||
.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.report_call_event("Channel Joined", cx)
|
||||
})?;
|
||||
this.update(cx, |this, cx| this.report_call_event("Channel Joined", cx))?;
|
||||
Ok(room)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -128,7 +128,11 @@ impl Room {
|
|||
|
||||
let maintain_connection = cx.spawn({
|
||||
let client = client.clone();
|
||||
move |this, cx| Self::maintain_connection(this, client.clone(), cx).log_err()
|
||||
async move |this, cx| {
|
||||
Self::maintain_connection(this, client.clone(), cx)
|
||||
.log_err()
|
||||
.await
|
||||
}
|
||||
});
|
||||
|
||||
Audio::play_sound(Sound::Joined, cx);
|
||||
|
@ -172,7 +176,7 @@ impl Room {
|
|||
user_store: Entity<UserStore>,
|
||||
cx: &mut App,
|
||||
) -> Task<Result<Entity<Self>>> {
|
||||
cx.spawn(move |mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let response = client.request(proto::CreateRoom {}).await?;
|
||||
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
|
||||
let room = cx.new(|cx| {
|
||||
|
@ -192,7 +196,7 @@ impl Room {
|
|||
|
||||
let initial_project_id = if let Some(initial_project) = initial_project {
|
||||
let initial_project_id = room
|
||||
.update(&mut cx, |room, cx| {
|
||||
.update(cx, |room, cx| {
|
||||
room.share_project(initial_project.clone(), cx)
|
||||
})?
|
||||
.await?;
|
||||
|
@ -202,7 +206,7 @@ impl Room {
|
|||
};
|
||||
|
||||
let did_join = room
|
||||
.update(&mut cx, |room, cx| {
|
||||
.update(cx, |room, cx| {
|
||||
room.leave_when_empty = true;
|
||||
room.call(called_user_id, initial_project_id, cx)
|
||||
})?
|
||||
|
@ -358,7 +362,7 @@ impl Room {
|
|||
async fn maintain_connection(
|
||||
this: WeakEntity<Self>,
|
||||
client: Arc<Client>,
|
||||
mut cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<()> {
|
||||
let mut client_status = client.status();
|
||||
loop {
|
||||
|
@ -370,7 +374,7 @@ impl Room {
|
|||
|
||||
this.upgrade()
|
||||
.ok_or_else(|| anyhow!("room was dropped"))?
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
this.status = RoomStatus::Rejoining;
|
||||
cx.notify();
|
||||
})?;
|
||||
|
@ -386,7 +390,7 @@ impl Room {
|
|||
log::info!("client reconnected, attempting to rejoin room");
|
||||
|
||||
let Some(this) = this.upgrade() else { break };
|
||||
match this.update(&mut cx, |this, cx| this.rejoin(cx)) {
|
||||
match this.update(cx, |this, cx| this.rejoin(cx)) {
|
||||
Ok(task) => {
|
||||
if task.await.log_err().is_some() {
|
||||
return true;
|
||||
|
@ -435,7 +439,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(&mut cx, |this, cx| this.leave(cx))?.await?;
|
||||
this.update(cx, |this, cx| this.leave(cx))?.await?;
|
||||
}
|
||||
Err(anyhow!(
|
||||
"can't reconnect to room: client failed to re-establish connection"
|
||||
|
@ -490,12 +494,12 @@ impl Room {
|
|||
rejoined_projects,
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = response.await?;
|
||||
let message_id = response.message_id;
|
||||
let response = response.payload;
|
||||
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.status = RoomStatus::Online;
|
||||
this.apply_room_update(room_proto, cx)?;
|
||||
|
||||
|
@ -577,7 +581,7 @@ impl Room {
|
|||
let client = self.client.clone();
|
||||
let room_id = self.id;
|
||||
let role = role.into();
|
||||
cx.spawn(|_, _| async move {
|
||||
cx.spawn(async move |_, _| {
|
||||
client
|
||||
.request(proto::SetRoomParticipantRole {
|
||||
room_id,
|
||||
|
@ -709,11 +713,11 @@ impl Room {
|
|||
user_store.get_users(pending_participant_user_ids, cx),
|
||||
)
|
||||
});
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let (remote_participants, pending_participants) =
|
||||
futures::join!(remote_participants, pending_participants);
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.participant_user_ids.clear();
|
||||
|
||||
if let Some(participant) = local_participant {
|
||||
|
@ -1116,7 +1120,7 @@ impl Room {
|
|||
let client = self.client.clone();
|
||||
let room_id = self.id;
|
||||
self.pending_call_count += 1;
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let result = client
|
||||
.request(proto::Call {
|
||||
room_id,
|
||||
|
@ -1124,7 +1128,7 @@ impl Room {
|
|||
initial_project_id,
|
||||
})
|
||||
.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.pending_call_count -= 1;
|
||||
if this.should_leave() {
|
||||
this.leave(cx).detach_and_log_err(cx);
|
||||
|
@ -1145,11 +1149,11 @@ impl Room {
|
|||
let client = self.client.clone();
|
||||
let user_store = self.user_store.clone();
|
||||
cx.emit(Event::RemoteProjectJoined { project_id: id });
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let project =
|
||||
Project::in_room(id, client, user_store, language_registry, fs, cx.clone()).await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.joined_projects.retain(|project| {
|
||||
if let Some(project) = project.upgrade() {
|
||||
!project.read(cx).is_disconnected(cx)
|
||||
|
@ -1178,15 +1182,13 @@ impl Room {
|
|||
is_ssh_project: project.read(cx).is_via_ssh(),
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = request.await?;
|
||||
|
||||
project.update(&mut 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(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.shared_projects.insert(project.downgrade());
|
||||
let active_project = this.local_participant.active_project.as_ref();
|
||||
if active_project.map_or(false, |location| *location == project) {
|
||||
|
@ -1342,7 +1344,7 @@ impl Room {
|
|||
return Task::ready(Err(anyhow!("live-kit was not initialized")));
|
||||
};
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let (track, stream) = capture_local_audio_track(cx.background_executor())?.await;
|
||||
|
||||
let publication = participant
|
||||
|
@ -1355,7 +1357,7 @@ impl Room {
|
|||
)
|
||||
.await
|
||||
.map_err(|error| anyhow!("failed to publish track: {error}"));
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let live_kit = this
|
||||
.live_kit
|
||||
.as_mut()
|
||||
|
@ -1428,7 +1430,7 @@ impl Room {
|
|||
|
||||
let sources = cx.screen_capture_sources();
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let sources = sources.await??;
|
||||
let source = sources.first().ok_or_else(|| anyhow!("no display found"))?;
|
||||
|
||||
|
@ -1446,7 +1448,7 @@ impl Room {
|
|||
.await
|
||||
.map_err(|error| anyhow!("error publishing screen track {error:?}"));
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let live_kit = this
|
||||
.live_kit
|
||||
.as_mut()
|
||||
|
@ -1639,7 +1641,7 @@ fn spawn_room_connection(
|
|||
cx: &mut Context<'_, Room>,
|
||||
) {
|
||||
if let Some(connection_info) = livekit_connection_info {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let (room, mut events) = livekit::Room::connect(
|
||||
&connection_info.server_url,
|
||||
&connection_info.token,
|
||||
|
@ -1647,11 +1649,11 @@ fn spawn_room_connection(
|
|||
)
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let _handle_updates = cx.spawn(|this, mut cx| async move {
|
||||
this.update(cx, |this, cx| {
|
||||
let _handle_updates = cx.spawn(async move |this, cx| {
|
||||
while let Some(event) = events.recv().await {
|
||||
if this
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
this.livekit_room_updated(event, cx).warn_on_err();
|
||||
})
|
||||
.is_err()
|
||||
|
|
|
@ -47,10 +47,10 @@ impl OneAtATime {
|
|||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.cancel.replace(tx);
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
futures::select_biased! {
|
||||
_ = rx.fuse() => Ok(None),
|
||||
result = f(cx).fuse() => result.map(Some),
|
||||
result = f(cx.clone()).fuse() => result.map(Some),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -185,19 +185,19 @@ impl ActiveCall {
|
|||
};
|
||||
|
||||
let invite = if let Some(room) = room {
|
||||
cx.spawn(move |_, mut cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
let room = room.await.map_err(|err| anyhow!("{:?}", err))?;
|
||||
|
||||
let initial_project_id = if let Some(initial_project) = initial_project {
|
||||
Some(
|
||||
room.update(&mut cx, |room, cx| room.share_project(initial_project, cx))?
|
||||
room.update(cx, |room, cx| room.share_project(initial_project, cx))?
|
||||
.await?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
room.update(&mut cx, move |room, cx| {
|
||||
room.update(cx, move |room, cx| {
|
||||
room.call(called_user_id, initial_project_id, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
@ -208,7 +208,7 @@ impl ActiveCall {
|
|||
let client = self.client.clone();
|
||||
let user_store = self.user_store.clone();
|
||||
let room = cx
|
||||
.spawn(move |this, mut cx| async move {
|
||||
.spawn(async move |this, cx| {
|
||||
let create_room = async {
|
||||
let room = cx
|
||||
.update(|cx| {
|
||||
|
@ -222,14 +222,14 @@ impl ActiveCall {
|
|||
})?
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| this.set_room(Some(room.clone()), cx))?
|
||||
this.update(cx, |this, cx| this.set_room(Some(room.clone()), cx))?
|
||||
.await?;
|
||||
|
||||
anyhow::Ok(room)
|
||||
};
|
||||
|
||||
let room = create_room.await;
|
||||
this.update(&mut cx, |this, _| this.pending_room_creation = None)?;
|
||||
this.update(cx, |this, _| this.pending_room_creation = None)?;
|
||||
room.map_err(Arc::new)
|
||||
})
|
||||
.shared();
|
||||
|
@ -240,10 +240,10 @@ impl ActiveCall {
|
|||
})
|
||||
};
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let result = invite.await;
|
||||
if result.is_ok() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.report_call_event("Participant Invited", cx)
|
||||
})?;
|
||||
} else {
|
||||
|
@ -251,7 +251,7 @@ impl ActiveCall {
|
|||
log::error!("invite failed: {:?}", result);
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.pending_invites.remove(&called_user_id);
|
||||
cx.notify();
|
||||
})?;
|
||||
|
@ -304,15 +304,15 @@ impl ActiveCall {
|
|||
let room_id = call.room_id;
|
||||
let client = self.client.clone();
|
||||
let user_store = self.user_store.clone();
|
||||
let join = self
|
||||
._join_debouncer
|
||||
.spawn(cx, move |cx| Room::join(room_id, client, user_store, cx));
|
||||
let join = self._join_debouncer.spawn(cx, move |mut cx| async move {
|
||||
Room::join(room_id, client, user_store, &mut cx).await
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let room = join.await?;
|
||||
this.update(&mut cx, |this, cx| this.set_room(room.clone(), cx))?
|
||||
this.update(cx, |this, cx| this.set_room(room.clone(), cx))?
|
||||
.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.report_call_event("Incoming Call Accepted", cx)
|
||||
})?;
|
||||
Ok(())
|
||||
|
@ -352,17 +352,15 @@ impl ActiveCall {
|
|||
|
||||
let client = self.client.clone();
|
||||
let user_store = self.user_store.clone();
|
||||
let join = self._join_debouncer.spawn(cx, move |cx| async move {
|
||||
Room::join_channel(channel_id, client, user_store, cx).await
|
||||
let join = self._join_debouncer.spawn(cx, move |mut cx| async move {
|
||||
Room::join_channel(channel_id, client, user_store, &mut cx).await
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let room = join.await?;
|
||||
this.update(&mut cx, |this, cx| this.set_room(room.clone(), cx))?
|
||||
this.update(cx, |this, cx| this.set_room(room.clone(), cx))?
|
||||
.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.report_call_event("Channel Joined", cx)
|
||||
})?;
|
||||
this.update(cx, |this, cx| this.report_call_event("Channel Joined", cx))?;
|
||||
Ok(room)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ impl Room {
|
|||
let mut status = room.status();
|
||||
// Consume the initial status of the room.
|
||||
let _ = status.try_recv();
|
||||
let _maintain_room = cx.spawn(|this, mut cx| async move {
|
||||
let _maintain_room = cx.spawn(async move |this, cx| {
|
||||
while let Some(status) = status.next().await {
|
||||
let this = if let Some(this) = this.upgrade() {
|
||||
this
|
||||
|
@ -124,8 +124,7 @@ impl Room {
|
|||
};
|
||||
|
||||
if status == livekit_client_macos::ConnectionState::Disconnected {
|
||||
this.update(&mut cx, |this, cx| this.leave(cx).log_err())
|
||||
.ok();
|
||||
this.update(cx, |this, cx| this.leave(cx).log_err()).ok();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +132,7 @@ impl Room {
|
|||
|
||||
let _handle_updates = cx.spawn({
|
||||
let room = room.clone();
|
||||
move |this, mut cx| async move {
|
||||
async move |this, cx| {
|
||||
let mut updates = room.updates();
|
||||
while let Some(update) = updates.next().await {
|
||||
let this = if let Some(this) = this.upgrade() {
|
||||
|
@ -142,7 +141,7 @@ impl Room {
|
|||
break;
|
||||
};
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.live_kit_room_updated(update, cx).log_err()
|
||||
})
|
||||
.ok();
|
||||
|
@ -151,9 +150,9 @@ impl Room {
|
|||
});
|
||||
|
||||
let connect = room.connect(&connection_info.server_url, &connection_info.token);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
connect.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if this.can_use_microphone() {
|
||||
if let Some(live_kit) = &this.live_kit {
|
||||
if !live_kit.muted_by_user && !live_kit.deafened {
|
||||
|
@ -184,7 +183,11 @@ impl Room {
|
|||
|
||||
let maintain_connection = cx.spawn({
|
||||
let client = client.clone();
|
||||
move |this, cx| Self::maintain_connection(this, client.clone(), cx).log_err()
|
||||
async move |this, cx| {
|
||||
Self::maintain_connection(this, client.clone(), cx)
|
||||
.log_err()
|
||||
.await
|
||||
}
|
||||
});
|
||||
|
||||
Audio::play_sound(Sound::Joined, cx);
|
||||
|
@ -228,7 +231,7 @@ impl Room {
|
|||
user_store: Entity<UserStore>,
|
||||
cx: &mut App,
|
||||
) -> Task<Result<Entity<Self>>> {
|
||||
cx.spawn(move |mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let response = client.request(proto::CreateRoom {}).await?;
|
||||
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
|
||||
let room = cx.new(|cx| {
|
||||
|
@ -248,7 +251,7 @@ impl Room {
|
|||
|
||||
let initial_project_id = if let Some(initial_project) = initial_project {
|
||||
let initial_project_id = room
|
||||
.update(&mut cx, |room, cx| {
|
||||
.update(cx, |room, cx| {
|
||||
room.share_project(initial_project.clone(), cx)
|
||||
})?
|
||||
.await?;
|
||||
|
@ -258,7 +261,7 @@ impl Room {
|
|||
};
|
||||
|
||||
let did_join = room
|
||||
.update(&mut cx, |room, cx| {
|
||||
.update(cx, |room, cx| {
|
||||
room.leave_when_empty = true;
|
||||
room.call(called_user_id, initial_project_id, cx)
|
||||
})?
|
||||
|
@ -274,7 +277,7 @@ impl Room {
|
|||
channel_id: ChannelId,
|
||||
client: Arc<Client>,
|
||||
user_store: Entity<UserStore>,
|
||||
cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<Entity<Self>> {
|
||||
Self::from_join_response(
|
||||
client
|
||||
|
@ -292,7 +295,7 @@ impl Room {
|
|||
room_id: u64,
|
||||
client: Arc<Client>,
|
||||
user_store: Entity<UserStore>,
|
||||
cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<Entity<Self>> {
|
||||
Self::from_join_response(
|
||||
client.request(proto::JoinRoom { id: room_id }).await?,
|
||||
|
@ -333,7 +336,7 @@ impl Room {
|
|||
response: proto::JoinRoomResponse,
|
||||
client: Arc<Client>,
|
||||
user_store: Entity<UserStore>,
|
||||
mut cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<Entity<Self>> {
|
||||
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
|
||||
let room = cx.new(|cx| {
|
||||
|
@ -346,7 +349,7 @@ impl Room {
|
|||
cx,
|
||||
)
|
||||
})?;
|
||||
room.update(&mut cx, |room, cx| {
|
||||
room.update(cx, |room, cx| {
|
||||
room.leave_when_empty = room.channel_id.is_none();
|
||||
room.apply_room_update(room_proto, cx)?;
|
||||
anyhow::Ok(())
|
||||
|
@ -414,7 +417,7 @@ impl Room {
|
|||
async fn maintain_connection(
|
||||
this: WeakEntity<Self>,
|
||||
client: Arc<Client>,
|
||||
mut cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<()> {
|
||||
let mut client_status = client.status();
|
||||
loop {
|
||||
|
@ -426,7 +429,7 @@ impl Room {
|
|||
|
||||
this.upgrade()
|
||||
.ok_or_else(|| anyhow!("room was dropped"))?
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
this.status = RoomStatus::Rejoining;
|
||||
cx.notify();
|
||||
})?;
|
||||
|
@ -442,7 +445,7 @@ impl Room {
|
|||
log::info!("client reconnected, attempting to rejoin room");
|
||||
|
||||
let Some(this) = this.upgrade() else { break };
|
||||
match this.update(&mut cx, |this, cx| this.rejoin(cx)) {
|
||||
match this.update(cx, |this, cx| this.rejoin(cx)) {
|
||||
Ok(task) => {
|
||||
if task.await.log_err().is_some() {
|
||||
return true;
|
||||
|
@ -491,7 +494,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(&mut cx, |this, cx| this.leave(cx))?.await?;
|
||||
this.update(cx, |this, cx| this.leave(cx))?.await?;
|
||||
}
|
||||
Err(anyhow!(
|
||||
"can't reconnect to room: client failed to re-establish connection"
|
||||
|
@ -546,12 +549,12 @@ impl Room {
|
|||
rejoined_projects,
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = response.await?;
|
||||
let message_id = response.message_id;
|
||||
let response = response.payload;
|
||||
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.status = RoomStatus::Online;
|
||||
this.apply_room_update(room_proto, cx)?;
|
||||
|
||||
|
@ -633,7 +636,7 @@ impl Room {
|
|||
let client = self.client.clone();
|
||||
let room_id = self.id;
|
||||
let role = role.into();
|
||||
cx.spawn(|_, _| async move {
|
||||
cx.spawn(async move |_, _| {
|
||||
client
|
||||
.request(proto::SetRoomParticipantRole {
|
||||
room_id,
|
||||
|
@ -736,11 +739,11 @@ impl Room {
|
|||
)
|
||||
});
|
||||
|
||||
self.pending_room_update = Some(cx.spawn(|this, mut cx| async move {
|
||||
self.pending_room_update = Some(cx.spawn(async move |this, cx| {
|
||||
let (remote_participants, pending_participants) =
|
||||
futures::join!(remote_participants, pending_participants);
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.participant_user_ids.clear();
|
||||
|
||||
if let Some(participant) = local_participant {
|
||||
|
@ -1136,7 +1139,7 @@ impl Room {
|
|||
let client = self.client.clone();
|
||||
let room_id = self.id;
|
||||
self.pending_call_count += 1;
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let result = client
|
||||
.request(proto::Call {
|
||||
room_id,
|
||||
|
@ -1144,7 +1147,7 @@ impl Room {
|
|||
initial_project_id,
|
||||
})
|
||||
.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.pending_call_count -= 1;
|
||||
if this.should_leave() {
|
||||
this.leave(cx).detach_and_log_err(cx);
|
||||
|
@ -1165,11 +1168,11 @@ impl Room {
|
|||
let client = self.client.clone();
|
||||
let user_store = self.user_store.clone();
|
||||
cx.emit(Event::RemoteProjectJoined { project_id: id });
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let project =
|
||||
Project::in_room(id, client, user_store, language_registry, fs, cx.clone()).await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.joined_projects.retain(|project| {
|
||||
if let Some(project) = project.upgrade() {
|
||||
!project.read(cx).is_disconnected(cx)
|
||||
|
@ -1198,15 +1201,13 @@ impl Room {
|
|||
is_ssh_project: project.read(cx).is_via_ssh(),
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = request.await?;
|
||||
|
||||
project.update(&mut 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(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.shared_projects.insert(project.downgrade());
|
||||
let active_project = this.local_participant.active_project.as_ref();
|
||||
if active_project.map_or(false, |location| *location == project) {
|
||||
|
@ -1348,12 +1349,12 @@ impl Room {
|
|||
return Task::ready(Err(anyhow!("live-kit was not initialized")));
|
||||
};
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let publish_track = async {
|
||||
let track = LocalAudioTrack::create();
|
||||
this.upgrade()
|
||||
.ok_or_else(|| anyhow!("room was dropped"))?
|
||||
.update(&mut cx, |this, _| {
|
||||
.update(cx, |this, _| {
|
||||
this.live_kit
|
||||
.as_ref()
|
||||
.map(|live_kit| live_kit.room.publish_audio_track(track))
|
||||
|
@ -1364,7 +1365,7 @@ impl Room {
|
|||
let publication = publish_track.await;
|
||||
this.upgrade()
|
||||
.ok_or_else(|| anyhow!("room was dropped"))?
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
let live_kit = this
|
||||
.live_kit
|
||||
.as_mut()
|
||||
|
@ -1424,7 +1425,7 @@ impl Room {
|
|||
return Task::ready(Err(anyhow!("live-kit was not initialized")));
|
||||
};
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let publish_track = async {
|
||||
let displays = displays.await?;
|
||||
let display = displays
|
||||
|
@ -1433,7 +1434,7 @@ impl Room {
|
|||
let track = LocalVideoTrack::screen_share_for_display(display);
|
||||
this.upgrade()
|
||||
.ok_or_else(|| anyhow!("room was dropped"))?
|
||||
.update(&mut cx, |this, _| {
|
||||
.update(cx, |this, _| {
|
||||
this.live_kit
|
||||
.as_ref()
|
||||
.map(|live_kit| live_kit.room.publish_video_track(track))
|
||||
|
@ -1445,7 +1446,7 @@ impl Room {
|
|||
let publication = publish_track.await;
|
||||
this.upgrade()
|
||||
.ok_or_else(|| anyhow!("room was dropped"))?
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
let live_kit = this
|
||||
.live_kit
|
||||
.as_mut()
|
||||
|
|
|
@ -47,7 +47,7 @@ impl ChannelBuffer {
|
|||
client: Arc<Client>,
|
||||
user_store: Entity<UserStore>,
|
||||
channel_store: Entity<ChannelStore>,
|
||||
mut cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<Entity<Self>> {
|
||||
let response = client
|
||||
.request(proto::JoinChannelBuffer {
|
||||
|
@ -66,7 +66,7 @@ impl ChannelBuffer {
|
|||
let capability = channel_store.read(cx).channel_capability(channel.id);
|
||||
language::Buffer::remote(buffer_id, response.replica_id as u16, capability, base_text)
|
||||
})?;
|
||||
buffer.update(&mut 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)?;
|
||||
|
||||
|
@ -208,7 +208,7 @@ impl ChannelBuffer {
|
|||
let client = self.client.clone();
|
||||
let epoch = self.epoch();
|
||||
|
||||
self.acknowledge_task = Some(cx.spawn(move |_, cx| async move {
|
||||
self.acknowledge_task = Some(cx.spawn(async move |_, cx| {
|
||||
cx.background_executor()
|
||||
.timer(ACKNOWLEDGE_DEBOUNCE_INTERVAL)
|
||||
.await;
|
||||
|
|
|
@ -106,7 +106,7 @@ impl ChannelChat {
|
|||
channel_store: Entity<ChannelStore>,
|
||||
user_store: Entity<UserStore>,
|
||||
client: Arc<Client>,
|
||||
mut cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<Entity<Self>> {
|
||||
let channel_id = channel.id;
|
||||
let subscription = client.subscribe_to_entity(channel_id.0).unwrap();
|
||||
|
@ -132,7 +132,7 @@ impl ChannelChat {
|
|||
last_acknowledged_id: None,
|
||||
rng: StdRng::from_entropy(),
|
||||
first_loaded_message_id: None,
|
||||
_subscription: subscription.set_entity(&cx.entity(), &mut cx.to_async()),
|
||||
_subscription: subscription.set_entity(&cx.entity(), &cx.to_async()),
|
||||
}
|
||||
})?;
|
||||
Self::handle_loaded_messages(
|
||||
|
@ -141,7 +141,7 @@ impl ChannelChat {
|
|||
client,
|
||||
response.messages,
|
||||
response.done,
|
||||
&mut cx,
|
||||
cx,
|
||||
)
|
||||
.await?;
|
||||
Ok(handle)
|
||||
|
@ -205,7 +205,7 @@ impl ChannelChat {
|
|||
let outgoing_messages_lock = self.outgoing_messages_lock.clone();
|
||||
|
||||
// todo - handle messages that fail to send (e.g. >1024 chars)
|
||||
Ok(cx.spawn(move |this, mut cx| async move {
|
||||
Ok(cx.spawn(async move |this, cx| {
|
||||
let outgoing_message_guard = outgoing_messages_lock.lock().await;
|
||||
let request = rpc.request(proto::SendChannelMessage {
|
||||
channel_id: channel_id.0,
|
||||
|
@ -218,8 +218,8 @@ impl ChannelChat {
|
|||
drop(outgoing_message_guard);
|
||||
let response = response.message.ok_or_else(|| anyhow!("invalid message"))?;
|
||||
let id = response.id;
|
||||
let message = ChannelMessage::from_proto(response, &user_store, &mut cx).await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let message = ChannelMessage::from_proto(response, &user_store, cx).await?;
|
||||
this.update(cx, |this, cx| {
|
||||
this.insert_messages(SumTree::from_item(message, &()), cx);
|
||||
if this.first_loaded_message_id.is_none() {
|
||||
this.first_loaded_message_id = Some(id);
|
||||
|
@ -234,9 +234,9 @@ impl ChannelChat {
|
|||
channel_id: self.channel_id.0,
|
||||
message_id: id,
|
||||
});
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
response.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.message_removed(id, cx);
|
||||
})?;
|
||||
Ok(())
|
||||
|
@ -266,7 +266,7 @@ impl ChannelChat {
|
|||
nonce: Some(nonce.into()),
|
||||
mentions: mentions_to_proto(&message.mentions),
|
||||
});
|
||||
Ok(cx.spawn(move |_, _| async move {
|
||||
Ok(cx.spawn(async move |_, _| {
|
||||
request.await?;
|
||||
Ok(())
|
||||
}))
|
||||
|
@ -281,7 +281,7 @@ impl ChannelChat {
|
|||
let user_store = self.user_store.clone();
|
||||
let channel_id = self.channel_id;
|
||||
let before_message_id = self.first_loaded_message_id()?;
|
||||
Some(cx.spawn(move |this, mut cx| {
|
||||
Some(cx.spawn(async move |this, cx| {
|
||||
async move {
|
||||
let response = rpc
|
||||
.request(proto::GetChannelMessages {
|
||||
|
@ -295,13 +295,14 @@ impl ChannelChat {
|
|||
rpc,
|
||||
response.messages,
|
||||
response.done,
|
||||
&mut cx,
|
||||
cx,
|
||||
)
|
||||
.await?;
|
||||
|
||||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -439,7 +440,7 @@ impl ChannelChat {
|
|||
let user_store = self.user_store.clone();
|
||||
let rpc = self.rpc.clone();
|
||||
let channel_id = self.channel_id;
|
||||
cx.spawn(move |this, mut cx| {
|
||||
cx.spawn(async move |this, cx| {
|
||||
async move {
|
||||
let response = rpc
|
||||
.request(proto::JoinChannelChat {
|
||||
|
@ -452,11 +453,11 @@ impl ChannelChat {
|
|||
rpc.clone(),
|
||||
response.messages,
|
||||
response.done,
|
||||
&mut cx,
|
||||
cx,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let pending_messages = this.update(&mut cx, |this, _| {
|
||||
let pending_messages = this.update(cx, |this, _| {
|
||||
this.pending_messages().cloned().collect::<Vec<_>>()
|
||||
})?;
|
||||
|
||||
|
@ -472,10 +473,10 @@ impl ChannelChat {
|
|||
let message = ChannelMessage::from_proto(
|
||||
response.message.ok_or_else(|| anyhow!("invalid message"))?,
|
||||
&user_store,
|
||||
&mut cx,
|
||||
cx,
|
||||
)
|
||||
.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.insert_messages(SumTree::from_item(message, &()), cx);
|
||||
})?;
|
||||
}
|
||||
|
@ -483,6 +484,7 @@ impl ChannelChat {
|
|||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
|
|
@ -164,22 +164,22 @@ impl ChannelStore {
|
|||
|
||||
let mut connection_status = client.status();
|
||||
let (update_channels_tx, mut update_channels_rx) = mpsc::unbounded();
|
||||
let watch_connection_status = cx.spawn(|this, mut cx| async move {
|
||||
let watch_connection_status = cx.spawn(async move |this, cx| {
|
||||
while let Some(status) = connection_status.next().await {
|
||||
let this = this.upgrade()?;
|
||||
match status {
|
||||
client::Status::Connected { .. } => {
|
||||
this.update(&mut cx, |this, cx| this.handle_connect(cx))
|
||||
this.update(cx, |this, cx| this.handle_connect(cx))
|
||||
.ok()?
|
||||
.await
|
||||
.log_err()?;
|
||||
}
|
||||
client::Status::SignedOut | client::Status::UpgradeRequired => {
|
||||
this.update(&mut cx, |this, cx| this.handle_disconnect(false, cx))
|
||||
this.update(cx, |this, cx| this.handle_disconnect(false, cx))
|
||||
.ok();
|
||||
}
|
||||
_ => {
|
||||
this.update(&mut cx, |this, cx| this.handle_disconnect(true, cx))
|
||||
this.update(cx, |this, cx| this.handle_disconnect(true, cx))
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
@ -200,13 +200,12 @@ impl ChannelStore {
|
|||
_rpc_subscriptions: rpc_subscriptions,
|
||||
_watch_connection_status: watch_connection_status,
|
||||
disconnect_channel_buffers_task: None,
|
||||
_update_channels: cx.spawn(|this, mut cx| async move {
|
||||
_update_channels: cx.spawn(async move |this, cx| {
|
||||
maybe!(async move {
|
||||
while let Some(update_channels) = update_channels_rx.next().await {
|
||||
if let Some(this) = this.upgrade() {
|
||||
let update_task = this.update(&mut cx, |this, cx| {
|
||||
this.update_channels(update_channels, cx)
|
||||
})?;
|
||||
let update_task = this
|
||||
.update(cx, |this, cx| this.update_channels(update_channels, cx))?;
|
||||
if let Some(update_task) = update_task {
|
||||
update_task.await.log_err();
|
||||
}
|
||||
|
@ -310,7 +309,9 @@ impl ChannelStore {
|
|||
self.open_channel_resource(
|
||||
channel_id,
|
||||
|this| &mut this.opened_buffers,
|
||||
|channel, cx| ChannelBuffer::new(channel, client, user_store, channel_store, cx),
|
||||
async move |channel, cx| {
|
||||
ChannelBuffer::new(channel, client, user_store, channel_store, cx).await
|
||||
},
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
@ -328,14 +329,14 @@ impl ChannelStore {
|
|||
.request(proto::GetChannelMessagesById { message_ids }),
|
||||
)
|
||||
};
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Some(request) = request {
|
||||
let response = request.await?;
|
||||
let this = this
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("channel store dropped"))?;
|
||||
let user_store = this.update(&mut cx, |this, _| this.user_store.clone())?;
|
||||
ChannelMessage::from_proto_vec(response.messages, &user_store, &mut cx).await
|
||||
let user_store = this.update(cx, |this, _| this.user_store.clone())?;
|
||||
ChannelMessage::from_proto_vec(response.messages, &user_store, cx).await
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
@ -440,7 +441,7 @@ impl ChannelStore {
|
|||
self.open_channel_resource(
|
||||
channel_id,
|
||||
|this| &mut this.opened_chats,
|
||||
|channel, cx| ChannelChat::new(channel, this, user_store, client, cx),
|
||||
async move |channel, cx| ChannelChat::new(channel, this, user_store, client, cx).await,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
@ -450,7 +451,7 @@ impl ChannelStore {
|
|||
/// Make sure that the resource is only opened once, even if this method
|
||||
/// is called multiple times with the same channel id while the first task
|
||||
/// is still running.
|
||||
fn open_channel_resource<T, F, Fut>(
|
||||
fn open_channel_resource<T, F>(
|
||||
&mut self,
|
||||
channel_id: ChannelId,
|
||||
get_map: fn(&mut Self) -> &mut HashMap<ChannelId, OpenEntityHandle<T>>,
|
||||
|
@ -458,8 +459,7 @@ impl ChannelStore {
|
|||
cx: &mut Context<Self>,
|
||||
) -> Task<Result<Entity<T>>>
|
||||
where
|
||||
F: 'static + FnOnce(Arc<Channel>, AsyncApp) -> Fut,
|
||||
Fut: Future<Output = Result<Entity<T>>>,
|
||||
F: AsyncFnOnce(Arc<Channel>, &mut AsyncApp) -> Result<Entity<T>> + 'static,
|
||||
T: 'static,
|
||||
{
|
||||
let task = loop {
|
||||
|
@ -479,8 +479,8 @@ impl ChannelStore {
|
|||
},
|
||||
hash_map::Entry::Vacant(e) => {
|
||||
let task = cx
|
||||
.spawn(move |this, mut cx| async move {
|
||||
let channel = this.update(&mut cx, |this, _| {
|
||||
.spawn(async move |this, cx| {
|
||||
let channel = this.update(cx, |this, _| {
|
||||
this.channel_for_id(channel_id).cloned().ok_or_else(|| {
|
||||
Arc::new(anyhow!("no channel for id: {}", channel_id))
|
||||
})
|
||||
|
@ -493,9 +493,9 @@ impl ChannelStore {
|
|||
e.insert(OpenEntityHandle::Loading(task.clone()));
|
||||
cx.spawn({
|
||||
let task = task.clone();
|
||||
move |this, mut cx| async move {
|
||||
async move |this, cx| {
|
||||
let result = task.await;
|
||||
this.update(&mut cx, |this, _| match result {
|
||||
this.update(cx, |this, _| match result {
|
||||
Ok(model) => {
|
||||
get_map(this).insert(
|
||||
channel_id,
|
||||
|
@ -570,7 +570,7 @@ impl ChannelStore {
|
|||
) -> Task<Result<ChannelId>> {
|
||||
let client = self.client.clone();
|
||||
let name = name.trim_start_matches('#').to_owned();
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = client
|
||||
.request(proto::CreateChannel {
|
||||
name,
|
||||
|
@ -583,7 +583,7 @@ impl ChannelStore {
|
|||
.ok_or_else(|| anyhow!("missing channel in response"))?;
|
||||
let channel_id = ChannelId(channel.id);
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let task = this.update_channels(
|
||||
proto::UpdateChannels {
|
||||
channels: vec![channel],
|
||||
|
@ -611,7 +611,7 @@ impl ChannelStore {
|
|||
cx: &mut Context<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
let client = self.client.clone();
|
||||
cx.spawn(move |_, _| async move {
|
||||
cx.spawn(async move |_, _| {
|
||||
let _ = client
|
||||
.request(proto::MoveChannel {
|
||||
channel_id: channel_id.0,
|
||||
|
@ -630,7 +630,7 @@ impl ChannelStore {
|
|||
cx: &mut Context<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
let client = self.client.clone();
|
||||
cx.spawn(move |_, _| async move {
|
||||
cx.spawn(async move |_, _| {
|
||||
let _ = client
|
||||
.request(proto::SetChannelVisibility {
|
||||
channel_id: channel_id.0,
|
||||
|
@ -655,7 +655,7 @@ impl ChannelStore {
|
|||
|
||||
cx.notify();
|
||||
let client = self.client.clone();
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let result = client
|
||||
.request(proto::InviteChannelMember {
|
||||
channel_id: channel_id.0,
|
||||
|
@ -664,7 +664,7 @@ impl ChannelStore {
|
|||
})
|
||||
.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.outgoing_invites.remove(&(channel_id, user_id));
|
||||
cx.notify();
|
||||
})?;
|
||||
|
@ -687,7 +687,7 @@ impl ChannelStore {
|
|||
|
||||
cx.notify();
|
||||
let client = self.client.clone();
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let result = client
|
||||
.request(proto::RemoveChannelMember {
|
||||
channel_id: channel_id.0,
|
||||
|
@ -695,7 +695,7 @@ impl ChannelStore {
|
|||
})
|
||||
.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.outgoing_invites.remove(&(channel_id, user_id));
|
||||
cx.notify();
|
||||
})?;
|
||||
|
@ -717,7 +717,7 @@ impl ChannelStore {
|
|||
|
||||
cx.notify();
|
||||
let client = self.client.clone();
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let result = client
|
||||
.request(proto::SetChannelMemberRole {
|
||||
channel_id: channel_id.0,
|
||||
|
@ -726,7 +726,7 @@ impl ChannelStore {
|
|||
})
|
||||
.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.outgoing_invites.remove(&(channel_id, user_id));
|
||||
cx.notify();
|
||||
})?;
|
||||
|
@ -744,7 +744,7 @@ impl ChannelStore {
|
|||
) -> Task<Result<()>> {
|
||||
let client = self.client.clone();
|
||||
let name = new_name.to_string();
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let channel = client
|
||||
.request(proto::RenameChannel {
|
||||
channel_id: channel_id.0,
|
||||
|
@ -753,7 +753,7 @@ impl ChannelStore {
|
|||
.await?
|
||||
.channel
|
||||
.ok_or_else(|| anyhow!("missing channel in response"))?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let task = this.update_channels(
|
||||
proto::UpdateChannels {
|
||||
channels: vec![channel],
|
||||
|
@ -799,7 +799,7 @@ impl ChannelStore {
|
|||
) -> Task<Result<Vec<ChannelMembership>>> {
|
||||
let client = self.client.clone();
|
||||
let user_store = self.user_store.downgrade();
|
||||
cx.spawn(move |_, mut cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
let response = client
|
||||
.request(proto::GetChannelMembers {
|
||||
channel_id: channel_id.0,
|
||||
|
@ -807,7 +807,7 @@ impl ChannelStore {
|
|||
limit: limit as u64,
|
||||
})
|
||||
.await?;
|
||||
user_store.update(&mut cx, |user_store, _| {
|
||||
user_store.update(cx, |user_store, _| {
|
||||
user_store.insert(response.users);
|
||||
response
|
||||
.members
|
||||
|
@ -931,10 +931,10 @@ impl ChannelStore {
|
|||
buffers: buffer_versions,
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let mut response = response.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.opened_buffers.retain(|_, buffer| match buffer {
|
||||
OpenEntityHandle::Open(channel_buffer) => {
|
||||
let Some(channel_buffer) = channel_buffer.upgrade() else {
|
||||
|
@ -1006,13 +1006,13 @@ impl ChannelStore {
|
|||
cx.notify();
|
||||
self.did_subscribe = false;
|
||||
self.disconnect_channel_buffers_task.get_or_insert_with(|| {
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
if wait_for_reconnect {
|
||||
cx.background_executor().timer(RECONNECT_TIMEOUT).await;
|
||||
}
|
||||
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
for (_, buffer) in this.opened_buffers.drain() {
|
||||
if let OpenEntityHandle::Open(buffer) = buffer {
|
||||
if let Some(buffer) = buffer.upgrade() {
|
||||
|
@ -1136,10 +1136,10 @@ impl ChannelStore {
|
|||
let users = self
|
||||
.user_store
|
||||
.update(cx, |user_store, cx| user_store.get_users(all_user_ids, cx));
|
||||
Some(cx.spawn(|this, mut cx| async move {
|
||||
Some(cx.spawn(async move |this, cx| {
|
||||
let users = users.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
for entry in &channel_participants {
|
||||
let mut participants: Vec<_> = entry
|
||||
.participant_user_ids
|
||||
|
|
|
@ -144,9 +144,9 @@ pub fn init(client: &Arc<Client>, cx: &mut App) {
|
|||
let client = client.clone();
|
||||
move |_: &SignIn, cx| {
|
||||
if let Some(client) = client.upgrade() {
|
||||
cx.spawn(
|
||||
|cx| async move { client.authenticate_and_connect(true, &cx).log_err().await },
|
||||
)
|
||||
cx.spawn(async move |cx| {
|
||||
client.authenticate_and_connect(true, &cx).log_err().await
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ pub fn init(client: &Arc<Client>, cx: &mut App) {
|
|||
let client = client.clone();
|
||||
move |_: &SignOut, cx| {
|
||||
if let Some(client) = client.upgrade() {
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
client.sign_out(&cx).await;
|
||||
})
|
||||
.detach();
|
||||
|
@ -168,7 +168,7 @@ pub fn init(client: &Arc<Client>, cx: &mut App) {
|
|||
let client = client.clone();
|
||||
move |_: &Reconnect, cx| {
|
||||
if let Some(client) = client.upgrade() {
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
client.reconnect(&cx);
|
||||
})
|
||||
.detach();
|
||||
|
@ -640,7 +640,7 @@ impl Client {
|
|||
}
|
||||
Status::ConnectionLost => {
|
||||
let this = self.clone();
|
||||
state._reconnect_task = Some(cx.spawn(move |cx| async move {
|
||||
state._reconnect_task = Some(cx.spawn(async move |cx| {
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
let mut rng = StdRng::seed_from_u64(0);
|
||||
#[cfg(not(any(test, feature = "test-support")))]
|
||||
|
@ -964,13 +964,11 @@ impl Client {
|
|||
|
||||
cx.spawn({
|
||||
let this = self.clone();
|
||||
|cx| {
|
||||
async move {
|
||||
while let Some(message) = incoming.next().await {
|
||||
this.handle_message(message, &cx);
|
||||
// Don't starve the main thread when receiving lots of messages at once.
|
||||
smol::future::yield_now().await;
|
||||
}
|
||||
async move |cx| {
|
||||
while let Some(message) = incoming.next().await {
|
||||
this.handle_message(message, &cx);
|
||||
// Don't starve the main thread when receiving lots of messages at once.
|
||||
smol::future::yield_now().await;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -978,23 +976,21 @@ impl Client {
|
|||
|
||||
cx.spawn({
|
||||
let this = self.clone();
|
||||
move |cx| async move {
|
||||
match handle_io.await {
|
||||
Ok(()) => {
|
||||
if *this.status().borrow()
|
||||
== (Status::Connected {
|
||||
connection_id,
|
||||
peer_id,
|
||||
})
|
||||
{
|
||||
this.set_status(Status::SignedOut, &cx);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("connection error: {:?}", err);
|
||||
this.set_status(Status::ConnectionLost, &cx);
|
||||
async move |cx| match handle_io.await {
|
||||
Ok(()) => {
|
||||
if *this.status().borrow()
|
||||
== (Status::Connected {
|
||||
connection_id,
|
||||
peer_id,
|
||||
})
|
||||
{
|
||||
this.set_status(Status::SignedOut, &cx);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("connection error: {:?}", err);
|
||||
this.set_status(Status::ConnectionLost, &cx);
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
@ -1178,12 +1174,12 @@ impl Client {
|
|||
pub fn authenticate_with_browser(self: &Arc<Self>, cx: &AsyncApp) -> Task<Result<Credentials>> {
|
||||
let http = self.http.clone();
|
||||
let this = self.clone();
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let background = cx.background_executor().clone();
|
||||
|
||||
let (open_url_tx, open_url_rx) = oneshot::channel::<String>();
|
||||
cx.update(|cx| {
|
||||
cx.spawn(move |cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let url = open_url_rx.await?;
|
||||
cx.update(|cx| cx.open_url(&url))
|
||||
})
|
||||
|
@ -1545,25 +1541,23 @@ impl Client {
|
|||
original_sender_id,
|
||||
type_name
|
||||
);
|
||||
cx.spawn(move |_| async move {
|
||||
match future.await {
|
||||
Ok(()) => {
|
||||
log::debug!(
|
||||
"rpc message handled. client_id:{}, sender_id:{:?}, type:{}",
|
||||
client_id,
|
||||
original_sender_id,
|
||||
type_name
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
"error handling message. client_id:{}, sender_id:{:?}, type:{}, error:{:?}",
|
||||
client_id,
|
||||
original_sender_id,
|
||||
type_name,
|
||||
error
|
||||
);
|
||||
}
|
||||
cx.spawn(async move |_| match future.await {
|
||||
Ok(()) => {
|
||||
log::debug!(
|
||||
"rpc message handled. client_id:{}, sender_id:{:?}, type:{}",
|
||||
client_id,
|
||||
original_sender_id,
|
||||
type_name
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
"error handling message. client_id:{}, sender_id:{:?}, type:{}, error:{:?}",
|
||||
client_id,
|
||||
original_sender_id,
|
||||
type_name,
|
||||
error
|
||||
);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
|
|
@ -44,7 +44,7 @@ impl FakeServer {
|
|||
let state = Arc::downgrade(&server.state);
|
||||
move |cx| {
|
||||
let state = state.clone();
|
||||
cx.spawn(move |_| async move {
|
||||
cx.spawn(async move |_| {
|
||||
let state = state.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
|
||||
let mut state = state.lock();
|
||||
state.auth_count += 1;
|
||||
|
@ -63,7 +63,7 @@ impl FakeServer {
|
|||
let peer = peer.clone();
|
||||
let state = state.clone();
|
||||
let credentials = credentials.clone();
|
||||
cx.spawn(move |cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let state = state.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
|
||||
let peer = peer.upgrade().ok_or_else(|| anyhow!("server dropped"))?;
|
||||
if state.lock().forbid_connections {
|
||||
|
|
|
@ -168,11 +168,10 @@ impl UserStore {
|
|||
invite_info: None,
|
||||
client: Arc::downgrade(&client),
|
||||
update_contacts_tx,
|
||||
_maintain_contacts: cx.spawn(|this, mut cx| async move {
|
||||
_maintain_contacts: cx.spawn(async move |this, cx| {
|
||||
let _subscriptions = rpc_subscriptions;
|
||||
while let Some(message) = update_contacts_rx.next().await {
|
||||
if let Ok(task) =
|
||||
this.update(&mut cx, |this, cx| this.update_contacts(message, cx))
|
||||
if let Ok(task) = this.update(cx, |this, cx| this.update_contacts(message, cx))
|
||||
{
|
||||
task.log_err().await;
|
||||
} else {
|
||||
|
@ -180,7 +179,7 @@ impl UserStore {
|
|||
}
|
||||
}
|
||||
}),
|
||||
_maintain_current_user: cx.spawn(|this, mut cx| async move {
|
||||
_maintain_current_user: cx.spawn(async move |this, cx| {
|
||||
let mut status = client.status();
|
||||
let weak = Arc::downgrade(&client);
|
||||
drop(client);
|
||||
|
@ -192,10 +191,9 @@ impl UserStore {
|
|||
match status {
|
||||
Status::Connected { .. } => {
|
||||
if let Some(user_id) = client.user_id() {
|
||||
let fetch_user = if let Ok(fetch_user) = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
this.get_user(user_id, cx).log_err()
|
||||
}) {
|
||||
let fetch_user = if let Ok(fetch_user) =
|
||||
this.update(cx, |this, cx| this.get_user(user_id, cx).log_err())
|
||||
{
|
||||
fetch_user
|
||||
} else {
|
||||
break;
|
||||
|
@ -239,12 +237,12 @@ impl UserStore {
|
|||
|
||||
current_user_tx.send(user).await.ok();
|
||||
|
||||
this.update(&mut cx, |_, cx| cx.notify())?;
|
||||
this.update(cx, |_, cx| cx.notify())?;
|
||||
}
|
||||
}
|
||||
Status::SignedOut => {
|
||||
current_user_tx.send(None).await.ok();
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.accepted_tos_at = None;
|
||||
cx.emit(Event::PrivateUserInfoUpdated);
|
||||
cx.notify();
|
||||
|
@ -253,7 +251,7 @@ impl UserStore {
|
|||
.await;
|
||||
}
|
||||
Status::ConnectionLost => {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
cx.notify();
|
||||
this.clear_contacts()
|
||||
})?
|
||||
|
@ -350,7 +348,7 @@ impl UserStore {
|
|||
user_ids.extend(message.outgoing_requests.iter());
|
||||
|
||||
let load_users = self.get_users(user_ids.into_iter().collect(), cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
load_users.await?;
|
||||
|
||||
// Users are fetched in parallel above and cached in call to get_users
|
||||
|
@ -360,25 +358,22 @@ impl UserStore {
|
|||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("can't upgrade user store handle"))?;
|
||||
for contact in message.contacts {
|
||||
updated_contacts.push(Arc::new(
|
||||
Contact::from_proto(contact, &this, &mut cx).await?,
|
||||
));
|
||||
updated_contacts
|
||||
.push(Arc::new(Contact::from_proto(contact, &this, cx).await?));
|
||||
}
|
||||
|
||||
let mut incoming_requests = Vec::new();
|
||||
for request in message.incoming_requests {
|
||||
incoming_requests.push({
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.get_user(request.requester_id, cx)
|
||||
})?
|
||||
.await?
|
||||
this.update(cx, |this, cx| this.get_user(request.requester_id, cx))?
|
||||
.await?
|
||||
});
|
||||
}
|
||||
|
||||
let mut outgoing_requests = Vec::new();
|
||||
for requested_user_id in message.outgoing_requests {
|
||||
outgoing_requests.push(
|
||||
this.update(&mut cx, |this, cx| this.get_user(requested_user_id, cx))?
|
||||
this.update(cx, |this, cx| this.get_user(requested_user_id, cx))?
|
||||
.await?,
|
||||
);
|
||||
}
|
||||
|
@ -390,7 +385,7 @@ impl UserStore {
|
|||
let removed_outgoing_requests =
|
||||
HashSet::<u64>::from_iter(message.remove_outgoing_requests.iter().copied());
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
// Remove contacts
|
||||
this.contacts
|
||||
.retain(|contact| !removed_contacts.contains(&contact.user.id));
|
||||
|
@ -543,7 +538,7 @@ impl UserStore {
|
|||
cx: &Context<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
let client = self.client.upgrade();
|
||||
cx.spawn(move |_, _| async move {
|
||||
cx.spawn(async move |_, _| {
|
||||
client
|
||||
.ok_or_else(|| anyhow!("can't upgrade client reference"))?
|
||||
.request(proto::RespondToContactRequest {
|
||||
|
@ -565,12 +560,12 @@ impl UserStore {
|
|||
*self.pending_contact_requests.entry(user_id).or_insert(0) += 1;
|
||||
cx.notify();
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let response = client
|
||||
.ok_or_else(|| anyhow!("can't upgrade client reference"))?
|
||||
.request(request)
|
||||
.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if let Entry::Occupied(mut request_count) =
|
||||
this.pending_contact_requests.entry(user_id)
|
||||
{
|
||||
|
@ -614,9 +609,9 @@ impl UserStore {
|
|||
let mut user_ids_to_fetch = user_ids.clone();
|
||||
user_ids_to_fetch.retain(|id| !self.users.contains_key(id));
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
if !user_ids_to_fetch.is_empty() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.load_users(
|
||||
proto::GetUsers {
|
||||
user_ids: user_ids_to_fetch,
|
||||
|
@ -627,7 +622,7 @@ impl UserStore {
|
|||
.await?;
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
user_ids
|
||||
.iter()
|
||||
.map(|user_id| {
|
||||
|
@ -668,9 +663,9 @@ impl UserStore {
|
|||
}
|
||||
|
||||
let load_users = self.get_users(vec![user_id], cx);
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
load_users.await?;
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.users
|
||||
.get(&user_id)
|
||||
.cloned()
|
||||
|
@ -708,14 +703,14 @@ impl UserStore {
|
|||
};
|
||||
|
||||
let client = self.client.clone();
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Some(client) = client.upgrade() {
|
||||
let response = client
|
||||
.request(proto::AcceptTermsOfService {})
|
||||
.await
|
||||
.context("error accepting tos")?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.set_current_user_accepted_tos_at(Some(response.accepted_tos_at));
|
||||
cx.emit(Event::PrivateUserInfoUpdated);
|
||||
})
|
||||
|
@ -737,12 +732,12 @@ impl UserStore {
|
|||
cx: &Context<Self>,
|
||||
) -> Task<Result<Vec<Arc<User>>>> {
|
||||
let client = self.client.clone();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Some(rpc) = client.upgrade() {
|
||||
let response = rpc.request(request).await.context("error loading users")?;
|
||||
let users = response.users;
|
||||
|
||||
this.update(&mut cx, |this, _| this.insert(users))
|
||||
this.update(cx, |this, _| this.insert(users))
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
@ -796,8 +791,8 @@ impl UserStore {
|
|||
}
|
||||
if !missing_user_ids.is_empty() {
|
||||
let this = self.weak_self.clone();
|
||||
cx.spawn(|mut cx| async move {
|
||||
this.update(&mut cx, |this, cx| this.get_users(missing_user_ids, cx))?
|
||||
cx.spawn(async move |cx| {
|
||||
this.update(cx, |this, cx| this.get_users(missing_user_ids, cx))?
|
||||
.await
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
|
|
@ -562,7 +562,7 @@ async fn test_channel_buffers_and_server_restarts(
|
|||
deterministic.run_until_parked();
|
||||
|
||||
// Client C can't reconnect.
|
||||
client_c.override_establish_connection(|_, cx| cx.spawn(|_| future::pending()));
|
||||
client_c.override_establish_connection(|_, cx| cx.spawn(async |_| future::pending().await));
|
||||
|
||||
// Server stops.
|
||||
server.reset().await;
|
||||
|
|
|
@ -983,7 +983,7 @@ async fn test_server_restarts(
|
|||
server.reset().await;
|
||||
|
||||
// Users A and B reconnect to the call. User C has troubles reconnecting, so it leaves the room.
|
||||
client_c.override_establish_connection(|_, cx| cx.spawn(|_| future::pending()));
|
||||
client_c.override_establish_connection(|_, cx| cx.spawn(async |_| future::pending().await));
|
||||
executor.advance_clock(RECONNECT_TIMEOUT);
|
||||
assert_eq!(
|
||||
room_participants(&room_a, cx_a),
|
||||
|
@ -1156,9 +1156,9 @@ async fn test_server_restarts(
|
|||
server.reset().await;
|
||||
|
||||
// Users A and B have troubles reconnecting, so they leave the room.
|
||||
client_a.override_establish_connection(|_, cx| cx.spawn(|_| future::pending()));
|
||||
client_b.override_establish_connection(|_, cx| cx.spawn(|_| future::pending()));
|
||||
client_c.override_establish_connection(|_, cx| cx.spawn(|_| future::pending()));
|
||||
client_a.override_establish_connection(|_, cx| cx.spawn(async |_| future::pending().await));
|
||||
client_b.override_establish_connection(|_, cx| cx.spawn(async |_| future::pending().await));
|
||||
client_c.override_establish_connection(|_, cx| cx.spawn(async |_| future::pending().await));
|
||||
executor.advance_clock(RECONNECT_TIMEOUT);
|
||||
assert_eq!(
|
||||
room_participants(&room_a, cx_a),
|
||||
|
|
|
@ -208,8 +208,8 @@ impl TestServer {
|
|||
.unwrap()
|
||||
.set_id(user_id.to_proto())
|
||||
.override_authenticate(move |cx| {
|
||||
cx.spawn(|_| async move {
|
||||
let access_token = "the-token".to_string();
|
||||
let access_token = "the-token".to_string();
|
||||
cx.spawn(async move |_| {
|
||||
Ok(Credentials {
|
||||
user_id: user_id.to_proto(),
|
||||
access_token,
|
||||
|
@ -230,7 +230,7 @@ impl TestServer {
|
|||
let connection_killers = connection_killers.clone();
|
||||
let forbid_connections = forbid_connections.clone();
|
||||
let client_name = client_name.clone();
|
||||
cx.spawn(move |cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
if forbid_connections.load(SeqCst) {
|
||||
Err(EstablishConnectionError::other(anyhow!(
|
||||
"server is forbidding connections"
|
||||
|
|
|
@ -64,9 +64,9 @@ impl ChannelView {
|
|||
window,
|
||||
cx,
|
||||
);
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let channel_view = channel_view.await?;
|
||||
pane.update_in(&mut cx, |pane, window, cx| {
|
||||
pane.update_in(cx, |pane, window, cx| {
|
||||
telemetry::event!(
|
||||
"Channel Notes Opened",
|
||||
channel_id,
|
||||
|
@ -90,10 +90,10 @@ impl ChannelView {
|
|||
cx: &mut App,
|
||||
) -> Task<Result<Entity<Self>>> {
|
||||
let channel_view = Self::load(channel_id, workspace, window, cx);
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let channel_view = channel_view.await?;
|
||||
|
||||
pane.update_in(&mut cx, |pane, window, cx| {
|
||||
pane.update_in(cx, |pane, window, cx| {
|
||||
let buffer_id = channel_view.read(cx).channel_buffer.read(cx).remote_id(cx);
|
||||
|
||||
let existing_view = pane
|
||||
|
@ -166,11 +166,11 @@ impl ChannelView {
|
|||
let channel_buffer =
|
||||
channel_store.update(cx, |store, cx| store.open_channel_buffer(channel_id, cx));
|
||||
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let channel_buffer = channel_buffer.await?;
|
||||
let markdown = markdown.await.log_err();
|
||||
|
||||
channel_buffer.update(&mut cx, |channel_buffer, cx| {
|
||||
channel_buffer.update(cx, |channel_buffer, cx| {
|
||||
channel_buffer.buffer().update(cx, |buffer, cx| {
|
||||
buffer.set_language_registry(language_registry);
|
||||
let Some(markdown) = markdown else {
|
||||
|
@ -583,10 +583,10 @@ impl FollowableItem for ChannelView {
|
|||
|
||||
let open = ChannelView::load(ChannelId(state.channel_id), workspace, window, cx);
|
||||
|
||||
Some(window.spawn(cx, |mut cx| async move {
|
||||
Some(window.spawn(cx, async move |cx| {
|
||||
let this = open.await?;
|
||||
|
||||
let task = this.update_in(&mut cx, |this, window, cx| {
|
||||
let task = this.update_in(cx, |this, window, cx| {
|
||||
this.remote_id = Some(remote_id);
|
||||
|
||||
if let Some(state) = state.editor {
|
||||
|
|
|
@ -199,7 +199,7 @@ impl ChatPanel {
|
|||
workspace: WeakEntity<Workspace>,
|
||||
cx: AsyncWindowContext,
|
||||
) -> Task<Result<Entity<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let serialized_panel = if let Some(panel) = cx
|
||||
.background_spawn(async move { KEY_VALUE_STORE.read_kvp(CHAT_PANEL_KEY) })
|
||||
.await
|
||||
|
@ -211,7 +211,7 @@ impl ChatPanel {
|
|||
None
|
||||
};
|
||||
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let panel = Self::new(workspace, window, cx);
|
||||
if let Some(serialized_panel) = serialized_panel {
|
||||
panel.update(cx, |panel, cx| {
|
||||
|
@ -867,10 +867,10 @@ impl ChatPanel {
|
|||
})
|
||||
});
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let chat = open_chat.await?;
|
||||
let highlight_message_id = scroll_to_message_id;
|
||||
let scroll_to_message_id = this.update(&mut cx, |this, cx| {
|
||||
let scroll_to_message_id = this.update(cx, |this, cx| {
|
||||
this.set_active_chat(chat.clone(), cx);
|
||||
|
||||
scroll_to_message_id.or(this.last_acknowledged_message_id)
|
||||
|
@ -881,11 +881,11 @@ impl ChatPanel {
|
|||
ChannelChat::load_history_since_message(chat.clone(), message_id, cx.clone())
|
||||
.await
|
||||
{
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(highlight_message_id) = highlight_message_id {
|
||||
let task = cx.spawn(|this, mut cx| async move {
|
||||
let task = cx.spawn(async move |this, cx| {
|
||||
cx.background_executor().timer(Duration::from_secs(2)).await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.highlighted_message.take();
|
||||
cx.notify();
|
||||
})
|
||||
|
|
|
@ -137,11 +137,9 @@ impl MessageEditor {
|
|||
.detach();
|
||||
|
||||
let markdown = language_registry.language_for_name("Markdown");
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
let markdown = markdown.await.context("failed to load Markdown language")?;
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.set_language(Some(markdown), cx)
|
||||
})
|
||||
buffer.update(cx, |buffer, cx| buffer.set_language(Some(markdown), cx))
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
||||
|
@ -232,7 +230,7 @@ impl MessageEditor {
|
|||
) {
|
||||
if let language::BufferEvent::Reparsed | language::BufferEvent::Edited = event {
|
||||
let buffer = buffer.read(cx).snapshot();
|
||||
self.mentions_task = Some(cx.spawn_in(window, |this, cx| async move {
|
||||
self.mentions_task = Some(cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor()
|
||||
.timer(MENTIONS_DEBOUNCE_INTERVAL)
|
||||
.await;
|
||||
|
@ -251,7 +249,7 @@ impl MessageEditor {
|
|||
self.collect_mention_candidates(buffer, end_anchor, cx)
|
||||
{
|
||||
if !candidates.is_empty() {
|
||||
return cx.spawn(|_, cx| async move {
|
||||
return cx.spawn(async move |_, cx| {
|
||||
Ok(Some(
|
||||
Self::resolve_completions_for_candidates(
|
||||
&cx,
|
||||
|
@ -270,7 +268,7 @@ impl MessageEditor {
|
|||
self.collect_emoji_candidates(buffer, end_anchor, cx)
|
||||
{
|
||||
if !candidates.is_empty() {
|
||||
return cx.spawn(|_, cx| async move {
|
||||
return cx.spawn(async move |_, cx| {
|
||||
Ok(Some(
|
||||
Self::resolve_completions_for_candidates(
|
||||
&cx,
|
||||
|
@ -453,7 +451,7 @@ impl MessageEditor {
|
|||
async fn find_mentions(
|
||||
this: WeakEntity<MessageEditor>,
|
||||
buffer: BufferSnapshot,
|
||||
mut cx: AsyncWindowContext,
|
||||
cx: &mut AsyncWindowContext,
|
||||
) {
|
||||
let (buffer, ranges) = cx
|
||||
.background_spawn(async move {
|
||||
|
@ -462,7 +460,7 @@ impl MessageEditor {
|
|||
})
|
||||
.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let mut anchor_ranges = Vec::new();
|
||||
let mut mentioned_user_ids = Vec::new();
|
||||
let mut text = String::new();
|
||||
|
|
|
@ -1569,9 +1569,9 @@ impl CollabPanel {
|
|||
channel_store.create_channel(&channel_name, *location, cx)
|
||||
});
|
||||
if location.is_none() {
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let channel_id = create.await?;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.show_channel_modal(
|
||||
channel_id,
|
||||
channel_modal::Mode::InviteMembers,
|
||||
|
@ -1944,8 +1944,8 @@ impl CollabPanel {
|
|||
let user_store = self.user_store.clone();
|
||||
let channel_store = self.channel_store.clone();
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
workspace.toggle_modal(window, cx, |window, cx| {
|
||||
ChannelModal::new(
|
||||
user_store.clone(),
|
||||
|
@ -1976,11 +1976,11 @@ impl CollabPanel {
|
|||
&["Leave", "Cancel"],
|
||||
cx,
|
||||
);
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if answer.await? != 0 {
|
||||
return Ok(());
|
||||
}
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.channel_store.update(cx, |channel_store, cx| {
|
||||
channel_store.remove_member(channel_id, user_id, cx)
|
||||
})
|
||||
|
@ -2009,13 +2009,13 @@ impl CollabPanel {
|
|||
&["Remove", "Cancel"],
|
||||
cx,
|
||||
);
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if answer.await? == 0 {
|
||||
channel_store
|
||||
.update(&mut cx, |channels, _| channels.remove_channel(channel_id))?
|
||||
.update(cx, |channels, _| channels.remove_channel(channel_id))?
|
||||
.await
|
||||
.notify_async_err(&mut cx);
|
||||
this.update_in(&mut cx, |_, window, cx| cx.focus_self(window))
|
||||
.notify_async_err(cx);
|
||||
this.update_in(cx, |_, window, cx| cx.focus_self(window))
|
||||
.ok();
|
||||
}
|
||||
anyhow::Ok(())
|
||||
|
@ -2043,12 +2043,12 @@ impl CollabPanel {
|
|||
&["Remove", "Cancel"],
|
||||
cx,
|
||||
);
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
if answer.await? == 0 {
|
||||
user_store
|
||||
.update(&mut cx, |store, cx| store.remove_contact(user_id, cx))?
|
||||
.update(cx, |store, cx| store.remove_contact(user_id, cx))?
|
||||
.await
|
||||
.notify_async_err(&mut cx);
|
||||
.notify_async_err(cx);
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
|
@ -2161,11 +2161,11 @@ impl CollabPanel {
|
|||
.full_width()
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
let client = this.client.clone();
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
client
|
||||
.authenticate_and_connect(true, &cx)
|
||||
.await
|
||||
.notify_async_err(&mut cx);
|
||||
.notify_async_err(cx);
|
||||
})
|
||||
.detach()
|
||||
})),
|
||||
|
|
|
@ -300,9 +300,9 @@ impl PickerDelegate for ChannelModalDelegate {
|
|||
cx.background_executor().clone(),
|
||||
));
|
||||
|
||||
cx.spawn_in(window, |picker, mut cx| async move {
|
||||
cx.spawn_in(window, async move |picker, cx| {
|
||||
picker
|
||||
.update(&mut cx, |picker, cx| {
|
||||
.update(cx, |picker, cx| {
|
||||
let delegate = &mut picker.delegate;
|
||||
delegate.matching_member_indices.clear();
|
||||
delegate
|
||||
|
@ -316,10 +316,10 @@ impl PickerDelegate for ChannelModalDelegate {
|
|||
let search_members = self.channel_store.update(cx, |store, cx| {
|
||||
store.fuzzy_search_members(self.channel_id, query.clone(), 100, cx)
|
||||
});
|
||||
cx.spawn_in(window, |picker, mut cx| async move {
|
||||
cx.spawn_in(window, async move |picker, cx| {
|
||||
async {
|
||||
let members = search_members.await?;
|
||||
picker.update(&mut cx, |picker, cx| {
|
||||
picker.update(cx, |picker, cx| {
|
||||
picker.delegate.has_all_members =
|
||||
query.is_empty() && members.len() < 100;
|
||||
picker.delegate.matching_member_indices =
|
||||
|
@ -338,10 +338,10 @@ impl PickerDelegate for ChannelModalDelegate {
|
|||
let search_users = self
|
||||
.user_store
|
||||
.update(cx, |store, cx| store.fuzzy_search_users(query, cx));
|
||||
cx.spawn_in(window, |picker, mut cx| async move {
|
||||
cx.spawn_in(window, async move |picker, cx| {
|
||||
async {
|
||||
let users = search_users.await?;
|
||||
picker.update(&mut cx, |picker, cx| {
|
||||
picker.update(cx, |picker, cx| {
|
||||
picker.delegate.matching_users = users;
|
||||
cx.notify();
|
||||
})?;
|
||||
|
@ -489,9 +489,9 @@ impl ChannelModalDelegate {
|
|||
let update = self.channel_store.update(cx, |store, cx| {
|
||||
store.set_member_role(self.channel_id, user_id, new_role, cx)
|
||||
});
|
||||
cx.spawn_in(window, |picker, mut cx| async move {
|
||||
cx.spawn_in(window, async move |picker, cx| {
|
||||
update.await?;
|
||||
picker.update_in(&mut cx, |picker, window, cx| {
|
||||
picker.update_in(cx, |picker, window, cx| {
|
||||
let this = &mut picker.delegate;
|
||||
if let Some(member) = this.members.iter_mut().find(|m| m.user.id == user_id) {
|
||||
member.role = new_role;
|
||||
|
@ -513,9 +513,9 @@ impl ChannelModalDelegate {
|
|||
let update = self.channel_store.update(cx, |store, cx| {
|
||||
store.remove_member(self.channel_id, user_id, cx)
|
||||
});
|
||||
cx.spawn_in(window, |picker, mut cx| async move {
|
||||
cx.spawn_in(window, async move |picker, cx| {
|
||||
update.await?;
|
||||
picker.update_in(&mut cx, |picker, window, cx| {
|
||||
picker.update_in(cx, |picker, window, cx| {
|
||||
let this = &mut picker.delegate;
|
||||
if let Some(ix) = this.members.iter_mut().position(|m| m.user.id == user_id) {
|
||||
this.members.remove(ix);
|
||||
|
@ -551,10 +551,10 @@ impl ChannelModalDelegate {
|
|||
store.invite_member(self.channel_id, user.id, ChannelRole::Member, cx)
|
||||
});
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
invite_member.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let new_member = ChannelMembership {
|
||||
user,
|
||||
kind: proto::channel_member::Kind::Invitee,
|
||||
|
|
|
@ -102,10 +102,10 @@ impl PickerDelegate for ContactFinderDelegate {
|
|||
.user_store
|
||||
.update(cx, |store, cx| store.fuzzy_search_users(query, cx));
|
||||
|
||||
cx.spawn_in(window, |picker, mut cx| async move {
|
||||
cx.spawn_in(window, async move |picker, cx| {
|
||||
async {
|
||||
let potential_contacts = search_users.await?;
|
||||
picker.update(&mut cx, |picker, cx| {
|
||||
picker.update(cx, |picker, cx| {
|
||||
picker.delegate.potential_contacts = potential_contacts.into();
|
||||
cx.notify();
|
||||
})?;
|
||||
|
|
|
@ -96,10 +96,10 @@ impl NotificationPanel {
|
|||
|
||||
cx.new(|cx| {
|
||||
let mut status = client.status();
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
while (status.next().await).is_some() {
|
||||
if this
|
||||
.update(&mut cx, |_: &mut Self, cx| {
|
||||
.update(cx, |_: &mut Self, cx| {
|
||||
cx.notify();
|
||||
})
|
||||
.is_err()
|
||||
|
@ -181,7 +181,7 @@ impl NotificationPanel {
|
|||
workspace: WeakEntity<Workspace>,
|
||||
cx: AsyncWindowContext,
|
||||
) -> Task<Result<Entity<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let serialized_panel = if let Some(panel) = cx
|
||||
.background_spawn(async move { KEY_VALUE_STORE.read_kvp(NOTIFICATION_PANEL_KEY) })
|
||||
.await
|
||||
|
@ -193,7 +193,7 @@ impl NotificationPanel {
|
|||
None
|
||||
};
|
||||
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let panel = Self::new(workspace, window, cx);
|
||||
if let Some(serialized_panel) = serialized_panel {
|
||||
panel.update(cx, |panel, cx| {
|
||||
|
@ -445,12 +445,12 @@ impl NotificationPanel {
|
|||
.entry(notification_id)
|
||||
.or_insert_with(|| {
|
||||
let client = self.client.clone();
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor().timer(MARK_AS_READ_DELAY).await;
|
||||
client
|
||||
.request(proto::MarkNotificationRead { notification_id })
|
||||
.await?;
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.mark_as_read_tasks.remove(¬ification_id);
|
||||
})?;
|
||||
Ok(())
|
||||
|
@ -556,9 +556,9 @@ impl NotificationPanel {
|
|||
let notification_id = entry.id;
|
||||
self.current_notification_toast = Some((
|
||||
notification_id,
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor().timer(TOAST_DURATION).await;
|
||||
this.update(&mut cx, |this, cx| this.remove_toast(notification_id, cx))
|
||||
this.update(cx, |this, cx| this.remove_toast(notification_id, cx))
|
||||
.ok();
|
||||
}),
|
||||
));
|
||||
|
@ -643,7 +643,7 @@ impl Render for NotificationPanel {
|
|||
move |_, window, cx| {
|
||||
let client = client.clone();
|
||||
window
|
||||
.spawn(cx, move |cx| async move {
|
||||
.spawn(cx, async move |cx| {
|
||||
client
|
||||
.authenticate_and_connect(true, &cx)
|
||||
.log_err()
|
||||
|
|
|
@ -12,12 +12,12 @@ use workspace::AppState;
|
|||
pub fn init(app_state: &Arc<AppState>, cx: &mut App) {
|
||||
let app_state = Arc::downgrade(app_state);
|
||||
let mut incoming_call = ActiveCall::global(cx).read(cx).incoming();
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let mut notification_windows: Vec<WindowHandle<IncomingCallNotification>> = Vec::new();
|
||||
while let Some(incoming_call) = incoming_call.next().await {
|
||||
for window in notification_windows.drain(..) {
|
||||
window
|
||||
.update(&mut cx, |_, window, _| {
|
||||
.update(cx, |_, window, _| {
|
||||
window.remove_window();
|
||||
})
|
||||
.log_err();
|
||||
|
@ -75,7 +75,7 @@ impl IncomingCallNotificationState {
|
|||
let initial_project_id = self.call.initial_project.as_ref().map(|project| project.id);
|
||||
let app_state = self.app_state.clone();
|
||||
let cx: &mut App = cx;
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
join.await?;
|
||||
if let Some(project_id) = initial_project_id {
|
||||
cx.update(|cx| {
|
||||
|
|
|
@ -327,13 +327,13 @@ impl PickerDelegate for CommandPaletteDelegate {
|
|||
});
|
||||
self.updating_matches = Some((task, rx.clone()));
|
||||
|
||||
cx.spawn_in(window, move |picker, mut cx| async move {
|
||||
cx.spawn_in(window, async move |picker, cx| {
|
||||
let Some((commands, matches)) = rx.recv().await else {
|
||||
return;
|
||||
};
|
||||
|
||||
picker
|
||||
.update(&mut cx, |picker, cx| {
|
||||
.update(cx, |picker, cx| {
|
||||
picker
|
||||
.delegate
|
||||
.matches_updated(query, commands, matches, cx)
|
||||
|
|
|
@ -560,7 +560,7 @@ impl SerializableItem for ComponentPreview {
|
|||
let user_store = project.read(cx).user_store().clone();
|
||||
let language_registry = project.read(cx).languages().clone();
|
||||
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let user_store = user_store.clone();
|
||||
let language_registry = language_registry.clone();
|
||||
let weak_workspace = workspace.clone();
|
||||
|
|
|
@ -171,13 +171,17 @@ impl Client {
|
|||
let notification_handlers = notification_handlers.clone();
|
||||
let response_handlers = response_handlers.clone();
|
||||
let transport = transport.clone();
|
||||
move |cx| {
|
||||
async move |cx| {
|
||||
Self::handle_input(transport, notification_handlers, response_handlers, cx)
|
||||
.log_err()
|
||||
.await
|
||||
}
|
||||
});
|
||||
let stderr_input_task = cx.spawn(|_| Self::handle_stderr(transport.clone()).log_err());
|
||||
let input_task = cx.spawn(|_| async move {
|
||||
let stderr_input_task = cx.spawn({
|
||||
let transport = transport.clone();
|
||||
async move |_| Self::handle_stderr(transport).log_err().await
|
||||
});
|
||||
let input_task = cx.spawn(async move |_| {
|
||||
let (stdout, stderr) = futures::join!(stdout_input_task, stderr_input_task);
|
||||
stdout.or(stderr)
|
||||
});
|
||||
|
@ -217,7 +221,7 @@ impl Client {
|
|||
transport: Arc<dyn Transport>,
|
||||
notification_handlers: Arc<Mutex<HashMap<&'static str, NotificationHandler>>>,
|
||||
response_handlers: Arc<Mutex<Option<HashMap<RequestId, ResponseHandler>>>>,
|
||||
cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut receiver = transport.receive();
|
||||
|
||||
|
|
|
@ -41,16 +41,15 @@ impl ExtensionContextServerProxy for ContextServerFactoryRegistryProxy {
|
|||
|
||||
let id = id.clone();
|
||||
let extension = extension.clone();
|
||||
cx.spawn(|mut cx| async move {
|
||||
let extension_project =
|
||||
project.update(&mut cx, |project, cx| {
|
||||
Arc::new(ExtensionProject {
|
||||
worktree_ids: project
|
||||
.visible_worktrees(cx)
|
||||
.map(|worktree| worktree.read(cx).id().to_proto())
|
||||
.collect(),
|
||||
})
|
||||
})?;
|
||||
cx.spawn(async move |cx| {
|
||||
let extension_project = project.update(cx, |project, cx| {
|
||||
Arc::new(ExtensionProject {
|
||||
worktree_ids: project
|
||||
.visible_worktrees(cx)
|
||||
.map(|worktree| worktree.read(cx).id().to_proto())
|
||||
.collect(),
|
||||
})
|
||||
})?;
|
||||
|
||||
let command = extension
|
||||
.context_server_command(id.clone(), extension_project)
|
||||
|
|
|
@ -147,14 +147,14 @@ impl ContextServerManager {
|
|||
if self.update_servers_task.is_some() {
|
||||
self.needs_server_update = true;
|
||||
} else {
|
||||
self.update_servers_task = Some(cx.spawn(|this, mut cx| async move {
|
||||
this.update(&mut cx, |this, _| {
|
||||
self.update_servers_task = Some(cx.spawn(async move |this, cx| {
|
||||
this.update(cx, |this, _| {
|
||||
this.needs_server_update = false;
|
||||
})?;
|
||||
|
||||
Self::maintain_servers(this.clone(), cx.clone()).await?;
|
||||
Self::maintain_servers(this.clone(), cx).await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let has_any_context_servers = !this.servers().is_empty();
|
||||
if has_any_context_servers {
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
|
@ -186,13 +186,13 @@ impl ContextServerManager {
|
|||
cx: &mut Context<Self>,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
let id = id.clone();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
if let Some(server) = this.update(&mut cx, |this, _cx| this.servers.remove(&id))? {
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Some(server) = this.update(cx, |this, _cx| this.servers.remove(&id))? {
|
||||
server.stop()?;
|
||||
let config = server.config();
|
||||
let new_server = Arc::new(ContextServer::new(id.clone(), config));
|
||||
new_server.clone().start(&cx).await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.servers.insert(id.clone(), new_server);
|
||||
cx.emit(Event::ServerStopped {
|
||||
server_id: id.clone(),
|
||||
|
@ -214,10 +214,10 @@ impl ContextServerManager {
|
|||
.collect()
|
||||
}
|
||||
|
||||
async fn maintain_servers(this: WeakEntity<Self>, mut cx: AsyncApp) -> Result<()> {
|
||||
async fn maintain_servers(this: WeakEntity<Self>, cx: &mut AsyncApp) -> Result<()> {
|
||||
let mut desired_servers = HashMap::default();
|
||||
|
||||
let (registry, project) = this.update(&mut cx, |this, cx| {
|
||||
let (registry, project) = this.update(cx, |this, cx| {
|
||||
let location = this.project.read(cx).worktrees(cx).next().map(|worktree| {
|
||||
settings::SettingsLocation {
|
||||
worktree_id: worktree.read(cx).id(),
|
||||
|
@ -231,7 +231,7 @@ impl ContextServerManager {
|
|||
})?;
|
||||
|
||||
for (id, factory) in
|
||||
registry.read_with(&cx, |registry, _| registry.context_server_factories())?
|
||||
registry.read_with(cx, |registry, _| registry.context_server_factories())?
|
||||
{
|
||||
let config = desired_servers.entry(id).or_default();
|
||||
if config.command.is_none() {
|
||||
|
@ -244,7 +244,7 @@ impl ContextServerManager {
|
|||
let mut servers_to_start = HashMap::default();
|
||||
let mut servers_to_stop = HashMap::default();
|
||||
|
||||
this.update(&mut cx, |this, _cx| {
|
||||
this.update(cx, |this, _cx| {
|
||||
this.servers.retain(|id, server| {
|
||||
if desired_servers.contains_key(id) {
|
||||
true
|
||||
|
@ -270,16 +270,12 @@ impl ContextServerManager {
|
|||
|
||||
for (id, server) in servers_to_stop {
|
||||
server.stop().log_err();
|
||||
this.update(&mut cx, |_, cx| {
|
||||
cx.emit(Event::ServerStopped { server_id: id })
|
||||
})?;
|
||||
this.update(cx, |_, cx| cx.emit(Event::ServerStopped { server_id: id }))?;
|
||||
}
|
||||
|
||||
for (id, server) in servers_to_start {
|
||||
if server.start(&cx).await.log_err().is_some() {
|
||||
this.update(&mut cx, |_, cx| {
|
||||
cx.emit(Event::ServerStarted { server_id: id })
|
||||
})?;
|
||||
this.update(cx, |_, cx| cx.emit(Event::ServerStarted { server_id: id }))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,13 +47,13 @@ impl StdioTransport {
|
|||
let (stdout_sender, stdout_receiver) = channel::unbounded::<String>();
|
||||
let (stderr_sender, stderr_receiver) = channel::unbounded::<String>();
|
||||
|
||||
cx.spawn(|_| Self::handle_output(stdin, stdout_receiver).log_err())
|
||||
cx.spawn(async move |_| Self::handle_output(stdin, stdout_receiver).log_err().await)
|
||||
.detach();
|
||||
|
||||
cx.spawn(|_| async move { Self::handle_input(stdout, stdin_sender).await })
|
||||
cx.spawn(async move |_| Self::handle_input(stdout, stdin_sender).await)
|
||||
.detach();
|
||||
|
||||
cx.spawn(|_| async move { Self::handle_err(stderr, stderr_sender).await })
|
||||
cx.spawn(async move |_| Self::handle_err(stderr, stderr_sender).await)
|
||||
.detach();
|
||||
|
||||
Ok(Self {
|
||||
|
|
|
@ -226,17 +226,17 @@ impl RegisteredBuffer {
|
|||
let id = buffer.entity_id();
|
||||
let prev_pending_change =
|
||||
mem::replace(&mut self.pending_buffer_change, Task::ready(None));
|
||||
self.pending_buffer_change = cx.spawn(move |copilot, mut cx| async move {
|
||||
self.pending_buffer_change = cx.spawn(async move |copilot, cx| {
|
||||
prev_pending_change.await;
|
||||
|
||||
let old_version = copilot
|
||||
.update(&mut cx, |copilot, _| {
|
||||
.update(cx, |copilot, _| {
|
||||
let server = copilot.server.as_authenticated().log_err()?;
|
||||
let buffer = server.registered_buffers.get_mut(&id)?;
|
||||
Some(buffer.snapshot.version.clone())
|
||||
})
|
||||
.ok()??;
|
||||
let new_snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot()).ok()?;
|
||||
let new_snapshot = buffer.update(cx, |buffer, _| buffer.snapshot()).ok()?;
|
||||
|
||||
let content_changes = cx
|
||||
.background_spawn({
|
||||
|
@ -265,7 +265,7 @@ impl RegisteredBuffer {
|
|||
.await;
|
||||
|
||||
copilot
|
||||
.update(&mut cx, |copilot, _| {
|
||||
.update(cx, |copilot, _| {
|
||||
let server = copilot.server.as_authenticated().log_err()?;
|
||||
let buffer = server.registered_buffers.get_mut(&id)?;
|
||||
if !content_changes.is_empty() {
|
||||
|
@ -388,7 +388,7 @@ impl Copilot {
|
|||
let node_runtime = self.node_runtime.clone();
|
||||
let env = self.build_env(&language_settings.edit_predictions.copilot);
|
||||
let start_task = cx
|
||||
.spawn(move |this, cx| {
|
||||
.spawn(async move |this, cx| {
|
||||
Self::start_language_server(
|
||||
server_id,
|
||||
http,
|
||||
|
@ -398,6 +398,7 @@ impl Copilot {
|
|||
awaiting_sign_in_after_start,
|
||||
cx,
|
||||
)
|
||||
.await
|
||||
})
|
||||
.shared();
|
||||
self.server = CopilotServer::Starting { task: start_task };
|
||||
|
@ -442,7 +443,7 @@ impl Copilot {
|
|||
},
|
||||
"copilot".into(),
|
||||
Default::default(),
|
||||
cx.to_async(),
|
||||
&mut cx.to_async(),
|
||||
);
|
||||
let http = http_client::FakeHttpClient::create(|_| async { unreachable!() });
|
||||
let node_runtime = NodeRuntime::unavailable();
|
||||
|
@ -468,7 +469,7 @@ impl Copilot {
|
|||
env: Option<HashMap<String, String>>,
|
||||
this: WeakEntity<Self>,
|
||||
awaiting_sign_in_after_start: bool,
|
||||
mut cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) {
|
||||
let start_language_server = async {
|
||||
let server_path = get_copilot_lsp(http).await?;
|
||||
|
@ -495,7 +496,7 @@ impl Copilot {
|
|||
root_path,
|
||||
None,
|
||||
Default::default(),
|
||||
cx.clone(),
|
||||
cx,
|
||||
)?;
|
||||
|
||||
server
|
||||
|
@ -535,7 +536,7 @@ impl Copilot {
|
|||
};
|
||||
|
||||
let server = start_language_server.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
cx.notify();
|
||||
match server {
|
||||
Ok((server, status)) => {
|
||||
|
@ -569,7 +570,7 @@ impl Copilot {
|
|||
SignInStatus::SignedOut { .. } | SignInStatus::Unauthorized { .. } => {
|
||||
let lsp = server.lsp.clone();
|
||||
let task = cx
|
||||
.spawn(|this, mut cx| async move {
|
||||
.spawn(async move |this, cx| {
|
||||
let sign_in = async {
|
||||
let sign_in = lsp
|
||||
.request::<request::SignInInitiate>(
|
||||
|
@ -581,7 +582,7 @@ impl Copilot {
|
|||
Ok(request::SignInStatus::Ok { user: Some(user) })
|
||||
}
|
||||
request::SignInInitiateResult::PromptUserDeviceFlow(flow) => {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if let CopilotServer::Running(RunningCopilotServer {
|
||||
sign_in_status: status,
|
||||
..
|
||||
|
@ -610,7 +611,7 @@ impl Copilot {
|
|||
};
|
||||
|
||||
let sign_in = sign_in.await;
|
||||
this.update(&mut cx, |this, cx| match sign_in {
|
||||
this.update(cx, |this, cx| match sign_in {
|
||||
Ok(status) => {
|
||||
this.update_sign_in_status(status, cx);
|
||||
Ok(())
|
||||
|
@ -670,7 +671,7 @@ impl Copilot {
|
|||
let http = self.http.clone();
|
||||
let node_runtime = self.node_runtime.clone();
|
||||
let server_id = self.server_id;
|
||||
move |this, cx| async move {
|
||||
async move |this, cx| {
|
||||
clear_copilot_dir().await;
|
||||
Self::start_language_server(server_id, http, node_runtime, env, this, false, cx)
|
||||
.await
|
||||
|
|
|
@ -241,7 +241,7 @@ impl CopilotChat {
|
|||
let config_paths: HashSet<PathBuf> = copilot_chat_config_paths().into_iter().collect();
|
||||
let dir_path = copilot_chat_config_dir();
|
||||
|
||||
cx.spawn(|cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let mut parent_watch_rx = watch_config_dir(
|
||||
cx.background_executor(),
|
||||
fs.clone(),
|
||||
|
|
|
@ -83,7 +83,7 @@ impl EditPredictionProvider for CopilotCompletionProvider {
|
|||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let copilot = self.copilot.clone();
|
||||
self.pending_refresh = Some(cx.spawn(|this, mut cx| async move {
|
||||
self.pending_refresh = Some(cx.spawn(async move |this, cx| {
|
||||
if debounce {
|
||||
cx.background_executor()
|
||||
.timer(COPILOT_DEBOUNCE_TIMEOUT)
|
||||
|
@ -91,12 +91,12 @@ impl EditPredictionProvider for CopilotCompletionProvider {
|
|||
}
|
||||
|
||||
let completions = copilot
|
||||
.update(&mut cx, |copilot, cx| {
|
||||
.update(cx, |copilot, cx| {
|
||||
copilot.completions(&buffer, cursor_position, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if !completions.is_empty() {
|
||||
this.cycled = false;
|
||||
this.pending_refresh = None;
|
||||
|
@ -153,14 +153,14 @@ impl EditPredictionProvider for CopilotCompletionProvider {
|
|||
cx.notify();
|
||||
} else {
|
||||
let copilot = self.copilot.clone();
|
||||
self.pending_cycling_refresh = Some(cx.spawn(|this, mut cx| async move {
|
||||
self.pending_cycling_refresh = Some(cx.spawn(async move |this, cx| {
|
||||
let completions = copilot
|
||||
.update(&mut cx, |copilot, cx| {
|
||||
.update(cx, |copilot, cx| {
|
||||
copilot.completions_cycling(&buffer, cursor_position, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.cycled = true;
|
||||
this.file_extension = buffer.read(cx).file().and_then(|file| {
|
||||
Some(
|
||||
|
|
|
@ -37,11 +37,11 @@ pub fn initiate_sign_in(window: &mut Window, cx: &mut App) {
|
|||
});
|
||||
|
||||
let workspace = workspace.downgrade();
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
task.await;
|
||||
if let Some(copilot) = cx.update(|cx| Copilot::global(cx)).ok().flatten() {
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| match copilot.read(cx).status() {
|
||||
.update(cx, |workspace, cx| match copilot.read(cx).status() {
|
||||
Status::Authorized => workspace.show_toast(
|
||||
Toast::new(
|
||||
NotificationId::unique::<CopilotStartingToast>(),
|
||||
|
|
|
@ -583,7 +583,7 @@ impl TcpTransport {
|
|||
_ = cx.background_executor().timer(Duration::from_millis(timeout)).fuse() => {
|
||||
return Err(anyhow!(format!("Connection to TCP DAP timeout {}:{}", host, port)))
|
||||
},
|
||||
result = cx.spawn(|cx| async move {
|
||||
result = cx.spawn(async move |cx| {
|
||||
loop {
|
||||
match TcpStream::connect(address).await {
|
||||
Ok(stream) => return stream.split(),
|
||||
|
|
|
@ -103,10 +103,10 @@ impl DebugAdapterState {
|
|||
impl LogStore {
|
||||
fn new(cx: &Context<Self>) -> Self {
|
||||
let (rpc_tx, mut rpc_rx) = unbounded::<(SessionId, IoKind, String)>();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
while let Some((client_id, io_kind, message)) = rpc_rx.next().await {
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.on_rpc_log(client_id, io_kind, &message, cx);
|
||||
})?;
|
||||
}
|
||||
|
@ -118,10 +118,10 @@ impl LogStore {
|
|||
.detach_and_log_err(cx);
|
||||
|
||||
let (adapter_log_tx, mut adapter_log_rx) = unbounded::<(SessionId, IoKind, String)>();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
while let Some((client_id, io_kind, message)) = adapter_log_rx.next().await {
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.on_adapter_log(client_id, io_kind, &message, cx);
|
||||
})?;
|
||||
}
|
||||
|
@ -604,9 +604,9 @@ impl DapLogView {
|
|||
.update(cx, |_, cx| {
|
||||
cx.spawn({
|
||||
let buffer = cx.entity();
|
||||
|_, mut cx| async move {
|
||||
async move |_, cx| {
|
||||
let language = language.await.ok();
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.set_language(language, cx);
|
||||
})
|
||||
}
|
||||
|
|
|
@ -114,9 +114,9 @@ impl PickerDelegate for AttachModalDelegate {
|
|||
_window: &mut Window,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
) -> gpui::Task<()> {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
let Some(processes) = this
|
||||
.update(&mut cx, |this, _| {
|
||||
.update(cx, |this, _| {
|
||||
if let Some(processes) = this.delegate.candidates.clone() {
|
||||
processes
|
||||
} else {
|
||||
|
@ -172,7 +172,7 @@ impl PickerDelegate for AttachModalDelegate {
|
|||
)
|
||||
.await;
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
let delegate = &mut this.delegate;
|
||||
|
||||
delegate.matches = matches;
|
||||
|
|
|
@ -150,8 +150,8 @@ impl DebugPanel {
|
|||
workspace: WeakEntity<Workspace>,
|
||||
cx: AsyncWindowContext,
|
||||
) -> Task<Result<Entity<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
cx.spawn(async move |cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let debug_panel = DebugPanel::new(workspace, window, cx);
|
||||
|
||||
cx.observe(&debug_panel, |_, debug_panel, cx| {
|
||||
|
@ -349,11 +349,11 @@ impl DebugPanel {
|
|||
cx,
|
||||
);
|
||||
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
let pid_task = async move {
|
||||
let terminal = terminal_task.await?;
|
||||
|
||||
terminal.read_with(&mut cx, |terminal, _| terminal.pty_info.pid())
|
||||
terminal.read_with(cx, |terminal, _| terminal.pty_info.pid())
|
||||
};
|
||||
|
||||
pid_task.await
|
||||
|
|
|
@ -213,8 +213,8 @@ impl Render for Console {
|
|||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let session = self.session.clone();
|
||||
let token = self.last_token;
|
||||
self.update_output_task = cx.spawn_in(window, move |this, mut cx| async move {
|
||||
_ = session.update_in(&mut cx, move |session, window, cx| {
|
||||
self.update_output_task = cx.spawn_in(window, async move |this, cx| {
|
||||
_ = session.update_in(cx, move |session, window, cx| {
|
||||
let (output, last_processed_token) = session.output(token);
|
||||
|
||||
_ = this.update(cx, |this, cx| {
|
||||
|
@ -342,7 +342,7 @@ impl ConsoleQueryBarCompletionProvider {
|
|||
|
||||
let query = buffer.read(cx).text();
|
||||
|
||||
cx.spawn(|_, cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
let matches = fuzzy::match_strings(
|
||||
&string_matches,
|
||||
&query,
|
||||
|
|
|
@ -60,9 +60,9 @@ impl ModuleList {
|
|||
}
|
||||
|
||||
fn open_module(&mut self, path: Arc<Path>, window: &mut Window, cx: &mut Context<Self>) {
|
||||
cx.spawn_in(window, move |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let (worktree, relative_path) = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
this.workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().update(cx, |this, cx| {
|
||||
this.find_or_create_worktree(&path, false, cx)
|
||||
|
@ -72,7 +72,7 @@ impl ModuleList {
|
|||
.await?;
|
||||
|
||||
let buffer = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
this.workspace.update(cx, |this, cx| {
|
||||
this.project().update(cx, |this, cx| {
|
||||
let worktree_id = worktree.read(cx).id();
|
||||
|
@ -88,7 +88,7 @@ impl ModuleList {
|
|||
})??
|
||||
.await?;
|
||||
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.workspace.update(cx, |workspace, cx| {
|
||||
let project_path = buffer.read(cx).project_path(cx).ok_or_else(|| {
|
||||
anyhow!("Could not select a stack frame for unnamed buffer")
|
||||
|
|
|
@ -235,9 +235,9 @@ impl StackFrameList {
|
|||
return Task::ready(Err(anyhow!("Project path not found")));
|
||||
};
|
||||
|
||||
cx.spawn_in(window, move |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let (worktree, relative_path) = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
this.workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().update(cx, |this, cx| {
|
||||
this.find_or_create_worktree(&abs_path, false, cx)
|
||||
|
@ -246,7 +246,7 @@ impl StackFrameList {
|
|||
})??
|
||||
.await?;
|
||||
let buffer = this
|
||||
.update(&mut cx, |this, cx| {
|
||||
.update(cx, |this, cx| {
|
||||
this.workspace.update(cx, |this, cx| {
|
||||
this.project().update(cx, |this, cx| {
|
||||
let worktree_id = worktree.read(cx).id();
|
||||
|
@ -261,10 +261,10 @@ impl StackFrameList {
|
|||
})
|
||||
})??
|
||||
.await?;
|
||||
let position = buffer.update(&mut cx, |this, _| {
|
||||
let position = buffer.update(cx, |this, _| {
|
||||
this.snapshot().anchor_after(PointUtf16::new(row, 0))
|
||||
})?;
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.workspace.update(cx, |workspace, cx| {
|
||||
let project_path = buffer.read(cx).project_path(cx).ok_or_else(|| {
|
||||
anyhow!("Could not select a stack frame for unnamed buffer")
|
||||
|
@ -282,7 +282,7 @@ impl StackFrameList {
|
|||
})???
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.workspace.update(cx, |workspace, cx| {
|
||||
let breakpoint_store = workspace.project().read(cx).breakpoint_store();
|
||||
|
||||
|
|
|
@ -29,10 +29,10 @@ impl StartingState {
|
|||
task: Task<Result<Entity<Session>>>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let _notify_parent = cx.spawn(move |this, mut cx| async move {
|
||||
let _notify_parent = cx.spawn(async move |this, cx| {
|
||||
let entity = task.await;
|
||||
|
||||
this.update(&mut cx, |_, cx| {
|
||||
this.update(cx, |_, cx| {
|
||||
if let Ok(entity) = entity {
|
||||
cx.emit(StartingEvent::Finished(entity))
|
||||
} else {
|
||||
|
|
|
@ -40,13 +40,21 @@ pub async fn init_test_workspace(
|
|||
cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||
|
||||
let debugger_panel = workspace_handle
|
||||
.update(cx, |_, window, cx| cx.spawn_in(window, DebugPanel::load))
|
||||
.update(cx, |_, window, cx| {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
DebugPanel::load(this, cx.clone()).await
|
||||
})
|
||||
})
|
||||
.unwrap()
|
||||
.await
|
||||
.expect("Failed to load debug panel");
|
||||
|
||||
let terminal_panel = workspace_handle
|
||||
.update(cx, |_, window, cx| cx.spawn_in(window, TerminalPanel::load))
|
||||
.update(cx, |_, window, cx| {
|
||||
cx.spawn_in(window, async |this, cx| {
|
||||
TerminalPanel::load(this, cx.clone()).await
|
||||
})
|
||||
})
|
||||
.unwrap()
|
||||
.await
|
||||
.expect("Failed to load terminal panel");
|
||||
|
|
|
@ -251,12 +251,12 @@ impl ProjectDiagnosticsEditor {
|
|||
return;
|
||||
}
|
||||
let project_handle = self.project.clone();
|
||||
self.update_excerpts_task = Some(cx.spawn_in(window, |this, mut cx| async move {
|
||||
self.update_excerpts_task = Some(cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor()
|
||||
.timer(DIAGNOSTICS_UPDATE_DEBOUNCE)
|
||||
.await;
|
||||
loop {
|
||||
let Some((path, language_server_id)) = this.update(&mut cx, |this, _| {
|
||||
let Some((path, language_server_id)) = this.update(cx, |this, _| {
|
||||
let Some((path, language_server_id)) = this.paths_to_update.pop_first() else {
|
||||
this.update_excerpts_task.take();
|
||||
return None;
|
||||
|
@ -268,11 +268,11 @@ impl ProjectDiagnosticsEditor {
|
|||
};
|
||||
|
||||
if let Some(buffer) = project_handle
|
||||
.update(&mut cx, |project, cx| project.open_buffer(path.clone(), cx))?
|
||||
.update(cx, |project, cx| project.open_buffer(path.clone(), cx))?
|
||||
.await
|
||||
.log_err()
|
||||
{
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.update_excerpts(path, language_server_id, buffer, window, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
@ -419,9 +419,9 @@ impl ProjectDiagnosticsEditor {
|
|||
let excerpts = self.excerpts.clone().downgrade();
|
||||
let context = self.context;
|
||||
let editor = self.editor.clone().downgrade();
|
||||
cx.spawn_in(window, move |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let mut old_groups = this
|
||||
.update(&mut cx, |this, _| {
|
||||
.update(cx, |this, _| {
|
||||
mem::take(&mut this.path_states[path_ix].diagnostic_groups)
|
||||
})?
|
||||
.into_iter()
|
||||
|
@ -491,7 +491,7 @@ impl ProjectDiagnosticsEditor {
|
|||
entry.range.clone(),
|
||||
context,
|
||||
snapshot.clone(),
|
||||
(*cx).clone(),
|
||||
(**cx).clone(),
|
||||
)
|
||||
.await,
|
||||
)
|
||||
|
@ -507,7 +507,7 @@ impl ProjectDiagnosticsEditor {
|
|||
}
|
||||
}
|
||||
|
||||
let excerpt_id = excerpts.update(&mut cx, |excerpts, cx| {
|
||||
let excerpt_id = excerpts.update(cx, |excerpts, cx| {
|
||||
excerpts
|
||||
.insert_excerpts_after(
|
||||
prev_excerpt_id,
|
||||
|
@ -575,14 +575,14 @@ impl ProjectDiagnosticsEditor {
|
|||
}
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
new_group_ixs.push(this.path_states[path_ix].diagnostic_groups.len());
|
||||
this.path_states[path_ix]
|
||||
.diagnostic_groups
|
||||
.push(group_state);
|
||||
})?;
|
||||
} else if let Some((_, group_state)) = to_remove {
|
||||
excerpts.update(&mut cx, |excerpts, cx| {
|
||||
excerpts.update(cx, |excerpts, cx| {
|
||||
excerpts.remove_excerpts(group_state.excerpts.iter().copied(), cx)
|
||||
})?;
|
||||
blocks_to_remove.extend(group_state.blocks.iter().copied());
|
||||
|
@ -590,7 +590,7 @@ impl ProjectDiagnosticsEditor {
|
|||
prev_excerpt_id = *group_state.excerpts.last().unwrap();
|
||||
first_excerpt_id.get_or_insert(prev_excerpt_id);
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.path_states[path_ix]
|
||||
.diagnostic_groups
|
||||
.push(group_state)
|
||||
|
@ -598,9 +598,8 @@ impl ProjectDiagnosticsEditor {
|
|||
}
|
||||
}
|
||||
|
||||
let excerpts_snapshot =
|
||||
excerpts.update(&mut cx, |excerpts, cx| excerpts.snapshot(cx))?;
|
||||
editor.update(&mut cx, |editor, cx| {
|
||||
let excerpts_snapshot = excerpts.update(cx, |excerpts, cx| excerpts.snapshot(cx))?;
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.remove_blocks(blocks_to_remove, None, cx);
|
||||
let block_ids = editor.insert_blocks(
|
||||
blocks_to_add.into_iter().flat_map(|block| {
|
||||
|
@ -644,7 +643,7 @@ impl ProjectDiagnosticsEditor {
|
|||
Result::<(), anyhow::Error>::Ok(())
|
||||
})??;
|
||||
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
if this.path_states[path_ix].diagnostic_groups.is_empty() {
|
||||
this.path_states.remove(path_ix);
|
||||
}
|
||||
|
@ -709,7 +708,7 @@ impl ProjectDiagnosticsEditor {
|
|||
});
|
||||
})?;
|
||||
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
if this.path_states.is_empty() {
|
||||
if this.editor.focus_handle(cx).is_focused(window) {
|
||||
window.focus(&this.focus_handle);
|
||||
|
@ -1053,7 +1052,7 @@ fn context_range_for_entry(
|
|||
snapshot: BufferSnapshot,
|
||||
cx: AsyncApp,
|
||||
) -> Task<Range<Point>> {
|
||||
cx.spawn(move |cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
if let Some(rows) = heuristic_syntactic_expand(
|
||||
range.clone(),
|
||||
DIAGNOSTIC_EXPANSION_ROW_LIMIT,
|
||||
|
@ -1083,7 +1082,7 @@ async fn heuristic_syntactic_expand(
|
|||
input_range: Range<Point>,
|
||||
max_row_count: u32,
|
||||
snapshot: BufferSnapshot,
|
||||
cx: AsyncApp,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Option<RangeInclusive<BufferRow>> {
|
||||
let input_row_count = input_range.end.row - input_range.start.row;
|
||||
if input_row_count > max_row_count {
|
||||
|
|
|
@ -163,12 +163,12 @@ impl DiagnosticIndicator {
|
|||
.map(|entry| entry.diagnostic);
|
||||
if new_diagnostic != self.current_diagnostic {
|
||||
self.diagnostics_update =
|
||||
cx.spawn_in(window, |diagnostics_indicator, mut cx| async move {
|
||||
cx.spawn_in(window, async move |diagnostics_indicator, cx| {
|
||||
cx.background_executor()
|
||||
.timer(Duration::from_millis(50))
|
||||
.await;
|
||||
diagnostics_indicator
|
||||
.update(&mut cx, |diagnostics_indicator, cx| {
|
||||
.update(cx, |diagnostics_indicator, cx| {
|
||||
diagnostics_indicator.current_diagnostic = new_diagnostic;
|
||||
cx.notify();
|
||||
})
|
||||
|
|
|
@ -40,9 +40,9 @@ impl BlinkManager {
|
|||
|
||||
let epoch = self.next_blink_epoch();
|
||||
let interval = self.blink_interval;
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
Timer::after(interval).await;
|
||||
this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
|
||||
this.update(cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
@ -62,10 +62,10 @@ impl BlinkManager {
|
|||
|
||||
let epoch = self.next_blink_epoch();
|
||||
let interval = self.blink_interval;
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
Timer::after(interval).await;
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx))
|
||||
this.update(cx, |this, cx| this.blink_cursors(epoch, cx))
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
|
|
|
@ -51,7 +51,7 @@ pub fn switch_source_header(
|
|||
cx,
|
||||
)
|
||||
});
|
||||
cx.spawn_in(window, |_editor, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_editor, cx| {
|
||||
let switch_source_header = switch_source_header_task
|
||||
.await
|
||||
.with_context(|| format!("Switch source/header LSP request for path \"{source_file}\" failed"))?;
|
||||
|
@ -72,7 +72,7 @@ pub fn switch_source_header(
|
|||
})?;
|
||||
|
||||
workspace
|
||||
.update_in(&mut cx, |workspace, window, cx| {
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
workspace.open_abs_path(path, OpenOptions { visible: Some(OpenVisible::None), ..Default::default() }, window, cx)
|
||||
})
|
||||
.with_context(|| {
|
||||
|
|
|
@ -416,9 +416,9 @@ impl CompletionsMenu {
|
|||
cx,
|
||||
);
|
||||
|
||||
cx.spawn(move |editor, mut cx| async move {
|
||||
cx.spawn(async move |editor, cx| {
|
||||
if let Some(true) = resolve_task.await.log_err() {
|
||||
editor.update(&mut cx, |_, cx| cx.notify()).ok();
|
||||
editor.update(cx, |_, cx| cx.notify()).ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
|
|
@ -198,9 +198,9 @@ impl WrapMap {
|
|||
self.edits_since_sync = self.edits_since_sync.compose(&edits);
|
||||
}
|
||||
Err(wrap_task) => {
|
||||
self.background_task = Some(cx.spawn(|this, mut cx| async move {
|
||||
self.background_task = Some(cx.spawn(async move |this, cx| {
|
||||
let (snapshot, edits) = wrap_task.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.snapshot = snapshot;
|
||||
this.edits_since_sync = this
|
||||
.edits_since_sync
|
||||
|
@ -276,9 +276,9 @@ impl WrapMap {
|
|||
self.edits_since_sync = self.edits_since_sync.compose(&output_edits);
|
||||
}
|
||||
Err(update_task) => {
|
||||
self.background_task = Some(cx.spawn(|this, mut cx| async move {
|
||||
self.background_task = Some(cx.spawn(async move |this, cx| {
|
||||
let (snapshot, edits) = update_task.await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.snapshot = snapshot;
|
||||
this.edits_since_sync = this
|
||||
.edits_since_sync
|
||||
|
|
|
@ -185,7 +185,7 @@ use ui::{
|
|||
h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,
|
||||
Tooltip,
|
||||
};
|
||||
use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
|
||||
use util::{maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
item::{ItemHandle, PreviewTabsSettings},
|
||||
ItemId, RestoreOnStartupBehavior,
|
||||
|
@ -1715,9 +1715,9 @@ impl Editor {
|
|||
let project = workspace.project().clone();
|
||||
let create = project.update(cx, |project, cx| project.create_buffer(cx));
|
||||
|
||||
cx.spawn_in(window, |workspace, mut cx| async move {
|
||||
cx.spawn_in(window, async move |workspace, cx| {
|
||||
let buffer = create.await?;
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let editor =
|
||||
cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
|
||||
workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
|
||||
|
@ -1753,9 +1753,9 @@ impl Editor {
|
|||
let project = workspace.project().clone();
|
||||
let create = project.update(cx, |project, cx| project.create_buffer(cx));
|
||||
|
||||
cx.spawn_in(window, |workspace, mut cx| async move {
|
||||
cx.spawn_in(window, async move |workspace, cx| {
|
||||
let buffer = create.await?;
|
||||
workspace.update_in(&mut cx, move |workspace, window, cx| {
|
||||
workspace.update_in(cx, move |workspace, window, cx| {
|
||||
workspace.split_item(
|
||||
direction,
|
||||
Box::new(
|
||||
|
@ -2184,12 +2184,12 @@ impl Editor {
|
|||
drop(context_menu);
|
||||
|
||||
let query = Self::completion_query(buffer, cursor_position);
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
completion_menu
|
||||
.filter(query.as_deref(), cx.background_executor().clone())
|
||||
.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let mut context_menu = this.context_menu.borrow_mut();
|
||||
let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
|
||||
else {
|
||||
|
@ -4050,16 +4050,16 @@ impl Editor {
|
|||
cx,
|
||||
)
|
||||
});
|
||||
Some(cx.spawn_in(window, |editor, mut cx| async move {
|
||||
Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
if let Some(transaction) = on_type_formatting.await? {
|
||||
if push_to_client_history {
|
||||
buffer
|
||||
.update(&mut cx, |buffer, _| {
|
||||
.update(cx, |buffer, _| {
|
||||
buffer.push_transaction(transaction, Instant::now());
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
editor.update(&mut cx, |editor, cx| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.refresh_document_highlights(cx);
|
||||
})?;
|
||||
}
|
||||
|
@ -4215,9 +4215,9 @@ impl Editor {
|
|||
.map_or(true, |provider| provider.sort_completions());
|
||||
|
||||
let id = post_inc(&mut self.next_completion_id);
|
||||
let task = cx.spawn_in(window, |editor, mut cx| {
|
||||
let task = cx.spawn_in(window, async move |editor, cx| {
|
||||
async move {
|
||||
editor.update(&mut cx, |this, _| {
|
||||
editor.update(cx, |this, _| {
|
||||
this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
|
||||
})?;
|
||||
|
||||
|
@ -4267,7 +4267,7 @@ impl Editor {
|
|||
menu.visible().then_some(menu)
|
||||
};
|
||||
|
||||
editor.update_in(&mut cx, |editor, window, cx| {
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
match editor.context_menu.borrow().as_ref() {
|
||||
None => {}
|
||||
Some(CodeContextMenu::Completions(prev_menu)) => {
|
||||
|
@ -4308,6 +4308,7 @@ impl Editor {
|
|||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
});
|
||||
|
||||
self.completion_tasks.push((id, task));
|
||||
|
@ -4550,13 +4551,13 @@ impl Editor {
|
|||
let deployed_from_indicator = action.deployed_from_indicator;
|
||||
let mut task = self.code_actions_task.take();
|
||||
let action = action.clone();
|
||||
cx.spawn_in(window, |editor, mut cx| async move {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
while let Some(prev_task) = task {
|
||||
prev_task.await.log_err();
|
||||
task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
|
||||
task = editor.update(cx, |this, _| this.code_actions_task.take())?;
|
||||
}
|
||||
|
||||
let spawned_test_task = editor.update_in(&mut cx, |editor, window, cx| {
|
||||
let spawned_test_task = editor.update_in(cx, |editor, window, cx| {
|
||||
if editor.focus_handle.is_focused(window) {
|
||||
let multibuffer_point = action
|
||||
.deployed_from_indicator
|
||||
|
@ -4605,7 +4606,7 @@ impl Editor {
|
|||
Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
|
||||
});
|
||||
|
||||
Some(cx.spawn_in(window, |editor, mut cx| async move {
|
||||
Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
let task_context = match task_context {
|
||||
Some(task_context) => task_context.await,
|
||||
None => None,
|
||||
|
@ -4626,7 +4627,7 @@ impl Editor {
|
|||
&& code_actions
|
||||
.as_ref()
|
||||
.map_or(true, |actions| actions.is_empty());
|
||||
if let Ok(task) = editor.update_in(&mut cx, |editor, window, cx| {
|
||||
if let Ok(task) = editor.update_in(cx, |editor, window, cx| {
|
||||
*editor.context_menu.borrow_mut() =
|
||||
Some(CodeContextMenu::CodeActions(CodeActionsMenu {
|
||||
buffer,
|
||||
|
@ -4709,7 +4710,7 @@ impl Editor {
|
|||
let apply_code_action =
|
||||
provider.apply_code_action(buffer, action, excerpt_id, true, window, cx);
|
||||
let workspace = workspace.downgrade();
|
||||
Some(cx.spawn_in(window, |editor, cx| async move {
|
||||
Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
let project_transaction = apply_code_action.await?;
|
||||
Self::open_project_transaction(
|
||||
&editor,
|
||||
|
@ -4729,7 +4730,7 @@ impl Editor {
|
|||
workspace: WeakEntity<Workspace>,
|
||||
transaction: ProjectTransaction,
|
||||
title: String,
|
||||
mut cx: AsyncWindowContext,
|
||||
cx: &mut AsyncWindowContext,
|
||||
) -> Result<()> {
|
||||
let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
|
||||
cx.update(|_, cx| {
|
||||
|
@ -4743,7 +4744,7 @@ impl Editor {
|
|||
|
||||
if let Some((buffer, transaction)) = entries.first() {
|
||||
if entries.len() == 1 {
|
||||
let excerpt = this.update(&mut cx, |editor, cx| {
|
||||
let excerpt = this.update(cx, |editor, cx| {
|
||||
editor
|
||||
.buffer()
|
||||
.read(cx)
|
||||
|
@ -4751,7 +4752,7 @@ impl Editor {
|
|||
})?;
|
||||
if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
|
||||
if excerpted_buffer == *buffer {
|
||||
let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
|
||||
let all_edits_within_excerpt = buffer.read_with(cx, |buffer, _| {
|
||||
let excerpt_range = excerpt_range.to_offset(buffer);
|
||||
buffer
|
||||
.edited_ranges_for_transaction::<usize>(transaction)
|
||||
|
@ -4791,7 +4792,7 @@ impl Editor {
|
|||
multibuffer
|
||||
})?;
|
||||
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let project = workspace.project().clone();
|
||||
let editor =
|
||||
cx.new(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), window, cx));
|
||||
|
@ -4854,12 +4855,12 @@ impl Editor {
|
|||
return None;
|
||||
}
|
||||
|
||||
self.code_actions_task = Some(cx.spawn_in(window, |this, mut cx| async move {
|
||||
self.code_actions_task = Some(cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor()
|
||||
.timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
|
||||
.await;
|
||||
|
||||
let (providers, tasks) = this.update_in(&mut cx, |this, window, cx| {
|
||||
let (providers, tasks) = this.update_in(cx, |this, window, cx| {
|
||||
let providers = this.code_action_providers.clone();
|
||||
let tasks = this
|
||||
.code_action_providers
|
||||
|
@ -4884,7 +4885,7 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.available_code_actions = if actions.is_empty() {
|
||||
None
|
||||
} else {
|
||||
|
@ -4907,10 +4908,10 @@ impl Editor {
|
|||
self.show_git_blame_inline = false;
|
||||
|
||||
self.show_git_blame_inline_delay_task =
|
||||
Some(cx.spawn_in(window, |this, mut cx| async move {
|
||||
Some(cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor().timer(delay).await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.show_git_blame_inline = true;
|
||||
cx.notify();
|
||||
})
|
||||
|
@ -4935,7 +4936,7 @@ impl Editor {
|
|||
return None;
|
||||
}
|
||||
let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
|
||||
self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
|
||||
self.document_highlights_task = Some(cx.spawn(async move |this, cx| {
|
||||
cx.background_executor()
|
||||
.timer(Duration::from_millis(debounce))
|
||||
.await;
|
||||
|
@ -4953,7 +4954,7 @@ impl Editor {
|
|||
};
|
||||
|
||||
if let Some(highlights) = highlights {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
if this.pending_rename.is_some() {
|
||||
return;
|
||||
}
|
||||
|
@ -5046,12 +5047,12 @@ impl Editor {
|
|||
return;
|
||||
}
|
||||
let debounce = EditorSettings::get_global(cx).selection_highlight_debounce;
|
||||
self.selection_highlight_task = Some(cx.spawn_in(window, |editor, mut cx| async move {
|
||||
self.selection_highlight_task = Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
cx.background_executor()
|
||||
.timer(Duration::from_millis(debounce))
|
||||
.await;
|
||||
let Some(Some(matches_task)) = editor
|
||||
.update_in(&mut cx, |editor, _, cx| {
|
||||
.update_in(cx, |editor, _, cx| {
|
||||
if editor.selections.count() != 1 || editor.selections.line_mode {
|
||||
editor.clear_background_highlights::<SelectedTextHighlight>(cx);
|
||||
return None;
|
||||
|
@ -5116,7 +5117,7 @@ impl Editor {
|
|||
};
|
||||
let matches = matches_task.await;
|
||||
editor
|
||||
.update_in(&mut cx, |editor, _, cx| {
|
||||
.update_in(cx, |editor, _, cx| {
|
||||
editor.clear_background_highlights::<SelectedTextHighlight>(cx);
|
||||
if !matches.is_empty() {
|
||||
editor.highlight_background::<SelectedTextHighlight>(
|
||||
|
@ -5342,9 +5343,9 @@ impl Editor {
|
|||
fn show_cursor_names(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.show_cursor_names = true;
|
||||
cx.notify();
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.show_cursor_names = false;
|
||||
cx.notify()
|
||||
})
|
||||
|
@ -6230,7 +6231,7 @@ impl Editor {
|
|||
|
||||
let reveal_strategy = action.reveal;
|
||||
let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
let context = task_context.await?;
|
||||
let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
|
||||
|
||||
|
@ -6238,7 +6239,7 @@ impl Editor {
|
|||
resolved.reveal = reveal_strategy;
|
||||
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
.update(cx, |workspace, cx| {
|
||||
workspace::tasks::schedule_resolved_task(
|
||||
workspace,
|
||||
task_source_kind,
|
||||
|
@ -11806,19 +11807,19 @@ impl Editor {
|
|||
return Task::ready(());
|
||||
}
|
||||
let project = self.project.as_ref().map(Entity::downgrade);
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor().timer(UPDATE_DEBOUNCE).await;
|
||||
let Some(project) = project.and_then(|p| p.upgrade()) else {
|
||||
return;
|
||||
};
|
||||
let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
|
||||
let Ok(display_snapshot) = this.update(cx, |this, cx| {
|
||||
this.display_map.update(cx, |map, cx| map.snapshot(cx))
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let hide_runnables = project
|
||||
.update(&mut cx, |project, cx| {
|
||||
.update(cx, |project, cx| {
|
||||
// Do not display any test indicators in non-dev server remote projects.
|
||||
project.is_via_collab() && project.ssh_connection_string(cx).is_none()
|
||||
})
|
||||
|
@ -11836,7 +11837,7 @@ impl Editor {
|
|||
.await;
|
||||
|
||||
let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.clear_tasks();
|
||||
for (key, value) in rows {
|
||||
this.insert_tasks(key, value);
|
||||
|
@ -12425,11 +12426,11 @@ impl Editor {
|
|||
) -> Task<Result<Navigated>> {
|
||||
let definition =
|
||||
self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
|
||||
cx.spawn_in(window, |editor, mut cx| async move {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
if definition.await? == Navigated::Yes {
|
||||
return Ok(Navigated::Yes);
|
||||
}
|
||||
match editor.update_in(&mut cx, |editor, window, cx| {
|
||||
match editor.update_in(cx, |editor, window, cx| {
|
||||
editor.find_all_references(&FindAllReferences, window, cx)
|
||||
})? {
|
||||
Some(references) => references.await,
|
||||
|
@ -12523,10 +12524,10 @@ impl Editor {
|
|||
return Task::ready(Ok(Navigated::No));
|
||||
};
|
||||
|
||||
cx.spawn_in(window, |editor, mut cx| async move {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
let definitions = definitions.await?;
|
||||
let navigated = editor
|
||||
.update_in(&mut cx, |editor, window, cx| {
|
||||
.update_in(cx, |editor, window, cx| {
|
||||
editor.navigate_to_hover_links(
|
||||
Some(kind),
|
||||
definitions
|
||||
|
@ -12566,7 +12567,7 @@ impl Editor {
|
|||
None
|
||||
};
|
||||
|
||||
let url_finder = cx.spawn_in(window, |editor, mut cx| async move {
|
||||
let url_finder = cx.spawn_in(window, async move |editor, cx| {
|
||||
let url = if let Some(end_pos) = end_position {
|
||||
find_url_from_range(&buffer, start_position..end_pos, cx.clone())
|
||||
} else {
|
||||
|
@ -12574,7 +12575,7 @@ impl Editor {
|
|||
};
|
||||
|
||||
if let Some(url) = url {
|
||||
editor.update(&mut cx, |_, cx| {
|
||||
editor.update(cx, |_, cx| {
|
||||
cx.open_url(&url);
|
||||
})
|
||||
} else {
|
||||
|
@ -12605,12 +12606,12 @@ impl Editor {
|
|||
|
||||
let project = self.project.clone();
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
let result = find_file(&buffer, project, buffer_position, &mut cx).await;
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
let result = find_file(&buffer, project, buffer_position, cx).await;
|
||||
|
||||
if let Some((_, path)) = result {
|
||||
workspace
|
||||
.update_in(&mut cx, |workspace, window, cx| {
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
workspace.open_resolved_path(path, window, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
@ -12655,9 +12656,9 @@ impl Editor {
|
|||
}
|
||||
HoverLink::File(path) => {
|
||||
if let Some(workspace) = self.workspace() {
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
workspace
|
||||
.update_in(&mut cx, |workspace, window, cx| {
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
workspace.open_resolved_path(path, window, cx)
|
||||
})?
|
||||
.await
|
||||
|
@ -12668,14 +12669,14 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
};
|
||||
cx.spawn_in(window, |editor, mut cx| async move {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
let target = match target_task.await.context("target resolution task")? {
|
||||
TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
|
||||
TargetTaskResult::Location(None) => return Ok(Navigated::No),
|
||||
TargetTaskResult::Location(Some(target)) => target,
|
||||
};
|
||||
|
||||
editor.update_in(&mut cx, |editor, window, cx| {
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
let Some(workspace) = editor.workspace() else {
|
||||
return Navigated::No;
|
||||
};
|
||||
|
@ -12721,9 +12722,9 @@ impl Editor {
|
|||
})
|
||||
})
|
||||
} else if !definitions.is_empty() {
|
||||
cx.spawn_in(window, |editor, mut cx| async move {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
let (title, location_tasks, workspace) = editor
|
||||
.update_in(&mut cx, |editor, window, cx| {
|
||||
.update_in(cx, |editor, window, cx| {
|
||||
let tab_kind = match kind {
|
||||
Some(GotoDefinitionKind::Implementation) => "Implementations",
|
||||
_ => "Definitions",
|
||||
|
@ -12771,7 +12772,7 @@ impl Editor {
|
|||
return Ok(Navigated::No);
|
||||
};
|
||||
let opened = workspace
|
||||
.update_in(&mut cx, |workspace, window, cx| {
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
Self::open_locations_in_multibuffer(
|
||||
workspace,
|
||||
locations,
|
||||
|
@ -12802,8 +12803,8 @@ impl Editor {
|
|||
return Task::ready(Ok(None));
|
||||
};
|
||||
|
||||
cx.spawn_in(window, move |editor, mut cx| async move {
|
||||
let location_task = editor.update(&mut cx, |_, cx| {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
let location_task = editor.update(cx, |_, cx| {
|
||||
project.update(cx, |project, cx| {
|
||||
let language_server_name = project
|
||||
.language_server_statuses(cx)
|
||||
|
@ -12822,7 +12823,7 @@ impl Editor {
|
|||
let location = match location_task {
|
||||
Some(task) => Some({
|
||||
let target_buffer_handle = task.await.context("open local buffer")?;
|
||||
let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
|
||||
let range = target_buffer_handle.update(cx, |target_buffer, _| {
|
||||
let target_start = target_buffer
|
||||
.clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
|
||||
let target_end = target_buffer
|
||||
|
@ -12880,21 +12881,13 @@ impl Editor {
|
|||
let workspace = self.workspace()?;
|
||||
let project = workspace.read(cx).project().clone();
|
||||
let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
|
||||
Some(cx.spawn_in(window, |editor, mut cx| async move {
|
||||
let _cleanup = defer({
|
||||
let mut cx = cx.clone();
|
||||
move || {
|
||||
let _ = editor.update(&mut cx, |editor, _| {
|
||||
if let Ok(i) =
|
||||
editor
|
||||
.find_all_references_task_sources
|
||||
.binary_search_by(|anchor| {
|
||||
anchor.cmp(&head_anchor, &multi_buffer_snapshot)
|
||||
})
|
||||
{
|
||||
editor.find_all_references_task_sources.remove(i);
|
||||
}
|
||||
});
|
||||
Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
let _cleanup = cx.on_drop(&editor, move |editor, _| {
|
||||
if let Ok(i) = editor
|
||||
.find_all_references_task_sources
|
||||
.binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
|
||||
{
|
||||
editor.find_all_references_task_sources.remove(i);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -12903,7 +12896,7 @@ impl Editor {
|
|||
return anyhow::Ok(Navigated::No);
|
||||
}
|
||||
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let title = locations
|
||||
.first()
|
||||
.as_ref()
|
||||
|
@ -13067,11 +13060,11 @@ impl Editor {
|
|||
.unwrap_or_else(|| Task::ready(Ok(None)));
|
||||
drop(snapshot);
|
||||
|
||||
Some(cx.spawn_in(window, |this, mut cx| async move {
|
||||
Some(cx.spawn_in(window, async move |this, cx| {
|
||||
let rename_range = if let Some(range) = prepare_rename.await? {
|
||||
Some(range)
|
||||
} else {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let buffer = this.buffer.read(cx).snapshot(cx);
|
||||
let mut buffer_highlights = this
|
||||
.document_highlights_for_position(selection.head(), &buffer)
|
||||
|
@ -13085,7 +13078,7 @@ impl Editor {
|
|||
})?
|
||||
};
|
||||
if let Some(rename_range) = rename_range {
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let snapshot = cursor_buffer.read(cx).snapshot();
|
||||
let rename_buffer_range = rename_range.to_offset(&snapshot);
|
||||
let cursor_offset_in_rename_range =
|
||||
|
@ -13258,18 +13251,18 @@ impl Editor {
|
|||
cx,
|
||||
)?;
|
||||
|
||||
Some(cx.spawn_in(window, |editor, mut cx| async move {
|
||||
Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
let project_transaction = rename.await?;
|
||||
Self::open_project_transaction(
|
||||
&editor,
|
||||
workspace,
|
||||
project_transaction,
|
||||
format!("Rename: {} → {}", old_name, new_name),
|
||||
cx.clone(),
|
||||
cx,
|
||||
)
|
||||
.await?;
|
||||
|
||||
editor.update(&mut cx, |editor, cx| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.refresh_document_highlights(cx);
|
||||
})?;
|
||||
Ok(())
|
||||
|
@ -13416,7 +13409,7 @@ impl Editor {
|
|||
project.format(buffers, target, true, trigger, cx)
|
||||
});
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
let transaction = futures::select_biased! {
|
||||
transaction = format.log_err().fuse() => transaction,
|
||||
() = timeout => {
|
||||
|
@ -13426,7 +13419,7 @@ impl Editor {
|
|||
};
|
||||
|
||||
buffer
|
||||
.update(&mut cx, |buffer, cx| {
|
||||
.update(cx, |buffer, cx| {
|
||||
if let Some(transaction) = transaction {
|
||||
if !buffer.is_singleton() {
|
||||
buffer.push_transaction(&transaction.0, cx);
|
||||
|
@ -13471,7 +13464,7 @@ impl Editor {
|
|||
let apply_action = project.update(cx, |project, cx| {
|
||||
project.apply_code_action_kind(buffers, kind, true, cx)
|
||||
});
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
let transaction = futures::select_biased! {
|
||||
() = timeout => {
|
||||
log::warn!("timed out waiting for executing code action");
|
||||
|
@ -13480,7 +13473,7 @@ impl Editor {
|
|||
transaction = apply_action.log_err().fuse() => transaction,
|
||||
};
|
||||
buffer
|
||||
.update(&mut cx, |buffer, cx| {
|
||||
.update(cx, |buffer, cx| {
|
||||
// check if we need this
|
||||
if let Some(transaction) = transaction {
|
||||
if !buffer.is_singleton() {
|
||||
|
@ -13695,12 +13688,12 @@ impl Editor {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
self.inline_diagnostics_update = cx.spawn_in(window, |editor, mut cx| async move {
|
||||
self.inline_diagnostics_update = cx.spawn_in(window, async move |editor, cx| {
|
||||
if let Some(debounce) = debounce {
|
||||
cx.background_executor().timer(debounce).await;
|
||||
}
|
||||
let Some(snapshot) = editor
|
||||
.update(&mut cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
|
||||
.update(cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
|
||||
.ok()
|
||||
else {
|
||||
return;
|
||||
|
@ -13741,7 +13734,7 @@ impl Editor {
|
|||
.await;
|
||||
|
||||
editor
|
||||
.update(&mut cx, |editor, cx| {
|
||||
.update(cx, |editor, cx| {
|
||||
editor.inline_diagnostics = new_inline_diagnostics;
|
||||
cx.notify();
|
||||
})
|
||||
|
@ -14042,9 +14035,9 @@ impl Editor {
|
|||
|
||||
self.fold_creases(fold_ranges, true, window, cx);
|
||||
} else {
|
||||
self.toggle_fold_multiple_buffers = cx.spawn_in(window, |editor, mut cx| async move {
|
||||
self.toggle_fold_multiple_buffers = cx.spawn_in(window, async move |editor, cx| {
|
||||
editor
|
||||
.update_in(&mut cx, |editor, _, cx| {
|
||||
.update_in(cx, |editor, _, cx| {
|
||||
for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
|
||||
editor.fold_buffer(buffer_id, cx);
|
||||
}
|
||||
|
@ -14218,9 +14211,9 @@ impl Editor {
|
|||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
|
||||
} else {
|
||||
self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
|
||||
self.toggle_fold_multiple_buffers = cx.spawn(async move |editor, cx| {
|
||||
editor
|
||||
.update(&mut cx, |editor, cx| {
|
||||
.update(cx, |editor, cx| {
|
||||
for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
|
||||
editor.unfold_buffer(buffer_id, cx);
|
||||
}
|
||||
|
@ -14507,9 +14500,9 @@ impl Editor {
|
|||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let task = self.save_buffers_for_ranges_if_needed(&ranges, cx);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
cx.spawn(async move |this, cx| {
|
||||
task.await?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let snapshot = this.buffer.read(cx).snapshot(cx);
|
||||
let chunk_by = this
|
||||
.diff_hunks_in_ranges(&ranges, &snapshot)
|
||||
|
@ -15463,34 +15456,32 @@ impl Editor {
|
|||
let permalink_task = self.get_permalink_to_line(cx);
|
||||
let workspace = self.workspace();
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
match permalink_task.await {
|
||||
Ok(permalink) => {
|
||||
cx.update(|_, cx| {
|
||||
cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
Err(err) => {
|
||||
let message = format!("Failed to copy permalink: {err}");
|
||||
cx.spawn_in(window, async move |_, cx| match permalink_task.await {
|
||||
Ok(permalink) => {
|
||||
cx.update(|_, cx| {
|
||||
cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
Err(err) => {
|
||||
let message = format!("Failed to copy permalink: {err}");
|
||||
|
||||
Err::<(), anyhow::Error>(err).log_err();
|
||||
Err::<(), anyhow::Error>(err).log_err();
|
||||
|
||||
if let Some(workspace) = workspace {
|
||||
workspace
|
||||
.update_in(&mut cx, |workspace, _, cx| {
|
||||
struct CopyPermalinkToLine;
|
||||
if let Some(workspace) = workspace {
|
||||
workspace
|
||||
.update_in(cx, |workspace, _, cx| {
|
||||
struct CopyPermalinkToLine;
|
||||
|
||||
workspace.show_toast(
|
||||
Toast::new(
|
||||
NotificationId::unique::<CopyPermalinkToLine>(),
|
||||
message,
|
||||
),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
workspace.show_toast(
|
||||
Toast::new(
|
||||
NotificationId::unique::<CopyPermalinkToLine>(),
|
||||
message,
|
||||
),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -15520,34 +15511,32 @@ impl Editor {
|
|||
let permalink_task = self.get_permalink_to_line(cx);
|
||||
let workspace = self.workspace();
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
match permalink_task.await {
|
||||
Ok(permalink) => {
|
||||
cx.update(|_, cx| {
|
||||
cx.open_url(permalink.as_ref());
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
Err(err) => {
|
||||
let message = format!("Failed to open permalink: {err}");
|
||||
cx.spawn_in(window, async move |_, cx| match permalink_task.await {
|
||||
Ok(permalink) => {
|
||||
cx.update(|_, cx| {
|
||||
cx.open_url(permalink.as_ref());
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
Err(err) => {
|
||||
let message = format!("Failed to open permalink: {err}");
|
||||
|
||||
Err::<(), anyhow::Error>(err).log_err();
|
||||
Err::<(), anyhow::Error>(err).log_err();
|
||||
|
||||
if let Some(workspace) = workspace {
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
struct OpenPermalinkToLine;
|
||||
if let Some(workspace) = workspace {
|
||||
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,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -15619,8 +15608,8 @@ impl Editor {
|
|||
|
||||
let title = multibuffer.title(cx).to_string();
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
workspace.update_in(&mut cx, |workspace, window, cx| {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
Self::open_locations_in_multibuffer(
|
||||
workspace,
|
||||
locations,
|
||||
|
@ -17008,12 +16997,12 @@ impl Editor {
|
|||
}
|
||||
tasks
|
||||
});
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
for (buffer, task) in save_tasks {
|
||||
let result = task.await;
|
||||
if result.is_err() {
|
||||
let Some(path) = buffer
|
||||
.read_with(&cx, |buffer, cx| buffer.project_path(cx))
|
||||
.read_with(cx, |buffer, cx| buffer.project_path(cx))
|
||||
.ok()
|
||||
else {
|
||||
continue;
|
||||
|
@ -17212,10 +17201,10 @@ fn get_uncommitted_diff_for_buffer(
|
|||
tasks.push(project.open_uncommitted_diff(buffer.clone(), cx))
|
||||
}
|
||||
});
|
||||
cx.spawn(|mut cx| async move {
|
||||
cx.spawn(async move |cx| {
|
||||
let diffs = future::join_all(tasks).await;
|
||||
buffer
|
||||
.update(&mut cx, |buffer, cx| {
|
||||
.update(cx, |buffer, cx| {
|
||||
for diff in diffs.into_iter().flatten() {
|
||||
buffer.add_diff(diff, cx);
|
||||
}
|
||||
|
@ -18069,13 +18058,13 @@ impl SemanticsProvider for Entity<Project> {
|
|||
Some(self.update(cx, |project, cx| {
|
||||
let buffer = buffer.clone();
|
||||
let task = project.prepare_rename(buffer.clone(), position, cx);
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
cx.spawn(async move |_, cx| {
|
||||
Ok(match task.await? {
|
||||
PrepareRenameResponse::Success(range) => Some(range),
|
||||
PrepareRenameResponse::InvalidPosition => None,
|
||||
PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
|
||||
// Fallback on using TreeSitter info to determine identifier range
|
||||
buffer.update(&mut cx, |buffer, _| {
|
||||
buffer.update(cx, |buffer, _| {
|
||||
let snapshot = buffer.snapshot();
|
||||
let (range, kind) = snapshot.surrounding_word(position);
|
||||
if kind != Some(CharKind::Word) {
|
||||
|
|
|
@ -9312,6 +9312,7 @@ async fn test_word_completion(cx: &mut TestAppContext) {
|
|||
.server
|
||||
.on_request::<lsp::request::Completion, _, _>(move |_, cx| {
|
||||
let lsp_throttle_completions = lsp_throttle_completions.clone();
|
||||
let cx = cx.clone();
|
||||
async move {
|
||||
if lsp_throttle_completions.load(atomic::Ordering::Acquire) {
|
||||
cx.background_executor()
|
||||
|
|
|
@ -973,10 +973,10 @@ impl EditorElement {
|
|||
};
|
||||
editor.hovered_cursors.insert(
|
||||
key.clone(),
|
||||
cx.spawn_in(window, |editor, mut cx| async move {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
|
||||
editor
|
||||
.update(&mut cx, |editor, cx| {
|
||||
.update(cx, |editor, cx| {
|
||||
editor.hovered_cursors.remove(&key);
|
||||
cx.notify();
|
||||
})
|
||||
|
@ -5199,7 +5199,7 @@ impl EditorElement {
|
|||
|
||||
editor.scrollbar_marker_state.dirty = false;
|
||||
editor.scrollbar_marker_state.pending_refresh =
|
||||
Some(cx.spawn_in(window, |editor, mut cx| async move {
|
||||
Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
let scrollbar_size = scrollbar_layout.hitbox.size;
|
||||
let scrollbar_markers = cx
|
||||
.background_spawn(async move {
|
||||
|
@ -5346,7 +5346,7 @@ impl EditorElement {
|
|||
})
|
||||
.await;
|
||||
|
||||
editor.update(&mut cx, |editor, cx| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.scrollbar_marker_state.markers = scrollbar_markers;
|
||||
editor.scrollbar_marker_state.scrollbar_size = scrollbar_size;
|
||||
editor.scrollbar_marker_state.pending_refresh = None;
|
||||
|
|
|
@ -363,7 +363,7 @@ impl GitBlame {
|
|||
let blame = self.project.read(cx).blame_buffer(&self.buffer, None, cx);
|
||||
let provider_registry = GitHostingProviderRegistry::default_global(cx);
|
||||
|
||||
self.task = cx.spawn(|this, mut cx| async move {
|
||||
self.task = cx.spawn(async move |this, cx| {
|
||||
let result = cx
|
||||
.background_spawn({
|
||||
let snapshot = snapshot.clone();
|
||||
|
@ -386,7 +386,7 @@ impl GitBlame {
|
|||
})
|
||||
.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| match result {
|
||||
this.update(cx, |this, cx| match result {
|
||||
Ok(None) => {
|
||||
// Nothing to do, e.g. no repository found
|
||||
}
|
||||
|
@ -417,12 +417,12 @@ impl GitBlame {
|
|||
}
|
||||
|
||||
fn regenerate_on_edit(&mut self, cx: &mut Context<Self>) {
|
||||
self.regenerate_on_edit_task = cx.spawn(|this, mut cx| async move {
|
||||
self.regenerate_on_edit_task = cx.spawn(async move |this, cx| {
|
||||
cx.background_executor()
|
||||
.timer(REGENERATE_ON_EDIT_DEBOUNCE_INTERVAL)
|
||||
.await;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.generate(cx);
|
||||
})
|
||||
})
|
||||
|
|
|
@ -167,10 +167,10 @@ impl Editor {
|
|||
cx: &mut Context<Editor>,
|
||||
) {
|
||||
let reveal_task = self.cmd_click_reveal_task(point, modifiers, window, cx);
|
||||
cx.spawn_in(window, |editor, mut cx| async move {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
let definition_revealed = reveal_task.await.log_err().unwrap_or(Navigated::No);
|
||||
let find_references = editor
|
||||
.update_in(&mut cx, |editor, window, cx| {
|
||||
.update_in(cx, |editor, window, cx| {
|
||||
if definition_revealed == Navigated::Yes {
|
||||
return None;
|
||||
}
|
||||
|
@ -529,12 +529,12 @@ pub fn show_link_definition(
|
|||
let provider = editor.semantics_provider.clone();
|
||||
|
||||
let snapshot = snapshot.buffer_snapshot.clone();
|
||||
hovered_link_state.task = Some(cx.spawn_in(window, |this, mut cx| {
|
||||
hovered_link_state.task = Some(cx.spawn_in(window, async move |this, cx| {
|
||||
async move {
|
||||
let result = match &trigger_point {
|
||||
TriggerPoint::Text(_) => {
|
||||
if let Some((url_range, url)) = find_url(&buffer, buffer_position, cx.clone()) {
|
||||
this.update(&mut cx, |_, _| {
|
||||
this.update(cx, |_, _| {
|
||||
let range = maybe!({
|
||||
let start =
|
||||
snapshot.anchor_in_excerpt(excerpt_id, url_range.start)?;
|
||||
|
@ -545,7 +545,7 @@ pub fn show_link_definition(
|
|||
})
|
||||
.ok()
|
||||
} else if let Some((filename_range, filename)) =
|
||||
find_file(&buffer, project.clone(), buffer_position, &mut cx).await
|
||||
find_file(&buffer, project.clone(), buffer_position, cx).await
|
||||
{
|
||||
let range = maybe!({
|
||||
let start =
|
||||
|
@ -589,7 +589,7 @@ pub fn show_link_definition(
|
|||
)),
|
||||
};
|
||||
|
||||
this.update(&mut cx, |editor, cx| {
|
||||
this.update(cx, |editor, cx| {
|
||||
// Clear any existing highlights
|
||||
editor.clear_highlights::<HoveredLinkState>(cx);
|
||||
let Some(hovered_link_state) = editor.hovered_link_state.as_mut() else {
|
||||
|
@ -647,6 +647,7 @@ pub fn show_link_definition(
|
|||
Ok::<_, anyhow::Error>(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
}));
|
||||
|
||||
editor.hovered_link_state = Some(hovered_link_state);
|
||||
|
|
|
@ -149,18 +149,18 @@ pub fn hover_at_inlay(
|
|||
|
||||
let hover_popover_delay = EditorSettings::get_global(cx).hover_popover_delay;
|
||||
|
||||
let task = cx.spawn_in(window, |this, mut cx| {
|
||||
let task = cx.spawn_in(window, async move |this, cx| {
|
||||
async move {
|
||||
cx.background_executor()
|
||||
.timer(Duration::from_millis(hover_popover_delay))
|
||||
.await;
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.hover_state.diagnostic_popover = None;
|
||||
})?;
|
||||
|
||||
let language_registry = project.update(&mut cx, |p, _| p.languages().clone())?;
|
||||
let language_registry = project.update(cx, |p, _| p.languages().clone())?;
|
||||
let blocks = vec![inlay_hover.tooltip];
|
||||
let parsed_content = parse_blocks(&blocks, &language_registry, None, &mut cx).await;
|
||||
let parsed_content = parse_blocks(&blocks, &language_registry, None, cx).await;
|
||||
|
||||
let scroll_handle = ScrollHandle::new();
|
||||
let hover_popover = InfoPopover {
|
||||
|
@ -172,7 +172,7 @@ pub fn hover_at_inlay(
|
|||
anchor: None,
|
||||
};
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
// TODO: no background highlights happen for inlays currently
|
||||
this.hover_state.info_popovers = vec![hover_popover];
|
||||
cx.notify();
|
||||
|
@ -181,6 +181,7 @@ pub fn hover_at_inlay(
|
|||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
});
|
||||
|
||||
editor.hover_state.info_task = Some(task);
|
||||
|
@ -257,7 +258,7 @@ fn show_hover(
|
|||
|
||||
let hover_popover_delay = EditorSettings::get_global(cx).hover_popover_delay;
|
||||
|
||||
let task = cx.spawn_in(window, |this, mut cx| {
|
||||
let task = cx.spawn_in(window, async move |this, cx| {
|
||||
async move {
|
||||
// If we need to delay, delay a set amount initially before making the lsp request
|
||||
let delay = if ignore_timeout {
|
||||
|
@ -375,7 +376,7 @@ fn show_hover(
|
|||
None
|
||||
};
|
||||
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.update(cx, |this, _| {
|
||||
this.hover_state.diagnostic_popover = diagnostic_popover;
|
||||
})?;
|
||||
|
||||
|
@ -409,7 +410,7 @@ fn show_hover(
|
|||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let snapshot = this.update_in(&mut cx, |this, window, cx| this.snapshot(window, cx))?;
|
||||
let snapshot = this.update_in(cx, |this, window, cx| this.snapshot(window, cx))?;
|
||||
let mut hover_highlights = Vec::with_capacity(hovers_response.len());
|
||||
let mut info_popovers = Vec::with_capacity(
|
||||
hovers_response.len() + if invisible_char.is_some() { 1 } else { 0 },
|
||||
|
@ -420,7 +421,7 @@ fn show_hover(
|
|||
text: format!("Unicode character U+{:02X}", invisible as u32),
|
||||
kind: HoverBlockKind::PlainText,
|
||||
}];
|
||||
let parsed_content = parse_blocks(&blocks, &language_registry, None, &mut cx).await;
|
||||
let parsed_content = parse_blocks(&blocks, &language_registry, None, cx).await;
|
||||
let scroll_handle = ScrollHandle::new();
|
||||
info_popovers.push(InfoPopover {
|
||||
symbol_range: RangeInEditor::Text(range),
|
||||
|
@ -459,8 +460,7 @@ fn show_hover(
|
|||
|
||||
let blocks = hover_result.contents;
|
||||
let language = hover_result.language;
|
||||
let parsed_content =
|
||||
parse_blocks(&blocks, &language_registry, language, &mut cx).await;
|
||||
let parsed_content = parse_blocks(&blocks, &language_registry, language, cx).await;
|
||||
let scroll_handle = ScrollHandle::new();
|
||||
hover_highlights.push(range.clone());
|
||||
info_popovers.push(InfoPopover {
|
||||
|
@ -473,7 +473,7 @@ fn show_hover(
|
|||
});
|
||||
}
|
||||
|
||||
this.update_in(&mut cx, |editor, window, cx| {
|
||||
this.update_in(cx, |editor, window, cx| {
|
||||
if hover_highlights.is_empty() {
|
||||
editor.clear_background_highlights::<HoverState>(cx);
|
||||
} else {
|
||||
|
@ -493,6 +493,7 @@ fn show_hover(
|
|||
anyhow::Ok(())
|
||||
}
|
||||
.log_err()
|
||||
.await
|
||||
});
|
||||
|
||||
editor.hover_state.info_task = Some(task);
|
||||
|
@ -642,7 +643,7 @@ pub fn open_markdown_url(link: SharedString, window: &mut Window, cx: &mut App)
|
|||
cx,
|
||||
);
|
||||
|
||||
cx.spawn_in(window, |_, mut cx| async move {
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
let item = task.await?;
|
||||
// Ruby LSP uses URLs with #L1,1-4,4
|
||||
// we'll just take the first number and assume it's a line number
|
||||
|
@ -664,7 +665,7 @@ pub fn open_markdown_url(link: SharedString, window: &mut Window, cx: &mut App)
|
|||
let Some(editor) = cx.update(|_, cx| item.act_as::<Editor>(cx))? else {
|
||||
return Ok(());
|
||||
};
|
||||
editor.update_in(&mut cx, |editor, window, cx| {
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
editor.change_selections(
|
||||
Some(Autoscroll::fit()),
|
||||
window,
|
||||
|
|
|
@ -111,16 +111,15 @@ impl Editor {
|
|||
{
|
||||
Ok(result) => state.active_indent_range = result,
|
||||
Err(future) => {
|
||||
state.pending_refresh =
|
||||
Some(cx.spawn_in(window, |editor, mut cx| async move {
|
||||
let result = cx.background_spawn(future).await;
|
||||
editor
|
||||
.update(&mut cx, |editor, _| {
|
||||
editor.active_indent_guides_state.active_indent_range = result;
|
||||
editor.active_indent_guides_state.pending_refresh = None;
|
||||
})
|
||||
.log_err();
|
||||
}));
|
||||
state.pending_refresh = Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
let result = cx.background_spawn(future).await;
|
||||
editor
|
||||
.update(cx, |editor, _| {
|
||||
editor.active_indent_guides_state.active_indent_range = result;
|
||||
editor.active_indent_guides_state.pending_refresh = None;
|
||||
})
|
||||
.log_err();
|
||||
}));
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -412,13 +412,13 @@ impl InlayHintCache {
|
|||
} else {
|
||||
self.append_debounce
|
||||
};
|
||||
self.refresh_task = cx.spawn(|editor, mut cx| async move {
|
||||
self.refresh_task = cx.spawn(async move |editor, cx| {
|
||||
if let Some(debounce_duration) = debounce_duration {
|
||||
cx.background_executor().timer(debounce_duration).await;
|
||||
}
|
||||
|
||||
editor
|
||||
.update(&mut cx, |editor, cx| {
|
||||
.update(cx, |editor, cx| {
|
||||
spawn_new_update_tasks(
|
||||
editor,
|
||||
reason_description,
|
||||
|
@ -626,8 +626,8 @@ impl InlayHintCache {
|
|||
let server_id = *server_id;
|
||||
cached_hint.resolve_state = ResolveState::Resolving;
|
||||
drop(guard);
|
||||
cx.spawn_in(window, |editor, mut cx| async move {
|
||||
let resolved_hint_task = editor.update(&mut cx, |editor, cx| {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
let resolved_hint_task = editor.update(cx, |editor, cx| {
|
||||
let buffer = editor.buffer().read(cx).buffer(buffer_id)?;
|
||||
editor.semantics_provider.as_ref()?.resolve_inlay_hint(
|
||||
hint_to_resolve,
|
||||
|
@ -639,7 +639,7 @@ impl InlayHintCache {
|
|||
if let Some(resolved_hint_task) = resolved_hint_task {
|
||||
let mut resolved_hint =
|
||||
resolved_hint_task.await.context("hint resolve task")?;
|
||||
editor.update(&mut cx, |editor, _| {
|
||||
editor.update(cx, |editor, _| {
|
||||
if let Some(excerpt_hints) =
|
||||
editor.inlay_hint_cache.hints.get(&excerpt_id)
|
||||
{
|
||||
|
@ -846,14 +846,14 @@ fn new_update_task(
|
|||
excerpt_buffer: Entity<Buffer>,
|
||||
cx: &mut Context<Editor>,
|
||||
) -> Task<()> {
|
||||
cx.spawn(move |editor, mut cx| async move {
|
||||
cx.spawn(async move |editor, cx| {
|
||||
let visible_range_update_results = future::join_all(
|
||||
query_ranges
|
||||
.visible
|
||||
.into_iter()
|
||||
.filter_map(|visible_range| {
|
||||
let fetch_task = editor
|
||||
.update(&mut cx, |_, cx| {
|
||||
.update(cx, |_, cx| {
|
||||
fetch_and_update_hints(
|
||||
excerpt_buffer.clone(),
|
||||
query,
|
||||
|
@ -891,7 +891,7 @@ fn new_update_task(
|
|||
|
||||
for (range, result) in visible_range_update_results {
|
||||
if let Err(e) = result {
|
||||
query_range_failed(&range, e, &mut cx);
|
||||
query_range_failed(&range, e, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,7 +903,7 @@ fn new_update_task(
|
|||
.chain(query_ranges.after_visible.into_iter())
|
||||
.filter_map(|invisible_range| {
|
||||
let fetch_task = editor
|
||||
.update(&mut cx, |_, cx| {
|
||||
.update(cx, |_, cx| {
|
||||
fetch_and_update_hints(
|
||||
excerpt_buffer.clone(),
|
||||
query,
|
||||
|
@ -919,7 +919,7 @@ fn new_update_task(
|
|||
.await;
|
||||
for (range, result) in invisible_range_update_results {
|
||||
if let Err(e) = result {
|
||||
query_range_failed(&range, e, &mut cx);
|
||||
query_range_failed(&range, e, cx);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -932,10 +932,10 @@ fn fetch_and_update_hints(
|
|||
invalidate: bool,
|
||||
cx: &mut Context<Editor>,
|
||||
) -> Task<anyhow::Result<()>> {
|
||||
cx.spawn(|editor, mut cx| async move {
|
||||
let buffer_snapshot = excerpt_buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
|
||||
cx.spawn(async move |editor, cx|{
|
||||
let buffer_snapshot = excerpt_buffer.update(cx, |buffer, _| buffer.snapshot())?;
|
||||
let (lsp_request_limiter, multi_buffer_snapshot) =
|
||||
editor.update(&mut cx, |editor, cx| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
let multi_buffer_snapshot =
|
||||
editor.buffer().update(cx, |buffer, cx| buffer.snapshot(cx));
|
||||
let lsp_request_limiter = Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter);
|
||||
|
@ -953,7 +953,7 @@ fn fetch_and_update_hints(
|
|||
let fetch_range_to_log = fetch_range.start.to_point(&buffer_snapshot)
|
||||
..fetch_range.end.to_point(&buffer_snapshot);
|
||||
let inlay_hints_fetch_task = editor
|
||||
.update(&mut cx, |editor, cx| {
|
||||
.update(cx, |editor, cx| {
|
||||
if got_throttled {
|
||||
let query_not_around_visible_range = match editor
|
||||
.excerpts_for_inlay_hints_query(None, cx)
|
||||
|
@ -997,7 +997,7 @@ fn fetch_and_update_hints(
|
|||
.ok()
|
||||
.flatten();
|
||||
|
||||
let cached_excerpt_hints = editor.update(&mut cx, |editor, _| {
|
||||
let cached_excerpt_hints = editor.update(cx, |editor, _| {
|
||||
editor
|
||||
.inlay_hint_cache
|
||||
.hints
|
||||
|
@ -1005,7 +1005,7 @@ fn fetch_and_update_hints(
|
|||
.cloned()
|
||||
})?;
|
||||
|
||||
let visible_hints = editor.update(&mut cx, |editor, cx| editor.visible_inlay_hints(cx))?;
|
||||
let visible_hints = editor.update(cx, |editor, cx| editor.visible_inlay_hints(cx))?;
|
||||
let new_hints = match inlay_hints_fetch_task {
|
||||
Some(fetch_task) => {
|
||||
log::debug!(
|
||||
|
@ -1050,7 +1050,7 @@ fn fetch_and_update_hints(
|
|||
);
|
||||
log::trace!("New update: {new_update:?}");
|
||||
editor
|
||||
.update(&mut cx, |editor, cx| {
|
||||
.update(cx, |editor, cx| {
|
||||
apply_hint_update(
|
||||
editor,
|
||||
new_update,
|
||||
|
|
|
@ -87,7 +87,7 @@ impl FollowableItem for Editor {
|
|||
.collect::<Result<Vec<_>>>()
|
||||
});
|
||||
|
||||
Some(window.spawn(cx, |mut cx| async move {
|
||||
Some(window.spawn(cx, async move |cx| {
|
||||
let mut buffers = futures::future::try_join_all(buffers?)
|
||||
.await
|
||||
.debug_assert_ok("leaders don't share views for unshared buffers")?;
|
||||
|
@ -147,7 +147,7 @@ impl FollowableItem for Editor {
|
|||
scroll_y: state.scroll_y,
|
||||
..Default::default()
|
||||
},
|
||||
&mut cx,
|
||||
cx,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -319,8 +319,8 @@ impl FollowableItem for Editor {
|
|||
) -> Task<Result<()>> {
|
||||
let update_view::Variant::Editor(message) = message;
|
||||
let project = project.clone();
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
update_editor_from_message(this, project, message, &mut cx).await
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
update_editor_from_message(this, project, message, cx).await
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -776,9 +776,9 @@ impl Item for Editor {
|
|||
.into_iter()
|
||||
.map(|handle| handle.read(cx).base_buffer().unwrap_or(handle.clone()))
|
||||
.collect::<HashSet<_>>();
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if format {
|
||||
this.update_in(&mut cx, |editor, window, cx| {
|
||||
this.update_in(cx, |editor, window, cx| {
|
||||
editor.perform_format(
|
||||
project.clone(),
|
||||
FormatTrigger::Save,
|
||||
|
@ -793,7 +793,7 @@ impl Item for Editor {
|
|||
if buffers.len() == 1 {
|
||||
// Apply full save routine for singleton buffers, to allow to `touch` the file via the editor.
|
||||
project
|
||||
.update(&mut cx, |project, cx| project.save_buffers(buffers, cx))?
|
||||
.update(cx, |project, cx| project.save_buffers(buffers, cx))?
|
||||
.await?;
|
||||
} else {
|
||||
// For multi-buffers, only format and save the buffers with changes.
|
||||
|
@ -801,20 +801,16 @@ impl Item for Editor {
|
|||
// so that language servers or other downstream listeners of save events get notified.
|
||||
let (dirty_buffers, clean_buffers) = buffers.into_iter().partition(|buffer| {
|
||||
buffer
|
||||
.update(&mut cx, |buffer, _| {
|
||||
buffer.is_dirty() || buffer.has_conflict()
|
||||
})
|
||||
.update(cx, |buffer, _| buffer.is_dirty() || buffer.has_conflict())
|
||||
.unwrap_or(false)
|
||||
});
|
||||
|
||||
project
|
||||
.update(&mut cx, |project, cx| {
|
||||
project.save_buffers(dirty_buffers, cx)
|
||||
})?
|
||||
.update(cx, |project, cx| project.save_buffers(dirty_buffers, cx))?
|
||||
.await?;
|
||||
for buffer in clean_buffers {
|
||||
buffer
|
||||
.update(&mut cx, |buffer, cx| {
|
||||
.update(cx, |buffer, cx| {
|
||||
let version = buffer.saved_version().clone();
|
||||
let mtime = buffer.saved_mtime();
|
||||
buffer.did_save(version, mtime, cx);
|
||||
|
@ -859,13 +855,13 @@ impl Item for Editor {
|
|||
let buffers = self.buffer.read(cx).all_buffers();
|
||||
let reload_buffers =
|
||||
project.update(cx, |project, cx| project.reload_buffers(buffers, true, cx));
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let transaction = reload_buffers.log_err().await;
|
||||
this.update(&mut cx, |editor, cx| {
|
||||
this.update(cx, |editor, cx| {
|
||||
editor.request_autoscroll(Autoscroll::fit(), cx)
|
||||
})?;
|
||||
buffer
|
||||
.update(&mut cx, |buffer, cx| {
|
||||
.update(cx, |buffer, cx| {
|
||||
if let Some(transaction) = transaction {
|
||||
if !buffer.is_singleton() {
|
||||
buffer.push_transaction(&transaction.0, cx);
|
||||
|
@ -996,7 +992,9 @@ impl SerializableItem for Editor {
|
|||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Task<Result<()>> {
|
||||
window.spawn(cx, |_| DB.delete_unloaded_items(workspace_id, alive_items))
|
||||
window.spawn(cx, async move |_| {
|
||||
DB.delete_unloaded_items(workspace_id, alive_items).await
|
||||
})
|
||||
}
|
||||
|
||||
fn deserialize(
|
||||
|
@ -1040,11 +1038,11 @@ impl SerializableItem for Editor {
|
|||
contents: Some(contents),
|
||||
language,
|
||||
..
|
||||
} => window.spawn(cx, |mut cx| {
|
||||
} => window.spawn(cx, {
|
||||
let project = project.clone();
|
||||
async move {
|
||||
async move |cx| {
|
||||
let language_registry =
|
||||
project.update(&mut cx, |project, _| project.languages().clone())?;
|
||||
project.update(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
|
||||
|
@ -1059,11 +1057,11 @@ impl SerializableItem for Editor {
|
|||
|
||||
// First create the empty buffer
|
||||
let buffer = project
|
||||
.update(&mut cx, |project, cx| project.create_buffer(cx))?
|
||||
.update(cx, |project, cx| project.create_buffer(cx))?
|
||||
.await?;
|
||||
|
||||
// Then set the text so that the dirty bit is set correctly
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.set_language_registry(language_registry);
|
||||
if let Some(language) = language {
|
||||
buffer.set_language(Some(language), cx);
|
||||
|
@ -1102,7 +1100,7 @@ impl SerializableItem for Editor {
|
|||
|
||||
match project_item {
|
||||
Some(project_item) => {
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let (_, project_item) = project_item.await?;
|
||||
let buffer = project_item.downcast::<Buffer>().map_err(|_| {
|
||||
anyhow!("Project item at stored path was not a buffer")
|
||||
|
@ -1114,7 +1112,7 @@ impl SerializableItem for Editor {
|
|||
// simple, because we don't have to persist all of the metadata that we get
|
||||
// by loading the file (git diff base, ...).
|
||||
if let Some(buffer_text) = contents {
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
// If we did restore an mtime, we want to store it on the buffer
|
||||
// so that the next edit will mark the buffer as dirty/conflicted.
|
||||
if mtime.is_some() {
|
||||
|
@ -1166,9 +1164,9 @@ impl SerializableItem for Editor {
|
|||
cx,
|
||||
)
|
||||
});
|
||||
window.spawn(cx, |mut cx| async move {
|
||||
window.spawn(cx, async move |cx| {
|
||||
let editor = open_by_abs_path?.await?.downcast::<Editor>().with_context(|| format!("Failed to downcast to Editor after opening abs path {abs_path:?}"))?;
|
||||
editor.update_in(&mut cx, |editor, window, cx| {
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
editor.read_selections_from_db(item_id, workspace_id, window, cx);
|
||||
editor.read_scroll_position_from_db(item_id, workspace_id, window, cx);
|
||||
})?;
|
||||
|
@ -1228,7 +1226,7 @@ impl SerializableItem for Editor {
|
|||
|
||||
let snapshot = buffer.read(cx).snapshot();
|
||||
|
||||
Some(cx.spawn_in(window, |_this, cx| async move {
|
||||
Some(cx.spawn_in(window, async move |_this, cx| {
|
||||
cx.background_spawn(async move {
|
||||
let (contents, language) = if serialize_dirty_buffers && is_dirty {
|
||||
let contents = snapshot.text();
|
||||
|
|
|
@ -434,7 +434,7 @@ pub(crate) fn handle_from(
|
|||
let (buffer_version_initial, mut buffer_parse_status_rx) =
|
||||
buffer.read_with(cx, |buffer, _| (buffer.version(), buffer.parse_status()));
|
||||
|
||||
cx.spawn_in(window, |this, mut cx| async move {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let Some(buffer_parse_status) = buffer_parse_status_rx.recv().await.ok() else {
|
||||
return Some(());
|
||||
};
|
||||
|
@ -445,7 +445,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()).ok()?;
|
||||
|
||||
let Some(edit_behavior_state) =
|
||||
should_auto_close(&buffer_snapshot, &edited_ranges, &jsx_tag_auto_close_config)
|
||||
|
@ -456,7 +456,7 @@ pub(crate) fn handle_from(
|
|||
let ensure_no_edits_since_start = || -> Option<()> {
|
||||
// <div>wef,wefwef
|
||||
let has_edits_since_start = this
|
||||
.read_with(&cx, |this, cx| {
|
||||
.read_with(cx, |this, cx| {
|
||||
this.buffer.read_with(cx, |buffer, cx| {
|
||||
buffer.buffer(buffer_id).map_or(true, |buffer| {
|
||||
buffer.read_with(cx, |buffer, _| {
|
||||
|
@ -506,7 +506,7 @@ pub(crate) fn handle_from(
|
|||
ensure_no_edits_since_start()?;
|
||||
|
||||
let multi_buffer_snapshot = this
|
||||
.read_with(&cx, |this, cx| {
|
||||
.read_with(cx, |this, cx| {
|
||||
this.buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx))
|
||||
})
|
||||
.ok()?;
|
||||
|
@ -516,7 +516,7 @@ pub(crate) fn handle_from(
|
|||
|
||||
{
|
||||
let selections = this
|
||||
.read_with(&cx, |this, _| this.selections.disjoint_anchors().clone())
|
||||
.read_with(cx, |this, _| this.selections.disjoint_anchors().clone())
|
||||
.ok()?;
|
||||
for selection in selections.iter() {
|
||||
let Some(selection_buffer_offset_head) =
|
||||
|
@ -576,14 +576,14 @@ pub(crate) fn handle_from(
|
|||
}
|
||||
|
||||
buffer
|
||||
.update(&mut cx, |buffer, cx| {
|
||||
.update(cx, |buffer, cx| {
|
||||
buffer.edit(edits, None, cx);
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
if any_selections_need_update {
|
||||
let multi_buffer_snapshot = this
|
||||
.read_with(&cx, |this, cx| {
|
||||
.read_with(cx, |this, cx| {
|
||||
this.buffer.read_with(cx, |buffer, cx| buffer.snapshot(cx))
|
||||
})
|
||||
.ok()?;
|
||||
|
@ -601,7 +601,7 @@ pub(crate) fn handle_from(
|
|||
selection.map(|anchor| anchor.to_offset(&multi_buffer_snapshot))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
this.update_in(&mut cx, |this, window, cx| {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.change_selections_inner(None, false, window, cx, |s| {
|
||||
s.select(base_selections);
|
||||
});
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue