@@ -15130,16 +15130,21 @@ impl Editor {
})
.context("location tasks preparation")?;
- let locations = future::join_all(location_tasks)
+ let locations: Vec<Location> = future::join_all(location_tasks)
.await
.into_iter()
.filter_map(|location| location.transpose())
.collect::<Result<_>>()
.context("location tasks")?;
+ if locations.is_empty() {
+ return Ok(Navigated::No);
+ }
+
let Some(workspace) = workspace else {
return Ok(Navigated::No);
};
+
let opened = workspace
.update_in(cx, |workspace, window, cx| {
Self::open_locations_in_multibuffer(
@@ -15303,6 +15308,11 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Workspace>,
) {
+ if locations.is_empty() {
+ log::error!("bug: open_locations_in_multibuffer called with empty list of locations");
+ return;
+ }
+
// If there are multiple definitions, open them in a multibuffer
locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
let mut locations = locations.into_iter().peekable();
@@ -18289,18 +18299,18 @@ impl Editor {
return;
};
+ let title = multibuffer.title(cx).to_string();
+
let locations = self
.selections
- .disjoint_anchors()
- .iter()
- .map(|range| Location {
+ .all_anchors(cx)
+ .into_iter()
+ .map(|selection| Location {
buffer: buffer.clone(),
- range: range.start.text_anchor..range.end.text_anchor,
+ range: selection.start.text_anchor..selection.end.text_anchor,
})
.collect::<Vec<_>>();
- let title = multibuffer.title(cx).to_string();
-
cx.spawn_in(window, async move |_, cx| {
workspace.update_in(cx, |workspace, window, cx| {
Self::open_locations_in_multibuffer(
@@ -81,9 +81,9 @@ impl SelectionsCollection {
count
}
- /// The non-pending, non-overlapping selections. There could still be a pending
- /// selection that overlaps these if the mouse is being dragged, etc. Returned as
- /// selections over Anchors.
+ /// The non-pending, non-overlapping selections. There could be a pending selection that
+ /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a
+ /// pending selection. Returned as selections over Anchors.
pub fn disjoint_anchors(&self) -> Arc<[Selection<Anchor>]> {
self.disjoint.clone()
}
@@ -94,6 +94,20 @@ impl SelectionsCollection {
(0..disjoint.len()).map(move |ix| disjoint[ix].range())
}
+ /// Non-overlapping selections using anchors, including the pending selection.
+ pub fn all_anchors(&self, cx: &mut App) -> Arc<[Selection<Anchor>]> {
+ if self.pending.is_none() {
+ self.disjoint_anchors()
+ } else {
+ let all_offset_selections = self.all::<usize>(cx);
+ let buffer = self.buffer(cx);
+ all_offset_selections
+ .into_iter()
+ .map(|selection| selection_to_anchor_selection(selection, &buffer))
+ .collect()
+ }
+ }
+
pub fn pending_anchor(&self) -> Option<Selection<Anchor>> {
self.pending
.as_ref()
@@ -534,21 +548,11 @@ impl<'a> MutableSelectionsCollection<'a> {
}
}
- self.collection.disjoint = Arc::from_iter(selections.into_iter().map(|selection| {
- let end_bias = if selection.end > selection.start {
- Bias::Left
- } else {
- Bias::Right
- };
- Selection {
- id: selection.id,
- start: buffer.anchor_after(selection.start),
- end: buffer.anchor_at(selection.end, end_bias),
- reversed: selection.reversed,
- goal: selection.goal,
- }
- }));
-
+ self.collection.disjoint = Arc::from_iter(
+ selections
+ .into_iter()
+ .map(|selection| selection_to_anchor_selection(selection, &buffer)),
+ );
self.collection.pending = None;
self.selections_changed = true;
}
@@ -880,6 +884,27 @@ impl DerefMut for MutableSelectionsCollection<'_> {
}
}
+fn selection_to_anchor_selection<T>(
+ selection: Selection<T>,
+ buffer: &MultiBufferSnapshot,
+) -> Selection<Anchor>
+where
+ T: ToOffset + Ord,
+{
+ let end_bias = if selection.end > selection.start {
+ Bias::Left
+ } else {
+ Bias::Right
+ };
+ Selection {
+ id: selection.id,
+ start: buffer.anchor_after(selection.start),
+ end: buffer.anchor_at(selection.end, end_bias),
+ reversed: selection.reversed,
+ goal: selection.goal,
+ }
+}
+
// Panics if passed selections are not in order
fn resolve_selections_display<'a>(
selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,