Skip to content

Commit

Permalink
Update tree-sitter to 0.20
Browse files Browse the repository at this point in the history
0.20 includes querying improvements, we no longer have to convert
fragments to strings but can return an iterator of chunks instead.
  • Loading branch information
archseer committed Sep 6, 2021
1 parent 57ed518 commit 3cb95be
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 42 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion helix-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ unicode-segmentation = "1.8"
unicode-width = "0.1"
unicode-general-category = "0.4"
# slab = "0.4.2"
tree-sitter = "0.19"
tree-sitter = "0.20"
once_cell = "1.8"
arc-swap = "1"
regex = "1"
Expand Down
79 changes: 41 additions & 38 deletions helix-core/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,16 +276,6 @@ fn byte_range_to_str(range: std::ops::Range<usize>, source: RopeSlice) -> Cow<st
Cow::from(source.slice(start_char..end_char))
}

fn node_to_bytes<'a>(node: Node, source: RopeSlice<'a>) -> Cow<'a, [u8]> {
let start_char = source.byte_to_char(node.start_byte());
let end_char = source.byte_to_char(node.end_byte());
let fragment = source.slice(start_char..end_char);
match fragment.as_str() {
Some(fragment) => Cow::Borrowed(fragment.as_bytes()),
None => Cow::Owned(String::from(fragment).into_bytes()),
}
}

impl Syntax {
// buffer, grammar, config, grammars, sync_timeout?
pub fn new(
Expand Down Expand Up @@ -380,14 +370,11 @@ impl Syntax {

// TODO: if reusing cursors this might need resetting
if let Some(range) = &range {
cursor_ref.set_byte_range(range.start, range.end);
cursor_ref.set_byte_range(range.clone());
}

let captures = cursor_ref
.captures(query_ref, tree_ref.root_node(), move |n: Node| {
// &source[n.byte_range()]
node_to_bytes(n, source)
})
.captures(query_ref, tree_ref.root_node(), RopeProvider(source))
.peekable();

// manually craft the root layer based on the existing tree
Expand Down Expand Up @@ -501,10 +488,7 @@ impl LanguageLayer {
// let mut injections_by_pattern_index =
// vec![(None, Vec::new(), false); combined_injections_query.pattern_count()];
// let matches =
// cursor.matches(combined_injections_query, tree.root_node(), |n: Node| {
// // &source[n.byte_range()]
// node_to_bytes(n, source)
// });
// cursor.matches(combined_injections_query, tree.root_node(), RopeProvider(source));
// for mat in matches {
// let entry = &mut injections_by_pattern_index[mat.pattern_index];
// let (language_name, content_node, include_children) =
Expand Down Expand Up @@ -716,7 +700,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::{iter, mem, ops, str, usize};
use tree_sitter::{
Language as Grammar, Node, Parser, Point, Query, QueryCaptures, QueryCursor, QueryError,
QueryMatch, Range, Tree,
QueryMatch, Range, TextProvider, Tree,
};

const CANCELLATION_CHECK_INTERVAL: usize = 100;
Expand Down Expand Up @@ -776,32 +760,57 @@ struct LocalScope<'a> {
}

#[derive(Debug)]
struct HighlightIter<'a, 'tree: 'a, F>
struct HighlightIter<'a, F>
where
F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
{
source: RopeSlice<'a>,
byte_offset: usize,
injection_callback: F,
cancellation_flag: Option<&'a AtomicUsize>,
layers: Vec<HighlightIterLayer<'a, 'tree>>,
layers: Vec<HighlightIterLayer<'a>>,
iter_count: usize,
next_event: Option<HighlightEvent>,
last_highlight_range: Option<(usize, usize, usize)>,
}

struct HighlightIterLayer<'a, 'tree: 'a> {
// Adapter to convert rope chunks to bytes
struct ChunksBytes<'a> {
chunks: ropey::iter::Chunks<'a>,
}
impl<'a> Iterator for ChunksBytes<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
self.chunks.next().map(str::as_bytes)
}
}

struct RopeProvider<'a>(RopeSlice<'a>);
impl<'a> TextProvider<'a> for RopeProvider<'a> {
type I = ChunksBytes<'a>;

fn text(&mut self, node: Node) -> Self::I {
let start_char = self.0.byte_to_char(node.start_byte());
let end_char = self.0.byte_to_char(node.end_byte());
let fragment = self.0.slice(start_char..end_char);
ChunksBytes {
chunks: fragment.chunks(),
}
}
}

struct HighlightIterLayer<'a> {
_tree: Option<Tree>,
cursor: QueryCursor,
captures: iter::Peekable<QueryCaptures<'a, 'tree, Cow<'a, [u8]>>>,
captures: iter::Peekable<QueryCaptures<'a, 'a, RopeProvider<'a>>>,
config: &'a HighlightConfiguration,
highlight_end_stack: Vec<usize>,
scope_stack: Vec<LocalScope<'a>>,
ranges: Vec<Range>,
depth: usize,
}

impl<'a, 'tree: 'a> fmt::Debug for HighlightIterLayer<'a, 'tree> {
impl<'a> fmt::Debug for HighlightIterLayer<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HighlightIterLayer").finish()
}
Expand Down Expand Up @@ -972,7 +981,7 @@ impl HighlightConfiguration {
}
}

impl<'a, 'tree: 'a> HighlightIterLayer<'a, 'tree> {
impl<'a> HighlightIterLayer<'a> {
/// Create a new 'layer' of highlighting for this document.
///
/// In the even that the new layer contains "combined injections" (injections where multiple
Expand Down Expand Up @@ -1029,10 +1038,7 @@ impl<'a, 'tree: 'a> HighlightIterLayer<'a, 'tree> {
let matches = cursor.matches(
combined_injections_query,
tree.root_node(),
|n: Node| {
// &source[n.byte_range()]
node_to_bytes(n, source)
},
RopeProvider(source),
);
for mat in matches {
let entry = &mut injections_by_pattern_index[mat.pattern_index];
Expand Down Expand Up @@ -1079,10 +1085,7 @@ impl<'a, 'tree: 'a> HighlightIterLayer<'a, 'tree> {
let cursor_ref =
unsafe { mem::transmute::<_, &'static mut QueryCursor>(&mut cursor) };
let captures = cursor_ref
.captures(&config.query, tree_ref.root_node(), move |n: Node| {
// &source[n.byte_range()]
node_to_bytes(n, source)
})
.captures(&config.query, tree_ref.root_node(), RopeProvider(source))
.peekable();

result.push(HighlightIterLayer {
Expand Down Expand Up @@ -1236,7 +1239,7 @@ impl<'a, 'tree: 'a> HighlightIterLayer<'a, 'tree> {
}
}

impl<'a, 'tree: 'a, F> HighlightIter<'a, 'tree, F>
impl<'a, F> HighlightIter<'a, F>
where
F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
{
Expand Down Expand Up @@ -1287,7 +1290,7 @@ where
}
}

fn insert_layer(&mut self, mut layer: HighlightIterLayer<'a, 'tree>) {
fn insert_layer(&mut self, mut layer: HighlightIterLayer<'a>) {
if let Some(sort_key) = layer.sort_key() {
let mut i = 1;
while i < self.layers.len() {
Expand All @@ -1306,7 +1309,7 @@ where
}
}

impl<'a, 'tree: 'a, F> Iterator for HighlightIter<'a, 'tree, F>
impl<'a, F> Iterator for HighlightIter<'a, F>
where
F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a,
{
Expand Down Expand Up @@ -1570,7 +1573,7 @@ where
fn injection_for_match<'a>(
config: &HighlightConfiguration,
query: &'a Query,
query_match: &QueryMatch<'a>,
query_match: &QueryMatch<'a, 'a>,
source: RopeSlice<'a>,
) -> (Option<Cow<'a, str>>, Option<Node<'a>>, bool) {
let content_capture_index = config.injection_content_capture_index;
Expand Down
2 changes: 1 addition & 1 deletion helix-syntax/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ homepage = "https://helix-editor.com"
include = ["src/**/*", "languages/**/*", "build.rs", "!**/docs/**/*", "!**/test/**/*", "!**/examples/**/*", "!**/build/**/*"]

[dependencies]
tree-sitter = "0.19"
tree-sitter = "0.20"
libloading = "0.7"
anyhow = "1"

Expand Down

0 comments on commit 3cb95be

Please sign in to comment.