Skip to content

Commit 6c1f343

Browse files
committed
do not reparse unmodified injections
1 parent 18cfe86 commit 6c1f343

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

helix-core/src/syntax.rs

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use slotmap::{DefaultKey as LayerId, HopSlotMap};
1313
use std::{
1414
borrow::Cow,
1515
cell::RefCell,
16-
collections::{HashMap, HashSet, VecDeque},
16+
collections::{HashMap, VecDeque},
1717
fmt,
18+
mem::replace,
1819
path::Path,
1920
str::FromStr,
2021
sync::Arc,
@@ -594,6 +595,7 @@ impl Syntax {
594595
tree: None,
595596
config,
596597
depth: 0,
598+
flags: 0,
597599
ranges: vec![Range {
598600
start_byte: 0,
599601
end_byte: usize::MAX,
@@ -656,9 +658,10 @@ impl Syntax {
656658
}
657659
}
658660

659-
for layer in &mut self.layers.values_mut() {
661+
for layer in self.layers.values_mut() {
660662
// The root layer always covers the whole range (0..usize::MAX)
661663
if layer.depth == 0 {
664+
layer.flags = LAYER_MODIFIED;
662665
continue;
663666
}
664667

@@ -689,6 +692,8 @@ impl Syntax {
689692
edit.new_end_position,
690693
point_sub(range.end_point, edit.old_end_position),
691694
);
695+
696+
layer.flags |= LAYER_MOVED;
692697
}
693698
// if the edit starts in the space before and extends into the range
694699
else if edit.start_byte < range.start_byte {
@@ -703,11 +708,13 @@ impl Syntax {
703708
edit.new_end_position,
704709
point_sub(range.end_point, edit.old_end_position),
705710
);
711+
layer.flags = LAYER_MODIFIED;
706712
}
707713
// If the edit is an insertion at the start of the tree, shift
708714
else if edit.start_byte == range.start_byte && is_pure_insertion {
709715
range.start_byte = edit.new_end_byte;
710716
range.start_point = edit.new_end_position;
717+
layer.flags |= LAYER_MOVED;
711718
} else {
712719
range.end_byte = range
713720
.end_byte
@@ -717,6 +724,7 @@ impl Syntax {
717724
edit.new_end_position,
718725
point_sub(range.end_point, edit.old_end_position),
719726
);
727+
layer.flags = LAYER_MODIFIED;
720728
}
721729
}
722730
}
@@ -731,27 +739,30 @@ impl Syntax {
731739

732740
let source_slice = source.slice(..);
733741

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-
738742
while let Some(layer_id) = queue.pop_front() {
739-
// Mark the layer as touched
740-
touched.insert(layer_id);
741-
742743
let layer = &mut self.layers[layer_id];
743744

745+
// Mark the layer as touched
746+
layer.flags |= LAYER_TOUCHED;
747+
744748
// If a tree already exists, notify it of changes.
745749
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);
750+
if layer.flags & (LAYER_MODIFIED | LAYER_MOVED) != 0 {
751+
for edit in edits.iter().rev() {
752+
// Apply the edits in reverse.
753+
// If we applied them in order then edit 1 would disrupt the positioning of edit 2.
754+
tree.edit(edit);
755+
}
750756
}
751-
}
752757

753-
// Re-parse the tree.
754-
layer.parse(&mut ts_parser.parser, source)?;
758+
if layer.flags & LAYER_MODIFIED != 0 {
759+
// Re-parse the tree.
760+
layer.parse(&mut ts_parser.parser, source)?;
761+
}
762+
} else {
763+
// always parse if this layer has never been parsed before
764+
layer.parse(&mut ts_parser.parser, source)?;
765+
}
755766

756767
// Switch to an immutable borrow.
757768
let layer = &self.layers[layer_id];
@@ -855,6 +866,8 @@ impl Syntax {
855866
config,
856867
depth,
857868
ranges,
869+
// set the modified flag to ensure the layer is parsed
870+
flags: 0,
858871
})
859872
});
860873

@@ -869,7 +882,8 @@ impl Syntax {
869882
ts_parser.cursors.push(cursor);
870883

871884
// Remove all untouched layers
872-
self.layers.retain(|id, _| touched.contains(&id));
885+
self.layers
886+
.retain(|_, layer| replace(&mut layer.flags, 0) & LAYER_TOUCHED != 0);
873887

874888
Ok(())
875889
})
@@ -968,14 +982,19 @@ impl Syntax {
968982
// TODO: Folding
969983
}
970984

985+
const LAYER_MODIFIED: u32 = 0b001;
986+
const LAYER_MOVED: u32 = 0b010;
987+
const LAYER_TOUCHED: u32 = 0b100;
988+
971989
#[derive(Debug)]
972990
pub struct LanguageLayer {
973991
// mode
974992
// grammar
975993
pub config: Arc<HighlightConfiguration>,
976994
pub(crate) tree: Option<Tree>,
977995
pub ranges: Vec<Range>,
978-
pub depth: usize,
996+
pub depth: u32,
997+
pub flags: u32,
979998
}
980999

9811000
impl LanguageLayer {
@@ -1191,7 +1210,7 @@ struct HighlightIter<'a> {
11911210
layers: Vec<HighlightIterLayer<'a>>,
11921211
iter_count: usize,
11931212
next_event: Option<HighlightEvent>,
1194-
last_highlight_range: Option<(usize, usize, usize)>,
1213+
last_highlight_range: Option<(usize, usize, u32)>,
11951214
}
11961215

11971216
// Adapter to convert rope chunks to bytes
@@ -1224,7 +1243,7 @@ struct HighlightIterLayer<'a> {
12241243
config: &'a HighlightConfiguration,
12251244
highlight_end_stack: Vec<usize>,
12261245
scope_stack: Vec<LocalScope<'a>>,
1227-
depth: usize,
1246+
depth: u32,
12281247
ranges: &'a [Range],
12291248
}
12301249

0 commit comments

Comments
 (0)