Detailed changes
@@ -797,10 +797,11 @@ impl InlineAssistant {
if let Some(model) = LanguageModelRegistry::read_global(cx).active_model() {
let language_name = assist.editor.upgrade().and_then(|editor| {
let multibuffer = editor.read(cx).buffer().read(cx);
- let ranges = multibuffer.range_to_buffer_ranges(assist.range.clone(), cx);
+ let multibuffer_snapshot = multibuffer.snapshot(cx);
+ let ranges = multibuffer_snapshot.range_to_buffer_ranges(assist.range.clone());
ranges
.first()
- .and_then(|(buffer, _, _)| buffer.read(cx).language())
+ .and_then(|(excerpt, _)| excerpt.buffer().language())
.map(|language| language.name())
});
report_assistant_event(
@@ -2615,26 +2616,29 @@ impl EventEmitter<CodegenEvent> for CodegenAlternative {}
impl CodegenAlternative {
pub fn new(
- buffer: Model<MultiBuffer>,
+ multi_buffer: Model<MultiBuffer>,
range: Range<Anchor>,
active: bool,
telemetry: Option<Arc<Telemetry>>,
builder: Arc<PromptBuilder>,
cx: &mut ModelContext<Self>,
) -> Self {
- let snapshot = buffer.read(cx).snapshot(cx);
+ let snapshot = multi_buffer.read(cx).snapshot(cx);
- let (old_buffer, _, _) = buffer
- .read(cx)
- .range_to_buffer_ranges(range.clone(), cx)
+ let (old_excerpt, _) = snapshot
+ .range_to_buffer_ranges(range.clone())
.pop()
.unwrap();
let old_buffer = cx.new_model(|cx| {
- let old_buffer = old_buffer.read(cx);
- let text = old_buffer.as_rope().clone();
- let line_ending = old_buffer.line_ending();
- let language = old_buffer.language().cloned();
- let language_registry = old_buffer.language_registry();
+ let text = old_excerpt.buffer().as_rope().clone();
+ let line_ending = old_excerpt.buffer().line_ending();
+ let language = old_excerpt.buffer().language().cloned();
+ let language_registry = multi_buffer
+ .read(cx)
+ .buffer(old_excerpt.buffer_id())
+ .unwrap()
+ .read(cx)
+ .language_registry();
let mut buffer = Buffer::local_normalized(text, line_ending, cx);
buffer.set_language(language, cx);
@@ -2645,7 +2649,7 @@ impl CodegenAlternative {
});
Self {
- buffer: buffer.clone(),
+ buffer: multi_buffer.clone(),
old_buffer,
edit_position: None,
message_id: None,
@@ -2656,7 +2660,7 @@ impl CodegenAlternative {
generation: Task::ready(()),
diff: Diff::default(),
telemetry,
- _subscription: cx.subscribe(&buffer, Self::handle_buffer_event),
+ _subscription: cx.subscribe(&multi_buffer, Self::handle_buffer_event),
builder,
active,
edits: Vec::new(),
@@ -2867,10 +2871,11 @@ impl CodegenAlternative {
let telemetry = self.telemetry.clone();
let language_name = {
let multibuffer = self.buffer.read(cx);
- let ranges = multibuffer.range_to_buffer_ranges(self.range.clone(), cx);
+ let snapshot = multibuffer.snapshot(cx);
+ let ranges = snapshot.range_to_buffer_ranges(self.range.clone());
ranges
.first()
- .and_then(|(buffer, _, _)| buffer.read(cx).language())
+ .and_then(|(excerpt, _)| excerpt.buffer().language())
.map(|language| language.name())
};
@@ -257,17 +257,20 @@ impl CodegenAlternative {
) -> Self {
let snapshot = buffer.read(cx).snapshot(cx);
- let (old_buffer, _, _) = buffer
- .read(cx)
- .range_to_buffer_ranges(range.clone(), cx)
+ let (old_excerpt, _) = snapshot
+ .range_to_buffer_ranges(range.clone())
.pop()
.unwrap();
let old_buffer = cx.new_model(|cx| {
- let old_buffer = old_buffer.read(cx);
- let text = old_buffer.as_rope().clone();
- let line_ending = old_buffer.line_ending();
- let language = old_buffer.language().cloned();
- let language_registry = old_buffer.language_registry();
+ let text = old_excerpt.buffer().as_rope().clone();
+ let line_ending = old_excerpt.buffer().line_ending();
+ let language = old_excerpt.buffer().language().cloned();
+ let language_registry = buffer
+ .read(cx)
+ .buffer(old_excerpt.buffer_id())
+ .unwrap()
+ .read(cx)
+ .language_registry();
let mut buffer = Buffer::local_normalized(text, line_ending, cx);
buffer.set_language(language, cx);
@@ -471,10 +474,11 @@ impl CodegenAlternative {
let telemetry = self.telemetry.clone();
let language_name = {
let multibuffer = self.buffer.read(cx);
- let ranges = multibuffer.range_to_buffer_ranges(self.range.clone(), cx);
+ let snapshot = multibuffer.snapshot(cx);
+ let ranges = snapshot.range_to_buffer_ranges(self.range.clone());
ranges
.first()
- .and_then(|(buffer, _, _)| buffer.read(cx).language())
+ .and_then(|(excerpt, _)| excerpt.buffer().language())
.map(|language| language.name())
};
@@ -871,10 +871,11 @@ impl InlineAssistant {
if let Some(model) = LanguageModelRegistry::read_global(cx).active_model() {
let language_name = assist.editor.upgrade().and_then(|editor| {
let multibuffer = editor.read(cx).buffer().read(cx);
- let ranges = multibuffer.range_to_buffer_ranges(assist.range.clone(), cx);
+ let snapshot = multibuffer.snapshot(cx);
+ let ranges = snapshot.range_to_buffer_ranges(assist.range.clone());
ranges
.first()
- .and_then(|(buffer, _, _)| buffer.read(cx).language())
+ .and_then(|(excerpt, _)| excerpt.buffer().language())
.map(|language| language.name())
});
report_assistant_event(
@@ -1,11 +1,11 @@
use std::time::Duration;
-use editor::Editor;
+use editor::{AnchorRangeExt, Editor};
use gpui::{
EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, Task, View,
ViewContext, WeakView,
};
-use language::Diagnostic;
+use language::{Diagnostic, DiagnosticEntry};
use ui::{h_flex, prelude::*, Button, ButtonLike, Color, Icon, IconName, Label, Tooltip};
use workspace::{item::ItemHandle, StatusItemView, ToolbarItemEvent, Workspace};
@@ -148,7 +148,11 @@ impl DiagnosticIndicator {
(buffer, cursor_position)
});
let new_diagnostic = buffer
- .diagnostics_in_range::<_, usize>(cursor_position..cursor_position, false)
+ .diagnostics_in_range(cursor_position..cursor_position, false)
+ .map(|DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
+ diagnostic,
+ range: range.to_offset(&buffer),
+ })
.filter(|entry| !entry.range.is_empty())
.min_by_key(|entry| (entry.diagnostic.severity, entry.range.len()))
.map(|entry| entry.diagnostic);
@@ -99,8 +99,8 @@ use itertools::Itertools;
use language::{
language_settings::{self, all_language_settings, language_settings, InlayHintSettings},
markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CharKind, CodeLabel,
- CursorShape, Diagnostic, Documentation, IndentKind, IndentSize, Language, OffsetRangeExt,
- Point, Selection, SelectionGoal, TransactionId,
+ CursorShape, Diagnostic, DiagnosticEntry, Documentation, IndentKind, IndentSize, Language,
+ OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
};
use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
use linked_editing_ranges::refresh_linked_ranges;
@@ -3549,13 +3549,12 @@ impl Editor {
Bias::Left,
);
let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
- multi_buffer
- .range_to_buffer_ranges(multi_buffer_visible_range, cx)
+ multi_buffer_snapshot
+ .range_to_buffer_ranges(multi_buffer_visible_range)
.into_iter()
- .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
- .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
- let buffer = buffer_handle.read(cx);
- let buffer_file = project::File::from_dyn(buffer.file())?;
+ .filter(|(_, excerpt_visible_range)| !excerpt_visible_range.is_empty())
+ .filter_map(|(excerpt, excerpt_visible_range)| {
+ let buffer_file = project::File::from_dyn(excerpt.buffer().file())?;
let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
let worktree_entry = buffer_worktree
.read(cx)
@@ -3564,17 +3563,17 @@ impl Editor {
return None;
}
- let language = buffer.language()?;
+ let language = excerpt.buffer().language()?;
if let Some(restrict_to_languages) = restrict_to_languages {
if !restrict_to_languages.contains(language) {
return None;
}
}
Some((
- excerpt_id,
+ excerpt.id(),
(
- buffer_handle,
- buffer.version().clone(),
+ multi_buffer.buffer(excerpt.buffer_id()).unwrap(),
+ excerpt.buffer().version().clone(),
excerpt_visible_range,
),
))
@@ -9179,10 +9178,23 @@ impl Editor {
let snapshot = self.snapshot(cx);
loop {
let diagnostics = if direction == Direction::Prev {
- buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
+ buffer
+ .diagnostics_in_range(0..search_start, true)
+ .map(|DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
+ diagnostic,
+ range: range.to_offset(&buffer),
+ })
+ .collect::<Vec<_>>()
} else {
- buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
+ buffer
+ .diagnostics_in_range(search_start..buffer.len(), false)
+ .map(|DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
+ diagnostic,
+ range: range.to_offset(&buffer),
+ })
+ .collect::<Vec<_>>()
}
+ .into_iter()
.filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start));
let group = diagnostics
// relies on diagnostics_in_range to return diagnostics with the same starting range to
@@ -10289,11 +10301,12 @@ impl Editor {
let buffer = self.buffer.read(cx).snapshot(cx);
let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
let is_valid = buffer
- .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
+ .diagnostics_in_range(active_diagnostics.primary_range.clone(), false)
.any(|entry| {
+ let range = entry.range.to_offset(&buffer);
entry.diagnostic.is_primary
- && !entry.range.is_empty()
- && entry.range.start == primary_range_start
+ && !range.is_empty()
+ && range.start == primary_range_start
&& entry.diagnostic.message == active_diagnostics.primary_message
});
@@ -11493,21 +11506,23 @@ impl Editor {
let (buffer, selection) = if let Some(buffer) = self.buffer().read(cx).as_singleton() {
(buffer, selection_range.start.row..selection_range.end.row)
} else {
- let buffer_ranges = self
- .buffer()
- .read(cx)
- .range_to_buffer_ranges(selection_range, cx);
+ let multi_buffer = self.buffer().read(cx);
+ let multi_buffer_snapshot = multi_buffer.snapshot(cx);
+ let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
- let (buffer, range, _) = if selection.reversed {
+ let (excerpt, range) = if selection.reversed {
buffer_ranges.first()
} else {
buffer_ranges.last()
}?;
- let snapshot = buffer.read(cx).snapshot();
+ let snapshot = excerpt.buffer();
let selection = text::ToPoint::to_point(&range.start, &snapshot).row
..text::ToPoint::to_point(&range.end, &snapshot).row;
- (buffer.clone(), selection)
+ (
+ multi_buffer.buffer(excerpt.buffer_id()).unwrap().clone(),
+ selection,
+ )
};
Some((buffer, selection))
@@ -12399,17 +12414,18 @@ impl Editor {
};
let selections = self.selections.all::<usize>(cx);
- let buffer = self.buffer.read(cx);
+ let multi_buffer = self.buffer.read(cx);
+ let multi_buffer_snapshot = multi_buffer.snapshot(cx);
let mut new_selections_by_buffer = HashMap::default();
for selection in selections {
- for (buffer, range, _) in
- buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
+ for (excerpt, range) in
+ multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
{
- let mut range = range.to_point(buffer.read(cx));
+ let mut range = range.to_point(excerpt.buffer());
range.start.column = 0;
- range.end.column = buffer.read(cx).line_len(range.end.row);
+ range.end.column = excerpt.buffer().line_len(range.end.row);
new_selections_by_buffer
- .entry(buffer)
+ .entry(multi_buffer.buffer(excerpt.buffer_id()).unwrap())
.or_insert(Vec::new())
.push(range)
}
@@ -12508,13 +12524,15 @@ impl Editor {
}
None => {
let selections = self.selections.all::<usize>(cx);
- let buffer = self.buffer.read(cx);
+ let multi_buffer = self.buffer.read(cx);
for selection in selections {
- for (mut buffer_handle, mut range, _) in
- buffer.range_to_buffer_ranges(selection.range(), cx)
+ for (excerpt, mut range) in multi_buffer
+ .snapshot(cx)
+ .range_to_buffer_ranges(selection.range())
{
// When editing branch buffers, jump to the corresponding location
// in their base buffer.
+ let mut buffer_handle = multi_buffer.buffer(excerpt.buffer_id()).unwrap();
let buffer = buffer_handle.read(cx);
if let Some(base_buffer) = buffer.base_buffer() {
range = buffer.range_to_version(range, &base_buffer.read(cx).version());
@@ -45,7 +45,7 @@ use language::{
IndentGuideBackgroundColoring, IndentGuideColoring, IndentGuideSettings,
ShowWhitespaceSetting,
},
- ChunkRendererContext,
+ ChunkRendererContext, DiagnosticEntry,
};
use lsp::DiagnosticSeverity;
use multi_buffer::{
@@ -4741,10 +4741,11 @@ impl EditorElement {
if scrollbar_settings.diagnostics != ScrollbarDiagnostics::None {
let diagnostics = snapshot
.buffer_snapshot
- .diagnostics_in_range::<_, Point>(
- Point::zero()..max_point,
- false,
- )
+ .diagnostics_in_range(Point::zero()..max_point, false)
+ .map(|DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
+ diagnostic,
+ range: range.to_point(&snapshot.buffer_snapshot),
+ })
// Don't show diagnostics the user doesn't care about
.filter(|diagnostic| {
match (
@@ -266,12 +266,11 @@ fn show_hover(
// If there's a diagnostic, assign it on the hover state and notify
let mut local_diagnostic = snapshot
.buffer_snapshot
- .diagnostics_in_range::<_, usize>(anchor..anchor, false)
+ .diagnostics_in_range(anchor..anchor, false)
// Find the entry with the most specific range
- .min_by_key(|entry| entry.range.end - entry.range.start)
- .map(|entry| DiagnosticEntry {
- diagnostic: entry.diagnostic,
- range: entry.range.to_anchors(&snapshot.buffer_snapshot),
+ .min_by_key(|entry| {
+ let range = entry.range.to_offset(&snapshot.buffer_snapshot);
+ range.end - range.start
});
// Pull the primary diagnostic out so we can jump to it if the popover is clicked
@@ -456,16 +456,19 @@ impl Editor {
range: Range<Anchor>,
cx: &mut ViewContext<Editor>,
) -> Option<()> {
- let (buffer, range, _) = self
- .buffer
- .read(cx)
- .range_to_buffer_ranges(range, cx)
+ let multi_buffer = self.buffer.read(cx);
+ let multi_buffer_snapshot = multi_buffer.snapshot(cx);
+ let (excerpt, range) = multi_buffer_snapshot
+ .range_to_buffer_ranges(range)
.into_iter()
.next()?;
- buffer.update(cx, |branch_buffer, cx| {
- branch_buffer.merge_into_base(vec![range], cx);
- });
+ multi_buffer
+ .buffer(excerpt.buffer_id())
+ .unwrap()
+ .update(cx, |branch_buffer, cx| {
+ branch_buffer.merge_into_base(vec![range], cx);
+ });
if let Some(project) = self.project.clone() {
self.save(true, project, cx).detach_and_log_err(cx);
@@ -3943,14 +3943,14 @@ impl BufferSnapshot {
) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
where
T: 'a + Clone + ToOffset,
- O: 'a + FromAnchor + Ord,
+ O: 'a + FromAnchor,
{
let mut iterators: Vec<_> = self
.diagnostics
.iter()
.map(|(_, collection)| {
collection
- .range::<T, O>(search_range.clone(), self, true, reversed)
+ .range::<T, text::Anchor>(search_range.clone(), self, true, reversed)
.peekable()
})
.collect();
@@ -3964,7 +3964,7 @@ impl BufferSnapshot {
let cmp = a
.range
.start
- .cmp(&b.range.start)
+ .cmp(&b.range.start, self)
// when range is equal, sort by diagnostic severity
.then(a.diagnostic.severity.cmp(&b.diagnostic.severity))
// and stabilize order with group_id
@@ -3975,7 +3975,13 @@ impl BufferSnapshot {
cmp
}
})?;
- iterators[next_ix].next()
+ iterators[next_ix]
+ .next()
+ .map(|DiagnosticEntry { range, diagnostic }| DiagnosticEntry {
+ diagnostic,
+ range: FromAnchor::from_anchor(&range.start, self)
+ ..FromAnchor::from_anchor(&range.end, self),
+ })
})
}
@@ -128,13 +128,18 @@ impl SyntaxTreeView {
fn editor_updated(&mut self, did_reparse: bool, cx: &mut ViewContext<Self>) -> Option<()> {
// Find which excerpt the cursor is in, and the position within that excerpted buffer.
let editor_state = self.editor.as_mut()?;
- let (buffer, range, excerpt_id) = editor_state.editor.update(cx, |editor, cx| {
+ let snapshot = editor_state
+ .editor
+ .update(cx, |editor, cx| editor.snapshot(cx));
+ let (excerpt, buffer, range) = editor_state.editor.update(cx, |editor, cx| {
let selection_range = editor.selections.last::<usize>(cx).range();
- editor
- .buffer()
- .read(cx)
- .range_to_buffer_ranges(selection_range, cx)
- .pop()
+ let multi_buffer = editor.buffer().read(cx);
+ let (excerpt, range) = snapshot
+ .buffer_snapshot
+ .range_to_buffer_ranges(selection_range)
+ .pop()?;
+ let buffer = multi_buffer.buffer(excerpt.buffer_id()).unwrap().clone();
+ Some((excerpt, buffer, range))
})?;
// If the cursor has moved into a different excerpt, retrieve a new syntax layer
@@ -143,16 +148,16 @@ impl SyntaxTreeView {
.active_buffer
.get_or_insert_with(|| BufferState {
buffer: buffer.clone(),
- excerpt_id,
+ excerpt_id: excerpt.id(),
active_layer: None,
});
let mut prev_layer = None;
if did_reparse {
prev_layer = buffer_state.active_layer.take();
}
- if buffer_state.buffer != buffer || buffer_state.excerpt_id != excerpt_id {
+ if buffer_state.buffer != buffer || buffer_state.excerpt_id != excerpt.id() {
buffer_state.buffer = buffer.clone();
- buffer_state.excerpt_id = excerpt_id;
+ buffer_state.excerpt_id = excerpt.id();
buffer_state.active_layer = None;
}
@@ -1667,42 +1667,6 @@ impl MultiBuffer {
})
}
- pub fn range_to_buffer_ranges<T: ToOffset>(
- &self,
- range: Range<T>,
- cx: &AppContext,
- ) -> Vec<(Model<Buffer>, Range<usize>, ExcerptId)> {
- let snapshot = self.read(cx);
- let start = range.start.to_offset(&snapshot);
- let end = range.end.to_offset(&snapshot);
-
- let mut result = Vec::new();
- let mut cursor = snapshot.excerpts.cursor::<usize>(&());
- cursor.seek(&start, Bias::Right, &());
- if cursor.item().is_none() {
- cursor.prev(&());
- }
-
- while let Some(excerpt) = cursor.item() {
- if *cursor.start() > end {
- break;
- }
-
- let mut end_before_newline = cursor.end(&());
- if excerpt.has_trailing_newline {
- end_before_newline -= 1;
- }
- let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
- let start = excerpt_start + (cmp::max(start, *cursor.start()) - *cursor.start());
- let end = excerpt_start + (cmp::min(end, end_before_newline) - *cursor.start());
- let buffer = self.buffers.borrow()[&excerpt.buffer_id].buffer.clone();
- result.push((buffer, start..end, excerpt.id));
- cursor.next(&());
- }
-
- result
- }
-
pub fn remove_excerpts(
&mut self,
excerpt_ids: impl IntoIterator<Item = ExcerptId>,
@@ -3914,28 +3878,32 @@ impl MultiBufferSnapshot {
where
O: text::FromAnchor + 'a,
{
- self.as_singleton()
- .into_iter()
- .flat_map(move |(_, _, buffer)| buffer.diagnostic_group(group_id))
+ self.all_excerpts()
+ .flat_map(move |excerpt| excerpt.buffer().diagnostic_group(group_id))
}
- pub fn diagnostics_in_range<'a, T, O>(
+ pub fn diagnostics_in_range<'a, T>(
&'a self,
range: Range<T>,
reversed: bool,
- ) -> impl Iterator<Item = DiagnosticEntry<O>> + 'a
+ ) -> impl Iterator<Item = DiagnosticEntry<Anchor>> + 'a
where
T: 'a + ToOffset,
- O: 'a + text::FromAnchor + Ord,
{
- self.as_singleton()
- .into_iter()
- .flat_map(move |(_, _, buffer)| {
- buffer.diagnostics_in_range(
- range.start.to_offset(self)..range.end.to_offset(self),
- reversed,
- )
- })
+ let mut ranges = self.range_to_buffer_ranges(range);
+ if reversed {
+ ranges.reverse();
+ }
+ ranges.into_iter().flat_map(move |(excerpt, range)| {
+ let excerpt_id = excerpt.id();
+ excerpt.buffer().diagnostics_in_range(range, reversed).map(
+ move |DiagnosticEntry { diagnostic, range }| DiagnosticEntry {
+ diagnostic,
+ range: self.anchor_in_excerpt(excerpt_id, range.start).unwrap()
+ ..self.anchor_in_excerpt(excerpt_id, range.end).unwrap(),
+ },
+ )
+ })
}
pub fn syntax_ancestor<T: ToOffset>(
@@ -4185,6 +4153,42 @@ impl MultiBufferSnapshot {
})
}
+ pub fn range_to_buffer_ranges<T: ToOffset>(
+ &self,
+ range: Range<T>,
+ ) -> Vec<(MultiBufferExcerpt<'_>, Range<usize>)> {
+ let start = range.start.to_offset(self);
+ let end = range.end.to_offset(self);
+
+ let mut result = Vec::new();
+ let mut cursor = self.excerpts.cursor::<(usize, Point)>(&());
+ cursor.seek(&start, Bias::Right, &());
+ if cursor.item().is_none() {
+ cursor.prev(&());
+ }
+
+ while let Some(excerpt) = cursor.item() {
+ if cursor.start().0 > end {
+ break;
+ }
+
+ let mut end_before_newline = cursor.end(&()).0;
+ if excerpt.has_trailing_newline {
+ end_before_newline -= 1;
+ }
+ let excerpt_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
+ let start = excerpt_start + (cmp::max(start, cursor.start().0) - cursor.start().0);
+ let end = excerpt_start + (cmp::min(end, end_before_newline) - cursor.start().0);
+ result.push((
+ MultiBufferExcerpt::new(&excerpt, *cursor.start()),
+ start..end,
+ ));
+ cursor.next(&());
+ }
+
+ result
+ }
+
/// Returns excerpts overlapping the given ranges. If range spans multiple excerpts returns one range for each excerpt
///
/// The ranges are specified in the coordinate space of the multibuffer, not the individual excerpted buffers.
@@ -4664,6 +4668,10 @@ impl<'a> MultiBufferExcerpt<'a> {
self.excerpt.id
}
+ pub fn buffer_id(&self) -> BufferId {
+ self.excerpt.buffer_id
+ }
+
pub fn start_anchor(&self) -> Anchor {
Anchor {
buffer_id: Some(self.excerpt.buffer_id),
@@ -1234,14 +1234,13 @@ fn test_random_multibuffer(cx: &mut AppContext, mut rng: StdRng) {
start_ix..end_ix
);
- let excerpted_buffer_ranges = multibuffer
- .read(cx)
- .range_to_buffer_ranges(start_ix..end_ix, cx);
+ let snapshot = multibuffer.read(cx).snapshot(cx);
+ let excerpted_buffer_ranges = snapshot.range_to_buffer_ranges(start_ix..end_ix);
let excerpted_buffers_text = excerpted_buffer_ranges
.iter()
- .map(|(buffer, buffer_range, _)| {
- buffer
- .read(cx)
+ .map(|(excerpt, buffer_range)| {
+ excerpt
+ .buffer()
.text_for_range(buffer_range.clone())
.collect::<String>()
})
@@ -3047,6 +3047,12 @@ pub trait FromAnchor {
fn from_anchor(anchor: &Anchor, snapshot: &BufferSnapshot) -> Self;
}
+impl FromAnchor for Anchor {
+ fn from_anchor(anchor: &Anchor, _snapshot: &BufferSnapshot) -> Self {
+ *anchor
+ }
+}
+
impl FromAnchor for Point {
fn from_anchor(anchor: &Anchor, snapshot: &BufferSnapshot) -> Self {
snapshot.summary_for_anchor(anchor)