From b4bf968503a00e5909fea193fd57d014240b8226 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 1 Feb 2023 15:50:55 -0600 Subject: [PATCH] Share sort_layers function between query iterators The code in the `sort_layers` function was fully duplicated between the HighlightIter and the QueryIter. This change adds a common `sort_layers` function that accepts a layer Vec from both. --- helix-core/src/syntax.rs | 153 +++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 87 deletions(-) diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index 74950c740..28c0fa550 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -1475,7 +1475,7 @@ impl Syntax { range: Option>, cancellation_flag: Option<&'a AtomicUsize>, ) -> impl Iterator> + 'a { - let mut layers = self + let mut layers: Vec<_> = self .layers .iter() .filter_map(|(_, layer)| { @@ -1525,11 +1525,13 @@ impl Syntax { depth: layer.depth, // TODO: just reuse `layer` }) }) - .collect::>(); + .collect(); layers.sort_unstable_by_key(|layer| layer.sort_key()); - let mut result = HighlightIter { + sort_layers(&mut layers); + + HighlightIter { source, byte_offset: range.map_or(0, |r| r.start), cancellation_flag, @@ -1537,9 +1539,7 @@ impl Syntax { layers, next_event: None, last_highlight_range: None, - }; - result.sort_layers(); - result + } } pub fn tree_for_byte_range(&self, start: usize, end: usize) -> &Tree { @@ -2343,6 +2343,58 @@ impl<'a> IterLayer for QueryIterLayer<'a> { self.cursor } } + +/// Re-sort the given layers so that the next capture for the `layers[0]` is +/// the earliest capture in the document for all layers. +/// +/// This function assumes that `layers` is already sorted except for the +/// first layer in the `Vec`. This function shifts the first layer later in +/// the `Vec` after any layers with earlier captures. +/// +/// This is quicker than a regular full sort: it can only take as many +/// iterations as the number of layers and usually takes many fewer than +/// the full number of layers. The case when `layers[0]` is already the +/// layer with the earliest capture and the sort is a no-op is a fast-lane +/// which only takes one comparison operation. +/// +/// This function also removes any layers which have no more query captures +/// to emit. +fn sort_layers(layers: &mut Vec) { + while !layers.is_empty() { + // If `Layer::sort_key` returns `None`, the layer has no more captures + // to emit and can be removed. + if let Some(sort_key) = layers[0].sort_key() { + let mut i = 0; + while i + 1 < layers.len() { + if let Some(next_offset) = layers[i + 1].sort_key() { + // Compare `0`'s sort key to `i + 1`'s. If `i + 1` comes + // before `0`, shift the `0` layer so it comes after the + // `i + 1` layers. + if next_offset < sort_key { + i += 1; + continue; + } + } else { + let layer = layers.remove(i + 1); + PARSER.with(|ts_parser| { + let highlighter = &mut ts_parser.borrow_mut(); + highlighter.cursors.push(layer.cursor()); + }); + } + break; + } + if i > 0 { + layers[0..(i + 1)].rotate_left(1); + } + break; + } else { + let layer = layers.remove(0); + PARSER.with(|ts_parser| { + let highlighter = &mut ts_parser.borrow_mut(); + highlighter.cursors.push(layer.cursor()); + }); + } + } } #[derive(Clone)] @@ -2473,42 +2525,9 @@ impl<'a> HighlightIter<'a> { } else { result = event.map(Ok); } - self.sort_layers(); + sort_layers(&mut self.layers); result } - - fn sort_layers(&mut self) { - while !self.layers.is_empty() { - if let Some(sort_key) = self.layers[0].sort_key() { - let mut i = 0; - while i + 1 < self.layers.len() { - if let Some(next_offset) = self.layers[i + 1].sort_key() { - if next_offset < sort_key { - i += 1; - continue; - } - } else { - let layer = self.layers.remove(i + 1); - PARSER.with(|ts_parser| { - let highlighter = &mut ts_parser.borrow_mut(); - highlighter.cursors.push(layer.cursor); - }); - } - break; - } - if i > 0 { - self.layers[0..(i + 1)].rotate_left(1); - } - break; - } else { - let layer = self.layers.remove(0); - PARSER.with(|ts_parser| { - let highlighter = &mut ts_parser.borrow_mut(); - highlighter.cursors.push(layer.cursor); - }); - } - } - } } impl<'a> Iterator for HighlightIter<'a> { @@ -2660,7 +2679,7 @@ impl<'a> Iterator for HighlightIter<'a> { } } - self.sort_layers(); + sort_layers(&mut self.layers); continue 'main; } @@ -2669,7 +2688,7 @@ impl<'a> Iterator for HighlightIter<'a> { // a different layer, then skip over this one. if let Some((last_start, last_end, last_depth)) = self.last_highlight_range { if range.start == last_start && range.end == last_end && layer.depth < last_depth { - self.sort_layers(); + sort_layers(&mut self.layers); continue 'main; } } @@ -2688,7 +2707,7 @@ impl<'a> Iterator for HighlightIter<'a> { } } - self.sort_layers(); + sort_layers(&mut self.layers); continue 'main; } } @@ -2723,7 +2742,7 @@ impl<'a> Iterator for HighlightIter<'a> { .emit_event(range.start, Some(HighlightEvent::HighlightStart(highlight))); } - self.sort_layers(); + sort_layers(&mut self.layers); } } } @@ -2937,7 +2956,7 @@ fn pretty_print_tree_impl( struct QueryIterLayer<'a> { cursor: QueryCursor, - captures: iter::Peekable, &'a [u8]>>, + captures: RefCell, &'a [u8]>>>, layer: &'a LanguageLayer, } @@ -2947,16 +2966,6 @@ impl<'a> fmt::Debug for QueryIterLayer<'a> { } } -impl<'a> QueryIterLayer<'a> { - fn sort_key(&mut self) -> Option<(usize, isize)> { - let depth = -(self.layer.depth as isize); - let (match_, capture_index) = self.captures.peek()?; - let start = match_.captures[*capture_index].node.start_byte(); - - Some((start, depth)) - } -} - #[derive(Debug)] pub struct QueryIter<'a> { layers: Vec>, @@ -2966,38 +2975,8 @@ impl<'a> Iterator for QueryIter<'a> { type Item = (&'a LanguageLayer, QueryMatch<'a, 'a>, usize); fn next(&mut self) -> Option { - // Sort the layers so that the first layer in the Vec has the next - // capture ordered by start byte and depth (descending). - while !self.layers.is_empty() { - if let Some(sort_key) = self.layers[0].sort_key() { - let mut i = 0; - while i + 1 < self.layers.len() { - if let Some(next_sort_key) = self.layers[i + 1].sort_key() { - if next_sort_key < sort_key { - i += 1; - continue; - } - } else { - let layer = self.layers.remove(i + 1); - PARSER.with(|ts_parser| { - let parser = &mut ts_parser.borrow_mut(); - parser.cursors.push(layer.cursor); - }); - } - break; - } - if i > 0 { - self.layers[0..(i + 1)].rotate_left(1); - } - break; - } else { - let layer = self.layers.remove(0); - PARSER.with(|ts_parser| { - let parser = &mut ts_parser.borrow_mut(); - parser.cursors.push(layer.cursor); - }) - } - } + // Sort the layers so that the first layer contains the next capture. + sort_layers(&mut self.layers); // Emit the next capture from the lowest layer. If there are no more // layers, terminate.