on master help sign in
do not reparse unmodified injections (#4146)
543d75dPascal Kuthe
Cargo.lock+1
@@ -388,6 +388,7 @@ name = "helix-core"
388version = "0.6.0"
388version = "0.6.0"
389dependencies = [
389dependencies = [
390 "arc-swap",
390 "arc-swap",
391+ "bitflags",
391 "chrono",
392 "chrono",
392 "encoding_rs",
393 "encoding_rs",
393 "etcetera",
394 "etcetera",
helix-core/Cargo.toml+1
@@ -29,6 +29,7 @@ tree-sitter = "0.20"
29once_cell = "1.15"
29once_cell = "1.15"
30arc-swap = "1"
30arc-swap = "1"
31regex = "1"
31regex = "1"
32+bitflags = "1.3"
32
33
33log = "0.4"
34log = "0.4"
34serde = { version = "1.0", features = ["derive"] }
35serde = { version = "1.0", features = ["derive"] }
helix-core/src/syntax.rs+52−21
@@ -8,13 +8,15 @@ use crate::{
8};
8};
9
9
10use arc_swap::{ArcSwap, Guard};
10use arc_swap::{ArcSwap, Guard};
11+use bitflags::bitflags;
11use slotmap::{DefaultKey as LayerId, HopSlotMap};
12use slotmap::{DefaultKey as LayerId, HopSlotMap};
12
13
13use std::{
14use std::{
14 borrow::Cow,
15 borrow::Cow,
15 cell::RefCell,
16 cell::RefCell,
16− collections::{HashMap, HashSet, VecDeque},
17+ collections::{HashMap, VecDeque},
17 fmt,
18 fmt,
19+ mem::replace,
18 path::Path,
20 path::Path,
19 str::FromStr,
21 str::FromStr,
20 sync::Arc,
22 sync::Arc,
@@ -594,6 +596,7 @@ impl Syntax {
594 tree: None,
596 tree: None,
595 config,
597 config,
596 depth: 0,
598 depth: 0,
599+ flags: LayerUpdateFlags::empty(),
597 ranges: vec![Range {
600 ranges: vec![Range {
598 start_byte: 0,
601 start_byte: 0,
599 end_byte: usize::MAX,
602 end_byte: usize::MAX,
@@ -656,9 +659,10 @@ impl Syntax {
656 }
659 }
657 }
660 }
658
661
659− for layer in &mut self.layers.values_mut() {
662+ for layer in self.layers.values_mut() {
660 // The root layer always covers the whole range (0..usize::MAX)
663 // The root layer always covers the whole range (0..usize::MAX)
661 if layer.depth == 0 {
664 if layer.depth == 0 {
665+ layer.flags = LayerUpdateFlags::MODIFIED;
662 continue;
666 continue;
663 }
667 }
664
668
@@ -689,6 +693,8 @@ impl Syntax {
689 edit.new_end_position,
693 edit.new_end_position,
690 point_sub(range.end_point, edit.old_end_position),
694 point_sub(range.end_point, edit.old_end_position),
691 );
695 );
696+
697+ layer.flags |= LayerUpdateFlags::MOVED;
692 }
698 }
693 // if the edit starts in the space before and extends into the range
699 // if the edit starts in the space before and extends into the range
694 else if edit.start_byte < range.start_byte {
700 else if edit.start_byte < range.start_byte {
@@ -703,11 +709,13 @@ impl Syntax {
703 edit.new_end_position,
709 edit.new_end_position,
704 point_sub(range.end_point, edit.old_end_position),
710 point_sub(range.end_point, edit.old_end_position),
705 );
711 );
712+ layer.flags = LayerUpdateFlags::MODIFIED;
706 }
713 }
707 // If the edit is an insertion at the start of the tree, shift
714 // If the edit is an insertion at the start of the tree, shift
708 else if edit.start_byte == range.start_byte && is_pure_insertion {
715 else if edit.start_byte == range.start_byte && is_pure_insertion {
709 range.start_byte = edit.new_end_byte;
716 range.start_byte = edit.new_end_byte;
710 range.start_point = edit.new_end_position;
717 range.start_point = edit.new_end_position;
718+ layer.flags |= LayerUpdateFlags::MOVED;
711 } else {
719 } else {
712 range.end_byte = range
720 range.end_byte = range
713 .end_byte
721 .end_byte
@@ -717,6 +725,7 @@ impl Syntax {
717 edit.new_end_position,
725 edit.new_end_position,
718 point_sub(range.end_point, edit.old_end_position),
726 point_sub(range.end_point, edit.old_end_position),
719 );
727 );
728+ layer.flags = LayerUpdateFlags::MODIFIED;
720 }
729 }
721 }
730 }
722 }
731 }
@@ -731,27 +740,33 @@ impl Syntax {
731
740
732 let source_slice = source.slice(..);
741 let source_slice = source.slice(..);
733
742
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−
738 while let Some(layer_id) = queue.pop_front() {
743 while let Some(layer_id) = queue.pop_front() {
739− // Mark the layer as touched
740− touched.insert(layer_id);
741−
742 let layer = &mut self.layers[layer_id];
744 let layer = &mut self.layers[layer_id];
743
745
746+ // Mark the layer as touched
747+ layer.flags |= LayerUpdateFlags::TOUCHED;
748+
744 // If a tree already exists, notify it of changes.
749 // If a tree already exists, notify it of changes.
745 if let Some(tree) = &mut layer.tree {
750 if let Some(tree) = &mut layer.tree {
751+ if layer
752+ .flags
753+ .intersects(LayerUpdateFlags::MODIFIED | LayerUpdateFlags::MOVED)
754+ {
746− for edit in edits.iter().rev() {
755+ for edit in edits.iter().rev() {
747− // Apply the edits in reverse.
756+ // Apply the edits in reverse.
748− // If we applied them in order then edit 1 would disrupt the positioning of edit 2.
757+ // If we applied them in order then edit 1 would disrupt the positioning of edit 2.
749− tree.edit(edit);
758+ tree.edit(edit);
759+ }
750 }
760 }
751− }
752
761
762+ if layer.flags.contains(LayerUpdateFlags::MODIFIED) {
753− // Re-parse the tree.
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
754− layer.parse(&mut ts_parser.parser, source)?;
768+ layer.parse(&mut ts_parser.parser, source)?;
769+ }
755
770
756 // Switch to an immutable borrow.
771 // Switch to an immutable borrow.
757 let layer = &self.layers[layer_id];
772 let layer = &self.layers[layer_id];
@@ -855,6 +870,8 @@ impl Syntax {
855 config,
870 config,
856 depth,
871 depth,
857 ranges,
872 ranges,
873+ // set the modified flag to ensure the layer is parsed
874+ flags: LayerUpdateFlags::empty(),
858 })
875 })
859 });
876 });
860
877
@@ -868,8 +885,11 @@ impl Syntax {
868 // Return the cursor back in the pool.
885 // Return the cursor back in the pool.
869 ts_parser.cursors.push(cursor);
886 ts_parser.cursors.push(cursor);
870
887
871− // Remove all untouched layers
888+ // Reset all `LayerUpdateFlags` and remove all untouched layers
872− self.layers.retain(|id, _| touched.contains(&id));
889+ self.layers.retain(|_, layer| {
890+ replace(&mut layer.flags, LayerUpdateFlags::empty())
891+ .contains(LayerUpdateFlags::TOUCHED)
892+ });
873
893
874 Ok(())
894 Ok(())
875 })
895 })
@@ -968,6 +988,16 @@ impl Syntax {
968 // TODO: Folding
988 // TODO: Folding
969}
989}
970
990
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+
971#[derive(Debug)]
1001#[derive(Debug)]
972pub struct LanguageLayer {
1002pub struct LanguageLayer {
973 // mode
1003 // mode
@@ -975,7 +1005,8 @@ pub struct LanguageLayer {
975 pub config: Arc<HighlightConfiguration>,
1005 pub config: Arc<HighlightConfiguration>,
976 pub(crate) tree: Option<Tree>,
1006 pub(crate) tree: Option<Tree>,
977 pub ranges: Vec<Range>,
1007 pub ranges: Vec<Range>,
978− pub depth: usize,
1008+ pub depth: u32,
1009+ flags: LayerUpdateFlags,
979}
1010}
980
1011
981impl LanguageLayer {
1012impl LanguageLayer {
@@ -1191,7 +1222,7 @@ struct HighlightIter<'a> {
1191 layers: Vec<HighlightIterLayer<'a>>,
1222 layers: Vec<HighlightIterLayer<'a>>,
1192 iter_count: usize,
1223 iter_count: usize,
1193 next_event: Option<HighlightEvent>,
1224 next_event: Option<HighlightEvent>,
1194− last_highlight_range: Option<(usize, usize, usize)>,
1225+ last_highlight_range: Option<(usize, usize, u32)>,
1195}
1226}
1196
1227
1197// Adapter to convert rope chunks to bytes
1228// Adapter to convert rope chunks to bytes
@@ -1224,7 +1255,7 @@ struct HighlightIterLayer<'a> {
1224 config: &'a HighlightConfiguration,
1255 config: &'a HighlightConfiguration,
1225 highlight_end_stack: Vec<usize>,
1256 highlight_end_stack: Vec<usize>,
1226 scope_stack: Vec<LocalScope<'a>>,
1257 scope_stack: Vec<LocalScope<'a>>,
1227− depth: usize,
1258+ depth: u32,
1228 ranges: &'a [Range],
1259 ranges: &'a [Range],
1229}
1260}
1230
1261