|
|
@ -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,18 +740,18 @@ 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 {
|
|
|
|
|
|
|
|
if layer
|
|
|
|
|
|
|
|
.flags
|
|
|
|
|
|
|
|
.intersects(LayerUpdateFlags::MODIFIED | LayerUpdateFlags::MOVED)
|
|
|
|
|
|
|
|
{
|
|
|
|
for edit in edits.iter().rev() {
|
|
|
|
for edit in edits.iter().rev() {
|
|
|
|
// Apply the edits in reverse.
|
|
|
|
// Apply the edits in reverse.
|
|
|
|
// If we applied them in order then edit 1 would disrupt the positioning of edit 2.
|
|
|
|
// If we applied them in order then edit 1 would disrupt the positioning of edit 2.
|
|
|
@ -750,8 +759,14 @@ impl Syntax {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if layer.flags.contains(LayerUpdateFlags::MODIFIED) {
|
|
|
|
// Re-parse the tree.
|
|
|
|
// Re-parse the tree.
|
|
|
|
layer.parse(&mut ts_parser.parser, source)?;
|
|
|
|
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],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|