mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
gpui: Actually remove the Result from AsyncApp (#45809)
Depends on: https://github.com/zed-industries/zed/pull/45768 Refactor plan: https://gist.github.com/mikayla-maki/6c4bf263fd80050715ba01f45478796e Overall plan: https://gist.github.com/mikayla-maki/7bb5078e4385a2e683e1e1eb40d17d38 This is the big one. Release Notes: - N/A --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4831e5cba9
commit
97c35c084b
223 changed files with 2272 additions and 2822 deletions
|
|
@ -375,18 +375,16 @@ impl ToolCall {
|
|||
})
|
||||
.ok()??;
|
||||
let buffer = buffer.await.log_err()?;
|
||||
let position = buffer
|
||||
.update(cx, |buffer, _| {
|
||||
let snapshot = buffer.snapshot();
|
||||
if let Some(row) = location.line {
|
||||
let column = snapshot.indent_size_for_line(row).len;
|
||||
let point = snapshot.clip_point(Point::new(row, column), Bias::Left);
|
||||
snapshot.anchor_before(point)
|
||||
} else {
|
||||
Anchor::min_for_buffer(snapshot.remote_id())
|
||||
}
|
||||
})
|
||||
.ok()?;
|
||||
let position = buffer.update(cx, |buffer, _| {
|
||||
let snapshot = buffer.snapshot();
|
||||
if let Some(row) = location.line {
|
||||
let column = snapshot.indent_size_for_line(row).len;
|
||||
let point = snapshot.clip_point(Point::new(row, column), Bias::Left);
|
||||
snapshot.anchor_before(point)
|
||||
} else {
|
||||
Anchor::min_for_buffer(snapshot.remote_id())
|
||||
}
|
||||
});
|
||||
|
||||
Some(ResolvedLocation { buffer, position })
|
||||
}
|
||||
|
|
@ -1803,7 +1801,7 @@ impl AcpThread {
|
|||
.ok();
|
||||
|
||||
let old_checkpoint = git_store
|
||||
.update(cx, |git, cx| git.checkpoint(cx))?
|
||||
.update(cx, |git, cx| git.checkpoint(cx))
|
||||
.await
|
||||
.context("failed to get old checkpoint")
|
||||
.log_err();
|
||||
|
|
@ -1983,7 +1981,7 @@ impl AcpThread {
|
|||
rewind.await?;
|
||||
if let Some(checkpoint) = checkpoint {
|
||||
git_store
|
||||
.update(cx, |git, cx| git.restore_checkpoint(checkpoint, cx))?
|
||||
.update(cx, |git, cx| git.restore_checkpoint(checkpoint, cx))
|
||||
.await?;
|
||||
}
|
||||
|
||||
|
|
@ -2001,7 +1999,7 @@ impl AcpThread {
|
|||
|
||||
let telemetry = ActionLogTelemetry::from(&*self);
|
||||
cx.spawn(async move |this, cx| {
|
||||
cx.update(|cx| truncate.run(id.clone(), cx))?.await?;
|
||||
cx.update(|cx| truncate.run(id.clone(), cx)).await?;
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some((ix, _)) = this.user_message_mut(&id) {
|
||||
// Collect all terminals from entries that will be removed
|
||||
|
|
@ -2060,7 +2058,7 @@ impl AcpThread {
|
|||
let equal = git_store
|
||||
.update(cx, |git, cx| {
|
||||
git.compare_checkpoints(old_checkpoint.clone(), new_checkpoint, cx)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
.unwrap_or(true);
|
||||
|
||||
|
|
@ -2119,17 +2117,14 @@ impl AcpThread {
|
|||
let project = self.project.clone();
|
||||
let action_log = self.action_log.clone();
|
||||
cx.spawn(async move |this, cx| {
|
||||
let load = project
|
||||
.update(cx, |project, cx| {
|
||||
let path = project
|
||||
.project_path_for_absolute_path(&path, cx)
|
||||
.ok_or_else(|| {
|
||||
acp::Error::resource_not_found(Some(path.display().to_string()))
|
||||
})?;
|
||||
Ok(project.open_buffer(path, cx))
|
||||
})
|
||||
.map_err(|e| acp::Error::internal_error().data(e.to_string()))
|
||||
.flatten()?;
|
||||
let load = project.update(cx, |project, cx| {
|
||||
let path = project
|
||||
.project_path_for_absolute_path(&path, cx)
|
||||
.ok_or_else(|| {
|
||||
acp::Error::resource_not_found(Some(path.display().to_string()))
|
||||
})?;
|
||||
Ok::<_, acp::Error>(project.open_buffer(path, cx))
|
||||
})?;
|
||||
|
||||
let buffer = load.await?;
|
||||
|
||||
|
|
@ -2148,9 +2143,9 @@ impl AcpThread {
|
|||
} else {
|
||||
action_log.update(cx, |action_log, cx| {
|
||||
action_log.buffer_read(buffer.clone(), cx);
|
||||
})?;
|
||||
});
|
||||
|
||||
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot())?;
|
||||
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
|
||||
this.update(cx, |this, _| {
|
||||
this.shared_buffers.insert(buffer.clone(), snapshot.clone());
|
||||
})?;
|
||||
|
|
@ -2179,7 +2174,7 @@ impl AcpThread {
|
|||
}),
|
||||
cx,
|
||||
);
|
||||
})?;
|
||||
});
|
||||
|
||||
Ok(snapshot.text_for_range(start..end).collect::<String>())
|
||||
})
|
||||
|
|
@ -2200,7 +2195,7 @@ impl AcpThread {
|
|||
.context("invalid path")?;
|
||||
anyhow::Ok(project.open_buffer(path, cx))
|
||||
});
|
||||
let buffer = load??.await?;
|
||||
let buffer = load?.await?;
|
||||
let snapshot = this.update(cx, |this, cx| {
|
||||
this.shared_buffers
|
||||
.get(&buffer)
|
||||
|
|
@ -2235,7 +2230,7 @@ impl AcpThread {
|
|||
}),
|
||||
cx,
|
||||
);
|
||||
})?;
|
||||
});
|
||||
|
||||
let format_on_save = cx.update(|cx| {
|
||||
action_log.update(cx, |action_log, cx| {
|
||||
|
|
@ -2257,7 +2252,7 @@ impl AcpThread {
|
|||
action_log.buffer_edited(buffer.clone(), cx);
|
||||
});
|
||||
format_on_save
|
||||
})?;
|
||||
});
|
||||
|
||||
if format_on_save {
|
||||
let format_task = project.update(cx, |project, cx| {
|
||||
|
|
@ -2268,16 +2263,16 @@ impl AcpThread {
|
|||
FormatTrigger::Save,
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
format_task.await.log_err();
|
||||
|
||||
action_log.update(cx, |action_log, cx| {
|
||||
action_log.buffer_edited(buffer.clone(), cx);
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
project
|
||||
.update(cx, |project, cx| project.save_buffer(buffer, cx))?
|
||||
.update(cx, |project, cx| project.save_buffer(buffer, cx))
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
|
@ -2323,7 +2318,7 @@ impl AcpThread {
|
|||
project
|
||||
.remote_client()
|
||||
.and_then(|r| r.read(cx).default_system_shell())
|
||||
})?
|
||||
})
|
||||
.unwrap_or_else(|| get_default_system_shell_preferring_bash());
|
||||
let (task_command, task_args) =
|
||||
ShellBuilder::new(&Shell::Program(shell), is_windows)
|
||||
|
|
@ -2341,10 +2336,10 @@ impl AcpThread {
|
|||
},
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
cx.new(|cx| {
|
||||
anyhow::Ok(cx.new(|cx| {
|
||||
Terminal::new(
|
||||
terminal_id,
|
||||
&format!("{} {}", command, args.join(" ")),
|
||||
|
|
@ -2354,7 +2349,7 @@ impl AcpThread {
|
|||
language_registry,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
}))
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ impl Diff {
|
|||
.await
|
||||
.log_err();
|
||||
|
||||
buffer.update(cx, |buffer, cx| buffer.set_language(language.clone(), cx))?;
|
||||
buffer.update(cx, |buffer, cx| buffer.set_language(language.clone(), cx));
|
||||
|
||||
let diff = build_buffer_diff(
|
||||
old_text.unwrap_or("".into()).into(),
|
||||
|
|
@ -45,31 +45,29 @@ impl Diff {
|
|||
)
|
||||
.await?;
|
||||
|
||||
multibuffer
|
||||
.update(cx, |multibuffer, cx| {
|
||||
let hunk_ranges = {
|
||||
let buffer = buffer.read(cx);
|
||||
diff.read(cx)
|
||||
.snapshot(cx)
|
||||
.hunks_intersecting_range(
|
||||
Anchor::min_for_buffer(buffer.remote_id())
|
||||
..Anchor::max_for_buffer(buffer.remote_id()),
|
||||
buffer,
|
||||
)
|
||||
.map(|diff_hunk| diff_hunk.buffer_range.to_point(buffer))
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
multibuffer.update(cx, |multibuffer, cx| {
|
||||
let hunk_ranges = {
|
||||
let buffer = buffer.read(cx);
|
||||
diff.read(cx)
|
||||
.snapshot(cx)
|
||||
.hunks_intersecting_range(
|
||||
Anchor::min_for_buffer(buffer.remote_id())
|
||||
..Anchor::max_for_buffer(buffer.remote_id()),
|
||||
buffer,
|
||||
)
|
||||
.map(|diff_hunk| diff_hunk.buffer_range.to_point(buffer))
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
multibuffer.set_excerpts_for_path(
|
||||
PathKey::for_buffer(&buffer, cx),
|
||||
buffer.clone(),
|
||||
hunk_ranges,
|
||||
multibuffer_context_lines(cx),
|
||||
cx,
|
||||
);
|
||||
multibuffer.add_diff(diff, cx);
|
||||
})
|
||||
.log_err();
|
||||
multibuffer.set_excerpts_for_path(
|
||||
PathKey::for_buffer(&buffer, cx),
|
||||
buffer.clone(),
|
||||
hunk_ranges,
|
||||
multibuffer_context_lines(cx),
|
||||
cx,
|
||||
);
|
||||
multibuffer.add_diff(diff, cx);
|
||||
});
|
||||
|
||||
anyhow::Ok(())
|
||||
}
|
||||
|
|
@ -206,8 +204,8 @@ impl PendingDiff {
|
|||
let buffer_diff = self.diff.clone();
|
||||
let base_text = self.base_text.clone();
|
||||
self.update_diff = cx.spawn(async move |diff, cx| {
|
||||
let text_snapshot = buffer.read_with(cx, |buffer, _| buffer.text_snapshot())?;
|
||||
let language = buffer.read_with(cx, |buffer, _| buffer.language().cloned())?;
|
||||
let text_snapshot = buffer.read_with(cx, |buffer, _| buffer.text_snapshot());
|
||||
let language = buffer.read_with(cx, |buffer, _| buffer.language().cloned());
|
||||
let update = buffer_diff
|
||||
.update(cx, |diff, cx| {
|
||||
diff.update_diff(
|
||||
|
|
@ -217,7 +215,7 @@ impl PendingDiff {
|
|||
language,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
let (task1, task2) = buffer_diff.update(cx, |diff, cx| {
|
||||
let task1 = diff.set_snapshot(update.clone(), &text_snapshot, cx);
|
||||
|
|
@ -226,7 +224,7 @@ impl PendingDiff {
|
|||
.unwrap()
|
||||
.update(cx, |diff, cx| diff.set_snapshot(update, &text_snapshot, cx));
|
||||
(task1, task2)
|
||||
})?;
|
||||
});
|
||||
task1.await;
|
||||
task2.await;
|
||||
diff.update(cx, |diff, cx| {
|
||||
|
|
@ -374,36 +372,37 @@ async fn build_buffer_diff(
|
|||
language_registry: Option<Arc<LanguageRegistry>>,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<Entity<BufferDiff>> {
|
||||
let language = cx.update(|cx| buffer.read(cx).language().cloned())?;
|
||||
let buffer = cx.update(|cx| buffer.read(cx).snapshot())?;
|
||||
let language = cx.update(|cx| buffer.read(cx).language().cloned());
|
||||
let text_snapshot = cx.update(|cx| buffer.read(cx).text_snapshot());
|
||||
let buffer = cx.update(|cx| buffer.read(cx).snapshot());
|
||||
|
||||
let secondary_diff = cx.new(|cx| BufferDiff::new(&buffer, cx))?;
|
||||
let secondary_diff = cx.new(|cx| BufferDiff::new(&buffer, cx));
|
||||
|
||||
let update = secondary_diff
|
||||
.update(cx, |secondary_diff, cx| {
|
||||
secondary_diff.update_diff(
|
||||
buffer.text.clone(),
|
||||
text_snapshot.clone(),
|
||||
Some(old_text),
|
||||
true,
|
||||
language.clone(),
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
|
||||
secondary_diff
|
||||
.update(cx, |secondary_diff, cx| {
|
||||
secondary_diff.language_changed(language.clone(), language_registry.clone(), cx);
|
||||
secondary_diff.set_snapshot(update.clone(), &buffer, cx)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
|
||||
let diff = cx.new(|cx| BufferDiff::new(&buffer, cx))?;
|
||||
let diff = cx.new(|cx| BufferDiff::new(&buffer, cx));
|
||||
diff.update(cx, |diff, cx| {
|
||||
diff.language_changed(language, language_registry, cx);
|
||||
diff.set_secondary_diff(secondary_diff);
|
||||
diff.set_snapshot(update.clone(), &buffer, cx)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
Ok(diff)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ pub async fn create_terminal_entity(
|
|||
project.environment().update(cx, |env, cx| {
|
||||
env.directory_environment(dir.clone().into(), cx)
|
||||
})
|
||||
})?
|
||||
})
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
|
|
@ -225,11 +225,9 @@ pub async fn create_terminal_entity(
|
|||
.remote_client()
|
||||
.and_then(|r| r.read(cx).default_system_shell())
|
||||
.map(Shell::Program)
|
||||
})?
|
||||
})
|
||||
.unwrap_or_else(|| Shell::Program(get_default_system_shell_preferring_bash()));
|
||||
let is_windows = project
|
||||
.read_with(cx, |project, cx| project.path_style(cx).is_windows())
|
||||
.unwrap_or(cfg!(windows));
|
||||
let is_windows = project.read_with(cx, |project, cx| project.path_style(cx).is_windows());
|
||||
let (task_command, task_args) = task::ShellBuilder::new(&shell, is_windows)
|
||||
.redirect_stdin_to_dev_null()
|
||||
.build(Some(command.clone()), &args);
|
||||
|
|
@ -246,6 +244,6 @@ pub async fn create_terminal_entity(
|
|||
},
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ impl ActionLog {
|
|||
.ok();
|
||||
let buffer_repo = git_store.read_with(cx, |git_store, cx| {
|
||||
git_store.repository_and_path_for_buffer_id(buffer.read(cx).remote_id(), cx)
|
||||
})?;
|
||||
});
|
||||
|
||||
let (mut git_diff_updates_tx, mut git_diff_updates_rx) = watch::channel(());
|
||||
let _repo_subscription =
|
||||
|
|
@ -214,7 +214,7 @@ impl ActionLog {
|
|||
}
|
||||
}
|
||||
}))
|
||||
})?
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -394,54 +394,51 @@ impl ActionLog {
|
|||
buffer.read(cx).language().cloned(),
|
||||
))
|
||||
})??;
|
||||
let update = diff.update(cx, |diff, cx| {
|
||||
diff.update_diff(
|
||||
buffer_snapshot.clone(),
|
||||
Some(new_base_text),
|
||||
true,
|
||||
language,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let mut unreviewed_edits = Patch::default();
|
||||
if let Ok(update) = update {
|
||||
let update = update.await;
|
||||
|
||||
diff.update(cx, |diff, cx| {
|
||||
diff.set_snapshot(update.clone(), &buffer_snapshot, cx)
|
||||
})?
|
||||
let update = diff
|
||||
.update(cx, |diff, cx| {
|
||||
diff.update_diff(
|
||||
buffer_snapshot.clone(),
|
||||
Some(new_base_text),
|
||||
true,
|
||||
language,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await;
|
||||
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx))?;
|
||||
diff.update(cx, |diff, cx| {
|
||||
diff.set_snapshot(update.clone(), &buffer_snapshot, cx)
|
||||
})
|
||||
.await;
|
||||
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx));
|
||||
|
||||
unreviewed_edits = cx
|
||||
.background_spawn({
|
||||
let buffer_snapshot = buffer_snapshot.clone();
|
||||
let new_diff_base = new_diff_base.clone();
|
||||
async move {
|
||||
let mut unreviewed_edits = Patch::default();
|
||||
for hunk in diff_snapshot.hunks_intersecting_range(
|
||||
Anchor::min_for_buffer(buffer_snapshot.remote_id())
|
||||
..Anchor::max_for_buffer(buffer_snapshot.remote_id()),
|
||||
&buffer_snapshot,
|
||||
) {
|
||||
let old_range = new_diff_base
|
||||
.offset_to_point(hunk.diff_base_byte_range.start)
|
||||
..new_diff_base.offset_to_point(hunk.diff_base_byte_range.end);
|
||||
let new_range = hunk.range.start..hunk.range.end;
|
||||
unreviewed_edits.push(point_to_row_edit(
|
||||
Edit {
|
||||
old: old_range,
|
||||
new: new_range,
|
||||
},
|
||||
&new_diff_base,
|
||||
buffer_snapshot.as_rope(),
|
||||
));
|
||||
}
|
||||
unreviewed_edits
|
||||
let unreviewed_edits = cx
|
||||
.background_spawn({
|
||||
let buffer_snapshot = buffer_snapshot.clone();
|
||||
let new_diff_base = new_diff_base.clone();
|
||||
async move {
|
||||
let mut unreviewed_edits = Patch::default();
|
||||
for hunk in diff_snapshot.hunks_intersecting_range(
|
||||
Anchor::min_for_buffer(buffer_snapshot.remote_id())
|
||||
..Anchor::max_for_buffer(buffer_snapshot.remote_id()),
|
||||
&buffer_snapshot,
|
||||
) {
|
||||
let old_range = new_diff_base
|
||||
.offset_to_point(hunk.diff_base_byte_range.start)
|
||||
..new_diff_base.offset_to_point(hunk.diff_base_byte_range.end);
|
||||
let new_range = hunk.range.start..hunk.range.end;
|
||||
unreviewed_edits.push(point_to_row_edit(
|
||||
Edit {
|
||||
old: old_range,
|
||||
new: new_range,
|
||||
},
|
||||
&new_diff_base,
|
||||
buffer_snapshot.as_rope(),
|
||||
));
|
||||
}
|
||||
})
|
||||
.await;
|
||||
}
|
||||
unreviewed_edits
|
||||
}
|
||||
})
|
||||
.await;
|
||||
this.update(cx, |this, cx| {
|
||||
let tracked_buffer = this
|
||||
.tracked_buffers
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ impl ActivityIndicator {
|
|||
cx,
|
||||
);
|
||||
buffer.set_capability(language::Capability::ReadOnly, cx);
|
||||
})?;
|
||||
});
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
workspace.add_item_to_active_pane(
|
||||
Box::new(cx.new(|cx| {
|
||||
|
|
|
|||
|
|
@ -250,10 +250,10 @@ impl NativeAgent {
|
|||
log::debug!("Creating new NativeAgent");
|
||||
|
||||
let project_context = cx
|
||||
.update(|cx| Self::build_project_context(&project, prompt_store.as_ref(), cx))?
|
||||
.update(|cx| Self::build_project_context(&project, prompt_store.as_ref(), cx))
|
||||
.await;
|
||||
|
||||
cx.new(|cx| {
|
||||
Ok(cx.new(|cx| {
|
||||
let context_server_store = project.read(cx).context_server_store();
|
||||
let context_server_registry =
|
||||
cx.new(|cx| ContextServerRegistry::new(context_server_store.clone(), cx));
|
||||
|
|
@ -295,7 +295,7 @@ impl NativeAgent {
|
|||
fs,
|
||||
_subscriptions: subscriptions,
|
||||
}
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn register_session(
|
||||
|
|
@ -512,10 +512,12 @@ impl NativeAgent {
|
|||
let buffer_task =
|
||||
project.update(cx, |project, cx| project.open_buffer(project_path, cx));
|
||||
let rope_task = cx.spawn(async move |cx| {
|
||||
buffer_task.await?.read_with(cx, |buffer, cx| {
|
||||
let buffer = buffer_task.await?;
|
||||
let (project_entry_id, rope) = buffer.read_with(cx, |buffer, cx| {
|
||||
let project_entry_id = buffer.entry_id(cx).context("buffer has no file")?;
|
||||
anyhow::Ok((project_entry_id, buffer.as_rope().clone()))
|
||||
})?
|
||||
})?;
|
||||
anyhow::Ok((project_entry_id, rope))
|
||||
});
|
||||
// Build a string from the rope on a background thread.
|
||||
cx.background_spawn(async move {
|
||||
|
|
@ -761,10 +763,10 @@ impl NativeAgent {
|
|||
let thread = task.await?;
|
||||
let acp_thread =
|
||||
this.update(cx, |this, cx| this.register_session(thread.clone(), cx))?;
|
||||
let events = thread.update(cx, |thread, cx| thread.replay(cx))?;
|
||||
let events = thread.update(cx, |thread, cx| thread.replay(cx));
|
||||
cx.update(|cx| {
|
||||
NativeAgentConnection::handle_thread_events(events, acp_thread.downgrade(), cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
Ok(acp_thread)
|
||||
})
|
||||
|
|
@ -811,7 +813,7 @@ impl NativeAgent {
|
|||
};
|
||||
let db_thread = db_thread.await;
|
||||
database.save_thread(id, db_thread).await.log_err();
|
||||
history.update(cx, |history, cx| history.reload(cx)).ok();
|
||||
history.update(cx, |history, cx| history.reload(cx));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -849,7 +851,7 @@ impl NativeAgent {
|
|||
path_style,
|
||||
cx,
|
||||
);
|
||||
})?;
|
||||
});
|
||||
|
||||
for message in prompt.messages {
|
||||
let context_server::types::PromptMessage { role, content } = message;
|
||||
|
|
@ -866,13 +868,11 @@ impl NativeAgent {
|
|||
true,
|
||||
cx,
|
||||
);
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
})?;
|
||||
|
||||
thread.update(cx, |thread, cx| {
|
||||
thread.push_acp_user_block(id, [block], path_style, cx);
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
});
|
||||
}
|
||||
context_server::types::Role::Assistant => {
|
||||
acp_thread.update(cx, |acp_thread, cx| {
|
||||
|
|
@ -882,13 +882,11 @@ impl NativeAgent {
|
|||
true,
|
||||
cx,
|
||||
);
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
})?;
|
||||
|
||||
thread.update(cx, |thread, cx| {
|
||||
thread.push_acp_agent_block(block, cx);
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -902,11 +900,11 @@ impl NativeAgent {
|
|||
// Resume if MCP prompt did not end with a user message
|
||||
thread.resume(cx)
|
||||
}
|
||||
})??;
|
||||
})?;
|
||||
|
||||
cx.update(|cx| {
|
||||
NativeAgentConnection::handle_thread_events(response_stream, acp_thread, cx)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
|
@ -1187,33 +1185,30 @@ impl acp_thread::AgentConnection for NativeAgentConnection {
|
|||
log::debug!("Starting thread creation in async context");
|
||||
|
||||
// Create Thread
|
||||
let thread = agent.update(
|
||||
cx,
|
||||
|agent, cx: &mut gpui::Context<NativeAgent>| -> Result<_> {
|
||||
// Fetch default model from registry settings
|
||||
let registry = LanguageModelRegistry::read_global(cx);
|
||||
// Log available models for debugging
|
||||
let available_count = registry.available_models(cx).count();
|
||||
log::debug!("Total available models: {}", available_count);
|
||||
let thread = agent.update(cx, |agent, cx| {
|
||||
// Fetch default model from registry settings
|
||||
let registry = LanguageModelRegistry::read_global(cx);
|
||||
// Log available models for debugging
|
||||
let available_count = registry.available_models(cx).count();
|
||||
log::debug!("Total available models: {}", available_count);
|
||||
|
||||
let default_model = registry.default_model().and_then(|default_model| {
|
||||
agent
|
||||
.models
|
||||
.model_from_id(&LanguageModels::model_id(&default_model.model))
|
||||
});
|
||||
Ok(cx.new(|cx| {
|
||||
Thread::new(
|
||||
project.clone(),
|
||||
agent.project_context.clone(),
|
||||
agent.context_server_registry.clone(),
|
||||
agent.templates.clone(),
|
||||
default_model,
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
},
|
||||
)??;
|
||||
agent.update(cx, |agent, cx| agent.register_session(thread, cx))
|
||||
let default_model = registry.default_model().and_then(|default_model| {
|
||||
agent
|
||||
.models
|
||||
.model_from_id(&LanguageModels::model_id(&default_model.model))
|
||||
});
|
||||
cx.new(|cx| {
|
||||
Thread::new(
|
||||
project.clone(),
|
||||
agent.project_context.clone(),
|
||||
agent.context_server_registry.clone(),
|
||||
agent.templates.clone(),
|
||||
default_model,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
});
|
||||
Ok(agent.update(cx, |agent, cx| agent.register_session(thread, cx)))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1446,7 +1441,7 @@ impl ThreadEnvironment for AcpThreadEnvironment {
|
|||
let terminal = task?.await?;
|
||||
|
||||
let (drop_tx, drop_rx) = oneshot::channel();
|
||||
let terminal_id = terminal.read_with(cx, |terminal, _cx| terminal.id().clone())?;
|
||||
let terminal_id = terminal.read_with(cx, |terminal, _cx| terminal.id().clone());
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
drop_rx.await.ok();
|
||||
|
|
@ -1471,17 +1466,19 @@ pub struct AcpTerminalHandle {
|
|||
|
||||
impl TerminalHandle for AcpTerminalHandle {
|
||||
fn id(&self, cx: &AsyncApp) -> Result<acp::TerminalId> {
|
||||
self.terminal.read_with(cx, |term, _cx| term.id().clone())
|
||||
Ok(self.terminal.read_with(cx, |term, _cx| term.id().clone()))
|
||||
}
|
||||
|
||||
fn wait_for_exit(&self, cx: &AsyncApp) -> Result<Shared<Task<acp::TerminalExitStatus>>> {
|
||||
self.terminal
|
||||
.read_with(cx, |term, _cx| term.wait_for_exit())
|
||||
Ok(self
|
||||
.terminal
|
||||
.read_with(cx, |term, _cx| term.wait_for_exit()))
|
||||
}
|
||||
|
||||
fn current_output(&self, cx: &AsyncApp) -> Result<acp::TerminalOutputResponse> {
|
||||
self.terminal
|
||||
.read_with(cx, |term, cx| term.current_output(cx))
|
||||
Ok(self
|
||||
.terminal
|
||||
.read_with(cx, |term, cx| term.current_output(cx)))
|
||||
}
|
||||
|
||||
fn kill(&self, cx: &AsyncApp) -> Result<()> {
|
||||
|
|
@ -1489,13 +1486,14 @@ impl TerminalHandle for AcpTerminalHandle {
|
|||
self.terminal.update(cx, |terminal, cx| {
|
||||
terminal.kill(cx);
|
||||
});
|
||||
})?;
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn was_stopped_by_user(&self, cx: &AsyncApp) -> Result<bool> {
|
||||
self.terminal
|
||||
.read_with(cx, |term, _cx| term.was_stopped_by_user())
|
||||
Ok(self
|
||||
.terminal
|
||||
.read_with(cx, |term, _cx| term.was_stopped_by_user()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ impl EditAgent {
|
|||
let (events_tx, events_rx) = mpsc::unbounded();
|
||||
let conversation = conversation.clone();
|
||||
let output = cx.spawn(async move |cx| {
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
|
||||
let path = cx.update(|cx| snapshot.resolve_file_path(true, cx))?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
|
||||
let path = cx.update(|cx| snapshot.resolve_file_path(true, cx));
|
||||
let prompt = CreateFilePromptTemplate {
|
||||
path,
|
||||
edit_description,
|
||||
|
|
@ -148,7 +148,7 @@ impl EditAgent {
|
|||
let this = self.clone();
|
||||
let task = cx.spawn(async move |cx| {
|
||||
this.action_log
|
||||
.update(cx, |log, cx| log.buffer_created(buffer.clone(), cx))?;
|
||||
.update(cx, |log, cx| log.buffer_created(buffer.clone(), cx));
|
||||
this.overwrite_with_chunks_internal(buffer, parse_rx, output_events_tx, cx)
|
||||
.await?;
|
||||
parse_task.await
|
||||
|
|
@ -182,7 +182,7 @@ impl EditAgent {
|
|||
Anchor::min_max_range_for_buffer(buffer.read(cx).remote_id()),
|
||||
))
|
||||
.ok();
|
||||
})?;
|
||||
});
|
||||
|
||||
while let Some(event) = parse_rx.next().await {
|
||||
match event? {
|
||||
|
|
@ -203,7 +203,7 @@ impl EditAgent {
|
|||
)
|
||||
});
|
||||
buffer.read(cx).remote_id()
|
||||
})?;
|
||||
});
|
||||
output_events_tx
|
||||
.unbounded_send(EditAgentOutputEvent::Edited(
|
||||
Anchor::min_max_range_for_buffer(buffer_id),
|
||||
|
|
@ -231,8 +231,8 @@ impl EditAgent {
|
|||
let conversation = conversation.clone();
|
||||
let edit_format = self.edit_format;
|
||||
let output = cx.spawn(async move |cx| {
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
|
||||
let path = cx.update(|cx| snapshot.resolve_file_path(true, cx))?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
|
||||
let path = cx.update(|cx| snapshot.resolve_file_path(true, cx));
|
||||
let prompt = match edit_format {
|
||||
EditFormat::XmlTags => EditFileXmlPromptTemplate {
|
||||
path,
|
||||
|
|
@ -263,7 +263,7 @@ impl EditAgent {
|
|||
cx: &mut AsyncApp,
|
||||
) -> Result<EditAgentOutput> {
|
||||
self.action_log
|
||||
.update(cx, |log, cx| log.buffer_read(buffer.clone(), cx))?;
|
||||
.update(cx, |log, cx| log.buffer_read(buffer.clone(), cx));
|
||||
|
||||
let (output, edit_events) = Self::parse_edit_chunks(edit_chunks, self.edit_format, cx);
|
||||
let mut edit_events = edit_events.peekable();
|
||||
|
|
@ -274,7 +274,7 @@ impl EditAgent {
|
|||
continue;
|
||||
};
|
||||
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
|
||||
|
||||
// Resolve the old text in the background, updating the agent
|
||||
// location as we keep refining which range it corresponds to.
|
||||
|
|
@ -292,7 +292,7 @@ impl EditAgent {
|
|||
}),
|
||||
cx,
|
||||
);
|
||||
})?;
|
||||
});
|
||||
output_events
|
||||
.unbounded_send(EditAgentOutputEvent::ResolvingEditRange(old_range))
|
||||
.ok();
|
||||
|
|
@ -375,7 +375,7 @@ impl EditAgent {
|
|||
);
|
||||
});
|
||||
(min_edit_start, max_edit_end)
|
||||
})?;
|
||||
});
|
||||
output_events
|
||||
.unbounded_send(EditAgentOutputEvent::Edited(min_edit_start..max_edit_end))
|
||||
.ok();
|
||||
|
|
|
|||
|
|
@ -1473,9 +1473,9 @@ impl EditAgentTest {
|
|||
.provider(&selected_model.provider)
|
||||
.expect("Provider not found");
|
||||
provider.authenticate(cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
cx.update(|cx| {
|
||||
Ok(cx.update(|cx| {
|
||||
let models = LanguageModelRegistry::read_global(cx);
|
||||
let model = models
|
||||
.available_models(cx)
|
||||
|
|
@ -1485,7 +1485,7 @@ impl EditAgentTest {
|
|||
})
|
||||
.unwrap_or_else(|| panic!("Model {} not found", selected_model.model.0));
|
||||
model
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
async fn eval(&self, mut eval: EvalInput, cx: &mut TestAppContext) -> Result<EditEvalOutput> {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub fn load_agent_thread(
|
|||
cx.spawn(async move |cx| {
|
||||
let (agent, _) = connection.await?;
|
||||
let agent = agent.downcast::<crate::NativeAgentConnection>().unwrap();
|
||||
cx.update(|cx| agent.load_thread(session_id, cx))?.await
|
||||
cx.update(|cx| agent.load_thread(session_id, cx)).await
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ pub async fn get_buffer_content_or_outline(
|
|||
path: Option<&str>,
|
||||
cx: &AsyncApp,
|
||||
) -> Result<BufferContent> {
|
||||
let file_size = buffer.read_with(cx, |buffer, _| buffer.text().len())?;
|
||||
let file_size = buffer.read_with(cx, |buffer, _| buffer.text().len());
|
||||
|
||||
if file_size > AUTO_OUTLINE_SIZE {
|
||||
// For large files, use outline instead of full content
|
||||
// Wait until the buffer has been fully parsed, so we can read its outline
|
||||
buffer
|
||||
.read_with(cx, |buffer, _| buffer.parsing_idle())?
|
||||
.read_with(cx, |buffer, _| buffer.parsing_idle())
|
||||
.await;
|
||||
|
||||
let outline_items = buffer.read_with(cx, |buffer, _| {
|
||||
|
|
@ -42,7 +42,7 @@ pub async fn get_buffer_content_or_outline(
|
|||
.into_iter()
|
||||
.map(|item| item.to_point(&snapshot))
|
||||
.collect::<Vec<_>>()
|
||||
})?;
|
||||
});
|
||||
|
||||
// If no outline exists, fall back to first 1KB so the agent has some context
|
||||
if outline_items.is_empty() {
|
||||
|
|
@ -55,7 +55,7 @@ pub async fn get_buffer_content_or_outline(
|
|||
} else {
|
||||
format!("# First 1KB of file (file too large to show full content, and no outline available)\n\n{content}")
|
||||
}
|
||||
})?;
|
||||
});
|
||||
|
||||
return Ok(BufferContent {
|
||||
text,
|
||||
|
|
@ -76,7 +76,7 @@ pub async fn get_buffer_content_or_outline(
|
|||
})
|
||||
} else {
|
||||
// File is small enough, return full content
|
||||
let text = buffer.read_with(cx, |buffer, _| buffer.text())?;
|
||||
let text = buffer.read_with(cx, |buffer, _| buffer.text());
|
||||
Ok(BufferContent {
|
||||
text,
|
||||
is_outline: false,
|
||||
|
|
|
|||
|
|
@ -2413,7 +2413,7 @@ where
|
|||
cx.spawn(async move |cx| {
|
||||
let input = serde_json::from_value(input)?;
|
||||
let output = cx
|
||||
.update(|cx| self.0.clone().run(input, event_stream, cx))?
|
||||
.update(|cx| self.0.clone().run(input, event_stream, cx))
|
||||
.await?;
|
||||
let raw_output = serde_json::to_value(&output)?;
|
||||
Ok(AgentToolOutput {
|
||||
|
|
@ -2650,7 +2650,7 @@ impl ToolCallEventStream {
|
|||
.get_or_insert_default()
|
||||
.set_always_allow_tool_actions(true);
|
||||
});
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -403,10 +403,7 @@ pub fn get_prompt(
|
|||
arguments: HashMap<String, String>,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Task<Result<context_server::types::PromptsGetResponse>> {
|
||||
let server = match cx.update(|cx| server_store.read(cx).get_running_server(server_id)) {
|
||||
Ok(server) => server,
|
||||
Err(error) => return Task::ready(Err(error)),
|
||||
};
|
||||
let server = cx.update(|cx| server_store.read(cx).get_running_server(server_id));
|
||||
let Some(server) = server else {
|
||||
return Task::ready(Err(anyhow::anyhow!("Context server not found")));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -115,19 +115,19 @@ impl AgentTool for DeletePathTool {
|
|||
cx.spawn(async move |cx| {
|
||||
while let Some(path) = paths_rx.next().await {
|
||||
if let Ok(buffer) = project
|
||||
.update(cx, |project, cx| project.open_buffer(path, cx))?
|
||||
.update(cx, |project, cx| project.open_buffer(path, cx))
|
||||
.await
|
||||
{
|
||||
action_log.update(cx, |action_log, cx| {
|
||||
action_log.will_delete_buffer(buffer.clone(), cx)
|
||||
})?;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let deletion_task = project
|
||||
.update(cx, |project, cx| {
|
||||
project.delete_file(project_path, false, cx)
|
||||
})?
|
||||
})
|
||||
.with_context(|| {
|
||||
format!("Couldn't delete {path} because that path isn't in this project.")
|
||||
})?;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ impl AgentTool for DiagnosticsTool {
|
|||
cx.spawn(async move |cx| {
|
||||
let mut output = String::new();
|
||||
let buffer = buffer.await?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
|
||||
|
||||
for (_, group) in snapshot.diagnostic_groups(None) {
|
||||
let entry = &group.entries[group.primary_ix];
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ impl AgentTool for EditFileTool {
|
|||
let buffer = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_buffer(project_path.clone(), cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Check if the file has been modified since the agent last read it
|
||||
|
|
@ -357,7 +357,7 @@ impl AgentTool for EditFileTool {
|
|||
}
|
||||
}
|
||||
|
||||
let diff = cx.new(|cx| Diff::new(buffer.clone(), cx))?;
|
||||
let diff = cx.new(|cx| Diff::new(buffer.clone(), cx));
|
||||
event_stream.update_diff(diff.clone());
|
||||
let _finalize_diff = util::defer({
|
||||
let diff = diff.downgrade();
|
||||
|
|
@ -367,7 +367,7 @@ impl AgentTool for EditFileTool {
|
|||
}
|
||||
});
|
||||
|
||||
let old_snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
|
||||
let old_snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
|
||||
let old_text = cx
|
||||
.background_spawn({
|
||||
let old_snapshot = old_snapshot.clone();
|
||||
|
|
@ -399,9 +399,9 @@ impl AgentTool for EditFileTool {
|
|||
match event {
|
||||
EditAgentOutputEvent::Edited(range) => {
|
||||
if !emitted_location {
|
||||
let line = buffer.update(cx, |buffer, _cx| {
|
||||
let line = Some(buffer.update(cx, |buffer, _cx| {
|
||||
range.start.to_point(&buffer.snapshot()).row
|
||||
}).ok();
|
||||
}));
|
||||
if let Some(abs_path) = abs_path.clone() {
|
||||
event_stream.update_fields(ToolCallUpdateFields::new().locations(vec![ToolCallLocation::new(abs_path).line(line)]));
|
||||
}
|
||||
|
|
@ -411,7 +411,7 @@ impl AgentTool for EditFileTool {
|
|||
EditAgentOutputEvent::UnresolvedEditRange => hallucinated_old_text = true,
|
||||
EditAgentOutputEvent::AmbiguousEditRange(ranges) => ambiguous_ranges = ranges,
|
||||
EditAgentOutputEvent::ResolvingEditRange(range) => {
|
||||
diff.update(cx, |card, cx| card.reveal_range(range.clone(), cx))?;
|
||||
diff.update(cx, |card, cx| card.reveal_range(range.clone(), cx));
|
||||
// if !emitted_location {
|
||||
// let line = buffer.update(cx, |buffer, _cx| {
|
||||
// range.start.to_point(&buffer.snapshot()).row
|
||||
|
|
@ -428,23 +428,21 @@ impl AgentTool for EditFileTool {
|
|||
}
|
||||
|
||||
// If format_on_save is enabled, format the buffer
|
||||
let format_on_save_enabled = buffer
|
||||
.read_with(cx, |buffer, cx| {
|
||||
let settings = language_settings::language_settings(
|
||||
buffer.language().map(|l| l.name()),
|
||||
buffer.file(),
|
||||
cx,
|
||||
);
|
||||
settings.format_on_save != FormatOnSave::Off
|
||||
})
|
||||
.unwrap_or(false);
|
||||
let format_on_save_enabled = buffer.read_with(cx, |buffer, cx| {
|
||||
let settings = language_settings::language_settings(
|
||||
buffer.language().map(|l| l.name()),
|
||||
buffer.file(),
|
||||
cx,
|
||||
);
|
||||
settings.format_on_save != FormatOnSave::Off
|
||||
});
|
||||
|
||||
let edit_agent_output = output.await?;
|
||||
|
||||
if format_on_save_enabled {
|
||||
action_log.update(cx, |log, cx| {
|
||||
log.buffer_edited(buffer.clone(), cx);
|
||||
})?;
|
||||
});
|
||||
|
||||
let format_task = project.update(cx, |project, cx| {
|
||||
project.format(
|
||||
|
|
@ -454,30 +452,30 @@ impl AgentTool for EditFileTool {
|
|||
FormatTrigger::Save,
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
format_task.await.log_err();
|
||||
}
|
||||
|
||||
project
|
||||
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))?
|
||||
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))
|
||||
.await?;
|
||||
|
||||
action_log.update(cx, |log, cx| {
|
||||
log.buffer_edited(buffer.clone(), cx);
|
||||
})?;
|
||||
});
|
||||
|
||||
// Update the recorded read time after a successful edit so consecutive edits work
|
||||
if let Some(abs_path) = abs_path.as_ref() {
|
||||
if let Some(new_mtime) = buffer.read_with(cx, |buffer, _| {
|
||||
buffer.file().and_then(|file| file.disk_state().mtime())
|
||||
})? {
|
||||
}) {
|
||||
self.thread.update(cx, |thread, _| {
|
||||
thread.file_read_times.insert(abs_path.to_path_buf(), new_mtime);
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
let new_snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
|
||||
let new_snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
|
||||
let (new_text, unified_diff) = cx
|
||||
.background_spawn({
|
||||
let new_snapshot = new_snapshot.clone();
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ impl AgentTool for GrepTool {
|
|||
continue;
|
||||
}
|
||||
|
||||
let Ok((Some(path), mut parse_status)) = buffer.read_with(cx, |buffer, cx| {
|
||||
let (Some(path), mut parse_status) = buffer.read_with(cx, |buffer, cx| {
|
||||
(buffer.file().map(|file| file.full_path(cx)), buffer.parse_status())
|
||||
}) else {
|
||||
continue;
|
||||
|
|
@ -200,20 +200,21 @@ impl AgentTool for GrepTool {
|
|||
// Check if this file should be excluded based on its worktree settings
|
||||
if let Ok(Some(project_path)) = project.read_with(cx, |project, cx| {
|
||||
project.find_project_path(&path, cx)
|
||||
})
|
||||
&& cx.update(|cx| {
|
||||
}) {
|
||||
if cx.update(|cx| {
|
||||
let worktree_settings = WorktreeSettings::get(Some((&project_path).into()), cx);
|
||||
worktree_settings.is_path_excluded(&project_path.path)
|
||||
|| worktree_settings.is_path_private(&project_path.path)
|
||||
}).unwrap_or(false) {
|
||||
}) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while *parse_status.borrow() != ParseStatus::Idle {
|
||||
parse_status.changed().await?;
|
||||
}
|
||||
|
||||
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
|
||||
|
||||
let mut ranges = ranges
|
||||
.into_iter()
|
||||
|
|
|
|||
|
|
@ -167,14 +167,14 @@ impl AgentTool for ReadFileTool {
|
|||
self.project.update(cx, |project, cx| {
|
||||
project.open_image(project_path.clone(), cx)
|
||||
})
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
let image =
|
||||
image_entity.read_with(cx, |image_item, _| Arc::clone(&image_item.image))?;
|
||||
image_entity.read_with(cx, |image_item, _| Arc::clone(&image_item.image));
|
||||
|
||||
let language_model_image = cx
|
||||
.update(|cx| LanguageModelImage::from_image(image, cx))?
|
||||
.update(|cx| LanguageModelImage::from_image(image, cx))
|
||||
.await
|
||||
.context("processing image")?;
|
||||
|
||||
|
|
@ -197,21 +197,21 @@ impl AgentTool for ReadFileTool {
|
|||
project.update(cx, |project, cx| {
|
||||
project.open_buffer(project_path.clone(), cx)
|
||||
})
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
if buffer.read_with(cx, |buffer, _| {
|
||||
buffer
|
||||
.file()
|
||||
.as_ref()
|
||||
.is_none_or(|file| !file.disk_state().exists())
|
||||
})? {
|
||||
}) {
|
||||
anyhow::bail!("{file_path} not found");
|
||||
}
|
||||
|
||||
// Record the file read time and mtime
|
||||
if let Some(mtime) = buffer.read_with(cx, |buffer, _| {
|
||||
buffer.file().and_then(|file| file.disk_state().mtime())
|
||||
})? {
|
||||
}) {
|
||||
self.thread
|
||||
.update(cx, |thread, _| {
|
||||
thread.file_read_times.insert(abs_path.to_path_buf(), mtime);
|
||||
|
|
@ -239,11 +239,11 @@ impl AgentTool for ReadFileTool {
|
|||
let start = buffer.anchor_before(Point::new(start_row, 0));
|
||||
let end = buffer.anchor_before(Point::new(end_row, 0));
|
||||
buffer.text_for_range(start..end).collect::<String>()
|
||||
})?;
|
||||
});
|
||||
|
||||
action_log.update(cx, |log, cx| {
|
||||
log.buffer_read(buffer.clone(), cx);
|
||||
})?;
|
||||
});
|
||||
|
||||
Ok(result.into())
|
||||
} else {
|
||||
|
|
@ -257,7 +257,7 @@ impl AgentTool for ReadFileTool {
|
|||
|
||||
action_log.update(cx, |log, cx| {
|
||||
log.buffer_read(buffer.clone(), cx);
|
||||
})?;
|
||||
});
|
||||
|
||||
if buffer_content.is_outline {
|
||||
Ok(formatdoc! {"
|
||||
|
|
@ -297,7 +297,7 @@ impl AgentTool for ReadFileTool {
|
|||
acp::ToolCallContent::Content(acp::Content::new(markdown)),
|
||||
]));
|
||||
}
|
||||
})?;
|
||||
});
|
||||
|
||||
result
|
||||
})
|
||||
|
|
|
|||
|
|
@ -74,49 +74,29 @@ impl AgentTool for RestoreFileFromDiskTool {
|
|||
let mut clean_paths: Vec<PathBuf> = Vec::new();
|
||||
let mut not_found_paths: Vec<PathBuf> = Vec::new();
|
||||
let mut open_errors: Vec<(PathBuf, String)> = Vec::new();
|
||||
let mut dirty_check_errors: Vec<(PathBuf, String)> = Vec::new();
|
||||
let dirty_check_errors: Vec<(PathBuf, String)> = Vec::new();
|
||||
let mut reload_errors: Vec<String> = Vec::new();
|
||||
|
||||
for path in input_paths {
|
||||
let project_path =
|
||||
project.read_with(cx, |project, cx| project.find_project_path(&path, cx));
|
||||
|
||||
let project_path = match project_path {
|
||||
Ok(Some(project_path)) => project_path,
|
||||
Ok(None) => {
|
||||
not_found_paths.push(path);
|
||||
continue;
|
||||
}
|
||||
Err(error) => {
|
||||
open_errors.push((path, error.to_string()));
|
||||
continue;
|
||||
}
|
||||
let Some(project_path) =
|
||||
project.read_with(cx, |project, cx| project.find_project_path(&path, cx))
|
||||
else {
|
||||
not_found_paths.push(path);
|
||||
continue;
|
||||
};
|
||||
|
||||
let open_buffer_task =
|
||||
project.update(cx, |project, cx| project.open_buffer(project_path, cx));
|
||||
|
||||
let buffer = match open_buffer_task {
|
||||
Ok(task) => match task.await {
|
||||
Ok(buffer) => buffer,
|
||||
Err(error) => {
|
||||
open_errors.push((path, error.to_string()));
|
||||
continue;
|
||||
}
|
||||
},
|
||||
let buffer = match open_buffer_task.await {
|
||||
Ok(buffer) => buffer,
|
||||
Err(error) => {
|
||||
open_errors.push((path, error.to_string()));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let is_dirty = match buffer.read_with(cx, |buffer, _| buffer.is_dirty()) {
|
||||
Ok(is_dirty) => is_dirty,
|
||||
Err(error) => {
|
||||
dirty_check_errors.push((path, error.to_string()));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let is_dirty = buffer.read_with(cx, |buffer, _| buffer.is_dirty());
|
||||
|
||||
if is_dirty {
|
||||
buffers_to_reload.insert(buffer);
|
||||
|
|
@ -131,15 +111,8 @@ impl AgentTool for RestoreFileFromDiskTool {
|
|||
project.reload_buffers(buffers_to_reload, true, cx)
|
||||
});
|
||||
|
||||
match reload_task {
|
||||
Ok(task) => {
|
||||
if let Err(error) = task.await {
|
||||
reload_errors.push(error.to_string());
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
reload_errors.push(error.to_string());
|
||||
}
|
||||
if let Err(error) = reload_task.await {
|
||||
reload_errors.push(error.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,49 +71,29 @@ impl AgentTool for SaveFileTool {
|
|||
let mut clean_paths: Vec<PathBuf> = Vec::new();
|
||||
let mut not_found_paths: Vec<PathBuf> = Vec::new();
|
||||
let mut open_errors: Vec<(PathBuf, String)> = Vec::new();
|
||||
let mut dirty_check_errors: Vec<(PathBuf, String)> = Vec::new();
|
||||
let dirty_check_errors: Vec<(PathBuf, String)> = Vec::new();
|
||||
let mut save_errors: Vec<(String, String)> = Vec::new();
|
||||
|
||||
for path in input_paths {
|
||||
let project_path =
|
||||
project.read_with(cx, |project, cx| project.find_project_path(&path, cx));
|
||||
|
||||
let project_path = match project_path {
|
||||
Ok(Some(project_path)) => project_path,
|
||||
Ok(None) => {
|
||||
not_found_paths.push(path);
|
||||
continue;
|
||||
}
|
||||
Err(error) => {
|
||||
open_errors.push((path, error.to_string()));
|
||||
continue;
|
||||
}
|
||||
let Some(project_path) =
|
||||
project.read_with(cx, |project, cx| project.find_project_path(&path, cx))
|
||||
else {
|
||||
not_found_paths.push(path);
|
||||
continue;
|
||||
};
|
||||
|
||||
let open_buffer_task =
|
||||
project.update(cx, |project, cx| project.open_buffer(project_path, cx));
|
||||
|
||||
let buffer = match open_buffer_task {
|
||||
Ok(task) => match task.await {
|
||||
Ok(buffer) => buffer,
|
||||
Err(error) => {
|
||||
open_errors.push((path, error.to_string()));
|
||||
continue;
|
||||
}
|
||||
},
|
||||
let buffer = match open_buffer_task.await {
|
||||
Ok(buffer) => buffer,
|
||||
Err(error) => {
|
||||
open_errors.push((path, error.to_string()));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let is_dirty = match buffer.read_with(cx, |buffer, _| buffer.is_dirty()) {
|
||||
Ok(is_dirty) => is_dirty,
|
||||
Err(error) => {
|
||||
dirty_check_errors.push((path, error.to_string()));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let is_dirty = buffer.read_with(cx, |buffer, _| buffer.is_dirty());
|
||||
|
||||
if is_dirty {
|
||||
buffers_to_save.insert(buffer);
|
||||
|
|
@ -125,30 +105,19 @@ impl AgentTool for SaveFileTool {
|
|||
|
||||
// Save each buffer individually since there's no batch save API.
|
||||
for buffer in buffers_to_save {
|
||||
let path_for_buffer = match buffer.read_with(cx, |buffer, _| {
|
||||
buffer
|
||||
.file()
|
||||
.map(|file| file.path().to_rel_path_buf())
|
||||
.map(|path| path.as_rel_path().as_unix_str().to_owned())
|
||||
}) {
|
||||
Ok(path) => path.unwrap_or_else(|| "<unknown>".to_string()),
|
||||
Err(error) => {
|
||||
save_errors.push(("<unknown>".to_string(), error.to_string()));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let path_for_buffer = buffer
|
||||
.read_with(cx, |buffer, _| {
|
||||
buffer
|
||||
.file()
|
||||
.map(|file| file.path().to_rel_path_buf())
|
||||
.map(|path| path.as_rel_path().as_unix_str().to_owned())
|
||||
})
|
||||
.unwrap_or_else(|| "<unknown>".to_string());
|
||||
|
||||
let save_task = project.update(cx, |project, cx| project.save_buffer(buffer, cx));
|
||||
|
||||
match save_task {
|
||||
Ok(task) => {
|
||||
if let Err(error) = task.await {
|
||||
save_errors.push((path_for_buffer, error.to_string()));
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
save_errors.push((path_for_buffer, error.to_string()));
|
||||
}
|
||||
if let Err(error) = save_task.await {
|
||||
save_errors.push((path_for_buffer, error.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ impl AcpConnection {
|
|||
is_remote: bool,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<Self> {
|
||||
let shell = cx.update(|cx| TerminalSettings::get(None, cx).shell.clone())?;
|
||||
let shell = cx.update(|cx| TerminalSettings::get(None, cx).shell.clone());
|
||||
let builder = ShellBuilder::new(&shell, cfg!(windows)).non_interactive();
|
||||
let mut child =
|
||||
builder.build_std_command(Some(command.path.display().to_string()), &command.args);
|
||||
|
|
@ -133,13 +133,13 @@ impl AcpConnection {
|
|||
|
||||
let sessions = Rc::new(RefCell::new(HashMap::default()));
|
||||
|
||||
let (release_channel, version) = cx.update(|cx| {
|
||||
let (release_channel, version): (Option<&str>, String) = cx.update(|cx| {
|
||||
(
|
||||
release_channel::ReleaseChannel::try_global(cx)
|
||||
.map(|release_channel| release_channel.display_name()),
|
||||
release_channel::AppVersion::global(cx).to_string(),
|
||||
)
|
||||
})?;
|
||||
});
|
||||
|
||||
let client = ClientDelegate {
|
||||
sessions: sessions.clone(),
|
||||
|
|
@ -191,7 +191,7 @@ impl AcpConnection {
|
|||
AcpConnectionRegistry::default_global(cx).update(cx, |registry, cx| {
|
||||
registry.set_active_connection(server_name.clone(), &connection, cx)
|
||||
});
|
||||
})?;
|
||||
});
|
||||
|
||||
let response = connection
|
||||
.initialize(
|
||||
|
|
@ -343,7 +343,7 @@ impl AgentConnection for AcpConnection {
|
|||
}
|
||||
})?;
|
||||
|
||||
let use_config_options = cx.update(|cx| cx.has_flag::<AcpBetaFeatureFlag>())?;
|
||||
let use_config_options = cx.update(|cx| cx.has_flag::<AcpBetaFeatureFlag>());
|
||||
|
||||
// Config options take precedence over legacy modes/models
|
||||
let (modes, models, config_options) = if use_config_options && let Some(opts) = response.config_options {
|
||||
|
|
@ -532,8 +532,8 @@ impl AgentConnection for AcpConnection {
|
|||
}
|
||||
|
||||
let session_id = response.session_id;
|
||||
let action_log = cx.new(|_| ActionLog::new(project.clone()))?;
|
||||
let thread = cx.new(|cx| {
|
||||
let action_log = cx.new(|_| ActionLog::new(project.clone()));
|
||||
let thread: Entity<AcpThread> = cx.new(|cx| {
|
||||
AcpThread::new(
|
||||
self.server_name.clone(),
|
||||
self.clone(),
|
||||
|
|
@ -544,7 +544,7 @@ impl AgentConnection for AcpConnection {
|
|||
watch::Receiver::constant(self.agent_capabilities.prompt_capabilities.clone()),
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
|
||||
|
||||
let session = AcpSession {
|
||||
|
|
@ -1104,8 +1104,7 @@ impl acp::Client for ClientDelegate {
|
|||
cx,
|
||||
)
|
||||
})?;
|
||||
let terminal_id =
|
||||
terminal_entity.read_with(&self.cx, |terminal, _| terminal.id().clone())?;
|
||||
let terminal_id = terminal_entity.read_with(&self.cx, |terminal, _| terminal.id().clone());
|
||||
Ok(acp::CreateTerminalResponse::new(terminal_id))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ impl AgentServer for Gemini {
|
|||
extra_env.insert("SURFACE".to_owned(), "zed".to_owned());
|
||||
|
||||
if let Some(api_key) = cx
|
||||
.update(GoogleLanguageModelProvider::api_key_for_gemini_cli)?
|
||||
.update(GoogleLanguageModelProvider::api_key_for_gemini_cli)
|
||||
.await
|
||||
.ok()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -466,9 +466,9 @@ impl MessageEditor {
|
|||
}
|
||||
}
|
||||
});
|
||||
Ok((chunks, all_tracked_buffers))
|
||||
anyhow::Ok((chunks, all_tracked_buffers))
|
||||
})?;
|
||||
result
|
||||
Ok(result)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -678,28 +678,24 @@ impl MessageEditor {
|
|||
.update(cx, |project, cx| {
|
||||
project.project_path_for_absolute_path(&file_path, cx)
|
||||
})
|
||||
.map_err(|e| e.to_string())?
|
||||
.ok_or_else(|| "project path not found".to_string())?;
|
||||
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| project.open_buffer(project_path, cx))
|
||||
.map_err(|e| e.to_string())?
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
let start = Point::new(*line_range.start(), 0)
|
||||
.min(buffer.max_point());
|
||||
let end = Point::new(*line_range.end() + 1, 0)
|
||||
.min(buffer.max_point());
|
||||
let content = buffer.text_for_range(start..end).collect();
|
||||
Mention::Text {
|
||||
content,
|
||||
tracked_buffers: vec![cx.entity()],
|
||||
}
|
||||
})
|
||||
.map_err(|e| e.to_string())
|
||||
Ok(buffer.update(cx, |buffer, cx| {
|
||||
let start =
|
||||
Point::new(*line_range.start(), 0).min(buffer.max_point());
|
||||
let end = Point::new(*line_range.end() + 1, 0)
|
||||
.min(buffer.max_point());
|
||||
let content = buffer.text_for_range(start..end).collect();
|
||||
Mention::Text {
|
||||
content,
|
||||
tracked_buffers: vec![cx.entity()],
|
||||
}
|
||||
}))
|
||||
}
|
||||
})
|
||||
.shared();
|
||||
|
|
|
|||
|
|
@ -985,7 +985,7 @@ impl AcpThreadView {
|
|||
);
|
||||
});
|
||||
}
|
||||
})?;
|
||||
});
|
||||
|
||||
anyhow::Ok(())
|
||||
})
|
||||
|
|
@ -1019,7 +1019,7 @@ impl AcpThreadView {
|
|||
history_store
|
||||
.update(&mut cx.clone(), |store, cx| {
|
||||
store.save_thread(session_id.clone(), db_thread, cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
let thread_metadata = agent::DbThreadMetadata {
|
||||
|
|
@ -1652,18 +1652,18 @@ impl AcpThreadView {
|
|||
.iter()
|
||||
.take(entry_ix)
|
||||
.any(|entry| entry.diffs().next().is_some())
|
||||
})?;
|
||||
});
|
||||
|
||||
if has_earlier_edits {
|
||||
thread.update(cx, |thread, cx| {
|
||||
thread.action_log().update(cx, |action_log, cx| {
|
||||
action_log.keep_all_edits(None, cx);
|
||||
});
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
thread
|
||||
.update(cx, |thread, cx| thread.rewind(user_message_id, cx))?
|
||||
.update(cx, |thread, cx| thread.rewind(user_message_id, cx))
|
||||
.await?;
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.send_impl(message_editor, window, cx);
|
||||
|
|
@ -2140,7 +2140,7 @@ impl AcpThreadView {
|
|||
})
|
||||
});
|
||||
|
||||
if let Ok(Some(resolve_task)) = resolved_node_runtime {
|
||||
if let Some(resolve_task) = resolved_node_runtime {
|
||||
if let Ok(node_path) = resolve_task.await {
|
||||
task.command = Some(node_path.to_string_lossy().to_string());
|
||||
}
|
||||
|
|
@ -2159,11 +2159,11 @@ impl AcpThreadView {
|
|||
task.allow_concurrent_runs = true;
|
||||
task.hide = task::HideStrategy::Always;
|
||||
|
||||
let terminal = terminal_panel.update_in(cx, |terminal_panel, window, cx| {
|
||||
terminal_panel.spawn_task(&task, window, cx)
|
||||
})?;
|
||||
|
||||
let terminal = terminal.await?;
|
||||
let terminal = terminal_panel
|
||||
.update_in(cx, |terminal_panel, window, cx| {
|
||||
terminal_panel.spawn_task(&task, window, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
if check_exit_code {
|
||||
// For extension-based auth, wait for the process to exit and check exit code
|
||||
|
|
@ -2214,7 +2214,7 @@ impl AcpThreadView {
|
|||
}
|
||||
}
|
||||
_ = exit_status => {
|
||||
if !previous_attempt && project.read_with(cx, |project, _| project.is_via_remote_server())? && login.label.contains("gemini") {
|
||||
if !previous_attempt && project.read_with(cx, |project, _| project.is_via_remote_server()) && login.label.contains("gemini") {
|
||||
return cx.update(|window, cx| Self::spawn_external_agent_login(login, workspace, project.clone(), true, false, window, cx))?.await
|
||||
}
|
||||
return Err(anyhow!("exited before logging in"));
|
||||
|
|
@ -5667,14 +5667,14 @@ impl AcpThreadView {
|
|||
let markdown_language = markdown_language_task.await?;
|
||||
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| project.create_buffer(false, cx))?
|
||||
.update(cx, |project, cx| project.create_buffer(false, cx))
|
||||
.await?;
|
||||
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.set_text(markdown, cx);
|
||||
buffer.set_language(Some(markdown_language), cx);
|
||||
buffer.set_capability(language::Capability::ReadWrite, cx);
|
||||
})?;
|
||||
});
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let buffer = cx
|
||||
|
|
|
|||
|
|
@ -821,7 +821,8 @@ impl AgentConfiguration {
|
|||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
});
|
||||
anyhow::Ok(())
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
|
@ -1304,7 +1305,7 @@ fn show_unable_to_uninstall_extension_with_context_server(
|
|||
.context_servers
|
||||
.remove(&context_server_id.0);
|
||||
});
|
||||
})?;
|
||||
});
|
||||
anyhow::Ok(())
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ fn save_provider_to_settings(
|
|||
let task = cx.write_credentials(&api_url, "Bearer", api_key.as_bytes());
|
||||
cx.spawn(async move |cx| {
|
||||
task.await
|
||||
.map_err(|_| "Failed to write API key to keychain")?;
|
||||
.map_err(|_| SharedString::from("Failed to write API key to keychain"))?;
|
||||
cx.update(|cx| {
|
||||
update_settings_file(fs, cx, |settings, _cx| {
|
||||
settings
|
||||
|
|
@ -278,8 +278,7 @@ fn save_provider_to_settings(
|
|||
},
|
||||
);
|
||||
});
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1091,8 +1091,8 @@ impl<T: PromptCompletionProviderDelegate> CompletionProvider for PromptCompletio
|
|||
)
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
})?;
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
Ok(vec![CompletionResponse {
|
||||
completions,
|
||||
|
|
@ -1469,26 +1469,19 @@ pub(crate) fn search_symbols(
|
|||
let Some(symbols) = symbols_task.await.log_err() else {
|
||||
return Vec::new();
|
||||
};
|
||||
let Some((visible_match_candidates, external_match_candidates)): Option<(Vec<_>, Vec<_>)> =
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
symbols
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(id, symbol)| {
|
||||
StringMatchCandidate::new(id, symbol.label.filter_text())
|
||||
})
|
||||
.partition(|candidate| match &symbols[candidate.id].path {
|
||||
SymbolLocation::InProject(project_path) => project
|
||||
.entry_for_path(project_path, cx)
|
||||
.is_some_and(|e| !e.is_ignored),
|
||||
SymbolLocation::OutsideProject { .. } => false,
|
||||
})
|
||||
})
|
||||
.log_err()
|
||||
else {
|
||||
return Vec::new();
|
||||
};
|
||||
let (visible_match_candidates, external_match_candidates): (Vec<_>, Vec<_>) = project
|
||||
.update(cx, |project, cx| {
|
||||
symbols
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(id, symbol)| StringMatchCandidate::new(id, symbol.label.filter_text()))
|
||||
.partition(|candidate| match &symbols[candidate.id].path {
|
||||
SymbolLocation::InProject(project_path) => project
|
||||
.entry_for_path(project_path, cx)
|
||||
.is_some_and(|e| !e.is_ignored),
|
||||
SymbolLocation::OutsideProject { .. } => false,
|
||||
})
|
||||
});
|
||||
|
||||
const MAX_MATCHES: usize = 100;
|
||||
let mut visible_matches = cx.background_executor().block(fuzzy::match_strings(
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ impl InlineAssistant {
|
|||
if let Some(error) = configuration_error() {
|
||||
if let ConfigurationError::ProviderNotAuthenticated(provider) = error {
|
||||
cx.spawn(async move |_, cx| {
|
||||
cx.update(|cx| provider.authenticate(cx))?.await?;
|
||||
cx.update(|cx| provider.authenticate(cx)).await?;
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
|
@ -1633,7 +1633,7 @@ impl EditorInlineAssists {
|
|||
let editor = editor.upgrade().context("editor was dropped")?;
|
||||
cx.update_global(|assistant: &mut InlineAssistant, cx| {
|
||||
assistant.update_editor_highlights(&editor, cx);
|
||||
})?;
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1978,7 +1978,7 @@ impl CodeActionProvider for AssistantCodeActionProvider {
|
|||
let multibuffer_snapshot = multibuffer.read(cx);
|
||||
multibuffer_snapshot.anchor_range_in_excerpt(excerpt_id, action.range)
|
||||
})
|
||||
})?
|
||||
})
|
||||
.context("invalid range")?;
|
||||
|
||||
let prompt_store = prompt_store.await.ok();
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ impl MentionSet {
|
|||
let content = if full_mention_content
|
||||
&& let MentionUri::Directory { abs_path } = &mention_uri
|
||||
{
|
||||
cx.update(|cx| full_mention_for_directory(&project, abs_path, cx))?
|
||||
cx.update(|cx| full_mention_for_directory(&project, abs_path, cx))
|
||||
.await?
|
||||
} else {
|
||||
task.await.map_err(|e| anyhow!("{e}"))?
|
||||
|
|
@ -180,9 +180,7 @@ impl MentionSet {
|
|||
let image = cx
|
||||
.spawn(async move |_, cx| {
|
||||
let image = image_task.await.map_err(|e| e.to_string())?;
|
||||
let image = image
|
||||
.update(cx, |image, _| image.image.clone())
|
||||
.map_err(|e| e.to_string())?;
|
||||
let image = image.update(cx, |image, _| image.image.clone());
|
||||
Ok(image)
|
||||
})
|
||||
.shared();
|
||||
|
|
@ -291,10 +289,10 @@ impl MentionSet {
|
|||
let task = project.update(cx, |project, cx| project.open_image(project_path, cx));
|
||||
return cx.spawn(async move |_, cx| {
|
||||
let image = task.await?;
|
||||
let image = image.update(cx, |image, _| image.image.clone())?;
|
||||
let image = image.update(cx, |image, _| image.image.clone());
|
||||
let format = image.format;
|
||||
let image = cx
|
||||
.update(|cx| LanguageModelImage::from_image(image, cx))?
|
||||
.update(|cx| LanguageModelImage::from_image(image, cx))
|
||||
.await;
|
||||
if let Some(image) = image {
|
||||
Ok(Mention::Image(MentionImage {
|
||||
|
|
@ -365,8 +363,8 @@ impl MentionSet {
|
|||
content,
|
||||
tracked_buffers: vec![cx.entity()],
|
||||
}
|
||||
})?;
|
||||
anyhow::Ok(mention)
|
||||
});
|
||||
Ok(mention)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -493,9 +491,9 @@ impl MentionSet {
|
|||
let agent = agent.downcast::<agent::NativeAgentConnection>().unwrap();
|
||||
let summary = agent
|
||||
.0
|
||||
.update(cx, |agent, cx| agent.thread_summary(id, cx))?
|
||||
.update(cx, |agent, cx| agent.thread_summary(id, cx))
|
||||
.await?;
|
||||
anyhow::Ok(Mention::Text {
|
||||
Ok(Mention::Text {
|
||||
content: summary.to_string(),
|
||||
tracked_buffers: Vec::new(),
|
||||
})
|
||||
|
|
@ -512,7 +510,7 @@ impl MentionSet {
|
|||
});
|
||||
cx.spawn(async move |_, cx| {
|
||||
let text_thread = text_thread_task.await?;
|
||||
let xml = text_thread.update(cx, |text_thread, cx| text_thread.to_xml(cx))?;
|
||||
let xml = text_thread.update(cx, |text_thread, cx| text_thread.to_xml(cx));
|
||||
Ok(Mention::Text {
|
||||
content: xml,
|
||||
tracked_buffers: Vec::new(),
|
||||
|
|
@ -580,8 +578,8 @@ pub(crate) fn paste_images_as_context(
|
|||
})
|
||||
.ok();
|
||||
for image in images {
|
||||
let Ok((excerpt_id, text_anchor, multibuffer_anchor)) =
|
||||
editor.update_in(cx, |message_editor, window, cx| {
|
||||
let Some((excerpt_id, text_anchor, multibuffer_anchor)) = editor
|
||||
.update_in(cx, |message_editor, window, cx| {
|
||||
let snapshot = message_editor.snapshot(window, cx);
|
||||
let (excerpt_id, _, buffer_snapshot) =
|
||||
snapshot.buffer_snapshot().as_singleton().unwrap();
|
||||
|
|
@ -599,6 +597,7 @@ pub(crate) fn paste_images_as_context(
|
|||
);
|
||||
(*excerpt_id, text_anchor, multibuffer_anchor)
|
||||
})
|
||||
.ok()
|
||||
else {
|
||||
break;
|
||||
};
|
||||
|
|
@ -607,12 +606,10 @@ pub(crate) fn paste_images_as_context(
|
|||
let Some(start_anchor) = multibuffer_anchor else {
|
||||
continue;
|
||||
};
|
||||
let Ok(end_anchor) = editor.update(cx, |editor, cx| {
|
||||
let end_anchor = editor.update(cx, |editor, cx| {
|
||||
let snapshot = editor.buffer().read(cx).snapshot(cx);
|
||||
snapshot.anchor_before(start_anchor.to_offset(&snapshot) + content_len)
|
||||
}) else {
|
||||
continue;
|
||||
};
|
||||
});
|
||||
let image = Arc::new(image);
|
||||
let Ok(Some((crease_id, tx))) = cx.update(|window, cx| {
|
||||
insert_crease_for_mention(
|
||||
|
|
@ -648,23 +645,17 @@ pub(crate) fn paste_images_as_context(
|
|||
})
|
||||
.shared();
|
||||
|
||||
mention_set
|
||||
.update(cx, |mention_set, _cx| {
|
||||
mention_set.insert_mention(crease_id, MentionUri::PastedImage, task.clone())
|
||||
})
|
||||
.ok();
|
||||
mention_set.update(cx, |mention_set, _cx| {
|
||||
mention_set.insert_mention(crease_id, MentionUri::PastedImage, task.clone())
|
||||
});
|
||||
|
||||
if task.await.notify_async_err(cx).is_none() {
|
||||
editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.edit([(start_anchor..end_anchor, "")], cx);
|
||||
})
|
||||
.ok();
|
||||
mention_set
|
||||
.update(cx, |mention_set, _cx| {
|
||||
mention_set.remove_mention(&crease_id)
|
||||
})
|
||||
.ok();
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.edit([(start_anchor..end_anchor, "")], cx);
|
||||
});
|
||||
mention_set.update(cx, |mention_set, _cx| {
|
||||
mention_set.remove_mention(&crease_id)
|
||||
});
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
|
@ -822,42 +813,44 @@ fn full_mention_for_directory(
|
|||
cx.spawn(async move |cx| {
|
||||
let file_paths = worktree.read_with(cx, |worktree, _cx| {
|
||||
collect_files_in_path(worktree, &directory_path)
|
||||
})?;
|
||||
});
|
||||
let descendants_future = cx.update(|cx| {
|
||||
futures::future::join_all(file_paths.into_iter().map(|(worktree_path, full_path)| {
|
||||
let rel_path = worktree_path
|
||||
.strip_prefix(&directory_path)
|
||||
.log_err()
|
||||
.map_or_else(|| worktree_path.clone(), |rel_path| rel_path.into());
|
||||
futures::future::join_all(file_paths.into_iter().map(
|
||||
|(worktree_path, full_path): (Arc<RelPath>, String)| {
|
||||
let rel_path = worktree_path
|
||||
.strip_prefix(&directory_path)
|
||||
.log_err()
|
||||
.map_or_else(|| worktree_path.clone(), |rel_path| rel_path.into());
|
||||
|
||||
let open_task = project.update(cx, |project, cx| {
|
||||
project.buffer_store().update(cx, |buffer_store, cx| {
|
||||
let project_path = ProjectPath {
|
||||
worktree_id,
|
||||
path: worktree_path,
|
||||
};
|
||||
buffer_store.open_buffer(project_path, cx)
|
||||
let open_task = project.update(cx, |project, cx| {
|
||||
project.buffer_store().update(cx, |buffer_store, cx| {
|
||||
let project_path = ProjectPath {
|
||||
worktree_id,
|
||||
path: worktree_path,
|
||||
};
|
||||
buffer_store.open_buffer(project_path, cx)
|
||||
})
|
||||
});
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = open_task.await.log_err()?;
|
||||
let buffer_content = outline::get_buffer_content_or_outline(
|
||||
buffer.clone(),
|
||||
Some(&full_path),
|
||||
&cx,
|
||||
)
|
||||
.await
|
||||
.ok()?;
|
||||
|
||||
Some((rel_path, full_path, buffer_content.text, buffer))
|
||||
})
|
||||
});
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = open_task.await.log_err()?;
|
||||
let buffer_content = outline::get_buffer_content_or_outline(
|
||||
buffer.clone(),
|
||||
Some(&full_path),
|
||||
&cx,
|
||||
)
|
||||
.await
|
||||
.ok()?;
|
||||
|
||||
Some((rel_path, full_path, buffer_content.text, buffer))
|
||||
})
|
||||
}))
|
||||
})?;
|
||||
},
|
||||
))
|
||||
});
|
||||
|
||||
let contents = cx
|
||||
.background_spawn(async move {
|
||||
let (contents, tracked_buffers) = descendants_future
|
||||
let (contents, tracked_buffers): (Vec<_>, Vec<_>) = descendants_future
|
||||
.await
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ impl SlashCommand for DefaultSlashCommand {
|
|||
let store = PromptStore::global(cx);
|
||||
cx.spawn(async move |cx| {
|
||||
let store = store.await?;
|
||||
let prompts = store.read_with(cx, |store, _cx| store.default_prompt_metadata())?;
|
||||
let prompts = store.read_with(cx, |store, _cx| store.default_prompt_metadata());
|
||||
|
||||
let mut text = String::new();
|
||||
text.push('\n');
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ fn collect_diagnostics(
|
|||
.await
|
||||
.log_err()
|
||||
{
|
||||
let snapshot = cx.read_entity(&buffer, |buffer, _| buffer.snapshot())?;
|
||||
let snapshot = cx.read_entity(&buffer, |buffer, _| buffer.snapshot());
|
||||
collect_buffer_diagnostics(&mut output, &snapshot, options.include_warnings);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ fn collect_files(
|
|||
};
|
||||
if let Some(buffer) = open_buffer_task.await.log_err() {
|
||||
let mut output = SlashCommandOutput::default();
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
|
||||
append_buffer_to_output(
|
||||
&snapshot,
|
||||
Some(path_including_worktree_name.display(path_style).as_ref()),
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ impl SlashCommand for PromptSlashCommand {
|
|||
let cancellation_flag = Arc::new(AtomicBool::default());
|
||||
let prompts: Vec<PromptMetadata> = store
|
||||
.await?
|
||||
.read_with(cx, |store, cx| store.search(query, cancellation_flag, cx))?
|
||||
.read_with(cx, |store, cx| store.search(query, cancellation_flag, cx))
|
||||
.await;
|
||||
Ok(prompts
|
||||
.into_iter()
|
||||
|
|
@ -91,7 +91,7 @@ impl SlashCommand for PromptSlashCommand {
|
|||
.id_for_title(&title)
|
||||
.with_context(|| format!("no prompt found with title {:?}", title))?;
|
||||
anyhow::Ok(store.load(prompt_id, cx))
|
||||
})??
|
||||
})?
|
||||
.await?;
|
||||
anyhow::Ok(body)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1263,7 +1263,7 @@ impl TextThread {
|
|||
}
|
||||
|
||||
let token_count = cx
|
||||
.update(|cx| model.model.count_tokens(request, cx))?
|
||||
.update(|cx| model.model.count_tokens(request, cx))
|
||||
.await?;
|
||||
this.update(cx, |this, cx| {
|
||||
this.token_count = Some(token_count);
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ impl TextThreadStore {
|
|||
this.register_context_server_handlers(cx);
|
||||
this.reload(cx).detach_and_log_err(cx);
|
||||
this
|
||||
})?;
|
||||
});
|
||||
|
||||
Ok(this)
|
||||
})
|
||||
|
|
@ -166,7 +166,8 @@ impl TextThreadStore {
|
|||
})
|
||||
.collect();
|
||||
cx.notify();
|
||||
})
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_open_context(
|
||||
|
|
@ -196,7 +197,7 @@ impl TextThreadStore {
|
|||
.read(cx)
|
||||
.serialize_ops(&TextThreadVersion::default(), cx),
|
||||
)
|
||||
})??;
|
||||
})?;
|
||||
let operations = operations.await;
|
||||
Ok(proto::OpenContextResponse {
|
||||
context: Some(proto::Context { operations }),
|
||||
|
|
@ -224,7 +225,7 @@ impl TextThreadStore {
|
|||
.read(cx)
|
||||
.serialize_ops(&TextThreadVersion::default(), cx),
|
||||
))
|
||||
})??;
|
||||
})?;
|
||||
let operations = operations.await;
|
||||
Ok(proto::CreateContextResponse {
|
||||
context_id: context_id.to_proto(),
|
||||
|
|
@ -245,7 +246,7 @@ impl TextThreadStore {
|
|||
text_thread.update(cx, |text_thread, cx| text_thread.apply_ops([operation], cx));
|
||||
}
|
||||
Ok(())
|
||||
})?
|
||||
})
|
||||
}
|
||||
|
||||
async fn handle_synchronize_contexts(
|
||||
|
|
@ -290,7 +291,7 @@ impl TextThreadStore {
|
|||
anyhow::Ok(proto::SynchronizeContextsResponse {
|
||||
contexts: local_versions,
|
||||
})
|
||||
})?
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_project_shared(&mut self, cx: &mut Context<Self>) {
|
||||
|
|
@ -416,7 +417,7 @@ impl TextThreadStore {
|
|||
Some(project),
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
let operations = cx
|
||||
.background_spawn(async move {
|
||||
context_proto
|
||||
|
|
@ -426,7 +427,7 @@ impl TextThreadStore {
|
|||
.collect::<Result<Vec<_>>>()
|
||||
})
|
||||
.await?;
|
||||
text_thread.update(cx, |context, cx| context.apply_ops(operations, cx))?;
|
||||
text_thread.update(cx, |context, cx| context.apply_ops(operations, cx));
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(existing_context) = this.loaded_text_thread_for_id(&context_id, cx) {
|
||||
existing_context
|
||||
|
|
@ -473,7 +474,7 @@ impl TextThreadStore {
|
|||
Some(project),
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(existing_context) = this.loaded_text_thread_for_path(&path, cx) {
|
||||
existing_context
|
||||
|
|
@ -580,7 +581,7 @@ impl TextThreadStore {
|
|||
Some(project),
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
let operations = cx
|
||||
.background_spawn(async move {
|
||||
context_proto
|
||||
|
|
@ -590,7 +591,7 @@ impl TextThreadStore {
|
|||
.collect::<Result<Vec<_>>>()
|
||||
})
|
||||
.await?;
|
||||
text_thread.update(cx, |context, cx| context.apply_ops(operations, cx))?;
|
||||
text_thread.update(cx, |context, cx| context.apply_ops(operations, cx));
|
||||
this.update(cx, |this, cx| {
|
||||
if let Some(existing_context) = this.loaded_text_thread_for_id(&text_thread_id, cx)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -303,9 +303,9 @@ pub struct VoipParts {
|
|||
#[cfg(not(any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd")))]
|
||||
impl VoipParts {
|
||||
pub fn new(cx: &AsyncApp) -> anyhow::Result<Self> {
|
||||
let (apm, replays) = cx.try_read_default_global::<Audio, _>(|audio, _| {
|
||||
let (apm, replays) = cx.read_default_global::<Audio, _>(|audio, _| {
|
||||
(Arc::clone(&audio.echo_canceller), audio.replays.clone())
|
||||
})?;
|
||||
});
|
||||
let legacy_audio_compatible =
|
||||
AudioSettings::try_read_global(cx, |settings| settings.legacy_audio_compatible)
|
||||
.unwrap_or(true);
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ impl AutoUpdater {
|
|||
.0
|
||||
.clone()
|
||||
.context("auto-update not initialized")
|
||||
})??;
|
||||
})?;
|
||||
|
||||
set_status("Fetching remote server release", cx);
|
||||
let release = Self::get_release_asset(
|
||||
|
|
@ -456,7 +456,7 @@ impl AutoUpdater {
|
|||
let version_path = platform_dir.join(format!("{}.gz", release.version));
|
||||
smol::fs::create_dir_all(&platform_dir).await.ok();
|
||||
|
||||
let client = this.read_with(cx, |this, _| this.client.http_client())?;
|
||||
let client = this.read_with(cx, |this, _| this.client.http_client());
|
||||
|
||||
if smol::fs::metadata(&version_path).await.is_err() {
|
||||
log::info!(
|
||||
|
|
@ -482,7 +482,7 @@ impl AutoUpdater {
|
|||
.0
|
||||
.clone()
|
||||
.context("auto-update not initialized")
|
||||
})??;
|
||||
})?;
|
||||
|
||||
let release =
|
||||
Self::get_release_asset(&this, channel, version, "zed-remote-server", os, arch, cx)
|
||||
|
|
@ -500,7 +500,7 @@ impl AutoUpdater {
|
|||
arch: &str,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<ReleaseAsset> {
|
||||
let client = this.read_with(cx, |this, _| this.client.clone())?;
|
||||
let client = this.read_with(cx, |this, _| this.client.clone());
|
||||
|
||||
let (system_id, metrics_id, is_staff) = if client.telemetry().metrics_enabled() {
|
||||
(
|
||||
|
|
@ -563,7 +563,7 @@ impl AutoUpdater {
|
|||
this.status.clone(),
|
||||
ReleaseChannel::try_global(cx).unwrap_or(ReleaseChannel::Stable),
|
||||
)
|
||||
})?;
|
||||
});
|
||||
|
||||
Self::check_dependencies()?;
|
||||
|
||||
|
|
@ -571,12 +571,12 @@ impl AutoUpdater {
|
|||
this.status = AutoUpdateStatus::Checking;
|
||||
log::info!("Auto Update: checking for updates");
|
||||
cx.notify();
|
||||
})?;
|
||||
});
|
||||
|
||||
let fetched_release_data =
|
||||
Self::get_release_asset(&this, release_channel, None, "zed", OS, ARCH, cx).await?;
|
||||
let fetched_version = fetched_release_data.clone().version;
|
||||
let app_commit_sha = cx.update(|cx| AppCommitSha::try_global(cx).map(|sha| sha.full()));
|
||||
let app_commit_sha = Ok(cx.update(|cx| AppCommitSha::try_global(cx).map(|sha| sha.full())));
|
||||
let newer_version = Self::check_if_fetched_version_is_newer(
|
||||
release_channel,
|
||||
app_commit_sha,
|
||||
|
|
@ -586,7 +586,7 @@ impl AutoUpdater {
|
|||
)?;
|
||||
|
||||
let Some(newer_version) = newer_version else {
|
||||
return this.update(cx, |this, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
let status = match previous_status {
|
||||
AutoUpdateStatus::Updated { .. } => previous_status,
|
||||
_ => AutoUpdateStatus::Idle,
|
||||
|
|
@ -594,6 +594,7 @@ impl AutoUpdater {
|
|||
this.status = status;
|
||||
cx.notify();
|
||||
});
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
|
|
@ -601,7 +602,7 @@ impl AutoUpdater {
|
|||
version: newer_version.clone(),
|
||||
};
|
||||
cx.notify();
|
||||
})?;
|
||||
});
|
||||
|
||||
let installer_dir = InstallerDir::new().await?;
|
||||
let target_path = Self::target_path(&installer_dir).await?;
|
||||
|
|
@ -612,11 +613,11 @@ impl AutoUpdater {
|
|||
version: newer_version.clone(),
|
||||
};
|
||||
cx.notify();
|
||||
})?;
|
||||
});
|
||||
|
||||
let new_binary_path = Self::install_release(installer_dir, target_path, cx).await?;
|
||||
if let Some(new_binary_path) = new_binary_path {
|
||||
cx.update(|cx| cx.set_restart_path(new_binary_path))?;
|
||||
cx.update(|cx| cx.set_restart_path(new_binary_path));
|
||||
}
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
|
|
@ -626,7 +627,8 @@ impl AutoUpdater {
|
|||
version: newer_version,
|
||||
};
|
||||
cx.notify();
|
||||
})
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_if_fetched_version_is_newer(
|
||||
|
|
@ -807,9 +809,9 @@ async fn install_release_linux(
|
|||
downloaded_tar_gz: PathBuf,
|
||||
cx: &AsyncApp,
|
||||
) -> Result<Option<PathBuf>> {
|
||||
let channel = cx.update(|cx| ReleaseChannel::global(cx).dev_name())?;
|
||||
let channel = cx.update(|cx| ReleaseChannel::global(cx).dev_name());
|
||||
let home_dir = PathBuf::from(env::var("HOME").context("no HOME env var set")?);
|
||||
let running_app_path = cx.update(|cx| cx.app_path())??;
|
||||
let running_app_path = cx.update(|cx| cx.app_path())?;
|
||||
|
||||
let extracted = temp_dir.path().join("zed");
|
||||
fs::create_dir_all(&extracted)
|
||||
|
|
@ -874,7 +876,7 @@ async fn install_release_macos(
|
|||
downloaded_dmg: PathBuf,
|
||||
cx: &AsyncApp,
|
||||
) -> Result<Option<PathBuf>> {
|
||||
let running_app_path = cx.update(|cx| cx.app_path())??;
|
||||
let running_app_path = cx.update(|cx| cx.app_path())?;
|
||||
let running_app_filename = running_app_path
|
||||
.file_name()
|
||||
.with_context(|| format!("invalid running app path {running_app_path:?}"))?;
|
||||
|
|
|
|||
|
|
@ -207,8 +207,8 @@ pub fn notify_if_app_was_updated(cx: &mut App) {
|
|||
updater
|
||||
.set_should_show_update_notification(false, cx)
|
||||
.detach_and_log_err(cx);
|
||||
})
|
||||
})?;
|
||||
});
|
||||
});
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
|
|
|
|||
|
|
@ -112,24 +112,24 @@ impl ActiveCall {
|
|||
envelope: TypedEnvelope<proto::IncomingCall>,
|
||||
mut cx: AsyncApp,
|
||||
) -> Result<proto::Ack> {
|
||||
let user_store = this.read_with(&cx, |this, _| this.user_store.clone())?;
|
||||
let user_store = this.read_with(&cx, |this, _| this.user_store.clone());
|
||||
let call = IncomingCall {
|
||||
room_id: envelope.payload.room_id,
|
||||
participants: user_store
|
||||
.update(&mut cx, |user_store, cx| {
|
||||
user_store.get_users(envelope.payload.participant_user_ids, cx)
|
||||
})?
|
||||
})
|
||||
.await?,
|
||||
calling_user: user_store
|
||||
.update(&mut cx, |user_store, cx| {
|
||||
user_store.get_user(envelope.payload.calling_user_id, cx)
|
||||
})?
|
||||
})
|
||||
.await?,
|
||||
initial_project: envelope.payload.initial_project,
|
||||
};
|
||||
this.update(&mut cx, |this, _| {
|
||||
*this.incoming_call.0.borrow_mut() = Some(call);
|
||||
})?;
|
||||
});
|
||||
|
||||
Ok(proto::Ack {})
|
||||
}
|
||||
|
|
@ -147,7 +147,7 @@ impl ActiveCall {
|
|||
{
|
||||
incoming_call.take();
|
||||
}
|
||||
})?;
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ impl ActiveCall {
|
|||
|
||||
let initial_project_id = if let Some(initial_project) = initial_project {
|
||||
Some(
|
||||
room.update(cx, |room, cx| room.share_project(initial_project, cx))?
|
||||
room.update(cx, |room, cx| room.share_project(initial_project, cx))
|
||||
.await?,
|
||||
)
|
||||
} else {
|
||||
|
|
@ -196,7 +196,7 @@ impl ActiveCall {
|
|||
|
||||
room.update(cx, move |room, cx| {
|
||||
room.call(called_user_id, initial_project_id, cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
anyhow::Ok(())
|
||||
|
|
@ -216,7 +216,7 @@ impl ActiveCall {
|
|||
user_store,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
this.update(cx, |this, cx| this.set_room(Some(room.clone()), cx))?
|
||||
|
|
|
|||
|
|
@ -185,13 +185,13 @@ impl Room {
|
|||
room.local_participant.role = participant.role()
|
||||
}
|
||||
room
|
||||
})?;
|
||||
});
|
||||
|
||||
let initial_project_id = if let Some(initial_project) = initial_project {
|
||||
let initial_project_id = room
|
||||
.update(cx, |room, cx| {
|
||||
room.share_project(initial_project.clone(), cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
Some(initial_project_id)
|
||||
} else {
|
||||
|
|
@ -202,7 +202,7 @@ impl Room {
|
|||
.update(cx, |room, cx| {
|
||||
room.leave_when_empty = true;
|
||||
room.call(called_user_id, initial_project_id, cx)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
match did_join {
|
||||
Ok(()) => Ok(room),
|
||||
|
|
@ -286,12 +286,12 @@ impl Room {
|
|||
user_store,
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
room.update(&mut cx, |room, cx| {
|
||||
room.leave_when_empty = room.channel_id.is_none();
|
||||
room.apply_room_update(room_proto, cx)?;
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
})?;
|
||||
Ok(room)
|
||||
}
|
||||
|
||||
|
|
@ -379,7 +379,7 @@ impl Room {
|
|||
.update(cx, |this, cx| {
|
||||
this.status = RoomStatus::Rejoining;
|
||||
cx.notify();
|
||||
})?;
|
||||
});
|
||||
|
||||
// Wait for client to re-establish a connection to the server.
|
||||
let executor = cx.background_executor().clone();
|
||||
|
|
@ -390,15 +390,11 @@ impl Room {
|
|||
log::info!("client reconnected, attempting to rejoin room");
|
||||
|
||||
let Some(this) = this.upgrade() else { break };
|
||||
match this.update(cx, |this, cx| this.rejoin(cx)) {
|
||||
Ok(task) => {
|
||||
if task.await.log_err().is_some() {
|
||||
return true;
|
||||
} else {
|
||||
remaining_attempts -= 1;
|
||||
}
|
||||
}
|
||||
Err(_app_dropped) => return false,
|
||||
let task = this.update(cx, |this, cx| this.rejoin(cx));
|
||||
if task.await.log_err().is_some() {
|
||||
return true;
|
||||
} else {
|
||||
remaining_attempts -= 1;
|
||||
}
|
||||
} else if client_status.borrow().is_signed_out() {
|
||||
return false;
|
||||
|
|
@ -437,7 +433,7 @@ impl Room {
|
|||
// we leave the room and return an error.
|
||||
if let Some(this) = this.upgrade() {
|
||||
log::info!("reconnection failed, leaving room");
|
||||
this.update(cx, |this, cx| this.leave(cx))?.await?;
|
||||
this.update(cx, |this, cx| this.leave(cx)).await?;
|
||||
}
|
||||
anyhow::bail!("can't reconnect to room: client failed to re-establish connection");
|
||||
}
|
||||
|
|
@ -665,7 +661,7 @@ impl Room {
|
|||
mut cx: AsyncApp,
|
||||
) -> Result<()> {
|
||||
let room = envelope.payload.room.context("invalid room")?;
|
||||
this.update(&mut cx, |this, cx| this.apply_room_update(room, cx))?
|
||||
this.update(&mut cx, |this, cx| this.apply_room_update(room, cx))
|
||||
}
|
||||
|
||||
fn apply_room_update(&mut self, room: proto::Room, cx: &mut Context<Self>) -> Result<()> {
|
||||
|
|
@ -1203,7 +1199,7 @@ impl Room {
|
|||
cx.spawn(async move |this, cx| {
|
||||
let response = request.await?;
|
||||
|
||||
project.update(cx, |project, cx| project.shared(response.project_id, cx))??;
|
||||
project.update(cx, |project, cx| project.shared(response.project_id, cx))?;
|
||||
|
||||
// If the user's location is in this project, it changes from UnsharedProject to SharedProject.
|
||||
this.update(cx, |this, cx| {
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ impl ChannelBuffer {
|
|||
capability,
|
||||
base_text,
|
||||
)
|
||||
})?;
|
||||
buffer.update(cx, |buffer, cx| buffer.apply_ops(operations, cx))?;
|
||||
});
|
||||
buffer.update(cx, |buffer, cx| buffer.apply_ops(operations, cx));
|
||||
|
||||
let subscription = client.subscribe_to_entity(channel.id.0)?;
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ impl ChannelBuffer {
|
|||
};
|
||||
this.replace_collaborators(response.collaborators, cx);
|
||||
this
|
||||
})?)
|
||||
}))
|
||||
}
|
||||
|
||||
fn release(&mut self, _: &mut App) {
|
||||
|
|
@ -168,7 +168,7 @@ impl ChannelBuffer {
|
|||
cx.notify();
|
||||
this.buffer
|
||||
.update(cx, |buffer, cx| buffer.apply_ops(ops, cx))
|
||||
})?;
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -182,7 +182,8 @@ impl ChannelBuffer {
|
|||
this.replace_collaborators(message.payload.collaborators, cx);
|
||||
cx.emit(ChannelBufferEvent::CollaboratorsChanged);
|
||||
cx.notify();
|
||||
})
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_buffer_update(
|
||||
|
|
|
|||
|
|
@ -170,17 +170,14 @@ impl ChannelStore {
|
|||
match status {
|
||||
client::Status::Connected { .. } => {
|
||||
this.update(cx, |this, cx| this.handle_connect(cx))
|
||||
.ok()?
|
||||
.await
|
||||
.log_err()?;
|
||||
}
|
||||
client::Status::SignedOut | client::Status::UpgradeRequired => {
|
||||
this.update(cx, |this, cx| this.handle_disconnect(false, cx))
|
||||
.ok();
|
||||
this.update(cx, |this, cx| this.handle_disconnect(false, cx));
|
||||
}
|
||||
_ => {
|
||||
this.update(cx, |this, cx| this.handle_disconnect(true, cx))
|
||||
.ok();
|
||||
this.update(cx, |this, cx| this.handle_disconnect(true, cx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -204,7 +201,7 @@ impl ChannelStore {
|
|||
while let Some(update_channels) = update_channels_rx.next().await {
|
||||
if let Some(this) = this.upgrade() {
|
||||
let update_task = this
|
||||
.update(cx, |this, cx| this.update_channels(update_channels, cx))?;
|
||||
.update(cx, |this, cx| this.update_channels(update_channels, cx));
|
||||
if let Some(update_task) = update_task {
|
||||
update_task.await.log_err();
|
||||
}
|
||||
|
|
@ -814,7 +811,7 @@ impl ChannelStore {
|
|||
this.update_channels_tx
|
||||
.unbounded_send(message.payload)
|
||||
.unwrap();
|
||||
})?;
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -841,7 +838,8 @@ impl ChannelStore {
|
|||
.set_role(role)
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_connect(&mut self, cx: &mut Context<Self>) -> Task<Result<()>> {
|
||||
|
|
@ -965,8 +963,7 @@ impl ChannelStore {
|
|||
buffer.update(cx, |buffer, cx| buffer.disconnect(cx));
|
||||
}
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ impl ClientCredentialsProvider {
|
|||
}
|
||||
|
||||
fn server_url(&self, cx: &AsyncApp) -> Result<String> {
|
||||
cx.update(|cx| ClientSettings::get_global(cx).server_url.clone())
|
||||
Ok(cx.update(|cx| ClientSettings::get_global(cx).server_url.clone()))
|
||||
}
|
||||
|
||||
/// Reads the credentials from the provider.
|
||||
|
|
@ -934,10 +934,10 @@ impl Client {
|
|||
let connect_task = cx.update({
|
||||
let cloud_client = self.cloud_client.clone();
|
||||
move |cx| cloud_client.connect(cx)
|
||||
})??;
|
||||
})?;
|
||||
let connection = connect_task.await?;
|
||||
|
||||
let (mut messages, task) = cx.update(|cx| connection.spawn(cx))?;
|
||||
let (mut messages, task) = cx.update(|cx| connection.spawn(cx));
|
||||
task.detach();
|
||||
|
||||
cx.spawn({
|
||||
|
|
@ -977,8 +977,7 @@ impl Client {
|
|||
}
|
||||
})
|
||||
.detach();
|
||||
})
|
||||
.log_err();
|
||||
});
|
||||
|
||||
let credentials = self.sign_in(try_provider, cx).await?;
|
||||
|
||||
|
|
@ -1003,8 +1002,7 @@ impl Client {
|
|||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
})
|
||||
.log_err();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1249,14 +1247,8 @@ impl Client {
|
|||
credentials: &Credentials,
|
||||
cx: &AsyncApp,
|
||||
) -> Task<Result<Connection, EstablishConnectionError>> {
|
||||
let release_channel = cx
|
||||
.update(|cx| ReleaseChannel::try_global(cx))
|
||||
.ok()
|
||||
.flatten();
|
||||
let app_version = cx
|
||||
.update(|cx| AppVersion::global(cx).to_string())
|
||||
.ok()
|
||||
.unwrap_or_default();
|
||||
let release_channel = cx.update(|cx| ReleaseChannel::try_global(cx));
|
||||
let app_version = cx.update(|cx| AppVersion::global(cx).to_string());
|
||||
|
||||
let http = self.http.clone();
|
||||
let proxy = http.proxy().cloned();
|
||||
|
|
@ -1293,7 +1285,7 @@ impl Client {
|
|||
None => Box::new(TcpStream::connect(rpc_host).await?),
|
||||
})
|
||||
}
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
log::info!("connected to rpc endpoint {}", rpc_url);
|
||||
|
|
@ -1361,12 +1353,12 @@ impl Client {
|
|||
let (open_url_tx, open_url_rx) = oneshot::channel::<String>();
|
||||
cx.update(|cx| {
|
||||
cx.spawn(async move |cx| {
|
||||
let url = open_url_rx.await?;
|
||||
cx.update(|cx| cx.open_url(&url))
|
||||
if let Ok(url) = open_url_rx.await {
|
||||
cx.update(|cx| cx.open_url(&url));
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
})
|
||||
.log_err();
|
||||
.detach();
|
||||
});
|
||||
|
||||
let credentials = background
|
||||
.clone()
|
||||
|
|
@ -1468,7 +1460,7 @@ impl Client {
|
|||
})
|
||||
.await?;
|
||||
|
||||
cx.update(|cx| cx.activate(true))?;
|
||||
cx.update(|cx| cx.activate(true));
|
||||
Ok(credentials)
|
||||
})
|
||||
}
|
||||
|
|
@ -1687,8 +1679,7 @@ impl Client {
|
|||
for handler in self.message_to_client_handlers.lock().iter() {
|
||||
handler(&message, cx);
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn telemetry(&self) -> &Arc<Telemetry> {
|
||||
|
|
@ -2101,7 +2092,7 @@ mod tests {
|
|||
let (done_tx2, done_rx2) = smol::channel::unbounded();
|
||||
AnyProtoClient::from(client.clone()).add_entity_message_handler(
|
||||
move |entity: Entity<TestEntity>, _: TypedEnvelope<proto::JoinProject>, cx| {
|
||||
match entity.read_with(&cx, |entity, _| entity.id).unwrap() {
|
||||
match entity.read_with(&cx, |entity, _| entity.id) {
|
||||
1 => done_tx1.try_send(()).unwrap(),
|
||||
2 => done_tx2.try_send(()).unwrap(),
|
||||
_ => unreachable!(),
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ impl UserStore {
|
|||
} else {
|
||||
anyhow::Ok(())
|
||||
}
|
||||
})??;
|
||||
})?;
|
||||
|
||||
this.update(cx, |_, cx| cx.notify())?;
|
||||
}
|
||||
|
|
@ -299,7 +299,7 @@ impl UserStore {
|
|||
_: TypedEnvelope<proto::ShowContacts>,
|
||||
mut cx: AsyncApp,
|
||||
) -> Result<()> {
|
||||
this.update(&mut cx, |_, cx| cx.emit(Event::ShowContacts))?;
|
||||
this.update(&mut cx, |_, cx| cx.emit(Event::ShowContacts));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -312,7 +312,7 @@ impl UserStore {
|
|||
this.update_contacts_tx
|
||||
.unbounded_send(UpdateContacts::Update(message.payload))
|
||||
.unwrap();
|
||||
})?;
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -353,7 +353,7 @@ impl UserStore {
|
|||
let mut incoming_requests = Vec::new();
|
||||
for request in message.incoming_requests {
|
||||
incoming_requests.push({
|
||||
this.update(cx, |this, cx| this.get_user(request.requester_id, cx))?
|
||||
this.update(cx, |this, cx| this.get_user(request.requester_id, cx))
|
||||
.await?
|
||||
});
|
||||
}
|
||||
|
|
@ -361,7 +361,7 @@ impl UserStore {
|
|||
let mut outgoing_requests = Vec::new();
|
||||
for requested_user_id in message.outgoing_requests {
|
||||
outgoing_requests.push(
|
||||
this.update(cx, |this, cx| this.get_user(requested_user_id, cx))?
|
||||
this.update(cx, |this, cx| this.get_user(requested_user_id, cx))
|
||||
.await?,
|
||||
);
|
||||
}
|
||||
|
|
@ -428,7 +428,7 @@ impl UserStore {
|
|||
}
|
||||
|
||||
cx.notify();
|
||||
})?;
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
|
|
@ -798,7 +798,7 @@ impl UserStore {
|
|||
this.read_with(cx, |this, _cx| {
|
||||
this.client.upgrade().map(|client| client.cloud_client())
|
||||
})
|
||||
})??
|
||||
})?
|
||||
.ok_or(anyhow::anyhow!("Failed to get Cloud client"))?;
|
||||
|
||||
let response = cloud_client.get_authenticated_user().await?;
|
||||
|
|
@ -806,7 +806,7 @@ impl UserStore {
|
|||
this.update(cx, |this, cx| {
|
||||
this.update_authenticated_user(response, cx);
|
||||
})
|
||||
})??;
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -914,7 +914,7 @@ impl Contact {
|
|||
let user = user_store
|
||||
.update(cx, |user_store, cx| {
|
||||
user_store.get_user(contact.user_id, cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
Ok(Self {
|
||||
user,
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ impl EditPredictionDelegate for CodestralEditPredictionDelegate {
|
|||
let edits: Arc<[(Range<Anchor>, Arc<str>)]> =
|
||||
vec![(cursor_position..cursor_position, completion_text.into())].into();
|
||||
let edit_preview = buffer
|
||||
.read_with(cx, |buffer, cx| buffer.preview_edits(edits.clone(), cx))?
|
||||
.read_with(cx, |buffer, cx| buffer.preview_edits(edits.clone(), cx))
|
||||
.await;
|
||||
|
||||
this.update(cx, |this, cx| {
|
||||
|
|
|
|||
|
|
@ -800,7 +800,6 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
assert!(
|
||||
buffer
|
||||
.read_with(&cx, |buffer, _| { buffer.saved_version().to_owned() })
|
||||
.expect("App should not be dropped")
|
||||
.observed_all(&requested_version)
|
||||
);
|
||||
anyhow::Ok(())
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ impl ChannelView {
|
|||
};
|
||||
buffer.set_language(Some(markdown), cx);
|
||||
})
|
||||
})?;
|
||||
});
|
||||
|
||||
cx.new_window_entity(|window, cx| {
|
||||
let mut this = Self::new(
|
||||
|
|
|
|||
|
|
@ -2179,7 +2179,7 @@ impl CollabPanel {
|
|||
cx.spawn_in(window, async move |this, cx| {
|
||||
if answer.await? == 0 {
|
||||
channel_store
|
||||
.update(cx, |channels, _| channels.remove_channel(channel_id))?
|
||||
.update(cx, |channels, _| channels.remove_channel(channel_id))
|
||||
.await
|
||||
.notify_async_err(cx);
|
||||
this.update_in(cx, |_, window, cx| cx.focus_self(window))
|
||||
|
|
@ -2213,7 +2213,7 @@ impl CollabPanel {
|
|||
cx.spawn_in(window, async move |_, cx| {
|
||||
if answer.await? == 0 {
|
||||
user_store
|
||||
.update(cx, |store, cx| store.remove_contact(user_id, cx))?
|
||||
.update(cx, |store, cx| store.remove_contact(user_id, cx))
|
||||
.await
|
||||
.notify_async_err(cx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,27 +24,20 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut App) {
|
|||
}
|
||||
|
||||
if let Some(incoming_call) = incoming_call {
|
||||
let unique_screens = cx.update(|cx| cx.displays()).unwrap();
|
||||
let unique_screens = cx.update(|cx| cx.displays());
|
||||
let window_size = gpui::Size {
|
||||
width: px(400.),
|
||||
height: px(72.),
|
||||
};
|
||||
|
||||
for screen in unique_screens {
|
||||
if let Some(options) = cx
|
||||
.update(|cx| notification_window_options(screen, window_size, cx))
|
||||
.log_err()
|
||||
{
|
||||
let window = cx
|
||||
.open_window(options, |_, cx| {
|
||||
cx.new(|_| {
|
||||
IncomingCallNotification::new(
|
||||
incoming_call.clone(),
|
||||
app_state.clone(),
|
||||
)
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
let options =
|
||||
cx.update(|cx| notification_window_options(screen, window_size, cx));
|
||||
if let Ok(window) = cx.open_window(options, |_, cx| {
|
||||
cx.new(|_| {
|
||||
IncomingCallNotification::new(incoming_call.clone(), app_state.clone())
|
||||
})
|
||||
}) {
|
||||
notification_windows.push(window);
|
||||
}
|
||||
}
|
||||
|
|
@ -88,8 +81,7 @@ impl IncomingCallNotificationState {
|
|||
)
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
})
|
||||
.log_err();
|
||||
});
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
|
|
|
|||
|
|
@ -222,16 +222,12 @@ impl McpServer {
|
|||
} else if let Some(handler) = handlers.borrow().get(&request.method.as_ref()) {
|
||||
let outgoing_tx = outgoing_tx.clone();
|
||||
|
||||
if let Some(task) = cx
|
||||
.update(|cx| handler(request_id, request.params, cx))
|
||||
.log_err()
|
||||
{
|
||||
cx.spawn(async move |_| {
|
||||
let response = task.await;
|
||||
outgoing_tx.unbounded_send(response).ok();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
let task = cx.update(|cx| handler(request_id, request.params, cx));
|
||||
cx.spawn(async move |_| {
|
||||
let response = task.await;
|
||||
outgoing_tx.unbounded_send(response).ok();
|
||||
})
|
||||
.detach();
|
||||
} else {
|
||||
Self::send_err(
|
||||
request_id,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ impl StdioTransport {
|
|||
working_directory: &Option<PathBuf>,
|
||||
cx: &AsyncApp,
|
||||
) -> Result<Self> {
|
||||
let shell = cx.update(|cx| TerminalSettings::get(None, cx).shell.clone())?;
|
||||
let shell = cx.update(|cx| TerminalSettings::get(None, cx).shell.clone());
|
||||
let builder = ShellBuilder::new(&shell, cfg!(windows)).non_interactive();
|
||||
let mut command =
|
||||
builder.build_smol_command(Some(binary.executable.display().to_string()), &binary.args);
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ impl Copilot {
|
|||
let mut params = server.default_initialize_params(false, cx);
|
||||
params.initialization_options = Some(editor_info_json);
|
||||
server.initialize(params, configuration.into(), cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
this.update(cx, |_, cx| notify_did_change_config_to_server(&server, cx))?
|
||||
|
|
|
|||
|
|
@ -624,8 +624,6 @@ impl CopilotChat {
|
|||
) -> Result<(Arc<dyn HttpClient>, ApiToken, CopilotChatConfiguration)> {
|
||||
let this = cx
|
||||
.update(|cx| Self::global(cx))
|
||||
.ok()
|
||||
.flatten()
|
||||
.context("Copilot chat is not enabled")?;
|
||||
|
||||
let (oauth_token, api_token, client, configuration) = this.read_with(cx, |this, _| {
|
||||
|
|
@ -635,7 +633,7 @@ impl CopilotChat {
|
|||
this.client.clone(),
|
||||
this.configuration.clone(),
|
||||
)
|
||||
})?;
|
||||
});
|
||||
|
||||
let oauth_token = oauth_token.context("No OAuth token available")?;
|
||||
|
||||
|
|
@ -648,7 +646,7 @@ impl CopilotChat {
|
|||
this.update(cx, |this, cx| {
|
||||
this.api_token = Some(token.clone());
|
||||
cx.notify();
|
||||
})?;
|
||||
});
|
||||
token
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,14 +75,12 @@ impl EditPredictionDelegate for CopilotEditPredictionDelegate {
|
|||
let completions = copilot
|
||||
.update(cx, |copilot, cx| {
|
||||
copilot.completions(&buffer, cursor_position, cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
if let Some(mut completion) = completions.into_iter().next()
|
||||
&& let Some((trimmed_range, trimmed_text, snapshot)) = cx
|
||||
.update(|cx| trim_completion(&completion, cx))
|
||||
.ok()
|
||||
.flatten()
|
||||
&& let Some((trimmed_range, trimmed_text, snapshot)) =
|
||||
cx.update(|cx| trim_completion(&completion, cx))
|
||||
{
|
||||
let preview = buffer
|
||||
.update(cx, |this, cx| {
|
||||
|
|
@ -90,7 +88,7 @@ impl EditPredictionDelegate for CopilotEditPredictionDelegate {
|
|||
Arc::from([(trimmed_range.clone(), trimmed_text.clone())].as_slice()),
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
this.update(cx, |this, cx| {
|
||||
this.pending_refresh = None;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ impl CredentialsProvider for KeychainCredentialsProvider {
|
|||
url: &'a str,
|
||||
cx: &'a AsyncApp,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Option<(String, Vec<u8>)>>> + 'a>> {
|
||||
async move { cx.update(|cx| cx.read_credentials(url))?.await }.boxed_local()
|
||||
async move { cx.update(|cx| cx.read_credentials(url)).await }.boxed_local()
|
||||
}
|
||||
|
||||
fn write_credentials<'a>(
|
||||
|
|
@ -103,7 +103,7 @@ impl CredentialsProvider for KeychainCredentialsProvider {
|
|||
cx: &'a AsyncApp,
|
||||
) -> Pin<Box<dyn Future<Output = Result<()>> + 'a>> {
|
||||
async move {
|
||||
cx.update(move |cx| cx.write_credentials(url, username, password))?
|
||||
cx.update(move |cx| cx.write_credentials(url, username, password))
|
||||
.await
|
||||
}
|
||||
.boxed_local()
|
||||
|
|
@ -114,7 +114,7 @@ impl CredentialsProvider for KeychainCredentialsProvider {
|
|||
url: &'a str,
|
||||
cx: &'a AsyncApp,
|
||||
) -> Pin<Box<dyn Future<Output = Result<()>> + 'a>> {
|
||||
async move { cx.update(move |cx| cx.delete_credentials(url))?.await }.boxed_local()
|
||||
async move { cx.update(move |cx| cx.delete_credentials(url)).await }.boxed_local()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -178,9 +178,7 @@ impl TransportDelegate {
|
|||
self.tasks.lock().clear();
|
||||
|
||||
let log_dap_communications =
|
||||
cx.update(|cx| DebuggerSettings::get_global(cx).log_dap_communications)
|
||||
.with_context(|| "Failed to get Debugger Setting log dap communications error in transport::start_handlers. Defaulting to false")
|
||||
.unwrap_or(false);
|
||||
cx.update(|cx| DebuggerSettings::get_global(cx).log_dap_communications);
|
||||
|
||||
let connect = self.transport.lock().connect();
|
||||
let (input, output) = connect.await?;
|
||||
|
|
@ -550,10 +548,9 @@ impl TcpTransport {
|
|||
process = Some(p);
|
||||
};
|
||||
|
||||
let timeout = connection_args.timeout.unwrap_or_else(|| {
|
||||
cx.update(|cx| DebuggerSettings::get_global(cx).timeout)
|
||||
.unwrap_or(20000u64)
|
||||
});
|
||||
let timeout = connection_args
|
||||
.timeout
|
||||
.unwrap_or_else(|| cx.update(|cx| DebuggerSettings::get_global(cx).timeout));
|
||||
|
||||
log::info!(
|
||||
"Debug adapter has connected to TCP server {}:{}",
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ impl LogStore {
|
|||
if let Some(this) = this.upgrade() {
|
||||
this.update(cx, |this, cx| {
|
||||
this.add_debug_adapter_message(message, cx);
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
smol::future::yield_now().await;
|
||||
|
|
@ -170,7 +170,7 @@ impl LogStore {
|
|||
if let Some(this) = this.upgrade() {
|
||||
this.update(cx, |this, cx| {
|
||||
this.add_debug_adapter_log(message, cx);
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
smol::future::yield_now().await;
|
||||
|
|
@ -902,10 +902,10 @@ impl DapLogView {
|
|||
let language = language.await.ok();
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.set_language(language, cx);
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
.detach();
|
||||
});
|
||||
|
||||
self.editor = editor;
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ impl DebugPanel {
|
|||
dap_store
|
||||
.update(cx, |dap_store, cx| {
|
||||
dap_store.boot_session(session.clone(), definition, worktree, cx)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
}
|
||||
});
|
||||
|
|
@ -286,7 +286,7 @@ impl DebugPanel {
|
|||
.unbounded_send(format!("error: {:#}", error))
|
||||
.ok();
|
||||
session.shutdown(cx)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
}
|
||||
anyhow::Ok(())
|
||||
|
|
@ -404,7 +404,7 @@ impl DebugPanel {
|
|||
session.boot(binary, worktree, dap_store_handle.downgrade(), cx)
|
||||
});
|
||||
(session, task)
|
||||
})?;
|
||||
});
|
||||
Self::register_session(this.clone(), session.clone(), true, cx).await?;
|
||||
|
||||
if let Err(error) = task.await {
|
||||
|
|
@ -418,7 +418,7 @@ impl DebugPanel {
|
|||
))
|
||||
.ok();
|
||||
session.shutdown(cx)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
|
||||
return Err(error);
|
||||
|
|
@ -466,11 +466,10 @@ impl DebugPanel {
|
|||
session.boot(binary, worktree, dap_store_handle.downgrade(), cx)
|
||||
});
|
||||
(session, task)
|
||||
})?;
|
||||
});
|
||||
// Focus child sessions if the parent has never emitted a stopped event;
|
||||
// this improves our JavaScript experience, as it always spawns a "main" session that then spawns subsessions.
|
||||
let parent_ever_stopped =
|
||||
parent_session.update(cx, |this, _| this.has_ever_stopped())?;
|
||||
let parent_ever_stopped = parent_session.update(cx, |this, _| this.has_ever_stopped());
|
||||
Self::register_session(this, session, !parent_ever_stopped, cx).await?;
|
||||
task.await
|
||||
})
|
||||
|
|
@ -517,7 +516,7 @@ impl DebugPanel {
|
|||
return;
|
||||
}
|
||||
}
|
||||
session.update(cx, |session, cx| session.shutdown(cx)).ok();
|
||||
session.update(cx, |session, cx| session.shutdown(cx));
|
||||
this.update(cx, |this, cx| {
|
||||
this.retain_sessions(|other| entity_id != other.entity_id());
|
||||
if let Some(active_session_id) = this
|
||||
|
|
@ -1443,7 +1442,7 @@ async fn register_session_inner(
|
|||
session: Entity<Session>,
|
||||
cx: &mut AsyncWindowContext,
|
||||
) -> Result<Entity<DebugSession>> {
|
||||
let adapter_name = session.read_with(cx, |session, _| session.adapter())?;
|
||||
let adapter_name = session.read_with(cx, |session, _| session.adapter());
|
||||
this.update_in(cx, |_, window, cx| {
|
||||
cx.subscribe_in(
|
||||
&session,
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ impl NewProcessModal {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let Some(task_inventory) = task_store
|
||||
.update(cx, |task_store, _| task_store.task_inventory().cloned())?
|
||||
.update(cx, |task_store, _| task_store.task_inventory().cloned())
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
|
@ -194,7 +194,7 @@ impl NewProcessModal {
|
|||
.update(cx, |task_inventory, cx| {
|
||||
task_inventory
|
||||
.used_and_current_resolved_tasks(task_contexts.clone(), cx)
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
|
||||
if let Ok(task) = debug_picker.update(cx, |picker, cx| {
|
||||
|
|
|
|||
|
|
@ -1113,7 +1113,7 @@ impl RunningState {
|
|||
task_with_shell.clone(),
|
||||
cx,
|
||||
)
|
||||
})?.await?;
|
||||
}).await?;
|
||||
|
||||
let terminal_view = cx.new_window_entity(|window, cx| {
|
||||
TerminalView::new(
|
||||
|
|
@ -1135,7 +1135,7 @@ impl RunningState {
|
|||
})?;
|
||||
|
||||
let exit_status = terminal
|
||||
.read_with(cx, |terminal, cx| terminal.wait_for_completed_task(cx))?
|
||||
.read_with(cx, |terminal, cx| terminal.wait_for_completed_task(cx))
|
||||
.await
|
||||
.context("Failed to wait for completed task")?;
|
||||
|
||||
|
|
@ -1302,7 +1302,7 @@ impl RunningState {
|
|||
.pid()
|
||||
.map(|pid| pid.as_u32())
|
||||
.context("Terminal was spawned but PID was not available")
|
||||
})?
|
||||
})
|
||||
});
|
||||
|
||||
cx.background_spawn(async move { anyhow::Ok(sender.send(terminal_task.await).await?) })
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ impl BreakpointList {
|
|||
.update(cx, |this, cx| this.find_or_create_worktree(path, false, cx));
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let (worktree, relative_path) = task.await?;
|
||||
let worktree_id = worktree.read_with(cx, |this, _| this.id())?;
|
||||
let worktree_id = worktree.read_with(cx, |this, _| this.id());
|
||||
let item = this
|
||||
.update_in(cx, |this, window, cx| {
|
||||
this.workspace.update(cx, |this, cx| {
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ impl StackFrameList {
|
|||
.await?;
|
||||
let position = buffer.read_with(cx, |this, _| {
|
||||
this.snapshot().anchor_after(PointUtf16::new(row, 0))
|
||||
})?;
|
||||
});
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.workspace.update(cx, |workspace, cx| {
|
||||
let project_path = buffer
|
||||
|
|
|
|||
|
|
@ -183,13 +183,13 @@ impl StackTraceView {
|
|||
.await?;
|
||||
|
||||
let project_path = ProjectPath {
|
||||
worktree_id: worktree.read_with(cx, |tree, _| tree.id())?,
|
||||
worktree_id: worktree.read_with(cx, |tree, _| tree.id()),
|
||||
path: relative_path,
|
||||
};
|
||||
|
||||
if let Some(buffer) = this
|
||||
.read_with(cx, |this, _| this.project.clone())?
|
||||
.update(cx, |project, cx| project.open_buffer(project_path, cx))?
|
||||
.update(cx, |project, cx| project.open_buffer(project_path, cx))
|
||||
.await
|
||||
.log_err()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ impl ProjectDiagnosticsEditor {
|
|||
};
|
||||
|
||||
if let Some(buffer) = project_handle
|
||||
.update(cx, |project, cx| project.open_buffer(path.clone(), cx))?
|
||||
.update(cx, |project, cx| project.open_buffer(path.clone(), cx))
|
||||
.await
|
||||
.log_err()
|
||||
{
|
||||
|
|
@ -1088,9 +1088,8 @@ async fn heuristic_syntactic_expand(
|
|||
return Some(node_row_range);
|
||||
} else if node_name.ends_with("statement") || node_name.ends_with("declaration") {
|
||||
// Expand to the nearest dedent or blank line for statements and declarations.
|
||||
let tab_size = cx
|
||||
.update(|cx| snapshot.settings_at(node_range.start, cx).tab_size.get())
|
||||
.ok()?;
|
||||
let tab_size =
|
||||
cx.update(|cx| snapshot.settings_at(node_range.start, cx).tab_size.get());
|
||||
let indent_level = snapshot
|
||||
.line_indent_for_row(node_range.start.row)
|
||||
.len(tab_size);
|
||||
|
|
|
|||
|
|
@ -153,19 +153,19 @@ async fn collect_snapshots(
|
|||
.filter(|path| path.worktree_id == worktree_id)?;
|
||||
let relative_path: Arc<Path> = project_path.path.as_std_path().into();
|
||||
Some((project_path, relative_path))
|
||||
})? {
|
||||
}) {
|
||||
if let hash_map::Entry::Vacant(entry) = snapshots_by_path.entry(relative_path) {
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_buffer(project_path.clone(), cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
let diff = git_store
|
||||
.update(cx, |git_store, cx| {
|
||||
git_store.open_uncommitted_diff(buffer.clone(), cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx))?;
|
||||
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx));
|
||||
entry.insert((stored_event.old_snapshot.clone(), diff_snapshot));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1841,7 +1841,7 @@ impl EditPredictionStore {
|
|||
worktree_id: file.worktree_id(cx),
|
||||
path: file.path().clone(),
|
||||
})
|
||||
})?;
|
||||
});
|
||||
|
||||
let buffer_task = project.update(cx, |project, cx| {
|
||||
let (path, _, _) = project
|
||||
|
|
@ -1862,7 +1862,7 @@ impl EditPredictionStore {
|
|||
})?;
|
||||
|
||||
Some(project.open_buffer(path, cx))
|
||||
})?;
|
||||
});
|
||||
|
||||
if let Some(buffer_task) = buffer_task {
|
||||
let closest_buffer = buffer_task.await?;
|
||||
|
|
@ -1874,7 +1874,7 @@ impl EditPredictionStore {
|
|||
.into_iter()
|
||||
.min_by_key(|entry| entry.diagnostic.severity)
|
||||
.map(|entry| entry.range.start)
|
||||
})?
|
||||
})
|
||||
.map(|position| (closest_buffer, position));
|
||||
}
|
||||
}
|
||||
|
|
@ -1973,8 +1973,7 @@ impl EditPredictionStore {
|
|||
})
|
||||
},
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
}
|
||||
Err(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,16 +49,14 @@ impl EditPredictionResult {
|
|||
};
|
||||
}
|
||||
|
||||
let Some((edits, snapshot, edit_preview_task)) = edited_buffer
|
||||
.read_with(cx, |buffer, cx| {
|
||||
let Some((edits, snapshot, edit_preview_task)) =
|
||||
edited_buffer.read_with(cx, |buffer, cx| {
|
||||
let new_snapshot = buffer.snapshot();
|
||||
let edits: Arc<[_]> =
|
||||
interpolate_edits(&edited_buffer_snapshot, &new_snapshot, &edits)?.into();
|
||||
|
||||
Some((edits.clone(), new_snapshot, buffer.preview_edits(edits, cx)))
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
else {
|
||||
return Self {
|
||||
id,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ pub async fn apply_diff(
|
|||
cx: &mut AsyncApp,
|
||||
) -> Result<OpenedBuffers> {
|
||||
let worktree = project
|
||||
.read_with(cx, |project, cx| project.visible_worktrees(cx).next())?
|
||||
.read_with(cx, |project, cx| project.visible_worktrees(cx).next())
|
||||
.context("project has no worktree")?;
|
||||
|
||||
let paths: Vec<_> = diff_str
|
||||
|
|
@ -65,7 +65,7 @@ pub async fn apply_diff(
|
|||
} else {
|
||||
None
|
||||
}
|
||||
})?;
|
||||
});
|
||||
|
||||
if let Some(delete_task) = delete_task {
|
||||
delete_task.await?;
|
||||
|
|
@ -79,20 +79,20 @@ pub async fn apply_diff(
|
|||
let buffer = match included_files.entry(path.to_string()) {
|
||||
Entry::Occupied(entry) => entry.get().clone(),
|
||||
Entry::Vacant(entry) => {
|
||||
let buffer = if status == FileStatus::Created {
|
||||
let buffer: Entity<Buffer> = if status == FileStatus::Created {
|
||||
project
|
||||
.update(cx, |project, cx| project.create_buffer(true, cx))?
|
||||
.update(cx, |project, cx| project.create_buffer(true, cx))
|
||||
.await?
|
||||
} else {
|
||||
let project_path = project
|
||||
.update(cx, |project, cx| {
|
||||
project.find_project_path(path.as_ref(), cx)
|
||||
})?
|
||||
})
|
||||
.with_context(|| format!("no such path: {}", path))?;
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_buffer(project_path, cx)
|
||||
})?
|
||||
})
|
||||
.await?
|
||||
};
|
||||
entry.insert(buffer.clone());
|
||||
|
|
@ -111,7 +111,7 @@ pub async fn apply_diff(
|
|||
.with_context(|| format!("Diff:\n{diff_str}"))?,
|
||||
);
|
||||
anyhow::Ok(())
|
||||
})??;
|
||||
})?;
|
||||
}
|
||||
DiffEvent::FileEnd { renamed_to } => {
|
||||
let buffer = current_file
|
||||
|
|
@ -135,14 +135,14 @@ pub async fn apply_diff(
|
|||
new_project_path,
|
||||
cx,
|
||||
))
|
||||
})??
|
||||
})?
|
||||
.await?;
|
||||
}
|
||||
|
||||
let edits = mem::take(&mut edits);
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(edits, None, cx);
|
||||
})?;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -174,7 +174,7 @@ pub async fn refresh_worktree_entries(
|
|||
.as_local()
|
||||
.unwrap()
|
||||
.refresh_entries_for_paths(rel_paths)
|
||||
})?
|
||||
})
|
||||
.recv()
|
||||
.await;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,8 +177,7 @@ pub(crate) fn request_prediction_with_zeta1(
|
|||
})
|
||||
},
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
}
|
||||
|
||||
return Err(err);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use edit_prediction::{
|
|||
EditPredictionStore,
|
||||
zeta2::{zeta2_output_for_patch, zeta2_prompt_input},
|
||||
};
|
||||
use gpui::AsyncApp;
|
||||
use gpui::{AsyncApp, Entity};
|
||||
use std::sync::Arc;
|
||||
use zeta_prompt::format_zeta_prompt;
|
||||
|
||||
|
|
@ -46,36 +46,37 @@ pub async fn run_format_prompt(
|
|||
|
||||
step_progress.set_substatus("formatting zeta2 prompt");
|
||||
|
||||
let ep_store = cx.update(|cx| {
|
||||
let ep_store: Entity<EditPredictionStore> = cx.update(|cx| {
|
||||
EditPredictionStore::try_global(cx).context("EditPredictionStore not initialized")
|
||||
})??;
|
||||
})?;
|
||||
|
||||
let state = example.state.as_ref().context("state must be set")?;
|
||||
let snapshot = state.buffer.read_with(&cx, |buffer, _| buffer.snapshot())?;
|
||||
let snapshot = state.buffer.read_with(&cx, |buffer, _| buffer.snapshot());
|
||||
let project = state.project.clone();
|
||||
let (_, input) = ep_store.update(&mut cx, |ep_store, cx| {
|
||||
let events = ep_store
|
||||
.edit_history_for_project(&project, cx)
|
||||
.into_iter()
|
||||
.map(|e| e.event)
|
||||
.collect();
|
||||
anyhow::Ok(zeta2_prompt_input(
|
||||
&snapshot,
|
||||
example
|
||||
.context
|
||||
.as_ref()
|
||||
.context("context must be set")?
|
||||
.files
|
||||
.clone(),
|
||||
events,
|
||||
example.spec.cursor_path.clone(),
|
||||
example
|
||||
.buffer
|
||||
.as_ref()
|
||||
.context("buffer must be set")?
|
||||
.cursor_offset,
|
||||
))
|
||||
})??;
|
||||
let (_, input) =
|
||||
ep_store.update(&mut cx, |ep_store: &mut EditPredictionStore, cx| {
|
||||
let events = ep_store
|
||||
.edit_history_for_project(&project, cx)
|
||||
.into_iter()
|
||||
.map(|e| e.event)
|
||||
.collect();
|
||||
anyhow::Ok(zeta2_prompt_input(
|
||||
&snapshot,
|
||||
example
|
||||
.context
|
||||
.as_ref()
|
||||
.context("context must be set")?
|
||||
.files
|
||||
.clone(),
|
||||
events,
|
||||
example.spec.cursor_path.clone(),
|
||||
example
|
||||
.buffer
|
||||
.as_ref()
|
||||
.context("buffer must be set")?
|
||||
.cursor_offset,
|
||||
))
|
||||
})?;
|
||||
let prompt = format_zeta_prompt(&input);
|
||||
let expected_output = zeta2_output_for_patch(
|
||||
&input,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ pub async fn run_load_project(
|
|||
let (buffer, cursor_position) =
|
||||
cursor_position(example, &project, &open_buffers, &mut cx).await?;
|
||||
buffer
|
||||
.read_with(&cx, |buffer, _| buffer.parsing_idle())?
|
||||
.read_with(&cx, |buffer, _| buffer.parsing_idle())
|
||||
.await;
|
||||
let (example_buffer, language_name) = buffer.read_with(&cx, |buffer, _cx| {
|
||||
let cursor_point = cursor_position.to_point(&buffer);
|
||||
|
|
@ -64,7 +64,7 @@ pub async fn run_load_project(
|
|||
},
|
||||
language_name,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
|
||||
progress.set_info(language_name, InfoStyle::Normal);
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ async fn cursor_position(
|
|||
open_buffers: &OpenedBuffers,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Result<(Entity<Buffer>, Anchor)> {
|
||||
let language_registry = project.read_with(cx, |project, _| project.languages().clone())?;
|
||||
let language_registry = project.read_with(cx, |project, _| project.languages().clone());
|
||||
let result = language_registry
|
||||
.load_language_for_file_path(&example.spec.cursor_path)
|
||||
.await;
|
||||
|
|
@ -101,14 +101,14 @@ async fn cursor_position(
|
|||
buffer.clone()
|
||||
} else {
|
||||
// Since the worktree scanner is disabled, manually refresh entries for the cursor path.
|
||||
if let Some(worktree) = project.read_with(cx, |project, cx| project.worktrees(cx).next())? {
|
||||
if let Some(worktree) = project.read_with(cx, |project, cx| project.worktrees(cx).next()) {
|
||||
refresh_worktree_entries(&worktree, [&*example.spec.cursor_path], cx).await?;
|
||||
}
|
||||
|
||||
let cursor_path = project
|
||||
.read_with(cx, |project, cx| {
|
||||
project.find_project_path(&example.spec.cursor_path, cx)
|
||||
})?
|
||||
})
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"failed to find cursor path {}",
|
||||
|
|
@ -117,13 +117,13 @@ async fn cursor_position(
|
|||
})?;
|
||||
|
||||
project
|
||||
.update(cx, |project, cx| project.open_buffer(cursor_path, cx))?
|
||||
.update(cx, |project, cx| project.open_buffer(cursor_path, cx))
|
||||
.await?
|
||||
};
|
||||
|
||||
let (cursor_excerpt, cursor_offset_within_excerpt) = example.spec.cursor_excerpt()?;
|
||||
|
||||
let excerpt_offset = cursor_buffer.read_with(cx, |buffer, _cx| {
|
||||
let excerpt_offset = cursor_buffer.read_with(&*cx, |buffer, _cx| {
|
||||
let text = buffer.text();
|
||||
|
||||
let mut matches = text.match_indices(&cursor_excerpt);
|
||||
|
|
@ -139,11 +139,11 @@ async fn cursor_position(
|
|||
&example.spec.name
|
||||
);
|
||||
Ok(excerpt_offset)
|
||||
})??;
|
||||
})?;
|
||||
|
||||
let cursor_offset = excerpt_offset + cursor_offset_within_excerpt;
|
||||
let cursor_anchor =
|
||||
cursor_buffer.read_with(cx, |buffer, _| buffer.anchor_after(cursor_offset))?;
|
||||
cursor_buffer.read_with(&*cx, |buffer, _| buffer.anchor_after(cursor_offset));
|
||||
|
||||
Ok((cursor_buffer, cursor_anchor))
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ async fn setup_project(
|
|||
cx: &mut AsyncApp,
|
||||
) -> Result<Entity<Project>> {
|
||||
let ep_store = cx
|
||||
.update(|cx| EditPredictionStore::try_global(cx))?
|
||||
.update(|cx| EditPredictionStore::try_global(cx))
|
||||
.context("Store should be initialized at init")?;
|
||||
|
||||
let worktree_path = setup_worktree(example, step_progress).await?;
|
||||
|
|
@ -163,16 +163,13 @@ async fn setup_project(
|
|||
if let Some(project) = app_state.project_cache.get(&example.spec.repository_url) {
|
||||
ep_store.update(cx, |ep_store, _| {
|
||||
ep_store.clear_history_for_project(&project);
|
||||
})?;
|
||||
let buffer_store = project.read_with(cx, |project, _| project.buffer_store().clone())?;
|
||||
});
|
||||
let buffer_store = project.read_with(cx, |project, _| project.buffer_store().clone());
|
||||
let buffers = buffer_store.read_with(cx, |buffer_store, _| {
|
||||
buffer_store.buffers().collect::<Vec<_>>()
|
||||
})?;
|
||||
});
|
||||
for buffer in buffers {
|
||||
buffer
|
||||
.update(cx, |buffer, cx| buffer.reload(cx))?
|
||||
.await
|
||||
.ok();
|
||||
buffer.update(cx, |buffer, cx| buffer.reload(cx)).await.ok();
|
||||
}
|
||||
return Ok(project);
|
||||
}
|
||||
|
|
@ -188,20 +185,20 @@ async fn setup_project(
|
|||
false,
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
project.disable_worktree_scanner(cx);
|
||||
project.create_worktree(&worktree_path, true, cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
app_state
|
||||
.project_cache
|
||||
.insert(example.spec.repository_url.clone(), project.clone());
|
||||
|
||||
let buffer_store = project.read_with(cx, |project, _| project.buffer_store().clone())?;
|
||||
let buffer_store = project.read_with(cx, |project, _| project.buffer_store().clone());
|
||||
cx.subscribe(&buffer_store, {
|
||||
let project = project.clone();
|
||||
move |_, event, cx| match event {
|
||||
|
|
@ -210,7 +207,7 @@ async fn setup_project(
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
})?
|
||||
})
|
||||
.detach();
|
||||
|
||||
Ok(project)
|
||||
|
|
|
|||
|
|
@ -78,9 +78,9 @@ pub async fn run_prediction(
|
|||
.await;
|
||||
}
|
||||
|
||||
let ep_store = cx.update(|cx| {
|
||||
EditPredictionStore::try_global(cx).context("EditPredictionStore not initialized")
|
||||
})??;
|
||||
let ep_store = cx
|
||||
.update(|cx| EditPredictionStore::try_global(cx))
|
||||
.context("EditPredictionStore not initialized")?;
|
||||
|
||||
ep_store.update(&mut cx, |store, _cx| {
|
||||
let model = match provider {
|
||||
|
|
@ -93,7 +93,7 @@ pub async fn run_prediction(
|
|||
}
|
||||
};
|
||||
store.set_edit_prediction_model(model);
|
||||
})?;
|
||||
});
|
||||
step_progress.set_substatus("configuring model");
|
||||
let state = example.state.as_ref().context("state must be set")?;
|
||||
let run_dir = RUN_DIR.join(&example.spec.name);
|
||||
|
|
@ -101,8 +101,7 @@ pub async fn run_prediction(
|
|||
let updated_example = Arc::new(Mutex::new(example.clone()));
|
||||
let current_run_ix = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
let mut debug_rx =
|
||||
ep_store.update(&mut cx, |store, cx| store.debug_info(&state.project, cx))?;
|
||||
let mut debug_rx = ep_store.update(&mut cx, |store, cx| store.debug_info(&state.project, cx));
|
||||
let debug_task = cx.background_spawn({
|
||||
let updated_example = updated_example.clone();
|
||||
let current_run_ix = current_run_ix.clone();
|
||||
|
|
@ -185,7 +184,7 @@ pub async fn run_prediction(
|
|||
cloud_llm_client::PredictEditsRequestTrigger::Cli,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
let actual_patch = prediction
|
||||
|
|
@ -219,7 +218,7 @@ pub async fn run_prediction(
|
|||
|
||||
ep_store.update(&mut cx, |store, _| {
|
||||
store.remove_project(&state.project);
|
||||
})?;
|
||||
});
|
||||
debug_task.await?;
|
||||
|
||||
*example = Arc::into_inner(updated_example)
|
||||
|
|
|
|||
|
|
@ -34,19 +34,19 @@ pub async fn run_context_retrieval(
|
|||
|
||||
let _lsp_handle = project.update(&mut cx, |project, cx| {
|
||||
project.register_buffer_with_language_servers(&state.buffer, cx)
|
||||
})?;
|
||||
});
|
||||
wait_for_language_servers_to_start(&project, &state.buffer, &step_progress, &mut cx).await?;
|
||||
|
||||
let ep_store = cx.update(|cx| {
|
||||
EditPredictionStore::try_global(cx).context("EditPredictionStore not initialized")
|
||||
})??;
|
||||
let ep_store = cx
|
||||
.update(|cx| EditPredictionStore::try_global(cx))
|
||||
.context("EditPredictionStore not initialized")?;
|
||||
|
||||
let mut events = ep_store.update(&mut cx, |store, cx| {
|
||||
store.register_buffer(&state.buffer, &project, cx);
|
||||
store.set_use_context(true);
|
||||
store.refresh_context(&project, &state.buffer, state.cursor_position, cx);
|
||||
store.debug_info(&project, cx)
|
||||
})?;
|
||||
});
|
||||
|
||||
while let Some(event) = events.next().await {
|
||||
match event {
|
||||
|
|
@ -58,7 +58,7 @@ pub async fn run_context_retrieval(
|
|||
}
|
||||
|
||||
let context_files =
|
||||
ep_store.update(&mut cx, |store, cx| store.context_for_project(&project, cx))?;
|
||||
ep_store.update(&mut cx, |store, cx| store.context_for_project(&project, cx));
|
||||
|
||||
let excerpt_count: usize = context_files.iter().map(|f| f.excerpts.len()).sum();
|
||||
step_progress.set_info(format!("{} excerpts", excerpt_count), InfoStyle::Normal);
|
||||
|
|
@ -75,10 +75,10 @@ async fn wait_for_language_servers_to_start(
|
|||
step_progress: &Arc<StepProgress>,
|
||||
cx: &mut AsyncApp,
|
||||
) -> anyhow::Result<()> {
|
||||
let lsp_store = project.read_with(cx, |project, _| project.lsp_store())?;
|
||||
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
|
||||
|
||||
let (language_server_ids, mut starting_language_server_ids) = buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
let (language_server_ids, mut starting_language_server_ids) =
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
lsp_store.update(cx, |lsp_store, cx| {
|
||||
let ids = lsp_store.language_servers_for_local_buffer(buffer, cx);
|
||||
let starting_ids = ids
|
||||
|
|
@ -88,8 +88,7 @@ async fn wait_for_language_servers_to_start(
|
|||
.collect::<HashSet<_>>();
|
||||
(ids, starting_ids)
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
});
|
||||
|
||||
step_progress.set_substatus(format!("waiting for {} LSPs", language_server_ids.len()));
|
||||
|
||||
|
|
@ -164,7 +163,7 @@ async fn wait_for_language_servers_to_start(
|
|||
];
|
||||
|
||||
project
|
||||
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))?
|
||||
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))
|
||||
.await?;
|
||||
|
||||
let mut pending_language_server_ids = lsp_store.read_with(cx, |lsp_store, _| {
|
||||
|
|
@ -178,7 +177,7 @@ async fn wait_for_language_servers_to_start(
|
|||
.is_some_and(|status| status.has_pending_diagnostic_updates)
|
||||
})
|
||||
.collect::<HashSet<_>>()
|
||||
})?;
|
||||
});
|
||||
while !pending_language_server_ids.is_empty() {
|
||||
futures::select! {
|
||||
language_server_id = rx.next() => {
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ impl RelatedExcerptStore {
|
|||
DefinitionTask::CacheMiss(task) => {
|
||||
let locations = task.await.log_err()??;
|
||||
let duration = start_time.elapsed();
|
||||
cx.update(|cx| {
|
||||
Some(cx.update(|cx| {
|
||||
(
|
||||
identifier,
|
||||
Arc::new(CacheEntry {
|
||||
|
|
@ -210,8 +210,7 @@ impl RelatedExcerptStore {
|
|||
}),
|
||||
Some(duration),
|
||||
)
|
||||
})
|
||||
.ok()
|
||||
}))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -280,12 +279,12 @@ async fn rebuild_related_files(
|
|||
if let hash_map::Entry::Vacant(e) = snapshots.entry(definition.buffer.entity_id()) {
|
||||
definition
|
||||
.buffer
|
||||
.read_with(cx, |buffer, _| buffer.parsing_idle())?
|
||||
.read_with(cx, |buffer, _| buffer.parsing_idle())
|
||||
.await;
|
||||
e.insert(
|
||||
definition
|
||||
.buffer
|
||||
.read_with(cx, |buffer, _| buffer.snapshot())?,
|
||||
.read_with(cx, |buffer, _| buffer.snapshot()),
|
||||
);
|
||||
}
|
||||
let worktree_id = definition.path.worktree_id;
|
||||
|
|
@ -296,7 +295,7 @@ async fn rebuild_related_files(
|
|||
if let Some(worktree) = project.worktree_for_id(worktree_id, cx) {
|
||||
e.insert(worktree.read(cx).root_name().as_unix_str().to_string());
|
||||
}
|
||||
})?;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ impl EditPredictionContextView {
|
|||
for (path, buffer, ranges) in paths {
|
||||
multibuffer.set_excerpts_for_path(path, buffer, ranges, 0, cx);
|
||||
}
|
||||
})?;
|
||||
});
|
||||
|
||||
editor.update_in(cx, |editor, window, cx| {
|
||||
editor.move_to_beginning(&Default::default(), window, cx);
|
||||
|
|
|
|||
|
|
@ -168,16 +168,19 @@ fn capture_example_as_markdown(
|
|||
fs.create_dir(&dir).await.ok();
|
||||
let mut path = dir.join(&example_spec.name.replace(' ', "--").replace(':', "-"));
|
||||
path.set_extension("md");
|
||||
project.update(cx, |project, cx| project.open_local_buffer(&path, cx))
|
||||
project
|
||||
.update(cx, |project, cx| project.open_local_buffer(&path, cx))
|
||||
.await?
|
||||
} else {
|
||||
project.update(cx, |project, cx| project.create_buffer(false, cx))
|
||||
}?
|
||||
.await?;
|
||||
project
|
||||
.update(cx, |project, cx| project.create_buffer(false, cx))
|
||||
.await?
|
||||
};
|
||||
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.set_text(example_spec.to_markdown(), cx);
|
||||
buffer.set_language(Some(markdown_language), cx);
|
||||
})?;
|
||||
});
|
||||
workspace_entity.update_in(cx, |workspace, window, cx| {
|
||||
workspace.add_item_to_active_pane(
|
||||
Box::new(
|
||||
|
|
|
|||
|
|
@ -74,8 +74,7 @@ impl BlinkManager {
|
|||
cx.spawn(async move |this, cx| {
|
||||
Timer::after(interval).await;
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(cx, |this, cx| this.blink_cursors(epoch, cx))
|
||||
.ok();
|
||||
this.update(cx, |this, cx| this.blink_cursors(epoch, cx));
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ pub fn switch_source_header(
|
|||
.map(|file| file.path())
|
||||
.map(|path| path.display(PathStyle::local()).to_string())
|
||||
.unwrap_or_else(|| "Unknown".to_string())
|
||||
})?;
|
||||
});
|
||||
|
||||
let switch_source_header = if let Some((client, project_id)) = upstream_client {
|
||||
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id())?;
|
||||
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id());
|
||||
let request = proto::LspExtSwitchSourceHeader {
|
||||
project_id,
|
||||
buffer_id: buffer_id.to_proto(),
|
||||
|
|
@ -67,7 +67,7 @@ pub fn switch_source_header(
|
|||
project::lsp_store::lsp_ext_command::SwitchSourceHeader,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("Switch source/header LSP request for path \"{source_file}\" failed")
|
||||
|
|
|
|||
|
|
@ -5512,12 +5512,10 @@ impl Editor {
|
|||
Some(cx.spawn_in(window, async move |editor, cx| {
|
||||
if let Some(transaction) = on_type_formatting.await? {
|
||||
if push_to_client_history {
|
||||
buffer
|
||||
.update(cx, |buffer, _| {
|
||||
buffer.push_transaction(transaction, Instant::now());
|
||||
buffer.finalize_last_transaction();
|
||||
})
|
||||
.ok();
|
||||
buffer.update(cx, |buffer, _| {
|
||||
buffer.push_transaction(transaction, Instant::now());
|
||||
buffer.finalize_last_transaction();
|
||||
});
|
||||
}
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.refresh_document_highlights(cx);
|
||||
|
|
@ -6306,7 +6304,7 @@ impl Editor {
|
|||
let project_transaction = lsp_store
|
||||
.update(cx, |lsp_store, cx| {
|
||||
lsp_store.apply_code_action(buffer_handle, command, false, cx)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
.context("applying post-completion command")?;
|
||||
if let Some(workspace) = editor.read_with(cx, |editor, _| editor.workspace())? {
|
||||
|
|
@ -6713,7 +6711,7 @@ impl Editor {
|
|||
.all(|range| {
|
||||
excerpt_range.start <= range.start && excerpt_range.end >= range.end
|
||||
})
|
||||
})?;
|
||||
});
|
||||
|
||||
if all_edits_within_excerpt {
|
||||
return Ok(());
|
||||
|
|
@ -6741,7 +6739,7 @@ impl Editor {
|
|||
}
|
||||
multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
|
||||
multibuffer
|
||||
})?;
|
||||
});
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let project = workspace.project().clone();
|
||||
|
|
@ -7101,13 +7099,9 @@ impl Editor {
|
|||
.timer(Duration::from_millis(debounce))
|
||||
.await;
|
||||
|
||||
let highlights = if let Some(highlights) = cx
|
||||
.update(|cx| {
|
||||
provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
{
|
||||
let highlights = if let Some(highlights) = cx.update(|cx| {
|
||||
provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
|
||||
}) {
|
||||
highlights.await.log_err()
|
||||
} else {
|
||||
None
|
||||
|
|
@ -16346,9 +16340,7 @@ impl Editor {
|
|||
return;
|
||||
};
|
||||
|
||||
let hide_runnables = project
|
||||
.update(cx, |project, _| project.is_via_collab())
|
||||
.unwrap_or(true);
|
||||
let hide_runnables = project.update(cx, |project, _| project.is_via_collab());
|
||||
if hide_runnables {
|
||||
return;
|
||||
}
|
||||
|
|
@ -16531,11 +16523,9 @@ impl Editor {
|
|||
let mut templates_with_tags = Vec::new();
|
||||
if let Some(inventory) = inventory {
|
||||
for RunnableTag(tag) in tags {
|
||||
let Ok(new_tasks) = inventory.update(cx, |inventory, cx| {
|
||||
let new_tasks = inventory.update(cx, |inventory, cx| {
|
||||
inventory.list_tasks(file.clone(), Some(language.clone()), worktree_id, cx)
|
||||
}) else {
|
||||
return templates_with_tags;
|
||||
};
|
||||
});
|
||||
templates_with_tags.extend(new_tasks.await.into_iter().filter(
|
||||
move |(_, template)| {
|
||||
template.tags.iter().any(|source_tag| source_tag == &tag)
|
||||
|
|
@ -17621,7 +17611,7 @@ impl Editor {
|
|||
.clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
|
||||
target_buffer.anchor_after(target_start)
|
||||
..target_buffer.anchor_before(target_end)
|
||||
})?;
|
||||
});
|
||||
Location {
|
||||
buffer: target_buffer_handle,
|
||||
range,
|
||||
|
|
@ -17720,7 +17710,7 @@ impl Editor {
|
|||
});
|
||||
|
||||
(locations, current_location_index)
|
||||
})?;
|
||||
});
|
||||
|
||||
let Some(current_location_index) = current_location_index else {
|
||||
// This indicates something has gone wrong, because we already
|
||||
|
|
@ -18459,27 +18449,27 @@ impl Editor {
|
|||
}
|
||||
};
|
||||
|
||||
buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
if let Some(transaction) = transaction
|
||||
&& !buffer.is_singleton()
|
||||
{
|
||||
buffer.push_transaction(&transaction.0, cx);
|
||||
}
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
if let Some(transaction) = transaction
|
||||
&& !buffer.is_singleton()
|
||||
{
|
||||
buffer.push_transaction(&transaction.0, cx);
|
||||
}
|
||||
cx.notify();
|
||||
});
|
||||
|
||||
if let Some(transaction_id_now) =
|
||||
buffer.read_with(cx, |b, cx| b.last_transaction_id(cx))?
|
||||
buffer.read_with(cx, |b, cx| b.last_transaction_id(cx))
|
||||
{
|
||||
let has_new_transaction = transaction_id_prev != Some(transaction_id_now);
|
||||
if has_new_transaction {
|
||||
_ = editor.update(cx, |editor, _| {
|
||||
editor
|
||||
.selection_history
|
||||
.insert_transaction(transaction_id_now, selections_prev);
|
||||
});
|
||||
editor
|
||||
.update(cx, |editor, _| {
|
||||
editor
|
||||
.selection_history
|
||||
.insert_transaction(transaction_id_now, selections_prev);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -18527,17 +18517,15 @@ impl Editor {
|
|||
}
|
||||
transaction = apply_action.log_err().fuse() => transaction,
|
||||
};
|
||||
buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
// check if we need this
|
||||
if let Some(transaction) = transaction
|
||||
&& !buffer.is_singleton()
|
||||
{
|
||||
buffer.push_transaction(&transaction.0, cx);
|
||||
}
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
// check if we need this
|
||||
if let Some(transaction) = transaction
|
||||
&& !buffer.is_singleton()
|
||||
{
|
||||
buffer.push_transaction(&transaction.0, cx);
|
||||
}
|
||||
cx.notify();
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
@ -18831,10 +18819,8 @@ impl Editor {
|
|||
if let Some(debounce) = debounce {
|
||||
cx.background_executor().timer(debounce).await;
|
||||
}
|
||||
let Some(snapshot) = editor.upgrade().and_then(|editor| {
|
||||
editor
|
||||
.update(cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
|
||||
.ok()
|
||||
let Some(snapshot) = editor.upgrade().map(|editor| {
|
||||
editor.update(cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -21217,19 +21203,14 @@ impl Editor {
|
|||
anyhow::Result::<()>::Err(err).log_err();
|
||||
|
||||
if let Some(workspace) = workspace {
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
struct OpenPermalinkToLine;
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
struct OpenPermalinkToLine;
|
||||
|
||||
workspace.show_toast(
|
||||
Toast::new(
|
||||
NotificationId::unique::<OpenPermalinkToLine>(),
|
||||
message,
|
||||
),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
workspace.show_toast(
|
||||
Toast::new(NotificationId::unique::<OpenPermalinkToLine>(), message),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -24025,20 +24006,15 @@ fn update_uncommitted_diff_for_buffer(
|
|||
});
|
||||
cx.spawn(async move |cx| {
|
||||
let diffs = future::join_all(tasks).await;
|
||||
if editor
|
||||
.read_with(cx, |editor, _cx| editor.temporary_diff_override)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
if editor.read_with(cx, |editor, _cx| editor.temporary_diff_override) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
for diff in diffs.into_iter().flatten() {
|
||||
buffer.add_diff(diff, cx);
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
for diff in diffs.into_iter().flatten() {
|
||||
buffer.add_diff(diff, cx);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -25081,7 +25057,7 @@ impl SemanticsProvider for Entity<Project> {
|
|||
snapshot.anchor_before(range.start)
|
||||
..snapshot.anchor_after(range.end),
|
||||
)
|
||||
})?
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -18251,7 +18251,7 @@ async fn test_on_type_formatting_is_applied_after_autoindent(cx: &mut TestAppCon
|
|||
"fn c() {\n d()\n .\n}\n",
|
||||
"OnTypeFormatting should triggered after autoindent applied"
|
||||
)
|
||||
})?;
|
||||
});
|
||||
|
||||
Ok(Some(vec![]))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -533,9 +533,9 @@ impl GitBlame {
|
|||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()
|
||||
})??;
|
||||
})?;
|
||||
let provider_registry =
|
||||
cx.update(|cx| GitHostingProviderRegistry::default_global(cx))?;
|
||||
cx.update(|cx| GitHostingProviderRegistry::default_global(cx));
|
||||
let (results, errors) = cx
|
||||
.background_spawn({
|
||||
async move {
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ pub(crate) fn find_url(
|
|||
) -> Option<(Range<text::Anchor>, String)> {
|
||||
const LIMIT: usize = 2048;
|
||||
|
||||
let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot()).ok()?;
|
||||
let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
|
||||
|
||||
let offset = position.to_offset(&snapshot);
|
||||
let mut token_start = offset;
|
||||
|
|
@ -535,9 +535,7 @@ pub(crate) fn find_url_from_range(
|
|||
) -> Option<String> {
|
||||
const LIMIT: usize = 2048;
|
||||
|
||||
let Ok(snapshot) = buffer.read_with(&cx, |buffer, _| buffer.snapshot()) else {
|
||||
return None;
|
||||
};
|
||||
let snapshot = buffer.read_with(&cx, |buffer, _| buffer.snapshot());
|
||||
|
||||
let start_offset = range.start.to_offset(&snapshot);
|
||||
let end_offset = range.end.to_offset(&snapshot);
|
||||
|
|
@ -595,7 +593,7 @@ pub(crate) async fn find_file(
|
|||
cx: &mut AsyncWindowContext,
|
||||
) -> Option<(Range<text::Anchor>, ResolvedPath)> {
|
||||
let project = project?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot()).ok()?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
|
||||
let scope = snapshot.language_scope_at(position);
|
||||
let (range, candidate_file_path) = surrounding_filename(&snapshot, position)?;
|
||||
let candidate_len = candidate_file_path.len();
|
||||
|
|
@ -610,7 +608,6 @@ pub(crate) async fn find_file(
|
|||
.update(cx, |project, cx| {
|
||||
project.resolve_path_in_buffer(candidate_file_path, buffer, cx)
|
||||
})
|
||||
.ok()?
|
||||
.await
|
||||
.filter(|s| s.is_file())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ pub fn hover_at_inlay(
|
|||
this.hover_state.diagnostic_popover = None;
|
||||
})?;
|
||||
|
||||
let language_registry = project.read_with(cx, |p, _| p.languages().clone())?;
|
||||
let language_registry = project.read_with(cx, |p, _| p.languages().clone());
|
||||
let blocks = vec![inlay_hover.tooltip];
|
||||
let parsed_content =
|
||||
parse_blocks(&blocks, Some(&language_registry), None, cx).await;
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ async fn update_editor_from_message(
|
|||
.into_iter()
|
||||
.map(|id| BufferId::new(id).map(|id| project.open_buffer_by_id(id, cx)))
|
||||
.collect::<Result<Vec<_>>>()
|
||||
})??;
|
||||
})?;
|
||||
let _inserted_excerpt_buffers = try_join_all(inserted_excerpt_buffers).await?;
|
||||
|
||||
// Update the editor's excerpts.
|
||||
|
|
@ -892,7 +892,7 @@ impl Item for Editor {
|
|||
project
|
||||
.update(cx, |project, cx| {
|
||||
project.save_buffers(buffers_to_save.clone(), cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
|
||||
|
|
@ -938,15 +938,13 @@ impl Item for Editor {
|
|||
this.update(cx, |editor, cx| {
|
||||
editor.request_autoscroll(Autoscroll::fit(), cx)
|
||||
})?;
|
||||
buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
if let Some(transaction) = transaction
|
||||
&& !buffer.is_singleton()
|
||||
{
|
||||
buffer.push_transaction(&transaction.0, cx);
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
if let Some(transaction) = transaction
|
||||
&& !buffer.is_singleton()
|
||||
{
|
||||
buffer.push_transaction(&transaction.0, cx);
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
@ -1103,7 +1101,7 @@ impl SerializableItem for Editor {
|
|||
let project = project.clone();
|
||||
async move |cx| {
|
||||
let language_registry =
|
||||
project.read_with(cx, |project, _| project.languages().clone())?;
|
||||
project.read_with(cx, |project, _| project.languages().clone());
|
||||
|
||||
let language = if let Some(language_name) = language {
|
||||
// We don't fail here, because we'd rather not set the language if the name changed
|
||||
|
|
@ -1118,7 +1116,7 @@ impl SerializableItem for Editor {
|
|||
|
||||
// First create the empty buffer
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| project.create_buffer(true, cx))?
|
||||
.update(cx, |project, cx| project.create_buffer(true, cx))
|
||||
.await
|
||||
.context("Failed to create buffer while deserializing editor")?;
|
||||
|
||||
|
|
@ -1132,7 +1130,7 @@ impl SerializableItem for Editor {
|
|||
if let Some(entry) = buffer.peek_undo_stack() {
|
||||
buffer.forget_transaction(entry.transaction_id());
|
||||
}
|
||||
})?;
|
||||
});
|
||||
|
||||
cx.update(|window, cx| {
|
||||
cx.new(|cx| {
|
||||
|
|
@ -1187,7 +1185,7 @@ impl SerializableItem for Editor {
|
|||
if let Some(entry) = buffer.peek_undo_stack() {
|
||||
buffer.forget_transaction(entry.transaction_id());
|
||||
}
|
||||
})?;
|
||||
});
|
||||
}
|
||||
|
||||
cx.update(|window, cx| {
|
||||
|
|
@ -1229,7 +1227,7 @@ impl SerializableItem for Editor {
|
|||
..
|
||||
} => window.spawn(cx, async move |cx| {
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| project.create_buffer(true, cx))?
|
||||
.update(cx, |project, cx| project.create_buffer(true, cx))
|
||||
.await
|
||||
.context("Failed to create buffer")?;
|
||||
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ pub(crate) fn handle_from(
|
|||
};
|
||||
}
|
||||
|
||||
let buffer_snapshot = buffer.read_with(cx, |buf, _| buf.snapshot()).ok()?;
|
||||
let buffer_snapshot = buffer.read_with(cx, |buf, _| buf.snapshot());
|
||||
|
||||
let Some(edit_behavior_state) =
|
||||
should_auto_close(&buffer_snapshot, &edited_ranges, &jsx_tag_auto_close_config)
|
||||
|
|
@ -567,11 +567,9 @@ pub(crate) fn handle_from(
|
|||
}
|
||||
}
|
||||
|
||||
buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
buffer.edit(edits, None, cx);
|
||||
})
|
||||
.ok()?;
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(edits, None, cx);
|
||||
});
|
||||
|
||||
if any_selections_need_update {
|
||||
let multi_buffer_snapshot = this
|
||||
|
|
|
|||
|
|
@ -99,9 +99,7 @@ pub(super) fn refresh_linked_ranges(
|
|||
let cx = cx.to_async();
|
||||
let highlights = async move {
|
||||
let edits = linked_edits_task.await.log_err()?;
|
||||
let snapshot = cx
|
||||
.read_entity(&buffer, |buffer, _| buffer.snapshot())
|
||||
.ok()?;
|
||||
let snapshot = cx.read_entity(&buffer, |buffer, _| buffer.snapshot());
|
||||
let buffer_id = snapshot.remote_id();
|
||||
|
||||
// Find the range containing our current selection.
|
||||
|
|
|
|||
|
|
@ -60,27 +60,22 @@ async fn lsp_task_context(
|
|||
buffer: &Entity<Buffer>,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Option<TaskContext> {
|
||||
let (worktree_store, environment) = project
|
||||
.read_with(cx, |project, _| {
|
||||
(project.worktree_store(), project.environment().clone())
|
||||
})
|
||||
.ok()?;
|
||||
let (worktree_store, environment) = project.read_with(cx, |project, _| {
|
||||
(project.worktree_store(), project.environment().clone())
|
||||
});
|
||||
|
||||
let worktree_abs_path = cx
|
||||
.update(|cx| {
|
||||
let worktree_id = buffer.read(cx).file().map(|f| f.worktree_id(cx));
|
||||
let worktree_abs_path = cx.update(|cx| {
|
||||
let worktree_id = buffer.read(cx).file().map(|f| f.worktree_id(cx));
|
||||
|
||||
worktree_id
|
||||
.and_then(|worktree_id| worktree_store.read(cx).worktree_for_id(worktree_id, cx))
|
||||
.and_then(|worktree| worktree.read(cx).root_dir())
|
||||
})
|
||||
.ok()?;
|
||||
worktree_id
|
||||
.and_then(|worktree_id| worktree_store.read(cx).worktree_for_id(worktree_id, cx))
|
||||
.and_then(|worktree| worktree.read(cx).root_dir())
|
||||
});
|
||||
|
||||
let project_env = environment
|
||||
.update(cx, |environment, cx| {
|
||||
environment.buffer_environment(buffer, &worktree_store, cx)
|
||||
})
|
||||
.ok()?
|
||||
.await;
|
||||
|
||||
Some(TaskContext {
|
||||
|
|
@ -126,19 +121,18 @@ pub fn lsp_tasks(
|
|||
let source_kind = match buffer.update(cx, |buffer, _| {
|
||||
buffer.language().map(|language| language.name())
|
||||
}) {
|
||||
Ok(Some(language_name)) => TaskSourceKind::Lsp {
|
||||
Some(language_name) => TaskSourceKind::Lsp {
|
||||
server: server_id,
|
||||
language_name: SharedString::from(language_name),
|
||||
},
|
||||
Ok(None) => continue,
|
||||
Err(_) => return Vec::new(),
|
||||
None => continue,
|
||||
};
|
||||
let id_base = source_kind.to_id_base();
|
||||
let lsp_buffer_context = lsp_task_context(&project, &buffer, cx)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Ok(runnables_task) = project.update(cx, |project, cx| {
|
||||
let runnables_task = project.update(cx, |project, cx| {
|
||||
let buffer_id = buffer.read(cx).remote_id();
|
||||
project.request_lsp(
|
||||
buffer,
|
||||
|
|
@ -149,8 +143,8 @@ pub fn lsp_tasks(
|
|||
},
|
||||
cx,
|
||||
)
|
||||
}) && let Some(new_runnables) = runnables_task.await.log_err()
|
||||
{
|
||||
});
|
||||
if let Some(new_runnables) = runnables_task.await.log_err() {
|
||||
new_lsp_tasks.extend(new_runnables.runnables.into_iter().filter_map(
|
||||
|(location, runnable)| {
|
||||
let resolved_task =
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub fn go_to_parent_module(
|
|||
let upstream_client = lsp_store.read(cx).upstream_client();
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
let location_links = if let Some((client, project_id)) = upstream_client {
|
||||
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id())?;
|
||||
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id());
|
||||
|
||||
let request = proto::LspExtGoToParentModule {
|
||||
project_id,
|
||||
|
|
@ -103,7 +103,7 @@ pub fn go_to_parent_module(
|
|||
.collect::<anyhow::Result<_>>()
|
||||
.context("go to parent module via collab")?
|
||||
} else {
|
||||
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
|
||||
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
|
||||
let position = trigger_anchor.text_anchor.to_point_utf16(&buffer_snapshot);
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
|
|
@ -113,7 +113,7 @@ pub fn go_to_parent_module(
|
|||
project::lsp_store::lsp_ext_command::GoToParentModule { position },
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
.context("go to parent module")?
|
||||
};
|
||||
|
|
@ -161,7 +161,7 @@ pub fn expand_macro_recursively(
|
|||
let upstream_client = project.read(cx).lsp_store().read(cx).upstream_client();
|
||||
cx.spawn_in(window, async move |_editor, cx| {
|
||||
let macro_expansion = if let Some((client, project_id)) = upstream_client {
|
||||
let buffer_id = buffer.update(cx, |buffer, _| buffer.remote_id())?;
|
||||
let buffer_id = buffer.update(cx, |buffer, _| buffer.remote_id());
|
||||
let request = proto::LspExtExpandMacro {
|
||||
project_id,
|
||||
buffer_id: buffer_id.to_proto(),
|
||||
|
|
@ -176,7 +176,7 @@ pub fn expand_macro_recursively(
|
|||
expansion: response.expansion,
|
||||
}
|
||||
} else {
|
||||
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
|
||||
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
|
||||
let position = trigger_anchor.text_anchor.to_point_utf16(&buffer_snapshot);
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
|
|
@ -186,7 +186,7 @@ pub fn expand_macro_recursively(
|
|||
ExpandMacro { position },
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
.context("expand macro")?
|
||||
};
|
||||
|
|
@ -200,7 +200,7 @@ pub fn expand_macro_recursively(
|
|||
}
|
||||
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| project.create_buffer(false, cx))?
|
||||
.update(cx, |project, cx| project.create_buffer(false, cx))
|
||||
.await?;
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
|
|
@ -252,7 +252,7 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
|
|||
let upstream_client = project.read(cx).lsp_store().read(cx).upstream_client();
|
||||
cx.spawn_in(window, async move |_editor, cx| {
|
||||
let docs_urls = if let Some((client, project_id)) = upstream_client {
|
||||
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id())?;
|
||||
let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id());
|
||||
let request = proto::LspExtOpenDocs {
|
||||
project_id,
|
||||
buffer_id: buffer_id.to_proto(),
|
||||
|
|
@ -267,7 +267,7 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
|
|||
local: response.local,
|
||||
}
|
||||
} else {
|
||||
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot())?;
|
||||
let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
|
||||
let position = trigger_anchor.text_anchor.to_point_utf16(&buffer_snapshot);
|
||||
project
|
||||
.update(cx, |project, cx| {
|
||||
|
|
@ -277,7 +277,7 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
|
|||
project::lsp_store::lsp_ext_command::OpenDocs { position },
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await
|
||||
.context("open docs")?
|
||||
};
|
||||
|
|
@ -303,7 +303,8 @@ pub fn open_docs(editor: &mut Editor, _: &OpenDocs, window: &mut Window, cx: &mu
|
|||
if let Some(web_url) = docs_urls.web {
|
||||
cx.open_url(&web_url);
|
||||
}
|
||||
})
|
||||
});
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ fn main() {
|
|||
registry.set_default_model(Some(agent_model.clone()), cx);
|
||||
});
|
||||
judge_model
|
||||
})?;
|
||||
});
|
||||
|
||||
let mut examples = Vec::new();
|
||||
|
||||
|
|
@ -210,7 +210,8 @@ fn main() {
|
|||
|
||||
if examples.is_empty() {
|
||||
eprintln!("Filter matched no examples");
|
||||
return cx.update(|cx| cx.quit());
|
||||
cx.update(|cx| cx.quit());
|
||||
return anyhow::Ok(());
|
||||
}
|
||||
|
||||
let mut repo_urls = HashSet::default();
|
||||
|
|
@ -294,7 +295,7 @@ fn main() {
|
|||
let result = async {
|
||||
example.setup().await?;
|
||||
let run_output = cx
|
||||
.update(|cx| example.run(app_state.clone(), cx))?
|
||||
.update(|cx| example.run(app_state.clone(), cx))
|
||||
.await?;
|
||||
let judge_output = judge_example(
|
||||
example.clone(),
|
||||
|
|
@ -328,7 +329,8 @@ fn main() {
|
|||
|
||||
app_state.client.telemetry().flush_events().await;
|
||||
|
||||
cx.update(|cx| cx.quit())
|
||||
cx.update(|cx| cx.quit());
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ impl ExampleContext {
|
|||
} else {
|
||||
thread.proceed(cx)
|
||||
}
|
||||
})??;
|
||||
})?;
|
||||
|
||||
let task = self.app.background_spawn(async move {
|
||||
let mut messages = Vec::new();
|
||||
|
|
@ -357,11 +357,13 @@ impl ExampleContext {
|
|||
}
|
||||
|
||||
pub fn edits(&self) -> HashMap<Arc<RelPath>, FileEdits> {
|
||||
self.agent_thread
|
||||
.read_with(&self.app, |thread, cx| {
|
||||
let action_log = thread.action_log().read(cx);
|
||||
HashMap::from_iter(action_log.changed_buffers(cx).into_iter().map(
|
||||
|(buffer, diff)| {
|
||||
self.agent_thread.read_with(&self.app, |thread, cx| {
|
||||
let action_log = thread.action_log().read(cx);
|
||||
HashMap::from_iter(
|
||||
action_log
|
||||
.changed_buffers(cx)
|
||||
.into_iter()
|
||||
.map(|(buffer, diff)| {
|
||||
let snapshot = buffer.read(cx).snapshot();
|
||||
|
||||
let file = snapshot.file().unwrap();
|
||||
|
|
@ -381,10 +383,9 @@ impl ExampleContext {
|
|||
.collect();
|
||||
|
||||
(file.path().clone(), FileEdits { hunks })
|
||||
},
|
||||
))
|
||||
})
|
||||
.unwrap()
|
||||
}),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn agent_thread(&self) -> Entity<Thread> {
|
||||
|
|
@ -393,16 +394,14 @@ impl ExampleContext {
|
|||
}
|
||||
|
||||
impl AppContext for ExampleContext {
|
||||
type Result<T> = anyhow::Result<T>;
|
||||
|
||||
fn new<T: 'static>(
|
||||
&mut self,
|
||||
build_entity: impl FnOnce(&mut gpui::Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
) -> Entity<T> {
|
||||
self.app.new(build_entity)
|
||||
}
|
||||
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<gpui::Reservation<T>> {
|
||||
fn reserve_entity<T: 'static>(&mut self) -> gpui::Reservation<T> {
|
||||
self.app.reserve_entity()
|
||||
}
|
||||
|
||||
|
|
@ -410,7 +409,7 @@ impl AppContext for ExampleContext {
|
|||
&mut self,
|
||||
reservation: gpui::Reservation<T>,
|
||||
build_entity: impl FnOnce(&mut gpui::Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
) -> Entity<T> {
|
||||
self.app.insert_entity(reservation, build_entity)
|
||||
}
|
||||
|
||||
|
|
@ -418,25 +417,21 @@ impl AppContext for ExampleContext {
|
|||
&mut self,
|
||||
handle: &Entity<T>,
|
||||
update: impl FnOnce(&mut T, &mut gpui::Context<T>) -> R,
|
||||
) -> Self::Result<R>
|
||||
) -> R
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.app.update_entity(handle, update)
|
||||
}
|
||||
|
||||
fn as_mut<'a, T>(&'a mut self, handle: &Entity<T>) -> Self::Result<gpui::GpuiBorrow<'a, T>>
|
||||
fn as_mut<'a, T>(&'a mut self, handle: &Entity<T>) -> gpui::GpuiBorrow<'a, T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.app.as_mut(handle)
|
||||
}
|
||||
|
||||
fn read_entity<T, R>(
|
||||
&self,
|
||||
handle: &Entity<T>,
|
||||
read: impl FnOnce(&T, &App) -> R,
|
||||
) -> Self::Result<R>
|
||||
fn read_entity<T, R>(&self, handle: &Entity<T>, read: impl FnOnce(&T, &App) -> R) -> R
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
|
|
@ -471,7 +466,7 @@ impl AppContext for ExampleContext {
|
|||
self.app.background_spawn(future)
|
||||
}
|
||||
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
|
||||
fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> R
|
||||
where
|
||||
G: gpui::Global,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -62,39 +62,29 @@ impl Example for CodeBlockCitations {
|
|||
cx.assert(citation.contains("/"), format!("Slash in {citation:?}",))
|
||||
{
|
||||
let path_range = PathWithRange::new(citation);
|
||||
let path = cx
|
||||
.agent_thread()
|
||||
.update(cx, |thread, cx| {
|
||||
thread
|
||||
.project()
|
||||
.read(cx)
|
||||
.find_project_path(path_range.path.as_ref(), cx)
|
||||
})
|
||||
.ok()
|
||||
.flatten();
|
||||
let path = cx.agent_thread().update(cx, |thread, cx| {
|
||||
thread
|
||||
.project()
|
||||
.read(cx)
|
||||
.find_project_path(path_range.path.as_ref(), cx)
|
||||
});
|
||||
|
||||
if let Ok(path) = cx.assert_some(path, format!("Valid path: {citation:?}"))
|
||||
{
|
||||
let buffer_text = {
|
||||
let buffer = match cx.agent_thread().update(cx, |thread, cx| {
|
||||
thread
|
||||
.project()
|
||||
.update(cx, |project, cx| project.open_buffer(path, cx))
|
||||
}) {
|
||||
Ok(buffer_task) => buffer_task.await.ok(),
|
||||
Err(err) => {
|
||||
cx.assert(
|
||||
false,
|
||||
format!("Expected Ok(buffer), not {err:?}"),
|
||||
)
|
||||
.ok();
|
||||
break;
|
||||
}
|
||||
};
|
||||
let buffer = cx
|
||||
.agent_thread()
|
||||
.update(cx, |thread, cx| {
|
||||
thread
|
||||
.project()
|
||||
.update(cx, |project, cx| project.open_buffer(path, cx))
|
||||
})
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let Ok(buffer_text) = cx.assert_some(
|
||||
buffer.and_then(|buffer| {
|
||||
buffer.read_with(cx, |buffer, _| buffer.text()).ok()
|
||||
buffer.map(|buffer| {
|
||||
buffer.read_with(cx, |buffer, _| buffer.text())
|
||||
}),
|
||||
"Reading buffer text succeeded",
|
||||
) else {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ impl Example for FileChangeNotificationExample {
|
|||
.read(cx)
|
||||
.find_project_path("README", cx)
|
||||
.expect("README file should exist in this repo")
|
||||
})?;
|
||||
});
|
||||
|
||||
let buffer = {
|
||||
cx.agent_thread()
|
||||
|
|
@ -37,7 +37,7 @@ impl Example for FileChangeNotificationExample {
|
|||
thread
|
||||
.project()
|
||||
.update(cx, |project, cx| project.open_buffer(project_path, cx))
|
||||
})?
|
||||
})
|
||||
.await?
|
||||
};
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ impl Example for FileChangeNotificationExample {
|
|||
thread.action_log().update(cx, |action_log, cx| {
|
||||
action_log.buffer_read(buffer.clone(), cx);
|
||||
});
|
||||
})?;
|
||||
});
|
||||
|
||||
// Start conversation (specific message is not important)
|
||||
cx.prompt_with_max_turns("Find all files in this repo", 1)
|
||||
|
|
@ -54,7 +54,7 @@ impl Example for FileChangeNotificationExample {
|
|||
// Edit the README buffer - the model should get a notification on next turn
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(0..buffer.len(), "Surprise!")], None, cx);
|
||||
})?;
|
||||
});
|
||||
|
||||
// Run for some more turns.
|
||||
// The model shouldn't thank us for letting it know about the file change.
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ impl ExampleInstance {
|
|||
worktree
|
||||
.update(cx, |worktree, _cx| {
|
||||
worktree.as_local().unwrap().scan_complete()
|
||||
})?
|
||||
})
|
||||
.await;
|
||||
|
||||
struct LanguageServerState {
|
||||
|
|
@ -233,39 +233,40 @@ impl ExampleInstance {
|
|||
|
||||
let lsp = if let Some(language_server) = &meta.language_server {
|
||||
// Open a file that matches the language to cause LSP to start.
|
||||
let language_file = worktree.read_with(cx, |worktree, _cx| {
|
||||
worktree
|
||||
.files(false, 0)
|
||||
.find_map(|e| {
|
||||
if e.path.clone().extension()
|
||||
== Some(&language_server.file_extension)
|
||||
{
|
||||
Some(ProjectPath {
|
||||
worktree_id: worktree.id(),
|
||||
path: e.path.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.context("Failed to find a file for example language")
|
||||
})??;
|
||||
let language_file = worktree
|
||||
.read_with(cx, |worktree, _cx| {
|
||||
worktree
|
||||
.files(false, 0)
|
||||
.find_map(|e| {
|
||||
if e.path.clone().extension()
|
||||
== Some(&language_server.file_extension)
|
||||
{
|
||||
Some(ProjectPath {
|
||||
worktree_id: worktree.id(),
|
||||
path: e.path.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.context("Failed to find a file for example language")
|
||||
})?;
|
||||
|
||||
let open_language_file_buffer_task = project.update(cx, |project, cx| {
|
||||
project.open_buffer(language_file.clone(), cx)
|
||||
})?;
|
||||
});
|
||||
|
||||
let language_file_buffer = open_language_file_buffer_task.await?;
|
||||
|
||||
let lsp_open_handle = project.update(cx, |project, cx| {
|
||||
project.register_buffer_with_language_servers(&language_file_buffer, cx)
|
||||
})?;
|
||||
});
|
||||
|
||||
wait_for_lang_server(&project, &language_file_buffer, this.log_prefix.clone(), cx).await?;
|
||||
|
||||
diagnostic_summary_before = project.read_with(cx, |project, cx| {
|
||||
project.diagnostic_summary(false, cx)
|
||||
})?;
|
||||
project.diagnostic_summary(false, cx)
|
||||
});
|
||||
|
||||
diagnostics_before = query_lsp_diagnostics(project.clone(), cx).await?;
|
||||
if diagnostics_before.is_some() && language_server.allow_preexisting_diagnostics {
|
||||
|
|
@ -337,7 +338,7 @@ impl ExampleInstance {
|
|||
});
|
||||
|
||||
thread
|
||||
}).unwrap();
|
||||
});
|
||||
|
||||
let mut example_cx = ExampleContext::new(
|
||||
meta.clone(),
|
||||
|
|
@ -371,13 +372,13 @@ impl ExampleInstance {
|
|||
.update(|cx| {
|
||||
let project = project.clone();
|
||||
cx.spawn(async move |cx| query_lsp_diagnostics(project, cx).await)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
println!("{}Got diagnostics", this.log_prefix);
|
||||
|
||||
diagnostic_summary_after = project.read_with(cx, |project, cx| {
|
||||
project.diagnostic_summary(false, cx)
|
||||
})?;
|
||||
project.diagnostic_summary(false, cx)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -389,7 +390,7 @@ impl ExampleInstance {
|
|||
fs::write(this.run_directory.join("diagnostics_after.txt"), diagnostics_after)?;
|
||||
}
|
||||
|
||||
thread.update(cx, |thread, _cx| {
|
||||
Ok(thread.update(cx, |thread, _cx| {
|
||||
RunOutput {
|
||||
repository_diff,
|
||||
diagnostic_summary_before,
|
||||
|
|
@ -401,7 +402,7 @@ impl ExampleInstance {
|
|||
thread_markdown: thread.to_markdown(),
|
||||
programmatic_assertions: example_cx.assertions,
|
||||
}
|
||||
})
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -614,17 +615,19 @@ struct EvalTerminalHandle {
|
|||
|
||||
impl agent::TerminalHandle for EvalTerminalHandle {
|
||||
fn id(&self, cx: &AsyncApp) -> Result<acp::TerminalId> {
|
||||
self.terminal.read_with(cx, |term, _cx| term.id().clone())
|
||||
Ok(self.terminal.read_with(cx, |term, _cx| term.id().clone()))
|
||||
}
|
||||
|
||||
fn wait_for_exit(&self, cx: &AsyncApp) -> Result<Shared<Task<acp::TerminalExitStatus>>> {
|
||||
self.terminal
|
||||
.read_with(cx, |term, _cx| term.wait_for_exit())
|
||||
Ok(self
|
||||
.terminal
|
||||
.read_with(cx, |term, _cx| term.wait_for_exit()))
|
||||
}
|
||||
|
||||
fn current_output(&self, cx: &AsyncApp) -> Result<acp::TerminalOutputResponse> {
|
||||
self.terminal
|
||||
.read_with(cx, |term, cx| term.current_output(cx))
|
||||
Ok(self
|
||||
.terminal
|
||||
.read_with(cx, |term, cx| term.current_output(cx)))
|
||||
}
|
||||
|
||||
fn kill(&self, cx: &AsyncApp) -> Result<()> {
|
||||
|
|
@ -632,13 +635,14 @@ impl agent::TerminalHandle for EvalTerminalHandle {
|
|||
self.terminal.update(cx, |terminal, cx| {
|
||||
terminal.kill(cx);
|
||||
});
|
||||
})?;
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn was_stopped_by_user(&self, cx: &AsyncApp) -> Result<bool> {
|
||||
self.terminal
|
||||
.read_with(cx, |term, _cx| term.was_stopped_by_user())
|
||||
Ok(self
|
||||
.terminal
|
||||
.read_with(cx, |term, _cx| term.was_stopped_by_user()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -653,7 +657,7 @@ impl agent::ThreadEnvironment for EvalThreadEnvironment {
|
|||
let project = self.project.clone();
|
||||
cx.spawn(async move |cx| {
|
||||
let language_registry =
|
||||
project.read_with(cx, |project, _cx| project.languages().clone())?;
|
||||
project.read_with(cx, |project, _cx| project.languages().clone());
|
||||
let id = acp::TerminalId::new(uuid::Uuid::new_v4().to_string());
|
||||
let terminal =
|
||||
acp_thread::create_terminal_entity(command, &[], vec![], cwd.clone(), &project, cx)
|
||||
|
|
@ -668,7 +672,7 @@ impl agent::ThreadEnvironment for EvalThreadEnvironment {
|
|||
language_registry,
|
||||
cx,
|
||||
)
|
||||
})?;
|
||||
});
|
||||
Ok(Rc::new(EvalTerminalHandle { terminal }) as Rc<dyn agent::TerminalHandle>)
|
||||
})
|
||||
}
|
||||
|
|
@ -899,25 +903,20 @@ pub fn wait_for_lang_server(
|
|||
|
||||
let (mut tx, mut rx) = mpsc::channel(1);
|
||||
|
||||
let lsp_store = project
|
||||
.read_with(cx, |project, _| project.lsp_store())
|
||||
.unwrap();
|
||||
let lsp_store = project.read_with(cx, |project, _| project.lsp_store());
|
||||
|
||||
let has_lang_server = buffer
|
||||
.update(cx, |buffer, cx| {
|
||||
lsp_store.update(cx, |lsp_store, cx| {
|
||||
lsp_store
|
||||
.running_language_servers_for_local_buffer(buffer, cx)
|
||||
.next()
|
||||
.is_some()
|
||||
})
|
||||
let has_lang_server = buffer.update(cx, |buffer, cx| {
|
||||
lsp_store.update(cx, |lsp_store, cx| {
|
||||
lsp_store
|
||||
.running_language_servers_for_local_buffer(buffer, cx)
|
||||
.next()
|
||||
.is_some()
|
||||
})
|
||||
.unwrap_or(false);
|
||||
});
|
||||
|
||||
if has_lang_server {
|
||||
project
|
||||
.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx))
|
||||
.unwrap()
|
||||
.detach();
|
||||
}
|
||||
|
||||
|
|
@ -984,7 +983,7 @@ pub async fn query_lsp_diagnostics(
|
|||
.filter(|(_, _, summary)| summary.error_count > 0 || summary.warning_count > 0)
|
||||
.map(|(project_path, _, _)| project_path)
|
||||
.collect::<Vec<_>>()
|
||||
})?;
|
||||
});
|
||||
|
||||
if paths_with_diagnostics.is_empty() {
|
||||
return Ok(None);
|
||||
|
|
@ -993,9 +992,9 @@ pub async fn query_lsp_diagnostics(
|
|||
let mut output = String::new();
|
||||
for project_path in paths_with_diagnostics {
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| project.open_buffer(project_path, cx))?
|
||||
.update(cx, |project, cx| project.open_buffer(project_path, cx))
|
||||
.await?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot())?;
|
||||
let snapshot = buffer.read_with(cx, |buffer, _cx| buffer.snapshot());
|
||||
|
||||
for (_, group) in snapshot.diagnostic_groups(None) {
|
||||
let entry = &group.entries[group.primary_ix];
|
||||
|
|
|
|||
|
|
@ -245,8 +245,7 @@ impl HeadlessExtensionStore {
|
|||
cx,
|
||||
));
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
let _ = join_all(removal_tasks).await;
|
||||
|
||||
fs.remove_dir(
|
||||
|
|
@ -304,7 +303,7 @@ impl HeadlessExtensionStore {
|
|||
let missing_extensions = extension_store
|
||||
.update(&mut cx, |extension_store, cx| {
|
||||
extension_store.sync_extensions(requested_extensions.collect(), cx)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(proto::SyncExtensionsResponse {
|
||||
|
|
@ -343,7 +342,7 @@ impl HeadlessExtensionStore {
|
|||
PathBuf::from(envelope.payload.tmp_dir),
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(proto::Ack {})
|
||||
|
|
|
|||
|
|
@ -681,11 +681,11 @@ impl WasmHost {
|
|||
// Run wasi-dependent operations on tokio.
|
||||
// wasmtime_wasi internally uses tokio for I/O operations.
|
||||
let (extension_task, manifest, work_dir, tx, zed_api_version) =
|
||||
gpui_tokio::Tokio::spawn(cx, load_extension(zed_api_version, component))?.await??;
|
||||
gpui_tokio::Tokio::spawn(cx, load_extension(zed_api_version, component)).await??;
|
||||
|
||||
// Run the extension message loop on tokio since extension
|
||||
// calls may invoke wasi functions that require a tokio runtime.
|
||||
let task = Arc::new(gpui_tokio::Tokio::spawn(cx, extension_task)?);
|
||||
let task = Arc::new(gpui_tokio::Tokio::spawn(cx, extension_task));
|
||||
|
||||
Ok(WasmExtension {
|
||||
manifest,
|
||||
|
|
|
|||
|
|
@ -471,7 +471,7 @@ impl ExtensionImports for WasmState {
|
|||
}
|
||||
.boxed_local()
|
||||
})
|
||||
.await?
|
||||
.await
|
||||
.to_wasmtime_result()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1004,7 +1004,7 @@ impl ExtensionImports for WasmState {
|
|||
}
|
||||
.boxed_local()
|
||||
})
|
||||
.await?
|
||||
.await
|
||||
.to_wasmtime_result()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use editor::{Editor, EditorElement, EditorStyle};
|
|||
use extension_host::{ExtensionManifest, ExtensionOperation, ExtensionStore};
|
||||
use fuzzy::{StringMatchCandidate, match_strings};
|
||||
use gpui::{
|
||||
Action, App, ClipboardItem, Context, Corner, Entity, EventEmitter, Flatten, Focusable,
|
||||
Action, App, ClipboardItem, Context, Corner, Entity, EventEmitter, Focusable,
|
||||
InteractiveElement, KeyContext, ParentElement, Point, Render, Styled, Task, TextStyle,
|
||||
UniformListScrollHandle, WeakEntity, Window, actions, point, uniform_list,
|
||||
};
|
||||
|
|
@ -131,25 +131,22 @@ pub fn init(cx: &mut App) {
|
|||
let workspace_handle = cx.entity().downgrade();
|
||||
window
|
||||
.spawn(cx, async move |cx| {
|
||||
let extension_path =
|
||||
match Flatten::flatten(prompt.await.map_err(|e| e.into())) {
|
||||
Ok(Some(mut paths)) => paths.pop()?,
|
||||
Ok(None) => return None,
|
||||
Err(err) => {
|
||||
workspace_handle
|
||||
.update(cx, |workspace, cx| {
|
||||
workspace.show_portal_error(err.to_string(), cx);
|
||||
})
|
||||
.ok();
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let extension_path = match prompt.await.map_err(anyhow::Error::from) {
|
||||
Ok(Some(mut paths)) => paths.pop()?,
|
||||
Ok(None) => return None,
|
||||
Err(err) => {
|
||||
workspace_handle
|
||||
.update(cx, |workspace, cx| {
|
||||
workspace.show_portal_error(err.to_string(), cx);
|
||||
})
|
||||
.ok();
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let install_task = store
|
||||
.update(cx, |store, cx| {
|
||||
store.install_dev_extension(extension_path, cx)
|
||||
})
|
||||
.ok()?;
|
||||
let install_task = store.update(cx, |store, cx| {
|
||||
store.install_dev_extension(extension_path, cx)
|
||||
});
|
||||
|
||||
match install_task.await {
|
||||
Ok(_) => {}
|
||||
|
|
|
|||
|
|
@ -1225,35 +1225,27 @@ impl FileFinderDelegate {
|
|||
let query_path = Path::new(query.path_query());
|
||||
let mut path_matches = Vec::new();
|
||||
|
||||
let abs_file_exists = if let Ok(task) = project.update(cx, |this, cx| {
|
||||
this.resolve_abs_file_path(query.path_query(), cx)
|
||||
}) {
|
||||
task.await.is_some()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let abs_file_exists = project
|
||||
.update(cx, |this, cx| {
|
||||
this.resolve_abs_file_path(query.path_query(), cx)
|
||||
})
|
||||
.await
|
||||
.is_some();
|
||||
|
||||
if abs_file_exists {
|
||||
let update_result = project
|
||||
.update(cx, |project, cx| {
|
||||
if let Some((worktree, relative_path)) =
|
||||
project.find_worktree(query_path, cx)
|
||||
{
|
||||
path_matches.push(ProjectPanelOrdMatch(PathMatch {
|
||||
score: 1.0,
|
||||
positions: Vec::new(),
|
||||
worktree_id: worktree.read(cx).id().to_usize(),
|
||||
path: relative_path,
|
||||
path_prefix: RelPath::empty().into(),
|
||||
is_dir: false, // File finder doesn't support directories
|
||||
distance_to_relative_ancestor: usize::MAX,
|
||||
}));
|
||||
}
|
||||
})
|
||||
.log_err();
|
||||
if update_result.is_none() {
|
||||
return abs_file_exists;
|
||||
}
|
||||
project.update(cx, |project, cx| {
|
||||
if let Some((worktree, relative_path)) = project.find_worktree(query_path, cx) {
|
||||
path_matches.push(ProjectPanelOrdMatch(PathMatch {
|
||||
score: 1.0,
|
||||
positions: Vec::new(),
|
||||
worktree_id: worktree.read(cx).id().to_usize(),
|
||||
path: relative_path,
|
||||
path_prefix: RelPath::empty().into(),
|
||||
is_dir: false, // File finder doesn't support directories
|
||||
distance_to_relative_ancestor: usize::MAX,
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
picker
|
||||
|
|
|
|||
|
|
@ -744,8 +744,6 @@ pub async fn get_git_committer(cx: &AsyncApp) -> GitCommitter {
|
|||
.context("could not find git binary path")
|
||||
.log_err()
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ impl BranchListDelegate {
|
|||
cx.spawn(async move |_, cx| {
|
||||
repo.update(cx, |repo, _| {
|
||||
repo.create_branch(new_branch_name, base_branch)
|
||||
})?
|
||||
})
|
||||
.await??;
|
||||
|
||||
Ok(())
|
||||
|
|
@ -444,11 +444,11 @@ impl BranchListDelegate {
|
|||
Entry::Branch { branch, .. } => match branch.remote_name() {
|
||||
Some(remote_name) => {
|
||||
is_remote = true;
|
||||
repo.update(cx, |repo, _| repo.remove_remote(remote_name.to_string()))?
|
||||
repo.update(cx, |repo, _| repo.remove_remote(remote_name.to_string()))
|
||||
.await?
|
||||
}
|
||||
None => {
|
||||
repo.update(cx, |repo, _| repo.delete_branch(branch.name().to_string()))?
|
||||
repo.update(cx, |repo, _| repo.delete_branch(branch.name().to_string()))
|
||||
.await?
|
||||
}
|
||||
},
|
||||
|
|
@ -763,7 +763,7 @@ impl PickerDelegate for BranchListDelegate {
|
|||
|
||||
let branch = branch.clone();
|
||||
cx.spawn(async move |_, cx| {
|
||||
repo.update(cx, |repo, _| repo.change_branch(branch.name().to_string()))?
|
||||
repo.update(cx, |repo, _| repo.change_branch(branch.name().to_string()))
|
||||
.await??;
|
||||
|
||||
anyhow::Ok(())
|
||||
|
|
@ -1433,7 +1433,6 @@ mod tests {
|
|||
cx.spawn(async move |mut cx| {
|
||||
for branch in branch_names {
|
||||
repo.update(&mut cx, |repo, _| repo.create_branch(branch, None))
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
|
@ -1498,7 +1497,6 @@ mod tests {
|
|||
repo.update(&mut cx, |repo, _| {
|
||||
repo.create_remote(branch, String::from("test"))
|
||||
})
|
||||
.unwrap()
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue