do not reparse unmodified injections (#4146)

pull/1/head
Pascal Kuthe 2 years ago committed by GitHub
parent b58899bc8e
commit 543d75da23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

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 crate::{
}; };
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 @@ impl Syntax {
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 @@ impl Syntax {
} }
} }
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 @@ impl Syntax {
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 @@ impl Syntax {
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 @@ impl Syntax {
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 @@ impl Syntax {
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 @@ impl Syntax {
config, config,
depth, depth,
ranges, ranges,
// set the modified flag to ensure the layer is parsed
flags: LayerUpdateFlags::empty(),
}) })
}); });
@ -868,8 +885,11 @@ impl Syntax {
// 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 @@ impl Syntax {
// 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…
Cancel
Save