mirror of
https://github.com/ilyakooo0/helix.git
synced 2024-09-11 16:07:00 +03:00
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"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"bitflags",
|
||||
"chrono",
|
||||
"encoding_rs",
|
||||
"etcetera",
|
||||
|
@ -29,6 +29,7 @@ tree-sitter = "0.20"
|
||||
once_cell = "1.15"
|
||||
arc-swap = "1"
|
||||
regex = "1"
|
||||
bitflags = "1.3"
|
||||
|
||||
log = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
@ -8,13 +8,15 @@
|
||||
};
|
||||
|
||||
use arc_swap::{ArcSwap, Guard};
|
||||
use bitflags::bitflags;
|
||||
use slotmap::{DefaultKey as LayerId, HopSlotMap};
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::RefCell,
|
||||
collections::{HashMap, HashSet, VecDeque},
|
||||
collections::{HashMap, VecDeque},
|
||||
fmt,
|
||||
mem::replace,
|
||||
path::Path,
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
@ -594,6 +596,7 @@ pub fn new(source: &Rope, config: Arc<HighlightConfiguration>, loader: Arc<Loade
|
||||
tree: None,
|
||||
config,
|
||||
depth: 0,
|
||||
flags: LayerUpdateFlags::empty(),
|
||||
ranges: vec![Range {
|
||||
start_byte: 0,
|
||||
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)
|
||||
if layer.depth == 0 {
|
||||
layer.flags = LayerUpdateFlags::MODIFIED;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -689,6 +693,8 @@ fn point_sub(a: Point, b: Point) -> Point {
|
||||
edit.new_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
|
||||
else if edit.start_byte < range.start_byte {
|
||||
@ -703,11 +709,13 @@ fn point_sub(a: Point, b: Point) -> Point {
|
||||
edit.new_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
|
||||
else if edit.start_byte == range.start_byte && is_pure_insertion {
|
||||
range.start_byte = edit.new_end_byte;
|
||||
range.start_point = edit.new_end_position;
|
||||
layer.flags |= LayerUpdateFlags::MOVED;
|
||||
} else {
|
||||
range.end_byte = range
|
||||
.end_byte
|
||||
@ -717,6 +725,7 @@ fn point_sub(a: Point, b: Point) -> Point {
|
||||
edit.new_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 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() {
|
||||
// Mark the layer as touched
|
||||
touched.insert(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 let Some(tree) = &mut layer.tree {
|
||||
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);
|
||||
if layer
|
||||
.flags
|
||||
.intersects(LayerUpdateFlags::MODIFIED | LayerUpdateFlags::MOVED)
|
||||
{
|
||||
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.
|
||||
layer.parse(&mut ts_parser.parser, source)?;
|
||||
if layer.flags.contains(LayerUpdateFlags::MODIFIED) {
|
||||
// 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.
|
||||
let layer = &self.layers[layer_id];
|
||||
@ -855,6 +870,8 @@ fn point_sub(a: Point, b: Point) -> Point {
|
||||
config,
|
||||
depth,
|
||||
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.
|
||||
ts_parser.cursors.push(cursor);
|
||||
|
||||
// Remove all untouched layers
|
||||
self.layers.retain(|id, _| touched.contains(&id));
|
||||
// Reset all `LayerUpdateFlags` and remove all untouched layers
|
||||
self.layers.retain(|_, layer| {
|
||||
replace(&mut layer.flags, LayerUpdateFlags::empty())
|
||||
.contains(LayerUpdateFlags::TOUCHED)
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
@ -968,6 +988,16 @@ pub fn highlight_iter<'a>(
|
||||
// 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)]
|
||||
pub struct LanguageLayer {
|
||||
// mode
|
||||
@ -975,7 +1005,8 @@ pub struct LanguageLayer {
|
||||
pub config: Arc<HighlightConfiguration>,
|
||||
pub(crate) tree: Option<Tree>,
|
||||
pub ranges: Vec<Range>,
|
||||
pub depth: usize,
|
||||
pub depth: u32,
|
||||
flags: LayerUpdateFlags,
|
||||
}
|
||||
|
||||
impl LanguageLayer {
|
||||
@ -1191,7 +1222,7 @@ struct HighlightIter<'a> {
|
||||
layers: Vec<HighlightIterLayer<'a>>,
|
||||
iter_count: usize,
|
||||
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
|
||||
@ -1224,7 +1255,7 @@ struct HighlightIterLayer<'a> {
|
||||
config: &'a HighlightConfiguration,
|
||||
highlight_end_stack: Vec<usize>,
|
||||
scope_stack: Vec<LocalScope<'a>>,
|
||||
depth: usize,
|
||||
depth: u32,
|
||||
ranges: &'a [Range],
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user