Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5cb90d1
wip
cole-miller May 19, 2026
5b642fc
wip
cole-miller May 24, 2026
893fa92
update the project
cole-miller May 24, 2026
49b0450
carry through
cole-miller May 25, 2026
6fe84fa
adjustments
cole-miller May 25, 2026
4cac507
remove uses of new_with_base_text_buffer
cole-miller Jun 1, 2026
5608d03
clean up naming
cole-miller Jun 1, 2026
bc8d387
tidy up git store
cole-miller Jun 1, 2026
82fd4e5
wip
cole-miller Jun 1, 2026
c2fcd5a
set language initially
cole-miller Jun 3, 2026
5cf1f14
updates
cole-miller Jun 5, 2026
58acdc1
wip
cole-miller Jun 8, 2026
9538e65
finish cleaning up language changed
cole-miller Jun 8, 2026
db6cf95
wait for branch diff to finish parsing
cole-miller Jun 8, 2026
14b4865
explicitly handle diffs that haven't been calculated yet
cole-miller Jun 9, 2026
b8fcf0f
follow ups
cole-miller Jun 9, 2026
48b2128
improve snapshot_with_edits
cole-miller Jun 9, 2026
a818505
guard against concurrent calls to set_base_text
cole-miller Jun 9, 2026
c7d9a8c
add ui level override for hunk stagedness rendering
cole-miller Jun 9, 2026
6fbdba6
fix a bug where an orphaned weak unstaged diff could stick around for…
cole-miller Jun 9, 2026
f6f48fa
re-enable missing IndexMatchesHead optimization
cole-miller Jun 9, 2026
14ad3d3
garbage collect head and index text buffers
cole-miller Jun 9, 2026
e6eca6f
Merge remote-tracking branch 'origin/main' into staged-diff-refactor
cole-miller Jun 9, 2026
e8a22ad
fix after merge
cole-miller Jun 9, 2026
b444e3f
change todo
cole-miller Jun 9, 2026
220158c
clippy
cole-miller Jun 9, 2026
17add78
fix flakiness
cole-miller Jun 9, 2026
017ef7a
fix panic in rate predictions modal
cole-miller Jun 9, 2026
2dd4590
remove dependency
cole-miller Jun 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 13 additions & 51 deletions crates/acp_thread/src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl Diff {
) -> Self {
let multibuffer = cx.new(|_cx| MultiBuffer::without_headers(Capability::ReadOnly));
let new_buffer = cx.new(|cx| Buffer::local(new_text, cx));
let base_text_exists = old_text.is_some();
let base_text = old_text.clone().unwrap_or(String::new()).into();
let task = cx.spawn({
let multibuffer = multibuffer.clone();
Expand All @@ -40,8 +41,8 @@ impl Diff {

let diff = build_buffer_diff(
old_text.unwrap_or("".into()).into(),
base_text_exists,
&buffer,
Some(language_registry.clone()),
cx,
)
.await?;
Expand Down Expand Up @@ -88,16 +89,7 @@ impl Diff {
let language = buffer.read(cx).language().cloned();
let language_registry = buffer.read(cx).language_registry();
let buffer_diff = cx.new(|cx| {
let mut diff = BufferDiff::new_unchanged(&buffer_text_snapshot, cx);
diff.language_changed(language.clone(), language_registry.clone(), cx);
let secondary_diff = cx.new(|cx| {
// For the secondary diff buffer we skip assigning the language as we do not really need to perform any syntax highlighting on
// it. As a result, by skipping it we are potentially shaving off a lot of RSS plus we get a snappier feel for large diff
// view multibuffers.
BufferDiff::new_unchanged(&buffer_text_snapshot, cx)
});
diff.set_secondary_diff(secondary_diff);
diff
BufferDiff::new_unchanged(&buffer_text_snapshot, language, language_registry, cx)
});

let multibuffer = cx.new(|cx| {
Expand Down Expand Up @@ -233,28 +225,20 @@ impl PendingDiff {
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 base_text_snapshot = buffer_diff.read_with(cx, |diff, cx| diff.base_text(cx));
let update = buffer_diff
.update(cx, |diff, cx| {
diff.update_diff(
text_snapshot.clone(),
&base_text_snapshot,
Some(base_text.clone()),
None,
language,
cx,
)
})
.await;
let (task1, task2) = buffer_diff.update(cx, |diff, cx| {
let task1 = diff.set_snapshot(update.clone(), &text_snapshot, cx);
let task2 = diff
.secondary_diff()
.unwrap()
.update(cx, |diff, cx| diff.set_snapshot(update, &text_snapshot, cx));
(task1, task2)
buffer_diff.update(cx, |diff, cx| {
diff.set_snapshot(update.clone(), cx);
});
task1.await;
task2.await;
diff.update(cx, |diff, cx| {
if let Diff::Pending(diff) = diff {
diff.update_visible_ranges(cx);
Expand All @@ -272,7 +256,6 @@ impl PendingDiff {
let ranges = self.excerpt_ranges(cx);
let base_text = self.base_text.clone();
let new_buffer = self.new_buffer.read(cx);
let language_registry = new_buffer.language_registry();

let path = new_buffer
.file()
Expand All @@ -299,7 +282,7 @@ impl PendingDiff {
let buffer = buffer.clone();
async move |_this, cx| {
buffer.update(cx, |buffer, _| buffer.parsing_idle()).await;
build_buffer_diff(base_text, &buffer, language_registry, cx).await
build_buffer_diff(base_text, true, &buffer, cx).await
}
});

Expand Down Expand Up @@ -397,39 +380,18 @@ pub struct FinalizedDiff {

async fn build_buffer_diff(
old_text: Arc<str>,
base_text_exists: bool,
buffer: &Entity<Buffer>,
language_registry: Option<Arc<LanguageRegistry>>,
cx: &mut AsyncApp,
) -> Result<Entity<BufferDiff>> {
let language = cx.update(|cx| buffer.read(cx).language().cloned());
let text_snapshot = cx.update(|cx| buffer.read(cx).text_snapshot());
let language_registry = cx.update(|cx| buffer.read(cx).language_registry());
let buffer = cx.update(|cx| buffer.read(cx).snapshot());
let base_text = base_text_exists.then(|| old_text);

let secondary_diff = cx.new(|cx| BufferDiff::new(&buffer, cx));

let update = secondary_diff
.update(cx, |secondary_diff, cx| {
secondary_diff.update_diff(
text_snapshot.clone(),
Some(old_text),
Some(false),
language.clone(),
cx,
)
})
.await;

secondary_diff
.update(cx, |secondary_diff, 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, language, language_registry, 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)
diff.set_base_text(base_text, buffer.text, cx)
})
.await;
Ok(diff)
Expand Down
27 changes: 5 additions & 22 deletions crates/action_log/src/action_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,8 @@ impl ActionLog {
let text_snapshot = buffer.read(cx).text_snapshot();
let language = buffer.read(cx).language().cloned();
let language_registry = buffer.read(cx).language_registry();
let diff = cx.new(|cx| {
let mut diff = BufferDiff::new(&text_snapshot, cx);
diff.language_changed(language, language_registry, cx);
diff
});
let diff =
cx.new(|cx| BufferDiff::new(&text_snapshot, language, language_registry, cx));
let (diff_update_tx, diff_update_rx) = mpsc::unbounded();
let diff_base;
let unreviewed_edits;
Expand Down Expand Up @@ -465,29 +462,15 @@ impl ActionLog {
new_diff_base: Rope,
cx: &mut AsyncApp,
) -> Result<()> {
let (diff, language) = this.read_with(cx, |this, cx| {
let diff = this.read_with(cx, |this, _cx| {
let tracked_buffer = this
.tracked_buffers
.get(buffer)
.context("buffer not tracked")?;
anyhow::Ok((
tracked_buffer.diff.clone(),
buffer.read(cx).language().cloned(),
))
anyhow::Ok(tracked_buffer.diff.clone())
})??;
let update = diff
.update(cx, |diff, cx| {
diff.update_diff(
buffer_snapshot.clone(),
Some(new_base_text),
Some(true),
language,
cx,
)
})
.await;
diff.update(cx, |diff, cx| {
diff.set_snapshot(update.clone(), &buffer_snapshot, cx)
diff.set_base_text(Some(new_base_text), buffer_snapshot.clone(), cx)
})
.await;
let diff_snapshot = diff.update(cx, |diff, cx| diff.snapshot(cx));
Expand Down
2 changes: 2 additions & 0 deletions crates/agent_ui/src/agent_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ impl AgentDiffPane {
);
diff_display_editor
.set_render_diff_hunk_controls(diff_hunk_controls(&thread, workspace.clone()), cx);
diff_display_editor.set_render_diff_hunks_as_unstaged(cx);
diff_display_editor.update_editors(cx, |editor, _cx| {
editor.register_addon(AgentDiffAddon);
});
Expand Down Expand Up @@ -1572,6 +1573,7 @@ impl AgentDiff {
diff_hunk_controls(&thread, workspace.clone()),
cx,
);
editor.set_render_diff_hunks_as_unstaged(true, cx);
editor.set_expand_all_diff_hunks(cx);
editor.register_addon(EditorAgentDiffAddon);
});
Expand Down
1 change: 1 addition & 0 deletions crates/agent_ui/src/entry_view_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ fn create_editor_diff(
editor.set_show_code_actions(false, cx);
editor.set_show_git_diff_gutter(false, cx);
editor.set_expand_all_diff_hunks(cx);
editor.set_render_diff_hunks_as_unstaged(true, cx);
editor.set_text_style_refinement(diff_editor_text_style_refinement(cx));
editor
})
Expand Down
1 change: 0 additions & 1 deletion crates/buffer_diff/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ test-support = ["settings"]

[dependencies]
clock.workspace = true
futures.workspace = true
imara-diff.workspace = true
gpui.workspace = true
language.workspace = true
Expand Down
Loading
Loading