Avoid unnecessary code action requests when applying leader updates t… (#2489)

We noticed a huge amount of code actions requests being issued by
followers when applying leader updates. It was caused by a call to
`MultiBuffer::remove_excerpts` with an empty list of excerpts to remove.
This PR fixes that by avoiding emitting spurious events when multibuffer
excerpt manipulation methods are called with empty lists.
This commit is contained in:
Max Brunsfeld 2023-05-18 14:52:21 -07:00 committed by GitHub
commit ffe35d171c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 4 deletions

View file

@ -5517,10 +5517,12 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
}); });
let is_still_following = Rc::new(RefCell::new(true)); let is_still_following = Rc::new(RefCell::new(true));
let follower_edit_event_count = Rc::new(RefCell::new(0));
let pending_update = Rc::new(RefCell::new(None)); let pending_update = Rc::new(RefCell::new(None));
follower.update(cx, { follower.update(cx, {
let update = pending_update.clone(); let update = pending_update.clone();
let is_still_following = is_still_following.clone(); let is_still_following = is_still_following.clone();
let follower_edit_event_count = follower_edit_event_count.clone();
|_, cx| { |_, cx| {
cx.subscribe(&leader, move |_, leader, event, cx| { cx.subscribe(&leader, move |_, leader, event, cx| {
leader leader
@ -5533,6 +5535,9 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
if Editor::should_unfollow_on_event(event, cx) { if Editor::should_unfollow_on_event(event, cx) {
*is_still_following.borrow_mut() = false; *is_still_following.borrow_mut() = false;
} }
if let Event::BufferEdited = event {
*follower_edit_event_count.borrow_mut() += 1;
}
}) })
.detach(); .detach();
} }
@ -5552,6 +5557,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
assert_eq!(follower.selections.ranges(cx), vec![1..1]); assert_eq!(follower.selections.ranges(cx), vec![1..1]);
}); });
assert_eq!(*is_still_following.borrow(), true); assert_eq!(*is_still_following.borrow(), true);
assert_eq!(*follower_edit_event_count.borrow(), 0);
// Update the scroll position only // Update the scroll position only
leader.update(cx, |leader, cx| { leader.update(cx, |leader, cx| {
@ -5568,6 +5574,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
vec2f(1.5, 3.5) vec2f(1.5, 3.5)
); );
assert_eq!(*is_still_following.borrow(), true); assert_eq!(*is_still_following.borrow(), true);
assert_eq!(*follower_edit_event_count.borrow(), 0);
// Update the selections and scroll position. The follower's scroll position is updated // Update the selections and scroll position. The follower's scroll position is updated
// via autoscroll, not via the leader's exact scroll position. // via autoscroll, not via the leader's exact scroll position.

View file

@ -1167,6 +1167,9 @@ impl MultiBuffer {
) { ) {
self.sync(cx); self.sync(cx);
let ids = excerpt_ids.into_iter().collect::<Vec<_>>(); let ids = excerpt_ids.into_iter().collect::<Vec<_>>();
if ids.is_empty() {
return;
}
let mut buffers = self.buffers.borrow_mut(); let mut buffers = self.buffers.borrow_mut();
let mut snapshot = self.snapshot.borrow_mut(); let mut snapshot = self.snapshot.borrow_mut();
@ -4100,19 +4103,25 @@ mod tests {
let leader_multibuffer = cx.add_model(|_| MultiBuffer::new(0)); let leader_multibuffer = cx.add_model(|_| MultiBuffer::new(0));
let follower_multibuffer = cx.add_model(|_| MultiBuffer::new(0)); let follower_multibuffer = cx.add_model(|_| MultiBuffer::new(0));
let follower_edit_event_count = Rc::new(RefCell::new(0));
follower_multibuffer.update(cx, |_, cx| { follower_multibuffer.update(cx, |_, cx| {
cx.subscribe(&leader_multibuffer, |follower, _, event, cx| { let follower_edit_event_count = follower_edit_event_count.clone();
match event.clone() { cx.subscribe(
&leader_multibuffer,
move |follower, _, event, cx| match event.clone() {
Event::ExcerptsAdded { Event::ExcerptsAdded {
buffer, buffer,
predecessor, predecessor,
excerpts, excerpts,
} => follower.insert_excerpts_with_ids_after(predecessor, buffer, excerpts, cx), } => follower.insert_excerpts_with_ids_after(predecessor, buffer, excerpts, cx),
Event::ExcerptsRemoved { ids } => follower.remove_excerpts(ids, cx), Event::ExcerptsRemoved { ids } => follower.remove_excerpts(ids, cx),
Event::Edited => {
*follower_edit_event_count.borrow_mut() += 1;
}
_ => {} _ => {}
} },
}) )
.detach(); .detach();
}); });
@ -4151,6 +4160,7 @@ mod tests {
leader_multibuffer.read(cx).snapshot(cx).text(), leader_multibuffer.read(cx).snapshot(cx).text(),
follower_multibuffer.read(cx).snapshot(cx).text(), follower_multibuffer.read(cx).snapshot(cx).text(),
); );
assert_eq!(*follower_edit_event_count.borrow(), 2);
leader_multibuffer.update(cx, |leader, cx| { leader_multibuffer.update(cx, |leader, cx| {
let excerpt_ids = leader.excerpt_ids(); let excerpt_ids = leader.excerpt_ids();
@ -4160,6 +4170,27 @@ mod tests {
leader_multibuffer.read(cx).snapshot(cx).text(), leader_multibuffer.read(cx).snapshot(cx).text(),
follower_multibuffer.read(cx).snapshot(cx).text(), follower_multibuffer.read(cx).snapshot(cx).text(),
); );
assert_eq!(*follower_edit_event_count.borrow(), 3);
// Removing an empty set of excerpts is a noop.
leader_multibuffer.update(cx, |leader, cx| {
leader.remove_excerpts([], cx);
});
assert_eq!(
leader_multibuffer.read(cx).snapshot(cx).text(),
follower_multibuffer.read(cx).snapshot(cx).text(),
);
assert_eq!(*follower_edit_event_count.borrow(), 3);
// Adding an empty set of excerpts is a noop.
leader_multibuffer.update(cx, |leader, cx| {
leader.push_excerpts::<usize>(buffer_2.clone(), [], cx);
});
assert_eq!(
leader_multibuffer.read(cx).snapshot(cx).text(),
follower_multibuffer.read(cx).snapshot(cx).text(),
);
assert_eq!(*follower_edit_event_count.borrow(), 3);
leader_multibuffer.update(cx, |leader, cx| { leader_multibuffer.update(cx, |leader, cx| {
leader.clear(cx); leader.clear(cx);
@ -4168,6 +4199,7 @@ mod tests {
leader_multibuffer.read(cx).snapshot(cx).text(), leader_multibuffer.read(cx).snapshot(cx).text(),
follower_multibuffer.read(cx).snapshot(cx).text(), follower_multibuffer.read(cx).snapshot(cx).text(),
); );
assert_eq!(*follower_edit_event_count.borrow(), 4);
} }
#[gpui::test] #[gpui::test]