|
|
@ -234,7 +234,6 @@ impl Syntax {
|
|
|
|
/// Iterate over the highlighted regions for a given slice of source code.
|
|
|
|
/// Iterate over the highlighted regions for a given slice of source code.
|
|
|
|
pub fn highlight_iter<'a>(
|
|
|
|
pub fn highlight_iter<'a>(
|
|
|
|
&self,
|
|
|
|
&self,
|
|
|
|
ts_parser: &'a mut TSParser,
|
|
|
|
|
|
|
|
source: &'a [u8],
|
|
|
|
source: &'a [u8],
|
|
|
|
range: Option<std::ops::Range<usize>>,
|
|
|
|
range: Option<std::ops::Range<usize>>,
|
|
|
|
cancellation_flag: Option<&'a AtomicUsize>,
|
|
|
|
cancellation_flag: Option<&'a AtomicUsize>,
|
|
|
@ -288,7 +287,6 @@ impl Syntax {
|
|
|
|
byte_offset: range.map(|r| r.start).unwrap_or(0), // TODO: simplify
|
|
|
|
byte_offset: range.map(|r| r.start).unwrap_or(0), // TODO: simplify
|
|
|
|
injection_callback,
|
|
|
|
injection_callback,
|
|
|
|
cancellation_flag,
|
|
|
|
cancellation_flag,
|
|
|
|
highlighter: ts_parser,
|
|
|
|
|
|
|
|
iter_count: 0,
|
|
|
|
iter_count: 0,
|
|
|
|
layers: vec![layer],
|
|
|
|
layers: vec![layer],
|
|
|
|
next_event: None,
|
|
|
|
next_event: None,
|
|
|
@ -659,7 +657,6 @@ where
|
|
|
|
{
|
|
|
|
{
|
|
|
|
source: &'a [u8],
|
|
|
|
source: &'a [u8],
|
|
|
|
byte_offset: usize,
|
|
|
|
byte_offset: usize,
|
|
|
|
highlighter: &'a mut TSParser,
|
|
|
|
|
|
|
|
injection_callback: F,
|
|
|
|
injection_callback: F,
|
|
|
|
cancellation_flag: Option<&'a AtomicUsize>,
|
|
|
|
cancellation_flag: Option<&'a AtomicUsize>,
|
|
|
|
layers: Vec<HighlightIterLayer<'a>>,
|
|
|
|
layers: Vec<HighlightIterLayer<'a>>,
|
|
|
@ -846,7 +843,6 @@ impl<'a> HighlightIterLayer<'a> {
|
|
|
|
/// added to the returned vector.
|
|
|
|
/// added to the returned vector.
|
|
|
|
fn new<F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a>(
|
|
|
|
fn new<F: FnMut(&str) -> Option<&'a HighlightConfiguration> + 'a>(
|
|
|
|
source: &'a [u8],
|
|
|
|
source: &'a [u8],
|
|
|
|
highlighter: &mut TSParser,
|
|
|
|
|
|
|
|
cancellation_flag: Option<&'a AtomicUsize>,
|
|
|
|
cancellation_flag: Option<&'a AtomicUsize>,
|
|
|
|
injection_callback: &mut F,
|
|
|
|
injection_callback: &mut F,
|
|
|
|
mut config: &'a HighlightConfiguration,
|
|
|
|
mut config: &'a HighlightConfiguration,
|
|
|
@ -858,86 +854,103 @@ impl<'a> HighlightIterLayer<'a> {
|
|
|
|
loop {
|
|
|
|
loop {
|
|
|
|
// --> Tree parsing part
|
|
|
|
// --> Tree parsing part
|
|
|
|
|
|
|
|
|
|
|
|
if highlighter.parser.set_included_ranges(&ranges).is_ok() {
|
|
|
|
PARSER.with(|ts_parser| {
|
|
|
|
highlighter
|
|
|
|
let highlighter = &mut ts_parser.borrow_mut();
|
|
|
|
.parser
|
|
|
|
|
|
|
|
.set_language(config.language)
|
|
|
|
if highlighter.parser.set_included_ranges(&ranges).is_ok() {
|
|
|
|
.map_err(|_| Error::InvalidLanguage)?;
|
|
|
|
highlighter
|
|
|
|
|
|
|
|
.parser
|
|
|
|
unsafe { highlighter.parser.set_cancellation_flag(cancellation_flag) };
|
|
|
|
.set_language(config.language)
|
|
|
|
let tree = highlighter
|
|
|
|
.map_err(|_| Error::InvalidLanguage)?;
|
|
|
|
.parser
|
|
|
|
|
|
|
|
.parse(source, None)
|
|
|
|
unsafe { highlighter.parser.set_cancellation_flag(cancellation_flag) };
|
|
|
|
.ok_or(Error::Cancelled)?;
|
|
|
|
let tree = highlighter
|
|
|
|
unsafe { highlighter.parser.set_cancellation_flag(None) };
|
|
|
|
.parser
|
|
|
|
let mut cursor = highlighter.cursors.pop().unwrap_or_else(QueryCursor::new);
|
|
|
|
.parse(source, None)
|
|
|
|
|
|
|
|
.ok_or(Error::Cancelled)?;
|
|
|
|
// Process combined injections.
|
|
|
|
unsafe { highlighter.parser.set_cancellation_flag(None) };
|
|
|
|
if let Some(combined_injections_query) = &config.combined_injections_query {
|
|
|
|
let mut cursor = highlighter.cursors.pop().unwrap_or_else(QueryCursor::new);
|
|
|
|
let mut injections_by_pattern_index =
|
|
|
|
|
|
|
|
vec![(None, Vec::new(), false); combined_injections_query.pattern_count()];
|
|
|
|
// Process combined injections.
|
|
|
|
let matches =
|
|
|
|
if let Some(combined_injections_query) = &config.combined_injections_query {
|
|
|
|
cursor.matches(combined_injections_query, tree.root_node(), |n: Node| {
|
|
|
|
let mut injections_by_pattern_index = vec![
|
|
|
|
&source[n.byte_range()]
|
|
|
|
(None, Vec::new(), false);
|
|
|
|
});
|
|
|
|
combined_injections_query
|
|
|
|
for mat in matches {
|
|
|
|
.pattern_count()
|
|
|
|
let entry = &mut injections_by_pattern_index[mat.pattern_index];
|
|
|
|
];
|
|
|
|
let (language_name, content_node, include_children) =
|
|
|
|
let matches = cursor.matches(
|
|
|
|
injection_for_match(config, combined_injections_query, &mat, source);
|
|
|
|
combined_injections_query,
|
|
|
|
if language_name.is_some() {
|
|
|
|
tree.root_node(),
|
|
|
|
entry.0 = language_name;
|
|
|
|
|n: Node| &source[n.byte_range()],
|
|
|
|
}
|
|
|
|
);
|
|
|
|
if let Some(content_node) = content_node {
|
|
|
|
for mat in matches {
|
|
|
|
entry.1.push(content_node);
|
|
|
|
let entry = &mut injections_by_pattern_index[mat.pattern_index];
|
|
|
|
}
|
|
|
|
let (language_name, content_node, include_children) =
|
|
|
|
entry.2 = include_children;
|
|
|
|
injection_for_match(
|
|
|
|
}
|
|
|
|
config,
|
|
|
|
for (lang_name, content_nodes, includes_children) in injections_by_pattern_index
|
|
|
|
combined_injections_query,
|
|
|
|
{
|
|
|
|
&mat,
|
|
|
|
if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) {
|
|
|
|
source,
|
|
|
|
if let Some(next_config) = (injection_callback)(lang_name) {
|
|
|
|
|
|
|
|
let ranges = Self::intersect_ranges(
|
|
|
|
|
|
|
|
&ranges,
|
|
|
|
|
|
|
|
&content_nodes,
|
|
|
|
|
|
|
|
includes_children,
|
|
|
|
|
|
|
|
);
|
|
|
|
);
|
|
|
|
if !ranges.is_empty() {
|
|
|
|
if language_name.is_some() {
|
|
|
|
queue.push((next_config, depth + 1, ranges));
|
|
|
|
entry.0 = language_name;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(content_node) = content_node {
|
|
|
|
|
|
|
|
entry.1.push(content_node);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
entry.2 = include_children;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (lang_name, content_nodes, includes_children) in
|
|
|
|
|
|
|
|
injections_by_pattern_index
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty())
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if let Some(next_config) = (injection_callback)(lang_name) {
|
|
|
|
|
|
|
|
let ranges = Self::intersect_ranges(
|
|
|
|
|
|
|
|
&ranges,
|
|
|
|
|
|
|
|
&content_nodes,
|
|
|
|
|
|
|
|
includes_children,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
if !ranges.is_empty() {
|
|
|
|
|
|
|
|
queue.push((next_config, depth + 1, ranges));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --> Highlighting query part
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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 tree_ref = unsafe { mem::transmute::<_, &'static Tree>(&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()]
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.peekable();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.push(HighlightIterLayer {
|
|
|
|
|
|
|
|
highlight_end_stack: Vec::new(),
|
|
|
|
|
|
|
|
scope_stack: vec![LocalScope {
|
|
|
|
|
|
|
|
inherits: false,
|
|
|
|
|
|
|
|
range: 0..usize::MAX,
|
|
|
|
|
|
|
|
local_defs: Vec::new(),
|
|
|
|
|
|
|
|
}],
|
|
|
|
|
|
|
|
cursor,
|
|
|
|
|
|
|
|
depth,
|
|
|
|
|
|
|
|
_tree: Some(tree),
|
|
|
|
|
|
|
|
captures,
|
|
|
|
|
|
|
|
config,
|
|
|
|
|
|
|
|
ranges,
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --> Highlighting query part
|
|
|
|
Ok(()) // so we can use the try operator
|
|
|
|
|
|
|
|
})?;
|
|
|
|
// 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 tree_ref = unsafe { mem::transmute::<_, &'static Tree>(&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()]
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.peekable();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.push(HighlightIterLayer {
|
|
|
|
|
|
|
|
highlight_end_stack: Vec::new(),
|
|
|
|
|
|
|
|
scope_stack: vec![LocalScope {
|
|
|
|
|
|
|
|
inherits: false,
|
|
|
|
|
|
|
|
range: 0..usize::MAX,
|
|
|
|
|
|
|
|
local_defs: Vec::new(),
|
|
|
|
|
|
|
|
}],
|
|
|
|
|
|
|
|
cursor,
|
|
|
|
|
|
|
|
depth,
|
|
|
|
|
|
|
|
_tree: Some(tree),
|
|
|
|
|
|
|
|
captures,
|
|
|
|
|
|
|
|
config,
|
|
|
|
|
|
|
|
ranges,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if queue.is_empty() {
|
|
|
|
if queue.is_empty() {
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -1114,7 +1127,10 @@ where
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
let layer = self.layers.remove(0);
|
|
|
|
let layer = self.layers.remove(0);
|
|
|
|
self.highlighter.cursors.push(layer.cursor);
|
|
|
|
PARSER.with(|ts_parser| {
|
|
|
|
|
|
|
|
let highlighter = &mut ts_parser.borrow_mut();
|
|
|
|
|
|
|
|
highlighter.cursors.push(layer.cursor);
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1228,7 +1244,6 @@ where
|
|
|
|
if !ranges.is_empty() {
|
|
|
|
if !ranges.is_empty() {
|
|
|
|
match HighlightIterLayer::new(
|
|
|
|
match HighlightIterLayer::new(
|
|
|
|
self.source,
|
|
|
|
self.source,
|
|
|
|
self.highlighter,
|
|
|
|
|
|
|
|
self.cancellation_flag,
|
|
|
|
self.cancellation_flag,
|
|
|
|
&mut self.injection_callback,
|
|
|
|
&mut self.injection_callback,
|
|
|
|
config,
|
|
|
|
config,
|
|
|
|