Skip to content

Commit

Permalink
do not reparse unmodified injections
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalkuthe committed Oct 8, 2022
1 parent 18cfe86 commit 6f23b0d
Showing 1 changed file with 39 additions and 20 deletions.
59 changes: 39 additions & 20 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ 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,
Expand Down Expand Up @@ -594,6 +595,7 @@ impl Syntax {
tree: None,
config,
depth: 0,
flags: 0,
ranges: vec![Range {
start_byte: 0,
end_byte: usize::MAX,
Expand Down Expand Up @@ -656,9 +658,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)
if layer.depth == 0 {
layer.flags = LAYER_MODIFIED;
continue;
}

Expand Down Expand Up @@ -689,6 +692,8 @@ impl Syntax {
edit.new_end_position,
point_sub(range.end_point, edit.old_end_position),
);

layer.flags |= LAYER_MOVED;
}
// if the edit starts in the space before and extends into the range
else if edit.start_byte < range.start_byte {
Expand All @@ -703,11 +708,13 @@ impl Syntax {
edit.new_end_position,
point_sub(range.end_point, edit.old_end_position),
);
layer.flags = LAYER_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 |= LAYER_MOVED;
} else {
range.end_byte = range
.end_byte
Expand All @@ -717,6 +724,7 @@ impl Syntax {
edit.new_end_position,
point_sub(range.end_point, edit.old_end_position),
);
layer.flags = LAYER_MODIFIED;
}
}
}
Expand All @@ -731,27 +739,30 @@ impl Syntax {

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 |= LAYER_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 & (LAYER_MODIFIED | LAYER_MOVED) != 0 {
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 & LAYER_MODIFIED != 0 {
// 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];
Expand Down Expand Up @@ -855,6 +866,8 @@ impl Syntax {
config,
depth,
ranges,
// set the modified flag to ensure the layer is parsed
flags: LAYER_MODIFIED,
})
});

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

// Remove all untouched layers
self.layers.retain(|id, _| touched.contains(&id));
self.layers
.retain(|_, layer| replace(&mut layer.flags, 0) & LAYER_TOUCHED != 0);

Ok(())
})
Expand Down Expand Up @@ -968,14 +982,19 @@ impl Syntax {
// TODO: Folding
}

const LAYER_MODIFIED: u32 = 0b001;
const LAYER_MOVED: u32 = 0b010;
const LAYER_TOUCHED: u32 = 0b100;

#[derive(Debug)]
pub struct LanguageLayer {
// mode
// grammar
pub config: Arc<HighlightConfiguration>,
pub(crate) tree: Option<Tree>,
pub ranges: Vec<Range>,
pub depth: usize,
pub depth: u32,
pub flags: u32,
}

impl LanguageLayer {
Expand Down Expand Up @@ -1191,7 +1210,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
Expand Down Expand Up @@ -1224,7 +1243,7 @@ struct HighlightIterLayer<'a> {
config: &'a HighlightConfiguration,
highlight_end_stack: Vec<usize>,
scope_stack: Vec<LocalScope<'a>>,
depth: usize,
depth: u32,
ranges: &'a [Range],
}

Expand Down

0 comments on commit 6f23b0d

Please sign in to comment.