Skip to content

Commit

Permalink
Use a helper function for creating query captures
Browse files Browse the repository at this point in the history
This deduplicates some somewhat complex code between the highlight_iter
and query_iter.
  • Loading branch information
the-mikedavis committed Jan 11, 2024
1 parent 276ba75 commit 11bc183
Showing 1 changed file with 46 additions and 46 deletions.
92 changes: 46 additions & 46 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,37 @@ thread_local! {
})
}

/// Creates an iterator over the captures in a query within the given range,
/// re-using a cursor from the pool if available.
fn query_captures<'a, 'tree>(
query: &'a Query,
root: Node<'tree>,
source: RopeSlice<'a>,
range: Option<std::ops::Range<usize>>,
) -> (
QueryCursor,
QueryCaptures<'a, 'tree, RopeProvider<'a>, &'a [u8]>,
) {
// Reuse a cursor from the pool if available.
let mut cursor = PARSER.with(|ts_parser| {
let highlighter = &mut ts_parser.borrow_mut();
highlighter.cursors.pop().unwrap_or_else(QueryCursor::new)
});

// The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
// prevents them from being moved. But both of these values are really just
// pointers, so it's actually ok to move them.
let cursor_ref = unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };

// if reusing cursors & no range this resets to whole range
cursor_ref.set_byte_range(range.unwrap_or(0..usize::MAX));
cursor_ref.set_match_limit(TREE_SITTER_MATCH_LIMIT);

let captures = cursor_ref.captures(query, root, RopeProvider(source));

(cursor, captures)
}

#[derive(Debug)]
pub struct Syntax {
layers: HopSlotMap<LayerId, LanguageLayer>,
Expand Down Expand Up @@ -1281,28 +1312,13 @@ impl Syntax {
.layers
.iter()
.filter_map(|(_, layer)| {
// Reuse a cursor from the pool if available.
let mut cursor = PARSER.with(|ts_parser| {
let highlighter = &mut ts_parser.borrow_mut();
highlighter.cursors.pop().unwrap_or_else(QueryCursor::new)
});

// The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
// prevents them from being moved. But both of these values are really just
// pointers, so it's actually ok to move them.
let cursor_ref =
unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };

cursor_ref.set_byte_range(range.clone().unwrap_or(0..usize::MAX));
cursor_ref.set_match_limit(TREE_SITTER_MATCH_LIMIT);

let mut captures = cursor_ref
.captures(
query_fn(&layer.config),
layer.tree().root_node(),
RopeProvider(source),
)
.peekable();
let (cursor, captures) = query_captures(
query_fn(&layer.config),
layer.tree().root_node(),
source,
range.clone(),
);
let mut captures = captures.peekable();

// If there aren't any captures for this layer, skip the layer.
captures.peek()?;
Expand Down Expand Up @@ -1333,31 +1349,15 @@ impl Syntax {
.filter_map(|(_, layer)| {
// TODO: if range doesn't overlap layer range, skip it

// Reuse a cursor from the pool if available.
let mut cursor = PARSER.with(|ts_parser| {
let highlighter = &mut ts_parser.borrow_mut();
highlighter.cursors.pop().unwrap_or_else(QueryCursor::new)
});

// The `captures` iterator borrows the `Tree` and the `QueryCursor`, which
// prevents them from being moved. But both of these values are really just
// pointers, so it's actually ok to move them.
let cursor_ref =
unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };

// if reusing cursors & no range this resets to whole range
cursor_ref.set_byte_range(range.clone().unwrap_or(0..usize::MAX));
cursor_ref.set_match_limit(TREE_SITTER_MATCH_LIMIT);

let mut captures = cursor_ref
.captures(
&layer.config.query,
layer.tree().root_node(),
RopeProvider(source),
)
.peekable();
let (cursor, captures) = query_captures(
&layer.config.query,
layer.tree().root_node(),
source,
range.clone(),
);
let mut captures = captures.peekable();

// If there's no captures, skip the layer
// If there are no captures, skip the layer
captures.peek()?;

Some(HighlightIterLayer {
Expand Down

0 comments on commit 11bc183

Please sign in to comment.