mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
multi_buffer: Remove redundant buffer id field (#43459)
It is easy for us to get the two fields out of sync causing weird problems, there is no reason to have both here so. Release Notes: - N/A *or* Added/Fixed/Improved ... Co-authored by: Antonio Scandurra <antonio@zed.dev>
This commit is contained in:
parent
ab80ef1845
commit
fafe1afa61
39 changed files with 378 additions and 306 deletions
|
|
@ -347,13 +347,13 @@ impl ToolCall {
|
|||
let buffer = buffer.await.log_err()?;
|
||||
let position = buffer
|
||||
.update(cx, |buffer, _| {
|
||||
let snapshot = buffer.snapshot();
|
||||
if let Some(row) = location.line {
|
||||
let snapshot = buffer.snapshot();
|
||||
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
|
||||
Anchor::min_for_buffer(snapshot.remote_id())
|
||||
}
|
||||
})
|
||||
.ok()?;
|
||||
|
|
@ -2120,7 +2120,7 @@ impl AcpThread {
|
|||
position: edits
|
||||
.last()
|
||||
.map(|(range, _)| range.end)
|
||||
.unwrap_or(Anchor::MIN),
|
||||
.unwrap_or(Anchor::min_for_buffer(buffer.read(cx).remote_id())),
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -50,9 +50,14 @@ impl Diff {
|
|||
let hunk_ranges = {
|
||||
let buffer = buffer.read(cx);
|
||||
let diff = diff.read(cx);
|
||||
diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, buffer, cx)
|
||||
.map(|diff_hunk| diff_hunk.buffer_range.to_point(buffer))
|
||||
.collect::<Vec<_>>()
|
||||
diff.hunks_intersecting_range(
|
||||
Anchor::min_for_buffer(buffer.remote_id())
|
||||
..Anchor::max_for_buffer(buffer.remote_id()),
|
||||
buffer,
|
||||
cx,
|
||||
)
|
||||
.map(|diff_hunk| diff_hunk.buffer_range.to_point(buffer))
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
multibuffer.set_excerpts_for_path(
|
||||
|
|
@ -316,7 +321,12 @@ impl PendingDiff {
|
|||
let buffer = self.new_buffer.read(cx);
|
||||
let diff = self.diff.read(cx);
|
||||
let mut ranges = diff
|
||||
.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, buffer, cx)
|
||||
.hunks_intersecting_range(
|
||||
Anchor::min_for_buffer(buffer.remote_id())
|
||||
..Anchor::max_for_buffer(buffer.remote_id()),
|
||||
buffer,
|
||||
cx,
|
||||
)
|
||||
.map(|diff_hunk| diff_hunk.buffer_range.to_point(buffer))
|
||||
.collect::<Vec<_>>();
|
||||
ranges.extend(
|
||||
|
|
|
|||
|
|
@ -409,9 +409,11 @@ impl ActionLog {
|
|||
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..Anchor::MAX, &buffer_snapshot)
|
||||
{
|
||||
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);
|
||||
|
|
@ -732,12 +734,10 @@ impl ActionLog {
|
|||
cx: &mut Context<Self>,
|
||||
) -> Task<()> {
|
||||
let futures = self.changed_buffers(cx).into_keys().map(|buffer| {
|
||||
let reject = self.reject_edits_in_ranges(
|
||||
buffer,
|
||||
vec![Anchor::MIN..Anchor::MAX],
|
||||
telemetry.clone(),
|
||||
cx,
|
||||
);
|
||||
let buffer_ranges = vec![Anchor::min_max_range_for_buffer(
|
||||
buffer.read(cx).remote_id(),
|
||||
)];
|
||||
let reject = self.reject_edits_in_ranges(buffer, buffer_ranges, telemetry.clone(), cx);
|
||||
|
||||
async move {
|
||||
reject.await.log_err();
|
||||
|
|
@ -2010,7 +2010,8 @@ mod tests {
|
|||
|
||||
// User accepts the single hunk
|
||||
action_log.update(cx, |log, cx| {
|
||||
log.keep_edits_in_range(buffer.clone(), Anchor::MIN..Anchor::MAX, None, cx)
|
||||
let buffer_range = Anchor::min_max_range_for_buffer(buffer.read(cx).remote_id());
|
||||
log.keep_edits_in_range(buffer.clone(), buffer_range, None, cx)
|
||||
});
|
||||
cx.run_until_parked();
|
||||
assert_eq!(unreviewed_hunks(&action_log, cx), vec![]);
|
||||
|
|
@ -2031,7 +2032,14 @@ mod tests {
|
|||
// User rejects the hunk
|
||||
action_log
|
||||
.update(cx, |log, cx| {
|
||||
log.reject_edits_in_ranges(buffer.clone(), vec![Anchor::MIN..Anchor::MAX], None, cx)
|
||||
log.reject_edits_in_ranges(
|
||||
buffer.clone(),
|
||||
vec![Anchor::min_max_range_for_buffer(
|
||||
buffer.read(cx).remote_id(),
|
||||
)],
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -172,14 +172,14 @@ impl EditAgent {
|
|||
project.set_agent_location(
|
||||
Some(AgentLocation {
|
||||
buffer: buffer.downgrade(),
|
||||
position: language::Anchor::MAX,
|
||||
position: language::Anchor::max_for_buffer(buffer.read(cx).remote_id()),
|
||||
}),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
output_events_tx
|
||||
.unbounded_send(EditAgentOutputEvent::Edited(
|
||||
language::Anchor::MIN..language::Anchor::MAX,
|
||||
Anchor::min_max_range_for_buffer(buffer.read(cx).remote_id()),
|
||||
))
|
||||
.ok();
|
||||
})?;
|
||||
|
|
@ -187,7 +187,7 @@ impl EditAgent {
|
|||
while let Some(event) = parse_rx.next().await {
|
||||
match event? {
|
||||
CreateFileParserEvent::NewTextChunk { chunk } => {
|
||||
cx.update(|cx| {
|
||||
let buffer_id = cx.update(|cx| {
|
||||
buffer.update(cx, |buffer, cx| buffer.append(chunk, cx));
|
||||
self.action_log
|
||||
.update(cx, |log, cx| log.buffer_edited(buffer.clone(), cx));
|
||||
|
|
@ -195,15 +195,18 @@ impl EditAgent {
|
|||
project.set_agent_location(
|
||||
Some(AgentLocation {
|
||||
buffer: buffer.downgrade(),
|
||||
position: language::Anchor::MAX,
|
||||
position: language::Anchor::max_for_buffer(
|
||||
buffer.read(cx).remote_id(),
|
||||
),
|
||||
}),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
buffer.read(cx).remote_id()
|
||||
})?;
|
||||
output_events_tx
|
||||
.unbounded_send(EditAgentOutputEvent::Edited(
|
||||
language::Anchor::MIN..language::Anchor::MAX,
|
||||
Anchor::min_max_range_for_buffer(buffer_id),
|
||||
))
|
||||
.ok();
|
||||
}
|
||||
|
|
@ -1200,7 +1203,9 @@ mod tests {
|
|||
project.read_with(cx, |project, _| project.agent_location()),
|
||||
Some(AgentLocation {
|
||||
buffer: buffer.downgrade(),
|
||||
position: language::Anchor::MAX
|
||||
position: language::Anchor::max_for_buffer(
|
||||
cx.update(|cx| buffer.read(cx).remote_id())
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -1218,7 +1223,9 @@ mod tests {
|
|||
project.read_with(cx, |project, _| project.agent_location()),
|
||||
Some(AgentLocation {
|
||||
buffer: buffer.downgrade(),
|
||||
position: language::Anchor::MAX
|
||||
position: language::Anchor::max_for_buffer(
|
||||
cx.update(|cx| buffer.read(cx).remote_id())
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -1236,7 +1243,9 @@ mod tests {
|
|||
project.read_with(cx, |project, _| project.agent_location()),
|
||||
Some(AgentLocation {
|
||||
buffer: buffer.downgrade(),
|
||||
position: language::Anchor::MAX
|
||||
position: language::Anchor::max_for_buffer(
|
||||
cx.update(|cx| buffer.read(cx).remote_id())
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -1254,7 +1263,9 @@ mod tests {
|
|||
project.read_with(cx, |project, _| project.agent_location()),
|
||||
Some(AgentLocation {
|
||||
buffer: buffer.downgrade(),
|
||||
position: language::Anchor::MAX
|
||||
position: language::Anchor::max_for_buffer(
|
||||
cx.update(|cx| buffer.read(cx).remote_id())
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
|
|
@ -1269,7 +1280,9 @@ mod tests {
|
|||
project.read_with(cx, |project, _| project.agent_location()),
|
||||
Some(AgentLocation {
|
||||
buffer: buffer.downgrade(),
|
||||
position: language::Anchor::MAX
|
||||
position: language::Anchor::max_for_buffer(
|
||||
cx.update(|cx| buffer.read(cx).remote_id())
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,7 +275,9 @@ impl AgentTool for ReadFileTool {
|
|||
project.set_agent_location(
|
||||
Some(AgentLocation {
|
||||
buffer: buffer.downgrade(),
|
||||
position: anchor.unwrap_or(text::Anchor::MIN),
|
||||
position: anchor.unwrap_or_else(|| {
|
||||
text::Anchor::min_for_buffer(buffer.read(cx).remote_id())
|
||||
}),
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4103,7 +4103,9 @@ impl AcpThreadView {
|
|||
action_log
|
||||
.reject_edits_in_ranges(
|
||||
buffer.clone(),
|
||||
vec![Anchor::MIN..Anchor::MAX],
|
||||
vec![Anchor::min_max_range_for_buffer(
|
||||
buffer.read(cx).remote_id(),
|
||||
)],
|
||||
Some(telemetry.clone()),
|
||||
cx,
|
||||
)
|
||||
|
|
@ -4124,7 +4126,9 @@ impl AcpThreadView {
|
|||
action_log.update(cx, |action_log, cx| {
|
||||
action_log.keep_edits_in_range(
|
||||
buffer.clone(),
|
||||
Anchor::MIN..Anchor::MAX,
|
||||
Anchor::min_max_range_for_buffer(
|
||||
buffer.read(cx).remote_id(),
|
||||
),
|
||||
Some(telemetry.clone()),
|
||||
cx,
|
||||
);
|
||||
|
|
@ -4743,11 +4747,8 @@ impl AcpThreadView {
|
|||
let buffer = multibuffer.as_singleton();
|
||||
if agent_location.buffer.upgrade() == buffer {
|
||||
let excerpt_id = multibuffer.excerpt_ids().first().cloned();
|
||||
let anchor = editor::Anchor::in_buffer(
|
||||
excerpt_id.unwrap(),
|
||||
buffer.unwrap().read(cx).remote_id(),
|
||||
agent_location.position,
|
||||
);
|
||||
let anchor =
|
||||
editor::Anchor::in_buffer(excerpt_id.unwrap(), agent_location.position);
|
||||
editor.change_selections(Default::default(), window, cx, |selections| {
|
||||
selections.select_anchor_ranges([anchor..anchor]);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ impl AgentDiffPane {
|
|||
|
||||
let diff_hunk_ranges = diff
|
||||
.hunks_intersecting_range(
|
||||
language::Anchor::MIN..language::Anchor::MAX,
|
||||
language::Anchor::min_max_range_for_buffer(snapshot.remote_id()),
|
||||
&snapshot,
|
||||
cx,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -440,7 +440,6 @@ impl InlineAssistant {
|
|||
{
|
||||
let anchor_range = Anchor::range_in_buffer(
|
||||
excerpt_id,
|
||||
buffer.remote_id(),
|
||||
buffer.anchor_before(buffer_range.start)..buffer.anchor_after(buffer_range.end),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -797,7 +797,7 @@ impl TextThread {
|
|||
});
|
||||
let message = MessageAnchor {
|
||||
id: first_message_id,
|
||||
start: language::Anchor::MIN,
|
||||
start: language::Anchor::min_for_buffer(this.buffer.read(cx).remote_id()),
|
||||
};
|
||||
this.messages_metadata.insert(
|
||||
first_message_id,
|
||||
|
|
@ -1147,12 +1147,10 @@ impl TextThread {
|
|||
cx: &App,
|
||||
) -> bool {
|
||||
let version = &self.buffer.read(cx).version;
|
||||
let observed_start = range.start == language::Anchor::MIN
|
||||
|| range.start == language::Anchor::MAX
|
||||
|| version.observed(range.start.timestamp);
|
||||
let observed_end = range.end == language::Anchor::MIN
|
||||
|| range.end == language::Anchor::MAX
|
||||
|| version.observed(range.end.timestamp);
|
||||
let observed_start =
|
||||
range.start.is_min() || range.start.is_max() || version.observed(range.start.timestamp);
|
||||
let observed_end =
|
||||
range.end.is_min() || range.end.is_max() || version.observed(range.end.timestamp);
|
||||
observed_start && observed_end
|
||||
}
|
||||
|
||||
|
|
@ -2858,7 +2856,8 @@ impl TextThread {
|
|||
messages.next();
|
||||
}
|
||||
}
|
||||
let message_end_anchor = message_end.unwrap_or(language::Anchor::MAX);
|
||||
let message_end_anchor =
|
||||
message_end.unwrap_or(language::Anchor::max_for_buffer(buffer.remote_id()));
|
||||
let message_end = message_end_anchor.to_offset(buffer);
|
||||
|
||||
return Some(Message {
|
||||
|
|
|
|||
|
|
@ -153,6 +153,10 @@ impl std::fmt::Debug for BufferDiffInner {
|
|||
}
|
||||
|
||||
impl BufferDiffSnapshot {
|
||||
pub fn buffer_diff_id(&self) -> BufferId {
|
||||
self.inner.base_text.remote_id()
|
||||
}
|
||||
|
||||
fn empty(buffer: &text::BufferSnapshot, cx: &mut App) -> BufferDiffSnapshot {
|
||||
BufferDiffSnapshot {
|
||||
inner: BufferDiffInner {
|
||||
|
|
@ -340,7 +344,7 @@ impl BufferDiffInner {
|
|||
};
|
||||
|
||||
let hunk = PendingHunk {
|
||||
buffer_range: Anchor::MIN..Anchor::MAX,
|
||||
buffer_range: Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
diff_base_byte_range: 0..index_text.map_or(0, |rope| rope.len()),
|
||||
buffer_version: buffer.version().clone(),
|
||||
new_status,
|
||||
|
|
@ -780,7 +784,7 @@ fn compute_hunks(
|
|||
} else {
|
||||
tree.push(
|
||||
InternalDiffHunk {
|
||||
buffer_range: Anchor::MIN..Anchor::MAX,
|
||||
buffer_range: Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
diff_base_byte_range: 0..0,
|
||||
},
|
||||
&buffer,
|
||||
|
|
@ -941,10 +945,10 @@ impl BufferDiff {
|
|||
pub fn clear_pending_hunks(&mut self, cx: &mut Context<Self>) {
|
||||
if self.secondary_diff.is_some() {
|
||||
self.inner.pending_hunks = SumTree::from_summary(DiffHunkSummary {
|
||||
buffer_range: Anchor::MIN..Anchor::MIN,
|
||||
buffer_range: Anchor::min_min_range_for_buffer(self.buffer_id),
|
||||
});
|
||||
cx.emit(BufferDiffEvent::DiffChanged {
|
||||
changed_range: Some(Anchor::MIN..Anchor::MAX),
|
||||
changed_range: Some(Anchor::min_max_range_for_buffer(self.buffer_id)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1065,7 +1069,10 @@ impl BufferDiff {
|
|||
{
|
||||
(false, new_state.compare(state, buffer))
|
||||
}
|
||||
_ => (true, Some(text::Anchor::MIN..text::Anchor::MAX)),
|
||||
_ => (
|
||||
true,
|
||||
Some(text::Anchor::min_max_range_for_buffer(self.buffer_id)),
|
||||
),
|
||||
};
|
||||
|
||||
if let Some(secondary_changed_range) = secondary_diff_change
|
||||
|
|
@ -1126,7 +1133,11 @@ impl BufferDiff {
|
|||
buffer_snapshot: &'a text::BufferSnapshot,
|
||||
cx: &'a App,
|
||||
) -> impl 'a + Iterator<Item = DiffHunk> {
|
||||
self.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, buffer_snapshot, cx)
|
||||
self.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(buffer_snapshot.remote_id()),
|
||||
buffer_snapshot,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn hunks_intersecting_range<'a>(
|
||||
|
|
@ -1222,7 +1233,9 @@ impl BufferDiff {
|
|||
|
||||
impl DiffHunk {
|
||||
pub fn is_created_file(&self) -> bool {
|
||||
self.diff_base_byte_range == (0..0) && self.buffer_range == (Anchor::MIN..Anchor::MAX)
|
||||
self.diff_base_byte_range == (0..0)
|
||||
&& self.buffer_range.start.is_min()
|
||||
&& self.buffer_range.end.is_min()
|
||||
}
|
||||
|
||||
pub fn status(&self) -> DiffHunkStatus {
|
||||
|
|
@ -1389,7 +1402,10 @@ mod tests {
|
|||
let mut buffer = Buffer::new(ReplicaId::LOCAL, BufferId::new(1).unwrap(), buffer_text);
|
||||
let mut diff = BufferDiffSnapshot::new_sync(buffer.clone(), diff_base.clone(), cx);
|
||||
assert_hunks(
|
||||
diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &buffer),
|
||||
diff.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
&buffer,
|
||||
),
|
||||
&buffer,
|
||||
&diff_base,
|
||||
&[(1..2, "two\n", "HELLO\n", DiffHunkStatus::modified_none())],
|
||||
|
|
@ -1398,7 +1414,10 @@ mod tests {
|
|||
buffer.edit([(0..0, "point five\n")]);
|
||||
diff = BufferDiffSnapshot::new_sync(buffer.clone(), diff_base.clone(), cx);
|
||||
assert_hunks(
|
||||
diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &buffer),
|
||||
diff.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
&buffer,
|
||||
),
|
||||
&buffer,
|
||||
&diff_base,
|
||||
&[
|
||||
|
|
@ -1409,7 +1428,10 @@ mod tests {
|
|||
|
||||
diff = cx.update(|cx| BufferDiffSnapshot::empty(&buffer, cx));
|
||||
assert_hunks::<&str, _>(
|
||||
diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &buffer),
|
||||
diff.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
&buffer,
|
||||
),
|
||||
&buffer,
|
||||
&diff_base,
|
||||
&[],
|
||||
|
|
@ -1483,7 +1505,10 @@ mod tests {
|
|||
];
|
||||
|
||||
assert_hunks(
|
||||
uncommitted_diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &buffer),
|
||||
uncommitted_diff.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
&buffer,
|
||||
),
|
||||
&buffer,
|
||||
&head_text,
|
||||
&expected_hunks,
|
||||
|
|
@ -1542,8 +1567,11 @@ mod tests {
|
|||
})
|
||||
.await;
|
||||
assert_eq!(
|
||||
diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &buffer)
|
||||
.count(),
|
||||
diff.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
&buffer
|
||||
)
|
||||
.count(),
|
||||
8
|
||||
);
|
||||
|
||||
|
|
@ -2155,8 +2183,12 @@ mod tests {
|
|||
|
||||
let mut diff = uncommitted_diff(&working_copy, &index_text, head_text.clone(), cx);
|
||||
let mut hunks = diff.update(cx, |diff, cx| {
|
||||
diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &working_copy, cx)
|
||||
.collect::<Vec<_>>()
|
||||
diff.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(diff.buffer_id),
|
||||
&working_copy,
|
||||
cx,
|
||||
)
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
if hunks.is_empty() {
|
||||
return;
|
||||
|
|
@ -2185,8 +2217,12 @@ mod tests {
|
|||
|
||||
diff = uncommitted_diff(&working_copy, &index_text, head_text.clone(), cx);
|
||||
let found_hunks = diff.update(cx, |diff, cx| {
|
||||
diff.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &working_copy, cx)
|
||||
.collect::<Vec<_>>()
|
||||
diff.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(diff.buffer_id),
|
||||
&working_copy,
|
||||
cx,
|
||||
)
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
assert_eq!(hunks.len(), found_hunks.len());
|
||||
|
||||
|
|
|
|||
|
|
@ -1581,7 +1581,10 @@ async fn test_share_project(
|
|||
buffer_a.read_with(cx_a, |buffer, _| {
|
||||
buffer
|
||||
.snapshot()
|
||||
.selections_in_range(text::Anchor::MIN..text::Anchor::MAX, false)
|
||||
.selections_in_range(
|
||||
text::Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
false,
|
||||
)
|
||||
.count()
|
||||
== 1
|
||||
});
|
||||
|
|
@ -1622,7 +1625,10 @@ async fn test_share_project(
|
|||
buffer_a.read_with(cx_a, |buffer, _| {
|
||||
buffer
|
||||
.snapshot()
|
||||
.selections_in_range(text::Anchor::MIN..text::Anchor::MAX, false)
|
||||
.selections_in_range(
|
||||
text::Anchor::min_max_range_for_buffer(buffer.remote_id()),
|
||||
false,
|
||||
)
|
||||
.count()
|
||||
== 0
|
||||
});
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ impl DiagnosticBlock {
|
|||
if range.context.overlaps(&diagnostic.range, &snapshot) {
|
||||
Self::jump_to(
|
||||
editor,
|
||||
Anchor::range_in_buffer(excerpt_id, buffer_id, diagnostic.range),
|
||||
Anchor::range_in_buffer(excerpt_id, diagnostic.range),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ impl ProjectDiagnosticsEditor {
|
|||
.selections
|
||||
.all_anchors(&snapshot)
|
||||
.iter()
|
||||
.filter_map(|anchor| anchor.start.buffer_id)
|
||||
.filter_map(|anchor| anchor.start.text_anchor.buffer_id)
|
||||
.collect::<HashSet<_>>()
|
||||
});
|
||||
for buffer_id in buffer_ids {
|
||||
|
|
|
|||
|
|
@ -2976,7 +2976,7 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[gpui::test(iterations = 100)]
|
||||
#[gpui::test(iterations = 60)]
|
||||
fn test_random_blocks(cx: &mut gpui::TestAppContext, mut rng: StdRng) {
|
||||
cx.update(init_test);
|
||||
|
||||
|
|
|
|||
|
|
@ -1780,7 +1780,7 @@ impl Editor {
|
|||
let start_row = (multi_buffer_visible_start.row).min(max_row);
|
||||
let end_row = (multi_buffer_visible_start.row + 10).min(max_row);
|
||||
|
||||
if let Some((excerpt_id, buffer_id, buffer)) = multi_buffer.read(cx).as_singleton() {
|
||||
if let Some((excerpt_id, _, buffer)) = multi_buffer.read(cx).as_singleton() {
|
||||
let outline_items = buffer
|
||||
.outline_items_containing(
|
||||
Point::new(start_row, 0)..Point::new(end_row, 0),
|
||||
|
|
@ -1790,10 +1790,9 @@ impl Editor {
|
|||
.into_iter()
|
||||
.map(|outline_item| OutlineItem {
|
||||
depth: outline_item.depth,
|
||||
range: Anchor::range_in_buffer(*excerpt_id, buffer_id, outline_item.range),
|
||||
range: Anchor::range_in_buffer(*excerpt_id, outline_item.range),
|
||||
source_range_for_text: Anchor::range_in_buffer(
|
||||
*excerpt_id,
|
||||
buffer_id,
|
||||
outline_item.source_range_for_text,
|
||||
),
|
||||
text: outline_item.text,
|
||||
|
|
@ -1801,10 +1800,10 @@ impl Editor {
|
|||
name_ranges: outline_item.name_ranges,
|
||||
body_range: outline_item
|
||||
.body_range
|
||||
.map(|range| Anchor::range_in_buffer(*excerpt_id, buffer_id, range)),
|
||||
.map(|range| Anchor::range_in_buffer(*excerpt_id, range)),
|
||||
annotation_range: outline_item
|
||||
.annotation_range
|
||||
.map(|range| Anchor::range_in_buffer(*excerpt_id, buffer_id, range)),
|
||||
.map(|range| Anchor::range_in_buffer(*excerpt_id, range)),
|
||||
});
|
||||
return Some(outline_items.collect());
|
||||
}
|
||||
|
|
@ -3259,7 +3258,7 @@ impl Editor {
|
|||
}
|
||||
|
||||
if local {
|
||||
if let Some(buffer_id) = new_cursor_position.buffer_id {
|
||||
if let Some(buffer_id) = new_cursor_position.text_anchor.buffer_id {
|
||||
self.register_buffer(buffer_id, cx);
|
||||
}
|
||||
|
||||
|
|
@ -4198,8 +4197,8 @@ impl Editor {
|
|||
continue;
|
||||
}
|
||||
if self.selections.disjoint_anchor_ranges().any(|s| {
|
||||
if s.start.buffer_id != selection.start.buffer_id
|
||||
|| s.end.buffer_id != selection.end.buffer_id
|
||||
if s.start.text_anchor.buffer_id != selection.start.buffer_id
|
||||
|| s.end.text_anchor.buffer_id != selection.end.buffer_id
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -5484,6 +5483,7 @@ impl Editor {
|
|||
}
|
||||
let buffer_position = multibuffer_snapshot.anchor_before(position);
|
||||
let Some(buffer) = buffer_position
|
||||
.text_anchor
|
||||
.buffer_id
|
||||
.and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
|
||||
else {
|
||||
|
|
@ -6923,8 +6923,7 @@ impl Editor {
|
|||
continue;
|
||||
}
|
||||
|
||||
let range =
|
||||
Anchor::range_in_buffer(excerpt_id, buffer_id, *start..*end);
|
||||
let range = Anchor::range_in_buffer(excerpt_id, *start..*end);
|
||||
if highlight.kind == lsp::DocumentHighlightKind::WRITE {
|
||||
write_ranges.push(range);
|
||||
} else {
|
||||
|
|
@ -7033,11 +7032,8 @@ impl Editor {
|
|||
.anchor_after(search_range.start + match_range.start);
|
||||
let match_end = buffer_snapshot
|
||||
.anchor_before(search_range.start + match_range.end);
|
||||
let match_anchor_range = Anchor::range_in_buffer(
|
||||
excerpt_id,
|
||||
buffer_snapshot.remote_id(),
|
||||
match_start..match_end,
|
||||
);
|
||||
let match_anchor_range =
|
||||
Anchor::range_in_buffer(excerpt_id, match_start..match_end);
|
||||
(match_anchor_range != query_range).then_some(match_anchor_range)
|
||||
}),
|
||||
);
|
||||
|
|
@ -8212,8 +8208,7 @@ impl Editor {
|
|||
cx,
|
||||
);
|
||||
for (breakpoint, state) in breakpoints {
|
||||
let multi_buffer_anchor =
|
||||
Anchor::in_buffer(excerpt_id, buffer_snapshot.remote_id(), breakpoint.position);
|
||||
let multi_buffer_anchor = Anchor::in_buffer(excerpt_id, breakpoint.position);
|
||||
let position = multi_buffer_anchor
|
||||
.to_point(&multi_buffer_snapshot)
|
||||
.to_display_point(&snapshot);
|
||||
|
|
@ -20804,8 +20799,7 @@ impl Editor {
|
|||
let start = highlight.range.start.to_display_point(&snapshot);
|
||||
let end = highlight.range.end.to_display_point(&snapshot);
|
||||
let start_row = start.row().0;
|
||||
let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
|
||||
&& end.column() == 0
|
||||
let end_row = if !highlight.range.end.text_anchor.is_max() && end.column() == 0
|
||||
{
|
||||
end.row().0.saturating_sub(1)
|
||||
} else {
|
||||
|
|
@ -21361,7 +21355,7 @@ impl Editor {
|
|||
.for_each(|hint| {
|
||||
let inlay = Inlay::debugger(
|
||||
post_inc(&mut editor.next_inlay_id),
|
||||
Anchor::in_buffer(excerpt_id, buffer_id, hint.position),
|
||||
Anchor::in_buffer(excerpt_id, hint.position),
|
||||
hint.text(),
|
||||
);
|
||||
if !inlay.text().chars().contains(&'\n') {
|
||||
|
|
@ -24105,7 +24099,6 @@ impl EditorSnapshot {
|
|||
display_row_range: hunk_display_start.row()..end_row,
|
||||
multi_buffer_range: Anchor::range_in_buffer(
|
||||
hunk.excerpt_id,
|
||||
hunk.buffer_id,
|
||||
hunk.buffer_range,
|
||||
),
|
||||
is_created_file,
|
||||
|
|
|
|||
|
|
@ -21550,10 +21550,9 @@ async fn test_adjacent_diff_hunks(executor: BackgroundExecutor, cx: &mut TestApp
|
|||
.diff_hunks_in_ranges(&[Anchor::min()..Anchor::max()], &snapshot.buffer_snapshot())
|
||||
.collect::<Vec<_>>();
|
||||
let excerpt_id = editor.buffer.read(cx).excerpt_ids()[0];
|
||||
let buffer_id = hunks[0].buffer_id;
|
||||
hunks
|
||||
.into_iter()
|
||||
.map(|hunk| Anchor::range_in_buffer(excerpt_id, buffer_id, hunk.buffer_range))
|
||||
.map(|hunk| Anchor::range_in_buffer(excerpt_id, hunk.buffer_range))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
assert_eq!(hunk_ranges.len(), 2);
|
||||
|
|
@ -21641,10 +21640,9 @@ async fn test_adjacent_diff_hunks(executor: BackgroundExecutor, cx: &mut TestApp
|
|||
.diff_hunks_in_ranges(&[Anchor::min()..Anchor::max()], &snapshot.buffer_snapshot())
|
||||
.collect::<Vec<_>>();
|
||||
let excerpt_id = editor.buffer.read(cx).excerpt_ids()[0];
|
||||
let buffer_id = hunks[0].buffer_id;
|
||||
hunks
|
||||
.into_iter()
|
||||
.map(|hunk| Anchor::range_in_buffer(excerpt_id, buffer_id, hunk.buffer_range))
|
||||
.map(|hunk| Anchor::range_in_buffer(excerpt_id, hunk.buffer_range))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
assert_eq!(hunk_ranges.len(), 2);
|
||||
|
|
@ -21707,10 +21705,9 @@ async fn test_toggle_deletion_hunk_at_start_of_file(
|
|||
.diff_hunks_in_ranges(&[Anchor::min()..Anchor::max()], &snapshot.buffer_snapshot())
|
||||
.collect::<Vec<_>>();
|
||||
let excerpt_id = editor.buffer.read(cx).excerpt_ids()[0];
|
||||
let buffer_id = hunks[0].buffer_id;
|
||||
hunks
|
||||
.into_iter()
|
||||
.map(|hunk| Anchor::range_in_buffer(excerpt_id, buffer_id, hunk.buffer_range))
|
||||
.map(|hunk| Anchor::range_in_buffer(excerpt_id, hunk.buffer_range))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
assert_eq!(hunk_ranges.len(), 1);
|
||||
|
|
|
|||
|
|
@ -9283,7 +9283,7 @@ impl Element for EditorElement {
|
|||
HashMap::default();
|
||||
for selection in all_anchor_selections.iter() {
|
||||
let head = selection.head();
|
||||
if let Some(buffer_id) = head.buffer_id {
|
||||
if let Some(buffer_id) = head.text_anchor.buffer_id {
|
||||
anchors_by_buffer
|
||||
.entry(buffer_id)
|
||||
.and_modify(|(latest_id, latest_anchor)| {
|
||||
|
|
|
|||
|
|
@ -584,8 +584,11 @@ impl Editor {
|
|||
})
|
||||
.max_by_key(|hint| hint.id)
|
||||
{
|
||||
if let Some(ResolvedHint::Resolved(cached_hint)) =
|
||||
hovered_hint.position.buffer_id.and_then(|buffer_id| {
|
||||
if let Some(ResolvedHint::Resolved(cached_hint)) = hovered_hint
|
||||
.position
|
||||
.text_anchor
|
||||
.buffer_id
|
||||
.and_then(|buffer_id| {
|
||||
lsp_store.update(cx, |lsp_store, cx| {
|
||||
lsp_store.resolved_hint(buffer_id, hovered_hint.id, cx)
|
||||
})
|
||||
|
|
@ -757,7 +760,7 @@ impl Editor {
|
|||
let visible_inlay_hint_ids = self
|
||||
.visible_inlay_hints(cx)
|
||||
.iter()
|
||||
.filter(|inlay| inlay.position.buffer_id == Some(buffer_id))
|
||||
.filter(|inlay| inlay.position.text_anchor.buffer_id == Some(buffer_id))
|
||||
.map(|inlay| inlay.id)
|
||||
.collect::<Vec<_>>();
|
||||
let Some(inlay_hints) = &mut self.inlay_hints else {
|
||||
|
|
@ -858,9 +861,13 @@ impl Editor {
|
|||
self.visible_inlay_hints(cx)
|
||||
.iter()
|
||||
.filter(|inlay| {
|
||||
inlay.position.buffer_id.is_none_or(|buffer_id| {
|
||||
invalidate_hints_for_buffers.contains(&buffer_id)
|
||||
})
|
||||
inlay
|
||||
.position
|
||||
.text_anchor
|
||||
.buffer_id
|
||||
.is_none_or(|buffer_id| {
|
||||
invalidate_hints_for_buffers.contains(&buffer_id)
|
||||
})
|
||||
})
|
||||
.map(|inlay| inlay.id),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -455,21 +455,13 @@ async fn update_editor_from_message(
|
|||
})??;
|
||||
|
||||
// Deserialize the editor state.
|
||||
let (selections, pending_selection, scroll_top_anchor) = this.update(cx, |editor, cx| {
|
||||
let buffer = editor.buffer.read(cx).read(cx);
|
||||
let selections = message
|
||||
.selections
|
||||
.into_iter()
|
||||
.filter_map(|selection| deserialize_selection(&buffer, selection))
|
||||
.collect::<Vec<_>>();
|
||||
let pending_selection = message
|
||||
.pending_selection
|
||||
.and_then(|selection| deserialize_selection(&buffer, selection));
|
||||
let scroll_top_anchor = message
|
||||
.scroll_top_anchor
|
||||
.and_then(|anchor| deserialize_anchor(&buffer, anchor));
|
||||
anyhow::Ok((selections, pending_selection, scroll_top_anchor))
|
||||
})??;
|
||||
let selections = message
|
||||
.selections
|
||||
.into_iter()
|
||||
.filter_map(deserialize_selection)
|
||||
.collect::<Vec<_>>();
|
||||
let pending_selection = message.pending_selection.and_then(deserialize_selection);
|
||||
let scroll_top_anchor = message.scroll_top_anchor.and_then(deserialize_anchor);
|
||||
|
||||
// Wait until the buffer has received all of the operations referenced by
|
||||
// the editor's new state.
|
||||
|
|
@ -563,24 +555,20 @@ fn deserialize_excerpt_range(
|
|||
))
|
||||
}
|
||||
|
||||
fn deserialize_selection(
|
||||
buffer: &MultiBufferSnapshot,
|
||||
selection: proto::Selection,
|
||||
) -> Option<Selection<Anchor>> {
|
||||
fn deserialize_selection(selection: proto::Selection) -> Option<Selection<Anchor>> {
|
||||
Some(Selection {
|
||||
id: selection.id as usize,
|
||||
start: deserialize_anchor(buffer, selection.start?)?,
|
||||
end: deserialize_anchor(buffer, selection.end?)?,
|
||||
start: deserialize_anchor(selection.start?)?,
|
||||
end: deserialize_anchor(selection.end?)?,
|
||||
reversed: selection.reversed,
|
||||
goal: SelectionGoal::None,
|
||||
})
|
||||
}
|
||||
|
||||
fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor) -> Option<Anchor> {
|
||||
fn deserialize_anchor(anchor: proto::EditorAnchor) -> Option<Anchor> {
|
||||
let excerpt_id = ExcerptId::from_proto(anchor.excerpt_id);
|
||||
Some(Anchor::in_buffer(
|
||||
excerpt_id,
|
||||
buffer.buffer_id_for_excerpt(excerpt_id)?,
|
||||
language::proto::deserialize_anchor(anchor.anchor?)?,
|
||||
))
|
||||
}
|
||||
|
|
@ -1374,7 +1362,7 @@ impl ProjectItem for Editor {
|
|||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let mut editor = Self::for_buffer(buffer.clone(), Some(project), window, cx);
|
||||
if let Some((excerpt_id, buffer_id, snapshot)) =
|
||||
if let Some((excerpt_id, _, snapshot)) =
|
||||
editor.buffer().read(cx).snapshot(cx).as_singleton()
|
||||
&& WorkspaceSettings::get(None, cx).restore_on_file_reopen
|
||||
&& let Some(restoration_data) = Self::project_item_kind()
|
||||
|
|
@ -1397,11 +1385,8 @@ impl ProjectItem for Editor {
|
|||
});
|
||||
}
|
||||
let (top_row, offset) = restoration_data.scroll_position;
|
||||
let anchor = Anchor::in_buffer(
|
||||
*excerpt_id,
|
||||
buffer_id,
|
||||
snapshot.anchor_before(Point::new(top_row, 0)),
|
||||
);
|
||||
let anchor =
|
||||
Anchor::in_buffer(*excerpt_id, snapshot.anchor_before(Point::new(top_row, 0)));
|
||||
editor.set_scroll_anchor(ScrollAnchor { anchor, offset }, window, cx);
|
||||
}
|
||||
|
||||
|
|
@ -1783,11 +1768,7 @@ impl SearchableItem for Editor {
|
|||
.anchor_after(search_range.start + match_range.start);
|
||||
let end = search_buffer
|
||||
.anchor_before(search_range.start + match_range.end);
|
||||
Anchor::range_in_buffer(
|
||||
excerpt_id,
|
||||
search_buffer.remote_id(),
|
||||
start..end,
|
||||
)
|
||||
Anchor::range_in_buffer(excerpt_id, start..end)
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ pub(super) fn refresh_linked_ranges(
|
|||
let cursor_position = selection.head();
|
||||
let start_position = snapshot.anchor_before(cursor_position);
|
||||
let end_position = snapshot.anchor_after(selection.tail());
|
||||
if start_position.buffer_id != end_position.buffer_id
|
||||
|| end_position.buffer_id.is_none()
|
||||
if start_position.text_anchor.buffer_id != end_position.text_anchor.buffer_id
|
||||
|| end_position.text_anchor.buffer_id.is_none()
|
||||
{
|
||||
// Throw away selections spanning multiple buffers.
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ where
|
|||
.selections
|
||||
.disjoint_anchors_arc()
|
||||
.iter()
|
||||
.filter_map(|selection| Some((selection.head(), selection.head().buffer_id?)))
|
||||
.filter_map(|selection| Some((selection.head(), selection.head().text_anchor.buffer_id?)))
|
||||
.unique_by(|(_, buffer_id)| *buffer_id)
|
||||
.find_map(|(trigger_anchor, buffer_id)| {
|
||||
let buffer = editor.buffer().read(cx).buffer(buffer_id)?;
|
||||
|
|
|
|||
|
|
@ -322,7 +322,11 @@ fn cancel_flycheck_action(
|
|||
.disjoint_anchors_arc()
|
||||
.iter()
|
||||
.find_map(|selection| {
|
||||
let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?;
|
||||
let buffer_id = selection
|
||||
.start
|
||||
.text_anchor
|
||||
.buffer_id
|
||||
.or(selection.end.text_anchor.buffer_id)?;
|
||||
let project = project.read(cx);
|
||||
let entry_id = project
|
||||
.buffer_for_id(buffer_id, cx)?
|
||||
|
|
@ -347,7 +351,11 @@ fn run_flycheck_action(
|
|||
.disjoint_anchors_arc()
|
||||
.iter()
|
||||
.find_map(|selection| {
|
||||
let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?;
|
||||
let buffer_id = selection
|
||||
.start
|
||||
.text_anchor
|
||||
.buffer_id
|
||||
.or(selection.end.text_anchor.buffer_id)?;
|
||||
let project = project.read(cx);
|
||||
let entry_id = project
|
||||
.buffer_for_id(buffer_id, cx)?
|
||||
|
|
@ -372,7 +380,11 @@ fn clear_flycheck_action(
|
|||
.disjoint_anchors_arc()
|
||||
.iter()
|
||||
.find_map(|selection| {
|
||||
let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?;
|
||||
let buffer_id = selection
|
||||
.start
|
||||
.text_anchor
|
||||
.buffer_id
|
||||
.or(selection.end.text_anchor.buffer_id)?;
|
||||
let project = project.read(cx);
|
||||
let entry_id = project
|
||||
.buffer_for_id(buffer_id, cx)?
|
||||
|
|
|
|||
|
|
@ -490,11 +490,7 @@ impl EditorTestContext {
|
|||
);
|
||||
assert_eq!(
|
||||
multibuffer_snapshot
|
||||
.text_for_range(Anchor::range_in_buffer(
|
||||
excerpt_id,
|
||||
snapshot.remote_id(),
|
||||
range.context.clone()
|
||||
))
|
||||
.text_for_range(Anchor::range_in_buffer(excerpt_id, range.context.clone()))
|
||||
.collect::<String>(),
|
||||
expected_text,
|
||||
"{}",
|
||||
|
|
@ -675,11 +671,7 @@ impl std::fmt::Display for FormatMultiBufferAsMarkedText {
|
|||
}
|
||||
|
||||
let mut text = multibuffer_snapshot
|
||||
.text_for_range(Anchor::range_in_buffer(
|
||||
*excerpt_id,
|
||||
snapshot.remote_id(),
|
||||
range.context.clone(),
|
||||
))
|
||||
.text_for_range(Anchor::range_in_buffer(*excerpt_id, range.context.clone()))
|
||||
.collect::<String>();
|
||||
|
||||
let selections = selections
|
||||
|
|
|
|||
|
|
@ -223,7 +223,11 @@ impl CommitView {
|
|||
let snapshot = buffer.read(cx).snapshot();
|
||||
let diff = buffer_diff.read(cx);
|
||||
let diff_hunk_ranges = diff
|
||||
.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &snapshot, cx)
|
||||
.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(diff.buffer_id),
|
||||
&snapshot,
|
||||
cx,
|
||||
)
|
||||
.map(|diff_hunk| diff_hunk.buffer_range.to_point(&snapshot))
|
||||
.collect::<Vec<_>>();
|
||||
let path = snapshot.file().unwrap().path().clone();
|
||||
|
|
|
|||
|
|
@ -383,12 +383,8 @@ impl ProjectDiff {
|
|||
.collect::<Vec<_>>();
|
||||
if !ranges.iter().any(|range| range.start != range.end) {
|
||||
selection = false;
|
||||
if let Some((excerpt_id, buffer, range)) = self.editor.read(cx).active_excerpt(cx) {
|
||||
ranges = vec![multi_buffer::Anchor::range_in_buffer(
|
||||
excerpt_id,
|
||||
buffer.read(cx).remote_id(),
|
||||
range,
|
||||
)];
|
||||
if let Some((excerpt_id, _, range)) = self.editor.read(cx).active_excerpt(cx) {
|
||||
ranges = vec![multi_buffer::Anchor::range_in_buffer(excerpt_id, range)];
|
||||
} else {
|
||||
ranges = Vec::default();
|
||||
}
|
||||
|
|
@ -488,7 +484,11 @@ impl ProjectDiff {
|
|||
let snapshot = buffer.read(cx).snapshot();
|
||||
let diff_read = diff.read(cx);
|
||||
let diff_hunk_ranges = diff_read
|
||||
.hunks_intersecting_range(Anchor::MIN..Anchor::MAX, &snapshot, cx)
|
||||
.hunks_intersecting_range(
|
||||
Anchor::min_max_range_for_buffer(diff_read.buffer_id),
|
||||
&snapshot,
|
||||
cx,
|
||||
)
|
||||
.map(|diff_hunk| diff_hunk.buffer_range);
|
||||
let conflicts = conflict_addon
|
||||
.conflict_set(snapshot.remote_id())
|
||||
|
|
|
|||
|
|
@ -3427,7 +3427,7 @@ fn test_random_collaboration(cx: &mut App, mut rng: StdRng) {
|
|||
for buffer in &buffers {
|
||||
let buffer = buffer.read(cx).snapshot();
|
||||
let actual_remote_selections = buffer
|
||||
.selections_in_range(Anchor::MIN..Anchor::MAX, false)
|
||||
.selections_in_range(Anchor::min_max_range_for_buffer(buffer.remote_id()), false)
|
||||
.map(|(replica_id, _, _, selections)| (replica_id, selections.collect::<Vec<_>>()))
|
||||
.collect::<Vec<_>>();
|
||||
let expected_remote_selections = active_selections
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ impl SyntaxSnapshot {
|
|||
let slice = cursor.slice(
|
||||
&SyntaxLayerPosition {
|
||||
depth: depth + 1,
|
||||
range: Anchor::MIN..Anchor::MAX,
|
||||
range: Anchor::min_max_range_for_buffer(text.remote_id()),
|
||||
language: None,
|
||||
},
|
||||
Bias::Left,
|
||||
|
|
@ -493,7 +493,7 @@ impl SyntaxSnapshot {
|
|||
start_point: Point::zero().to_ts_point(),
|
||||
end_point: text.max_point().to_ts_point(),
|
||||
}],
|
||||
range: Anchor::MIN..Anchor::MAX,
|
||||
range: Anchor::min_max_range_for_buffer(text.remote_id()),
|
||||
mode: ParseMode::Single,
|
||||
});
|
||||
|
||||
|
|
@ -515,7 +515,7 @@ impl SyntaxSnapshot {
|
|||
} else {
|
||||
SyntaxLayerPosition {
|
||||
depth: max_depth + 1,
|
||||
range: Anchor::MAX..Anchor::MAX,
|
||||
range: Anchor::min_max_range_for_buffer(text.remote_id()),
|
||||
language: None,
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,12 +7,9 @@ use std::{
|
|||
ops::{AddAssign, Range, Sub},
|
||||
};
|
||||
use sum_tree::Bias;
|
||||
use text::BufferId;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct Anchor {
|
||||
/// Invariant: If buffer id is `None`, excerpt id must be `ExcerptId::min()` or `ExcerptId::max()`.
|
||||
pub buffer_id: Option<BufferId>,
|
||||
pub excerpt_id: ExcerptId,
|
||||
pub text_anchor: text::Anchor,
|
||||
pub diff_base_anchor: Option<text::Anchor>,
|
||||
|
|
@ -20,15 +17,14 @@ pub struct Anchor {
|
|||
|
||||
impl std::fmt::Debug for Anchor {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if *self == Self::min() {
|
||||
return f.write_str("Anchor::MIN");
|
||||
if self.is_min() {
|
||||
return write!(f, "Anchor::min({:?})", self.text_anchor.buffer_id);
|
||||
}
|
||||
if *self == Self::max() {
|
||||
return f.write_str("Anchor::MAX");
|
||||
if self.is_max() {
|
||||
return write!(f, "Anchor::max({:?})", self.text_anchor.buffer_id);
|
||||
}
|
||||
|
||||
f.debug_struct("Anchor")
|
||||
.field("buffer_id", &self.buffer_id)
|
||||
.field("excerpt_id", &self.excerpt_id)
|
||||
.field("text_anchor", &self.text_anchor)
|
||||
.field("diff_base_anchor", &self.diff_base_anchor)
|
||||
|
|
@ -44,35 +40,20 @@ impl Anchor {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn in_buffer(
|
||||
excerpt_id: ExcerptId,
|
||||
buffer_id: BufferId,
|
||||
text_anchor: text::Anchor,
|
||||
) -> Self {
|
||||
debug_assert!(
|
||||
text_anchor.buffer_id.is_none_or(|id| id == buffer_id),
|
||||
"buffer id does not match the one in the text anchor: {buffer_id:?} {text_anchor:?}",
|
||||
);
|
||||
pub fn in_buffer(excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Self {
|
||||
Self {
|
||||
buffer_id: Some(buffer_id),
|
||||
excerpt_id,
|
||||
text_anchor,
|
||||
diff_base_anchor: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn range_in_buffer(
|
||||
excerpt_id: ExcerptId,
|
||||
buffer_id: BufferId,
|
||||
range: Range<text::Anchor>,
|
||||
) -> Range<Self> {
|
||||
Self::in_buffer(excerpt_id, buffer_id, range.start)
|
||||
..Self::in_buffer(excerpt_id, buffer_id, range.end)
|
||||
pub fn range_in_buffer(excerpt_id: ExcerptId, range: Range<text::Anchor>) -> Range<Self> {
|
||||
Self::in_buffer(excerpt_id, range.start)..Self::in_buffer(excerpt_id, range.end)
|
||||
}
|
||||
|
||||
pub fn min() -> Self {
|
||||
Self {
|
||||
buffer_id: None,
|
||||
excerpt_id: ExcerptId::min(),
|
||||
text_anchor: text::Anchor::MIN,
|
||||
diff_base_anchor: None,
|
||||
|
|
@ -81,13 +62,24 @@ impl Anchor {
|
|||
|
||||
pub fn max() -> Self {
|
||||
Self {
|
||||
buffer_id: None,
|
||||
excerpt_id: ExcerptId::max(),
|
||||
text_anchor: text::Anchor::MAX,
|
||||
diff_base_anchor: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_min(&self) -> bool {
|
||||
self.excerpt_id == ExcerptId::min()
|
||||
&& self.text_anchor.is_min()
|
||||
&& self.diff_base_anchor.is_none()
|
||||
}
|
||||
|
||||
pub fn is_max(&self) -> bool {
|
||||
self.excerpt_id == ExcerptId::max()
|
||||
&& self.text_anchor.is_max()
|
||||
&& self.diff_base_anchor.is_none()
|
||||
}
|
||||
|
||||
pub fn cmp(&self, other: &Anchor, snapshot: &MultiBufferSnapshot) -> Ordering {
|
||||
if self == other {
|
||||
return Ordering::Equal;
|
||||
|
|
@ -101,8 +93,8 @@ impl Anchor {
|
|||
return excerpt_id_cmp;
|
||||
}
|
||||
if self_excerpt_id == ExcerptId::max()
|
||||
&& self.text_anchor == text::Anchor::MAX
|
||||
&& self.text_anchor == text::Anchor::MAX
|
||||
&& self.text_anchor.is_max()
|
||||
&& self.text_anchor.is_max()
|
||||
&& self.diff_base_anchor.is_none()
|
||||
&& other.diff_base_anchor.is_none()
|
||||
{
|
||||
|
|
@ -147,7 +139,6 @@ impl Anchor {
|
|||
&& let Some(excerpt) = snapshot.excerpt(self.excerpt_id)
|
||||
{
|
||||
return Self {
|
||||
buffer_id: Some(excerpt.buffer_id),
|
||||
excerpt_id: excerpt.id,
|
||||
text_anchor: self.text_anchor.bias_left(&excerpt.buffer),
|
||||
diff_base_anchor: self.diff_base_anchor.map(|a| {
|
||||
|
|
@ -171,7 +162,6 @@ impl Anchor {
|
|||
&& let Some(excerpt) = snapshot.excerpt(self.excerpt_id)
|
||||
{
|
||||
return Self {
|
||||
buffer_id: Some(excerpt.buffer_id),
|
||||
excerpt_id: excerpt.id,
|
||||
text_anchor: self.text_anchor.bias_right(&excerpt.buffer),
|
||||
diff_base_anchor: self.diff_base_anchor.map(|a| {
|
||||
|
|
@ -202,8 +192,8 @@ impl Anchor {
|
|||
}
|
||||
|
||||
pub fn is_valid(&self, snapshot: &MultiBufferSnapshot) -> bool {
|
||||
if *self == Anchor::min() || self.excerpt_id == ExcerptId::max() {
|
||||
!snapshot.is_empty()
|
||||
if self.is_min() || self.is_max() {
|
||||
true
|
||||
} else if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) {
|
||||
(self.text_anchor == excerpt.range.context.start
|
||||
|| self.text_anchor == excerpt.range.context.end
|
||||
|
|
|
|||
|
|
@ -158,12 +158,13 @@ impl MultiBufferDiffHunk {
|
|||
|
||||
pub fn is_created_file(&self) -> bool {
|
||||
self.diff_base_byte_range == (BufferOffset(0)..BufferOffset(0))
|
||||
&& self.buffer_range == (text::Anchor::MIN..text::Anchor::MAX)
|
||||
&& self.buffer_range.start.is_min()
|
||||
&& self.buffer_range.end.is_max()
|
||||
}
|
||||
|
||||
pub fn multi_buffer_range(&self) -> Range<Anchor> {
|
||||
let start = Anchor::in_buffer(self.excerpt_id, self.buffer_id, self.buffer_range.start);
|
||||
let end = Anchor::in_buffer(self.excerpt_id, self.buffer_id, self.buffer_range.end);
|
||||
let start = Anchor::in_buffer(self.excerpt_id, self.buffer_range.start);
|
||||
let end = Anchor::in_buffer(self.excerpt_id, self.buffer_range.end);
|
||||
start..end
|
||||
}
|
||||
}
|
||||
|
|
@ -1028,9 +1029,12 @@ impl MultiBuffer {
|
|||
},
|
||||
);
|
||||
this.singleton = true;
|
||||
let buffer_id = buffer.read(cx).remote_id();
|
||||
this.push_excerpts(
|
||||
buffer,
|
||||
[ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)],
|
||||
[ExcerptRange::new(text::Anchor::min_max_range_for_buffer(
|
||||
buffer_id,
|
||||
))],
|
||||
cx,
|
||||
);
|
||||
this
|
||||
|
|
@ -1912,7 +1916,7 @@ impl MultiBuffer {
|
|||
}
|
||||
|
||||
pub fn buffer_for_anchor(&self, anchor: Anchor, cx: &App) -> Option<Entity<Buffer>> {
|
||||
if let Some(buffer_id) = anchor.buffer_id {
|
||||
if let Some(buffer_id) = anchor.text_anchor.buffer_id {
|
||||
self.buffer(buffer_id)
|
||||
} else {
|
||||
let (_, buffer, _) = self.excerpt_containing(anchor, cx)?;
|
||||
|
|
@ -1975,7 +1979,7 @@ impl MultiBuffer {
|
|||
|
||||
found.map(|(point, excerpt_id)| {
|
||||
let text_anchor = snapshot.anchor_after(point);
|
||||
Anchor::in_buffer(excerpt_id, snapshot.remote_id(), text_anchor)
|
||||
Anchor::in_buffer(excerpt_id, text_anchor)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1990,7 +1994,7 @@ impl MultiBuffer {
|
|||
if range.context.start.cmp(&anchor, &snapshot).is_le()
|
||||
&& range.context.end.cmp(&anchor, &snapshot).is_ge()
|
||||
{
|
||||
return Some(Anchor::in_buffer(excerpt_id, snapshot.remote_id(), anchor));
|
||||
return Some(Anchor::in_buffer(excerpt_id, anchor));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2112,7 +2116,7 @@ impl MultiBuffer {
|
|||
let mut error = None;
|
||||
let mut futures = Vec::new();
|
||||
for anchor in anchors {
|
||||
if let Some(buffer_id) = anchor.buffer_id {
|
||||
if let Some(buffer_id) = anchor.text_anchor.buffer_id {
|
||||
if let Some(buffer) = self.buffers.get(&buffer_id) {
|
||||
buffer.buffer.update(cx, |buffer, _| {
|
||||
futures.push(buffer.wait_for_anchors([anchor.text_anchor]))
|
||||
|
|
@ -2143,7 +2147,11 @@ impl MultiBuffer {
|
|||
) -> Option<(Entity<Buffer>, language::Anchor)> {
|
||||
let snapshot = self.read(cx);
|
||||
let anchor = snapshot.anchor_before(position);
|
||||
let buffer = self.buffers.get(&anchor.buffer_id?)?.buffer.clone();
|
||||
let buffer = self
|
||||
.buffers
|
||||
.get(&anchor.text_anchor.buffer_id?)?
|
||||
.buffer
|
||||
.clone();
|
||||
Some((buffer, anchor.text_anchor))
|
||||
}
|
||||
|
||||
|
|
@ -2205,7 +2213,7 @@ impl MultiBuffer {
|
|||
.get(&buffer_id)
|
||||
.is_none_or(|old_diff| !new_diff.base_texts_eq(old_diff));
|
||||
|
||||
snapshot.diffs.insert(buffer_id, new_diff);
|
||||
snapshot.diffs.insert_or_replace(buffer_id, new_diff);
|
||||
|
||||
let mut excerpt_edits = Vec::new();
|
||||
for locator in &buffer_state.excerpts {
|
||||
|
|
@ -2402,7 +2410,11 @@ impl MultiBuffer {
|
|||
|
||||
pub fn add_diff(&mut self, diff: Entity<BufferDiff>, cx: &mut Context<Self>) {
|
||||
let buffer_id = diff.read(cx).buffer_id;
|
||||
self.buffer_diff_changed(diff.clone(), text::Anchor::MIN..text::Anchor::MAX, cx);
|
||||
self.buffer_diff_changed(
|
||||
diff.clone(),
|
||||
text::Anchor::min_max_range_for_buffer(buffer_id),
|
||||
cx,
|
||||
);
|
||||
self.diffs.insert(buffer_id, DiffState::new(diff, cx));
|
||||
}
|
||||
|
||||
|
|
@ -2500,16 +2512,8 @@ impl MultiBuffer {
|
|||
if last_hunk_row.is_some_and(|row| row >= diff_hunk.row_range.start) {
|
||||
continue;
|
||||
}
|
||||
let start = Anchor::in_buffer(
|
||||
diff_hunk.excerpt_id,
|
||||
diff_hunk.buffer_id,
|
||||
diff_hunk.buffer_range.start,
|
||||
);
|
||||
let end = Anchor::in_buffer(
|
||||
diff_hunk.excerpt_id,
|
||||
diff_hunk.buffer_id,
|
||||
diff_hunk.buffer_range.end,
|
||||
);
|
||||
let start = Anchor::in_buffer(diff_hunk.excerpt_id, diff_hunk.buffer_range.start);
|
||||
let end = Anchor::in_buffer(diff_hunk.excerpt_id, diff_hunk.buffer_range.end);
|
||||
let start = snapshot.excerpt_offset_for_anchor(&start);
|
||||
let end = snapshot.excerpt_offset_for_anchor(&end);
|
||||
last_hunk_row = Some(diff_hunk.row_range.start);
|
||||
|
|
@ -3945,9 +3949,7 @@ impl MultiBufferSnapshot {
|
|||
if hunk_end >= current_position {
|
||||
continue;
|
||||
}
|
||||
let start =
|
||||
Anchor::in_buffer(excerpt.id, excerpt.buffer_id, hunk.buffer_range.start)
|
||||
.to_point(self);
|
||||
let start = Anchor::in_buffer(excerpt.id, hunk.buffer_range.start).to_point(self);
|
||||
return Some(MultiBufferRow(start.row));
|
||||
}
|
||||
}
|
||||
|
|
@ -3964,8 +3966,7 @@ impl MultiBufferSnapshot {
|
|||
let Some(hunk) = hunks.next() else {
|
||||
continue;
|
||||
};
|
||||
let start = Anchor::in_buffer(excerpt.id, excerpt.buffer_id, hunk.buffer_range.start)
|
||||
.to_point(self);
|
||||
let start = Anchor::in_buffer(excerpt.id, hunk.buffer_range.start).to_point(self);
|
||||
return Some(MultiBufferRow(start.row));
|
||||
}
|
||||
}
|
||||
|
|
@ -4955,7 +4956,7 @@ impl MultiBufferSnapshot {
|
|||
{
|
||||
text_anchor = excerpt.range.context.end;
|
||||
}
|
||||
Anchor::in_buffer(excerpt.id, excerpt.buffer_id, text_anchor)
|
||||
Anchor::in_buffer(excerpt.id, text_anchor)
|
||||
} else if let Some(excerpt) = prev_excerpt {
|
||||
let mut text_anchor = excerpt
|
||||
.range
|
||||
|
|
@ -4968,7 +4969,7 @@ impl MultiBufferSnapshot {
|
|||
{
|
||||
text_anchor = excerpt.range.context.start;
|
||||
}
|
||||
Anchor::in_buffer(excerpt.id, excerpt.buffer_id, text_anchor)
|
||||
Anchor::in_buffer(excerpt.id, text_anchor)
|
||||
} else if anchor.text_anchor.bias == Bias::Left {
|
||||
Anchor::min()
|
||||
} else {
|
||||
|
|
@ -5050,7 +5051,7 @@ impl MultiBufferSnapshot {
|
|||
let buffer_start = excerpt.range.context.start.to_offset(&excerpt.buffer);
|
||||
let text_anchor =
|
||||
excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
|
||||
let anchor = Anchor::in_buffer(excerpt.id, excerpt.buffer_id, text_anchor);
|
||||
let anchor = Anchor::in_buffer(excerpt.id, text_anchor);
|
||||
match diff_base_anchor {
|
||||
Some(diff_base_anchor) => anchor.with_diff_base_anchor(diff_base_anchor),
|
||||
None => anchor,
|
||||
|
|
@ -5066,7 +5067,11 @@ impl MultiBufferSnapshot {
|
|||
/// Wraps the [`text::Anchor`] in a [`multi_buffer::Anchor`] if this multi-buffer is a singleton.
|
||||
pub fn as_singleton_anchor(&self, text_anchor: text::Anchor) -> Option<Anchor> {
|
||||
let (excerpt, buffer, _) = self.as_singleton()?;
|
||||
Some(Anchor::in_buffer(*excerpt, buffer, text_anchor))
|
||||
if text_anchor.buffer_id.is_none_or(|id| id == buffer) {
|
||||
Some(Anchor::in_buffer(*excerpt, text_anchor))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an anchor for the given excerpt and text anchor,
|
||||
|
|
@ -5099,12 +5104,8 @@ impl MultiBufferSnapshot {
|
|||
match text_anchor.buffer_id {
|
||||
Some(buffer_id) if buffer_id == excerpt.buffer_id => (),
|
||||
Some(_) => return None,
|
||||
None if text_anchor == text::Anchor::MAX || text_anchor == text::Anchor::MIN => {
|
||||
return Some(Anchor::in_buffer(
|
||||
excerpt.id,
|
||||
excerpt.buffer_id,
|
||||
text_anchor,
|
||||
));
|
||||
None if text_anchor.is_max() || text_anchor.is_min() => {
|
||||
return Some(Anchor::in_buffer(excerpt.id, text_anchor));
|
||||
}
|
||||
None => return None,
|
||||
}
|
||||
|
|
@ -5116,11 +5117,7 @@ impl MultiBufferSnapshot {
|
|||
return None;
|
||||
}
|
||||
|
||||
Some(Anchor::in_buffer(
|
||||
excerpt.id,
|
||||
excerpt.buffer_id,
|
||||
text_anchor,
|
||||
))
|
||||
Some(Anchor::in_buffer(excerpt.id, text_anchor))
|
||||
}
|
||||
|
||||
pub fn context_range_for_excerpt(&self, excerpt_id: ExcerptId) -> Option<Range<text::Anchor>> {
|
||||
|
|
@ -5128,7 +5125,7 @@ impl MultiBufferSnapshot {
|
|||
}
|
||||
|
||||
pub fn can_resolve(&self, anchor: &Anchor) -> bool {
|
||||
if *anchor == Anchor::min() || anchor.excerpt_id == ExcerptId::max() {
|
||||
if anchor.is_min() || anchor.is_max() {
|
||||
// todo(lw): should be `!self.is_empty()`
|
||||
true
|
||||
} else if let Some(excerpt) = self.excerpt(anchor.excerpt_id) {
|
||||
|
|
@ -5998,7 +5995,7 @@ impl MultiBufferSnapshot {
|
|||
..
|
||||
} = self.excerpt(anchor.excerpt_id)?;
|
||||
if cfg!(debug_assertions) {
|
||||
match anchor.buffer_id {
|
||||
match anchor.text_anchor.buffer_id {
|
||||
// we clearly are hitting this according to sentry, but in what situations can this occur?
|
||||
Some(anchor_buffer_id) => {
|
||||
assert_eq!(
|
||||
|
|
@ -6006,7 +6003,7 @@ impl MultiBufferSnapshot {
|
|||
"anchor {anchor:?} does not match with resolved excerpt {excerpt:?}"
|
||||
)
|
||||
}
|
||||
None => assert_eq!(anchor, Anchor::max()),
|
||||
None => assert!(anchor.is_max()),
|
||||
}
|
||||
};
|
||||
Some((
|
||||
|
|
@ -6019,19 +6016,18 @@ impl MultiBufferSnapshot {
|
|||
depth: item.depth,
|
||||
source_range_for_text: Anchor::range_in_buffer(
|
||||
excerpt_id,
|
||||
buffer_id,
|
||||
item.source_range_for_text,
|
||||
),
|
||||
range: Anchor::range_in_buffer(excerpt_id, buffer_id, item.range),
|
||||
range: Anchor::range_in_buffer(excerpt_id, item.range),
|
||||
text: item.text,
|
||||
highlight_ranges: item.highlight_ranges,
|
||||
name_ranges: item.name_ranges,
|
||||
body_range: item.body_range.map(|body_range| {
|
||||
Anchor::range_in_buffer(excerpt_id, buffer_id, body_range)
|
||||
}),
|
||||
annotation_range: item.annotation_range.map(|body_range| {
|
||||
Anchor::range_in_buffer(excerpt_id, buffer_id, body_range)
|
||||
}),
|
||||
body_range: item
|
||||
.body_range
|
||||
.map(|body_range| Anchor::range_in_buffer(excerpt_id, body_range)),
|
||||
annotation_range: item
|
||||
.annotation_range
|
||||
.map(|body_range| Anchor::range_in_buffer(excerpt_id, body_range)),
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
|
|
@ -6180,7 +6176,7 @@ impl MultiBufferSnapshot {
|
|||
}
|
||||
|
||||
pub fn buffer_id_for_anchor(&self, anchor: Anchor) -> Option<BufferId> {
|
||||
if let Some(id) = anchor.buffer_id {
|
||||
if let Some(id) = anchor.text_anchor.buffer_id {
|
||||
return Some(id);
|
||||
}
|
||||
let excerpt = self.excerpt_containing(anchor..anchor)?;
|
||||
|
|
@ -6212,10 +6208,8 @@ impl MultiBufferSnapshot {
|
|||
.selections_in_range(query_range, include_local)
|
||||
.flat_map(move |(replica_id, line_mode, cursor_shape, selections)| {
|
||||
selections.map(move |selection| {
|
||||
let mut start =
|
||||
Anchor::in_buffer(excerpt.id, excerpt.buffer_id, selection.start);
|
||||
let mut end =
|
||||
Anchor::in_buffer(excerpt.id, excerpt.buffer_id, selection.end);
|
||||
let mut start = Anchor::in_buffer(excerpt.id, selection.start);
|
||||
let mut end = Anchor::in_buffer(excerpt.id, selection.end);
|
||||
if range.start.cmp(&start, self).is_gt() {
|
||||
start = range.start;
|
||||
}
|
||||
|
|
@ -6687,7 +6681,8 @@ impl Excerpt {
|
|||
}
|
||||
|
||||
fn contains(&self, anchor: &Anchor) -> bool {
|
||||
(anchor.buffer_id == None || anchor.buffer_id == Some(self.buffer_id))
|
||||
(anchor.text_anchor.buffer_id == None
|
||||
|| anchor.text_anchor.buffer_id == Some(self.buffer_id))
|
||||
&& self
|
||||
.range
|
||||
.context
|
||||
|
|
@ -6723,19 +6718,11 @@ impl<'a> MultiBufferExcerpt<'a> {
|
|||
}
|
||||
|
||||
pub fn start_anchor(&self) -> Anchor {
|
||||
Anchor::in_buffer(
|
||||
self.excerpt.id,
|
||||
self.excerpt.buffer_id,
|
||||
self.excerpt.range.context.start,
|
||||
)
|
||||
Anchor::in_buffer(self.excerpt.id, self.excerpt.range.context.start)
|
||||
}
|
||||
|
||||
pub fn end_anchor(&self) -> Anchor {
|
||||
Anchor::in_buffer(
|
||||
self.excerpt.id,
|
||||
self.excerpt.buffer_id,
|
||||
self.excerpt.range.context.end,
|
||||
)
|
||||
Anchor::in_buffer(self.excerpt.id, self.excerpt.range.context.end)
|
||||
}
|
||||
|
||||
pub fn buffer(&self) -> &'a BufferSnapshot {
|
||||
|
|
|
|||
|
|
@ -3401,14 +3401,11 @@ fn test_summaries_for_anchors(cx: &mut TestAppContext) {
|
|||
),
|
||||
);
|
||||
|
||||
let id_1 = buffer_1.read_with(cx, |buffer, _| buffer.remote_id());
|
||||
let id_2 = buffer_2.read_with(cx, |buffer, _| buffer.remote_id());
|
||||
|
||||
let anchor_1 = Anchor::in_buffer(ids[0], id_1, text::Anchor::MIN);
|
||||
let anchor_1 = Anchor::in_buffer(ids[0], text::Anchor::MIN);
|
||||
let point_1 = snapshot.summaries_for_anchors::<Point, _>([&anchor_1])[0];
|
||||
assert_eq!(point_1, Point::new(0, 0));
|
||||
|
||||
let anchor_2 = Anchor::in_buffer(ids[1], id_2, text::Anchor::MIN);
|
||||
let anchor_2 = Anchor::in_buffer(ids[1], text::Anchor::MIN);
|
||||
let point_2 = snapshot.summaries_for_anchors::<Point, _>([&anchor_2])[0];
|
||||
assert_eq!(point_2, Point::new(3, 0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,11 +56,7 @@ impl MultiBuffer {
|
|||
let excerpt_id = self.excerpts_by_path.get(path)?.first()?;
|
||||
let snapshot = self.read(cx);
|
||||
let excerpt = snapshot.excerpt(*excerpt_id)?;
|
||||
Some(Anchor::in_buffer(
|
||||
excerpt.id,
|
||||
excerpt.buffer_id,
|
||||
excerpt.range.context.start,
|
||||
))
|
||||
Some(Anchor::in_buffer(excerpt.id, excerpt.range.context.start))
|
||||
}
|
||||
|
||||
pub fn excerpt_paths(&self) -> impl Iterator<Item = &PathKey> {
|
||||
|
|
@ -263,7 +259,6 @@ impl MultiBuffer {
|
|||
for range in ranges.by_ref().take(range_count) {
|
||||
let range = Anchor::range_in_buffer(
|
||||
excerpt_id,
|
||||
buffer_snapshot.remote_id(),
|
||||
buffer_snapshot.anchor_before(&range.primary.start)
|
||||
..buffer_snapshot.anchor_after(&range.primary.end),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2044,8 +2044,9 @@ impl OutlinePanel {
|
|||
PanelEntry::Fs(FsEntry::ExternalFile(..)) => None,
|
||||
PanelEntry::Search(SearchEntry { match_range, .. }) => match_range
|
||||
.start
|
||||
.text_anchor
|
||||
.buffer_id
|
||||
.or(match_range.end.buffer_id)
|
||||
.or(match_range.end.text_anchor.buffer_id)
|
||||
.map(|buffer_id| {
|
||||
outline_panel.update(cx, |outline_panel, cx| {
|
||||
outline_panel
|
||||
|
|
|
|||
|
|
@ -2746,7 +2746,7 @@ impl LocalLspStore {
|
|||
let actions = lsp_store
|
||||
.update(cx, move |this, cx| {
|
||||
let request = GetCodeActions {
|
||||
range: text::Anchor::MIN..text::Anchor::MAX,
|
||||
range: text::Anchor::min_max_range_for_buffer(buffer.read(cx).remote_id()),
|
||||
kinds: Some(code_action_kinds),
|
||||
};
|
||||
let server = LanguageServerToQuery::Other(language_server_id);
|
||||
|
|
|
|||
|
|
@ -4002,7 +4002,8 @@ impl Project {
|
|||
) -> Task<anyhow::Result<Vec<InlayHint>>> {
|
||||
let snapshot = buffer_handle.read(cx).snapshot();
|
||||
|
||||
let captures = snapshot.debug_variables_query(Anchor::MIN..range.end);
|
||||
let captures =
|
||||
snapshot.debug_variables_query(Anchor::min_for_buffer(snapshot.remote_id())..range.end);
|
||||
|
||||
let row = snapshot
|
||||
.summary_for_anchor::<text::PointUtf16>(&range.end)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,12 @@ impl<K: Clone + Ord, V: Clone> TreeMap<K, V> {
|
|||
self.0.insert_or_replace(MapEntry { key, value }, ());
|
||||
}
|
||||
|
||||
pub fn insert_or_replace(&mut self, key: K, value: V) -> Option<V> {
|
||||
self.0
|
||||
.insert_or_replace(MapEntry { key, value }, ())
|
||||
.map(|it| it.value)
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, iter: impl IntoIterator<Item = (K, V)>) {
|
||||
let edits: Vec<_> = iter
|
||||
.into_iter()
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ pub struct Anchor {
|
|||
|
||||
impl Debug for Anchor {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if *self == Self::MIN {
|
||||
return f.write_str("Anchor::MIN");
|
||||
if self.is_min() {
|
||||
return write!(f, "Anchor::min({:?})", self.buffer_id);
|
||||
}
|
||||
if *self == Self::MAX {
|
||||
return f.write_str("Anchor::MAX");
|
||||
if self.is_max() {
|
||||
return write!(f, "Anchor::max({:?})", self.buffer_id);
|
||||
}
|
||||
|
||||
f.debug_struct("Anchor")
|
||||
|
|
@ -49,6 +49,36 @@ impl Anchor {
|
|||
buffer_id: None,
|
||||
};
|
||||
|
||||
pub fn min_for_buffer(buffer_id: BufferId) -> Self {
|
||||
Self {
|
||||
timestamp: clock::Lamport::MIN,
|
||||
offset: usize::MIN,
|
||||
bias: Bias::Left,
|
||||
buffer_id: Some(buffer_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_for_buffer(buffer_id: BufferId) -> Self {
|
||||
Self {
|
||||
timestamp: clock::Lamport::MAX,
|
||||
offset: usize::MAX,
|
||||
bias: Bias::Right,
|
||||
buffer_id: Some(buffer_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn min_min_range_for_buffer(buffer_id: BufferId) -> std::ops::Range<Self> {
|
||||
let min = Self::min_for_buffer(buffer_id);
|
||||
min..min
|
||||
}
|
||||
pub fn max_max_range_for_buffer(buffer_id: BufferId) -> std::ops::Range<Self> {
|
||||
let max = Self::max_for_buffer(buffer_id);
|
||||
max..max
|
||||
}
|
||||
pub fn min_max_range_for_buffer(buffer_id: BufferId) -> std::ops::Range<Self> {
|
||||
Self::min_for_buffer(buffer_id)..Self::max_for_buffer(buffer_id)
|
||||
}
|
||||
|
||||
pub fn cmp(&self, other: &Anchor, buffer: &BufferSnapshot) -> Ordering {
|
||||
let fragment_id_comparison = if self.timestamp == other.timestamp {
|
||||
Ordering::Equal
|
||||
|
|
@ -109,7 +139,7 @@ impl Anchor {
|
|||
|
||||
/// Returns true when the [`Anchor`] is located inside a visible fragment.
|
||||
pub fn is_valid(&self, buffer: &BufferSnapshot) -> bool {
|
||||
if *self == Anchor::MIN || *self == Anchor::MAX {
|
||||
if self.is_min() || self.is_max() {
|
||||
true
|
||||
} else if self.buffer_id.is_none_or(|id| id != buffer.remote_id) {
|
||||
false
|
||||
|
|
@ -127,6 +157,18 @@ impl Anchor {
|
|||
item.is_some_and(|fragment| fragment.visible)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_min(&self) -> bool {
|
||||
self.timestamp == clock::Lamport::MIN
|
||||
&& self.offset == usize::MIN
|
||||
&& self.bias == Bias::Left
|
||||
}
|
||||
|
||||
pub fn is_max(&self) -> bool {
|
||||
self.timestamp == clock::Lamport::MAX
|
||||
&& self.offset == usize::MAX
|
||||
&& self.bias == Bias::Right
|
||||
}
|
||||
}
|
||||
|
||||
pub trait OffsetRangeExt {
|
||||
|
|
|
|||
|
|
@ -1652,10 +1652,7 @@ impl Buffer {
|
|||
) -> impl 'static + Future<Output = Result<()>> + use<It> {
|
||||
let mut futures = Vec::new();
|
||||
for anchor in anchors {
|
||||
if !self.version.observed(anchor.timestamp)
|
||||
&& anchor != Anchor::MAX
|
||||
&& anchor != Anchor::MIN
|
||||
{
|
||||
if !self.version.observed(anchor.timestamp) && !anchor.is_max() && !anchor.is_min() {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.edit_id_resolvers
|
||||
.entry(anchor.timestamp)
|
||||
|
|
@ -2258,9 +2255,9 @@ impl BufferSnapshot {
|
|||
let mut position = D::zero(());
|
||||
|
||||
anchors.map(move |(anchor, payload)| {
|
||||
if *anchor == Anchor::MIN {
|
||||
if anchor.is_min() {
|
||||
return (D::zero(()), payload);
|
||||
} else if *anchor == Anchor::MAX {
|
||||
} else if anchor.is_max() {
|
||||
return (D::from_text_summary(&self.visible_text.summary()), payload);
|
||||
}
|
||||
|
||||
|
|
@ -2318,9 +2315,9 @@ impl BufferSnapshot {
|
|||
}
|
||||
|
||||
pub fn offset_for_anchor(&self, anchor: &Anchor) -> usize {
|
||||
if *anchor == Anchor::MIN {
|
||||
if anchor.is_min() {
|
||||
0
|
||||
} else if *anchor == Anchor::MAX {
|
||||
} else if anchor.is_max() {
|
||||
self.visible_text.len()
|
||||
} else {
|
||||
debug_assert!(anchor.buffer_id == Some(self.remote_id));
|
||||
|
|
@ -2393,9 +2390,9 @@ impl BufferSnapshot {
|
|||
}
|
||||
|
||||
fn try_fragment_id_for_anchor(&self, anchor: &Anchor) -> Option<&Locator> {
|
||||
if *anchor == Anchor::MIN {
|
||||
if anchor.is_min() {
|
||||
Some(Locator::min_ref())
|
||||
} else if *anchor == Anchor::MAX {
|
||||
} else if anchor.is_max() {
|
||||
Some(Locator::max_ref())
|
||||
} else {
|
||||
let anchor_key = InsertionFragmentKey {
|
||||
|
|
@ -2440,9 +2437,9 @@ impl BufferSnapshot {
|
|||
|
||||
fn anchor_at_offset(&self, offset: usize, bias: Bias) -> Anchor {
|
||||
if bias == Bias::Left && offset == 0 {
|
||||
Anchor::MIN
|
||||
Anchor::min_for_buffer(self.remote_id)
|
||||
} else if bias == Bias::Right && offset == self.len() {
|
||||
Anchor::MAX
|
||||
Anchor::max_for_buffer(self.remote_id)
|
||||
} else {
|
||||
if cfg!(debug_assertions) {
|
||||
self.visible_text.assert_char_boundary(offset);
|
||||
|
|
@ -2462,8 +2459,8 @@ impl BufferSnapshot {
|
|||
}
|
||||
|
||||
pub fn can_resolve(&self, anchor: &Anchor) -> bool {
|
||||
*anchor == Anchor::MIN
|
||||
|| *anchor == Anchor::MAX
|
||||
anchor.is_min()
|
||||
|| anchor.is_max()
|
||||
|| (Some(self.remote_id) == anchor.buffer_id && self.version.observed(anchor.timestamp))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2268,17 +2268,13 @@ fn go_to_line(map: &DisplaySnapshot, display_point: DisplayPoint, line: usize) -
|
|||
..language::ToOffset::to_offset(&range.context.end, buffer);
|
||||
if offset >= excerpt_range.start && offset <= excerpt_range.end {
|
||||
let text_anchor = buffer.anchor_after(offset);
|
||||
let anchor = Anchor::in_buffer(excerpt, buffer.remote_id(), text_anchor);
|
||||
let anchor = Anchor::in_buffer(excerpt, text_anchor);
|
||||
return anchor.to_display_point(map);
|
||||
} else if offset <= excerpt_range.start {
|
||||
let anchor = Anchor::in_buffer(excerpt, buffer.remote_id(), range.context.start);
|
||||
let anchor = Anchor::in_buffer(excerpt, range.context.start);
|
||||
return anchor.to_display_point(map);
|
||||
} else {
|
||||
last_position = Some(Anchor::in_buffer(
|
||||
excerpt,
|
||||
buffer.remote_id(),
|
||||
range.context.end,
|
||||
));
|
||||
last_position = Some(Anchor::in_buffer(excerpt, range.context.end));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ impl MarksState {
|
|||
let text_anchors = anchors.get(name)?;
|
||||
let anchors = text_anchors
|
||||
.iter()
|
||||
.map(|anchor| Anchor::in_buffer(excerpt_id, buffer_id, *anchor))
|
||||
.map(|anchor| Anchor::in_buffer(excerpt_id, *anchor))
|
||||
.collect();
|
||||
return Some(Mark::Local(anchors));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue