Ensure muiltibuffer anchors are contained within their excerpt ranges

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Max Brunsfeld 2021-12-15 10:52:27 -08:00
parent cec0c5912c
commit 4bea16eb31
3 changed files with 126 additions and 79 deletions

View file

@ -92,6 +92,7 @@ impl workspace::Item for ProjectDiagnostics {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
let mut blocks = Vec::new(); let mut blocks = Vec::new();
let excerpts_snapshot =
this.excerpts.update(cx, |excerpts, excerpts_cx| { this.excerpts.update(cx, |excerpts, excerpts_cx| {
for group in snapshot.diagnostic_groups::<Point>() { for group in snapshot.diagnostic_groups::<Point>() {
let excerpt_start = cmp::min( let excerpt_start = cmp::min(
@ -128,7 +129,8 @@ impl workspace::Item for ProjectDiagnostics {
let settings = settings.clone(); let settings = settings.clone();
move |_| { move |_| {
let editor_style = &settings.borrow().theme.editor; let editor_style =
&settings.borrow().theme.editor;
let mut text_style = editor_style.text.clone(); let mut text_style = editor_style.text.clone();
text_style.color = diagnostic_style( text_style.color = diagnostic_style(
primary_diagnostic.severity, primary_diagnostic.severity,
@ -149,9 +151,10 @@ impl workspace::Item for ProjectDiagnostics {
); );
for entry in group.supporting { for entry in group.supporting {
let buffer_anchor = snapshot.anchor_before(entry.range.start); let buffer_anchor =
snapshot.anchor_before(entry.range.start);
blocks.push(BlockProperties { blocks.push(BlockProperties {
position: Anchor::new(excerpt_id.clone(), buffer_anchor), position: (excerpt_id.clone(), buffer_anchor),
height: entry.diagnostic.message.matches('\n').count() height: entry.diagnostic.message.matches('\n').count()
as u8 as u8
+ 1, + 1,
@ -164,9 +167,24 @@ impl workspace::Item for ProjectDiagnostics {
}); });
} }
} }
excerpts.snapshot(excerpts_cx)
}); });
this.editor.update(cx, |editor, cx| { this.editor.update(cx, |editor, cx| {
editor.insert_blocks(blocks, cx); editor.insert_blocks(
blocks.into_iter().map(|block| {
let (excerpt_id, text_anchor) = block.position;
BlockProperties {
position: excerpts_snapshot
.anchor_in_excerpt(excerpt_id, text_anchor),
height: block.height,
render: block.render,
disposition: block.disposition,
}
}),
cx,
);
}); });
}) })
} }

View file

@ -1360,9 +1360,11 @@ impl MultiBufferSnapshot {
} }
let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer); let buffer_start = excerpt.range.start.to_offset(&excerpt.buffer);
let text_anchor =
excerpt.clip_anchor(excerpt.buffer.anchor_at(buffer_start + overshoot, bias));
Anchor { Anchor {
excerpt_id: excerpt.id.clone(), excerpt_id: excerpt.id.clone(),
text_anchor: excerpt.buffer.anchor_at(buffer_start + overshoot, bias), text_anchor,
} }
} else if offset == 0 && bias == Bias::Left { } else if offset == 0 && bias == Bias::Left {
Anchor::min() Anchor::min()
@ -1371,6 +1373,22 @@ impl MultiBufferSnapshot {
} }
} }
pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
let mut cursor = self.excerpts.cursor::<Option<&ExcerptId>>();
cursor.seek(&Some(&excerpt_id), Bias::Left, &());
if let Some(excerpt) = cursor.item() {
if excerpt.id == excerpt_id {
let text_anchor = excerpt.clip_anchor(text_anchor);
drop(cursor);
return Anchor {
excerpt_id,
text_anchor,
};
}
}
panic!("excerpt not found");
}
pub fn parse_count(&self) -> usize { pub fn parse_count(&self) -> usize {
self.parse_count self.parse_count
} }
@ -1688,6 +1706,24 @@ impl Excerpt {
footer_height, footer_height,
} }
} }
fn clip_anchor(&self, text_anchor: text::Anchor) -> text::Anchor {
if text_anchor
.cmp(&self.range.start, &self.buffer)
.unwrap()
.is_lt()
{
self.range.start.clone()
} else if text_anchor
.cmp(&self.range.end, &self.buffer)
.unwrap()
.is_gt()
{
self.range.end.clone()
} else {
text_anchor
}
}
} }
impl fmt::Debug for Excerpt { impl fmt::Debug for Excerpt {

View file

@ -14,13 +14,6 @@ pub struct Anchor {
} }
impl Anchor { impl Anchor {
pub fn new(excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Self {
Self {
excerpt_id,
text_anchor,
}
}
pub fn min() -> Self { pub fn min() -> Self {
Self { Self {
excerpt_id: ExcerptId::min(), excerpt_id: ExcerptId::min(),