do not reparse unmodified injections (#4146)
This commit is contained in:
parent
b58899bc8e
commit
543d75da23
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -388,6 +388,7 @@ name = "helix-core"
|
|||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
|
"bitflags",
|
||||||
"chrono",
|
"chrono",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"etcetera",
|
"etcetera",
|
||||||
|
@ -29,6 +29,7 @@ tree-sitter = "0.20"
|
|||||||
once_cell = "1.15"
|
once_cell = "1.15"
|
||||||
arc-swap = "1"
|
arc-swap = "1"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
|
bitflags = "1.3"
|
||||||
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
@ -8,13 +8,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
use arc_swap::{ArcSwap, Guard};
|
use arc_swap::{ArcSwap, Guard};
|
||||||
|
use bitflags::bitflags;
|
||||||
use slotmap::{DefaultKey as LayerId, HopSlotMap};
|
use slotmap::{DefaultKey as LayerId, HopSlotMap};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{HashMap, HashSet, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
fmt,
|
fmt,
|
||||||
|
mem::replace,
|
||||||
path::Path,
|
path::Path,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
@ -594,6 +596,7 @@ pub fn new(source: &Rope, config: Arc<HighlightConfiguration>, loader: Arc<Loade
|
|||||||
tree: None,
|
tree: None,
|
||||||
config,
|
config,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
|
flags: LayerUpdateFlags::empty(),
|
||||||
ranges: vec![Range {
|
ranges: vec![Range {
|
||||||
start_byte: 0,
|
start_byte: 0,
|
||||||
end_byte: usize::MAX,
|
end_byte: usize::MAX,
|
||||||
@ -656,9 +659,10 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for layer in &mut self.layers.values_mut() {
|
for layer in self.layers.values_mut() {
|
||||||
// The root layer always covers the whole range (0..usize::MAX)
|
// The root layer always covers the whole range (0..usize::MAX)
|
||||||
if layer.depth == 0 {
|
if layer.depth == 0 {
|
||||||
|
layer.flags = LayerUpdateFlags::MODIFIED;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,6 +693,8 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
edit.new_end_position,
|
edit.new_end_position,
|
||||||
point_sub(range.end_point, edit.old_end_position),
|
point_sub(range.end_point, edit.old_end_position),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
layer.flags |= LayerUpdateFlags::MOVED;
|
||||||
}
|
}
|
||||||
// if the edit starts in the space before and extends into the range
|
// if the edit starts in the space before and extends into the range
|
||||||
else if edit.start_byte < range.start_byte {
|
else if edit.start_byte < range.start_byte {
|
||||||
@ -703,11 +709,13 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
edit.new_end_position,
|
edit.new_end_position,
|
||||||
point_sub(range.end_point, edit.old_end_position),
|
point_sub(range.end_point, edit.old_end_position),
|
||||||
);
|
);
|
||||||
|
layer.flags = LayerUpdateFlags::MODIFIED;
|
||||||
}
|
}
|
||||||
// If the edit is an insertion at the start of the tree, shift
|
// If the edit is an insertion at the start of the tree, shift
|
||||||
else if edit.start_byte == range.start_byte && is_pure_insertion {
|
else if edit.start_byte == range.start_byte && is_pure_insertion {
|
||||||
range.start_byte = edit.new_end_byte;
|
range.start_byte = edit.new_end_byte;
|
||||||
range.start_point = edit.new_end_position;
|
range.start_point = edit.new_end_position;
|
||||||
|
layer.flags |= LayerUpdateFlags::MOVED;
|
||||||
} else {
|
} else {
|
||||||
range.end_byte = range
|
range.end_byte = range
|
||||||
.end_byte
|
.end_byte
|
||||||
@ -717,6 +725,7 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
edit.new_end_position,
|
edit.new_end_position,
|
||||||
point_sub(range.end_point, edit.old_end_position),
|
point_sub(range.end_point, edit.old_end_position),
|
||||||
);
|
);
|
||||||
|
layer.flags = LayerUpdateFlags::MODIFIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -731,27 +740,33 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
|
|
||||||
let source_slice = source.slice(..);
|
let source_slice = source.slice(..);
|
||||||
|
|
||||||
let mut touched = HashSet::new();
|
|
||||||
|
|
||||||
// TODO: we should be able to avoid editing & parsing layers with ranges earlier in the document before the edit
|
|
||||||
|
|
||||||
while let Some(layer_id) = queue.pop_front() {
|
while let Some(layer_id) = queue.pop_front() {
|
||||||
// Mark the layer as touched
|
|
||||||
touched.insert(layer_id);
|
|
||||||
|
|
||||||
let layer = &mut self.layers[layer_id];
|
let layer = &mut self.layers[layer_id];
|
||||||
|
|
||||||
|
// Mark the layer as touched
|
||||||
|
layer.flags |= LayerUpdateFlags::TOUCHED;
|
||||||
|
|
||||||
// If a tree already exists, notify it of changes.
|
// If a tree already exists, notify it of changes.
|
||||||
if let Some(tree) = &mut layer.tree {
|
if let Some(tree) = &mut layer.tree {
|
||||||
for edit in edits.iter().rev() {
|
if layer
|
||||||
// Apply the edits in reverse.
|
.flags
|
||||||
// If we applied them in order then edit 1 would disrupt the positioning of edit 2.
|
.intersects(LayerUpdateFlags::MODIFIED | LayerUpdateFlags::MOVED)
|
||||||
tree.edit(edit);
|
{
|
||||||
|
for edit in edits.iter().rev() {
|
||||||
|
// Apply the edits in reverse.
|
||||||
|
// If we applied them in order then edit 1 would disrupt the positioning of edit 2.
|
||||||
|
tree.edit(edit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Re-parse the tree.
|
if layer.flags.contains(LayerUpdateFlags::MODIFIED) {
|
||||||
layer.parse(&mut ts_parser.parser, source)?;
|
// Re-parse the tree.
|
||||||
|
layer.parse(&mut ts_parser.parser, source)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// always parse if this layer has never been parsed before
|
||||||
|
layer.parse(&mut ts_parser.parser, source)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Switch to an immutable borrow.
|
// Switch to an immutable borrow.
|
||||||
let layer = &self.layers[layer_id];
|
let layer = &self.layers[layer_id];
|
||||||
@ -855,6 +870,8 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
config,
|
config,
|
||||||
depth,
|
depth,
|
||||||
ranges,
|
ranges,
|
||||||
|
// set the modified flag to ensure the layer is parsed
|
||||||
|
flags: LayerUpdateFlags::empty(),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -868,8 +885,11 @@ fn point_sub(a: Point, b: Point) -> Point {
|
|||||||
// Return the cursor back in the pool.
|
// Return the cursor back in the pool.
|
||||||
ts_parser.cursors.push(cursor);
|
ts_parser.cursors.push(cursor);
|
||||||
|
|
||||||
// Remove all untouched layers
|
// Reset all `LayerUpdateFlags` and remove all untouched layers
|
||||||
self.layers.retain(|id, _| touched.contains(&id));
|
self.layers.retain(|_, layer| {
|
||||||
|
replace(&mut layer.flags, LayerUpdateFlags::empty())
|
||||||
|
.contains(LayerUpdateFlags::TOUCHED)
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@ -968,6 +988,16 @@ pub fn highlight_iter<'a>(
|
|||||||
// TODO: Folding
|
// TODO: Folding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Flags that track the status of a layer
|
||||||
|
/// in the `Sytaxn::update` function
|
||||||
|
struct LayerUpdateFlags : u32{
|
||||||
|
const MODIFIED = 0b001;
|
||||||
|
const MOVED = 0b010;
|
||||||
|
const TOUCHED = 0b100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LanguageLayer {
|
pub struct LanguageLayer {
|
||||||
// mode
|
// mode
|
||||||
@ -975,7 +1005,8 @@ pub struct LanguageLayer {
|
|||||||
pub config: Arc<HighlightConfiguration>,
|
pub config: Arc<HighlightConfiguration>,
|
||||||
pub(crate) tree: Option<Tree>,
|
pub(crate) tree: Option<Tree>,
|
||||||
pub ranges: Vec<Range>,
|
pub ranges: Vec<Range>,
|
||||||
pub depth: usize,
|
pub depth: u32,
|
||||||
|
flags: LayerUpdateFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LanguageLayer {
|
impl LanguageLayer {
|
||||||
@ -1191,7 +1222,7 @@ struct HighlightIter<'a> {
|
|||||||
layers: Vec<HighlightIterLayer<'a>>,
|
layers: Vec<HighlightIterLayer<'a>>,
|
||||||
iter_count: usize,
|
iter_count: usize,
|
||||||
next_event: Option<HighlightEvent>,
|
next_event: Option<HighlightEvent>,
|
||||||
last_highlight_range: Option<(usize, usize, usize)>,
|
last_highlight_range: Option<(usize, usize, u32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adapter to convert rope chunks to bytes
|
// Adapter to convert rope chunks to bytes
|
||||||
@ -1224,7 +1255,7 @@ struct HighlightIterLayer<'a> {
|
|||||||
config: &'a HighlightConfiguration,
|
config: &'a HighlightConfiguration,
|
||||||
highlight_end_stack: Vec<usize>,
|
highlight_end_stack: Vec<usize>,
|
||||||
scope_stack: Vec<LocalScope<'a>>,
|
scope_stack: Vec<LocalScope<'a>>,
|
||||||
depth: usize,
|
depth: u32,
|
||||||
ranges: &'a [Range],
|
ranges: &'a [Range],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user