Fix more bugs in syntax map interpolation
This commit is contained in:
parent
58fda5ac1c
commit
ae9e1338f6
1 changed files with 112 additions and 73 deletions
|
@ -106,60 +106,67 @@ impl SyntaxSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut layers = SumTree::new();
|
let mut layers = SumTree::new();
|
||||||
let max_depth = self.layers.summary().max_depth;
|
let mut edits_for_depth = &edits[..];
|
||||||
let mut cursor = self.layers.cursor::<SyntaxLayerSummary>();
|
let mut cursor = self.layers.cursor::<SyntaxLayerSummary>();
|
||||||
cursor.next(&text);
|
cursor.next(text);
|
||||||
|
|
||||||
for depth in 0..=max_depth {
|
'outer: loop {
|
||||||
let mut edits = &edits[..];
|
let depth = cursor.end(text).max_depth;
|
||||||
if cursor.start().max_depth < depth {
|
|
||||||
|
// Preserve any layers at this depth that precede the first edit.
|
||||||
|
if let Some(first_edit) = edits_for_depth.first() {
|
||||||
|
let target = DepthAndMaxPosition(depth, text.anchor_before(first_edit.new.start.0));
|
||||||
|
if target.cmp(&cursor.start(), text).is_gt() {
|
||||||
|
let slice = cursor.slice(&target, Bias::Left, text);
|
||||||
|
layers.push_tree(slice, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If this layer follows all of the edits, then preserve it and any
|
||||||
|
// subsequent layers at this same depth.
|
||||||
|
else {
|
||||||
layers.push_tree(
|
layers.push_tree(
|
||||||
cursor.slice(
|
cursor.slice(
|
||||||
&DepthAndRange(depth, Anchor::MIN..Anchor::MAX),
|
&DepthAndRange(depth + 1, Anchor::MIN..Anchor::MAX),
|
||||||
Bias::Left,
|
Bias::Left,
|
||||||
text,
|
text,
|
||||||
),
|
),
|
||||||
text,
|
text,
|
||||||
);
|
);
|
||||||
}
|
edits_for_depth = &edits[..];
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
while let Some(layer) = cursor.item() {
|
let layer = if let Some(layer) = cursor.item() {
|
||||||
let mut endpoints = text.summaries_for_anchors::<(usize, Point), _>([
|
layer
|
||||||
&layer.range.start,
|
|
||||||
&layer.range.end,
|
|
||||||
]);
|
|
||||||
let layer_range = endpoints.next().unwrap()..endpoints.next().unwrap();
|
|
||||||
let start_byte = layer_range.start.0;
|
|
||||||
let start_point = layer_range.start.1;
|
|
||||||
|
|
||||||
// Preserve any layers at this depth that precede the first edit.
|
|
||||||
let first_edit = if let Some(edit) = edits.first() {
|
|
||||||
edit
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
let target = DepthAndMaxPosition(depth, text.anchor_before(first_edit.new.start.0));
|
|
||||||
if target.cmp(&cursor.start(), text).is_gt() {
|
|
||||||
layers.push_tree(cursor.slice(&target, Bias::Left, text), text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preserve any layers at this depth that follow the last edit.
|
let mut endpoints = text
|
||||||
let last_edit = edits.last().unwrap();
|
.summaries_for_anchors::<(usize, Point), _>([&layer.range.start, &layer.range.end]);
|
||||||
if last_edit.new.end.0 < layer_range.start.0 {
|
let layer_range = endpoints.next().unwrap()..endpoints.next().unwrap();
|
||||||
break;
|
let start_byte = layer_range.start.0;
|
||||||
}
|
let start_point = layer_range.start.1;
|
||||||
|
let end_byte = layer_range.end.0;
|
||||||
let mut layer = layer.clone();
|
|
||||||
for (i, edit) in edits.iter().enumerate().rev() {
|
|
||||||
// Ignore any edits that start after the end of this layer.
|
|
||||||
if edit.new.start.0 > layer_range.end.0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore edits that end before the start of this layer, and don't consider them
|
// Ignore edits that end before the start of this layer, and don't consider them
|
||||||
// for any subsequent layers at this same depth.
|
// for any subsequent layers at this same depth.
|
||||||
if edit.new.end.0 <= start_byte {
|
loop {
|
||||||
edits = &edits[i + 1..];
|
if let Some(edit) = edits_for_depth.first() {
|
||||||
|
if edit.new.end.0 < start_byte {
|
||||||
|
edits_for_depth = &edits_for_depth[1..];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut layer = layer.clone();
|
||||||
|
for edit in edits_for_depth {
|
||||||
|
// Ignore any edits that follow this layer.
|
||||||
|
if edit.new.start.0 > end_byte {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +203,6 @@ impl SyntaxSnapshot {
|
||||||
layers.push(layer, text);
|
layers.push(layer, text);
|
||||||
cursor.next(text);
|
cursor.next(text);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
layers.push_tree(cursor.suffix(&text), &text);
|
layers.push_tree(cursor.suffix(&text), &text);
|
||||||
drop(cursor);
|
drop(cursor);
|
||||||
|
@ -958,6 +964,31 @@ mod tests {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_edits_preceding_and_intersecting_injection() {
|
||||||
|
test_edit_sequence(&[
|
||||||
|
//
|
||||||
|
"const aaaaaaaaaaaa: B = c!(d(e.f));",
|
||||||
|
"const aˇa: B = c!(d(eˇ));",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
fn test_non_local_changes_create_injections() {
|
||||||
|
test_edit_sequence(&[
|
||||||
|
"
|
||||||
|
// a! {
|
||||||
|
static B: C = d;
|
||||||
|
// }
|
||||||
|
",
|
||||||
|
"
|
||||||
|
ˇa! {
|
||||||
|
static B: C = d;
|
||||||
|
ˇ}
|
||||||
|
",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
fn test_edit_sequence(steps: &[&str]) -> (Buffer, SyntaxMap) {
|
fn test_edit_sequence(steps: &[&str]) -> (Buffer, SyntaxMap) {
|
||||||
let registry = Arc::new(LanguageRegistry::test());
|
let registry = Arc::new(LanguageRegistry::test());
|
||||||
let language = Arc::new(rust_lang());
|
let language = Arc::new(rust_lang());
|
||||||
|
@ -1084,12 +1115,20 @@ mod tests {
|
||||||
ranges.push(0..new_text.len());
|
ranges.push(0..new_text.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
old_text[..ranges[0].start],
|
||||||
|
new_text[..ranges[0].start],
|
||||||
|
"invalid edit"
|
||||||
|
);
|
||||||
|
|
||||||
let mut delta = 0;
|
let mut delta = 0;
|
||||||
let mut edits = Vec::new();
|
let mut edits = Vec::new();
|
||||||
let mut ranges = ranges.into_iter().peekable();
|
let mut ranges = ranges.into_iter().peekable();
|
||||||
|
|
||||||
while let Some(inserted_range) = ranges.next() {
|
while let Some(inserted_range) = ranges.next() {
|
||||||
let old_start = (inserted_range.start as isize - delta) as usize;
|
let new_start = inserted_range.start;
|
||||||
|
let old_start = (new_start as isize - delta) as usize;
|
||||||
|
|
||||||
let following_text = if let Some(next_range) = ranges.peek() {
|
let following_text = if let Some(next_range) = ranges.peek() {
|
||||||
&new_text[inserted_range.end..next_range.start]
|
&new_text[inserted_range.end..next_range.start]
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue