Skip to content

Commit 700e838

Browse files
committed
do not reparse unmodified injections
1 parent 18cfe86 commit 700e838

File tree

2 files changed

+53
-21
lines changed

2 files changed

+53
-21
lines changed

helix-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ tree-sitter = "0.20"
2929
once_cell = "1.15"
3030
arc-swap = "1"
3131
regex = "1"
32+
bitflags = "1.3"
3233

3334
log = "0.4"
3435
serde = { version = "1.0", features = ["derive"] }

helix-core/src/syntax.rs

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ use crate::{
88
};
99

1010
use arc_swap::{ArcSwap, Guard};
11+
use bitflags::bitflags;
1112
use slotmap::{DefaultKey as LayerId, HopSlotMap};
1213

1314
use std::{
1415
borrow::Cow,
1516
cell::RefCell,
16-
collections::{HashMap, HashSet, VecDeque},
17+
collections::{HashMap, VecDeque},
1718
fmt,
19+
mem::replace,
1820
path::Path,
1921
str::FromStr,
2022
sync::Arc,
@@ -594,6 +596,7 @@ impl Syntax {
594596
tree: None,
595597
config,
596598
depth: 0,
599+
flags: LayerUpdateFlags::empty(),
597600
ranges: vec![Range {
598601
start_byte: 0,
599602
end_byte: usize::MAX,
@@ -656,9 +659,10 @@ impl Syntax {
656659
}
657660
}
658661

659-
for layer in &mut self.layers.values_mut() {
662+
for layer in self.layers.values_mut() {
660663
// The root layer always covers the whole range (0..usize::MAX)
661664
if layer.depth == 0 {
665+
layer.flags = LayerUpdateFlags::MODIFIED;
662666
continue;
663667
}
664668

@@ -689,6 +693,8 @@ impl Syntax {
689693
edit.new_end_position,
690694
point_sub(range.end_point, edit.old_end_position),
691695
);
696+
697+
layer.flags |= LayerUpdateFlags::MOVED;
692698
}
693699
// if the edit starts in the space before and extends into the range
694700
else if edit.start_byte < range.start_byte {
@@ -703,11 +709,13 @@ impl Syntax {
703709
edit.new_end_position,
704710
point_sub(range.end_point, edit.old_end_position),
705711
);
712+
layer.flags = LayerUpdateFlags::MODIFIED;
706713
}
707714
// If the edit is an insertion at the start of the tree, shift
708715
else if edit.start_byte == range.start_byte && is_pure_insertion {
709716
range.start_byte = edit.new_end_byte;
710717
range.start_point = edit.new_end_position;
718+
layer.flags |= LayerUpdateFlags::MOVED;
711719
} else {
712720
range.end_byte = range
713721
.end_byte
@@ -717,6 +725,7 @@ impl Syntax {
717725
edit.new_end_position,
718726
point_sub(range.end_point, edit.old_end_position),
719727
);
728+
layer.flags = LayerUpdateFlags::MODIFIED;
720729
}
721730
}
722731
}
@@ -731,27 +740,33 @@ impl Syntax {
731740

732741
let source_slice = source.slice(..);
733742

734-
let mut touched = HashSet::new();
735-
736-
// TODO: we should be able to avoid editing & parsing layers with ranges earlier in the document before the edit
737-
738743
while let Some(layer_id) = queue.pop_front() {
739-
// Mark the layer as touched
740-
touched.insert(layer_id);
741-
742744
let layer = &mut self.layers[layer_id];
743745

746+
// Mark the layer as touched
747+
layer.flags |= LayerUpdateFlags::TOUCHED;
748+
744749
// If a tree already exists, notify it of changes.
745750
if let Some(tree) = &mut layer.tree {
746-
for edit in edits.iter().rev() {
747-
// Apply the edits in reverse.
748-
// If we applied them in order then edit 1 would disrupt the positioning of edit 2.
749-
tree.edit(edit);
751+
if layer
752+
.flags
753+
.intersects(LayerUpdateFlags::MODIFIED | LayerUpdateFlags::MOVED)
754+
{
755+
for edit in edits.iter().rev() {
756+
// Apply the edits in reverse.
757+
// If we applied them in order then edit 1 would disrupt the positioning of edit 2.
758+
tree.edit(edit);
759+
}
750760
}
751-
}
752761

753-
// Re-parse the tree.
754-
layer.parse(&mut ts_parser.parser, source)?;
762+
if layer.flags.contains(LayerUpdateFlags::MODIFIED) {
763+
// Re-parse the tree.
764+
layer.parse(&mut ts_parser.parser, source)?;
765+
}
766+
} else {
767+
// always parse if this layer has never been parsed before
768+
layer.parse(&mut ts_parser.parser, source)?;
769+
}
755770

756771
// Switch to an immutable borrow.
757772
let layer = &self.layers[layer_id];
@@ -855,6 +870,8 @@ impl Syntax {
855870
config,
856871
depth,
857872
ranges,
873+
// set the modified flag to ensure the layer is parsed
874+
flags: LayerUpdateFlags::empty(),
858875
})
859876
});
860877

@@ -868,8 +885,11 @@ impl Syntax {
868885
// Return the cursor back in the pool.
869886
ts_parser.cursors.push(cursor);
870887

871-
// Remove all untouched layers
872-
self.layers.retain(|id, _| touched.contains(&id));
888+
// Reset all `LayerUpdateFlags` and remove all untouched layers
889+
self.layers.retain(|_, layer| {
890+
replace(&mut layer.flags, LayerUpdateFlags::empty())
891+
.contains(LayerUpdateFlags::TOUCHED)
892+
});
873893

874894
Ok(())
875895
})
@@ -968,14 +988,25 @@ impl Syntax {
968988
// TODO: Folding
969989
}
970990

991+
bitflags! {
992+
/// Flags that track the status of a layer
993+
/// in the `Sytaxn::update` function
994+
struct LayerUpdateFlags : u32{
995+
const MODIFIED = 0b001;
996+
const MOVED = 0b010;
997+
const TOUCHED = 0b100;
998+
}
999+
}
1000+
9711001
#[derive(Debug)]
9721002
pub struct LanguageLayer {
9731003
// mode
9741004
// grammar
9751005
pub config: Arc<HighlightConfiguration>,
9761006
pub(crate) tree: Option<Tree>,
9771007
pub ranges: Vec<Range>,
978-
pub depth: usize,
1008+
pub depth: u32,
1009+
flags: LayerUpdateFlags,
9791010
}
9801011

9811012
impl LanguageLayer {
@@ -1191,7 +1222,7 @@ struct HighlightIter<'a> {
11911222
layers: Vec<HighlightIterLayer<'a>>,
11921223
iter_count: usize,
11931224
next_event: Option<HighlightEvent>,
1194-
last_highlight_range: Option<(usize, usize, usize)>,
1225+
last_highlight_range: Option<(usize, usize, u32)>,
11951226
}
11961227

11971228
// Adapter to convert rope chunks to bytes
@@ -1224,7 +1255,7 @@ struct HighlightIterLayer<'a> {
12241255
config: &'a HighlightConfiguration,
12251256
highlight_end_stack: Vec<usize>,
12261257
scope_stack: Vec<LocalScope<'a>>,
1227-
depth: usize,
1258+
depth: u32,
12281259
ranges: &'a [Range],
12291260
}
12301261

0 commit comments

Comments
 (0)