use a single query for injections

In the past we used two separate queries for combined and normal injections. There was no real reason for this (except historical/slightly easier implementation). Instead, we now use a single query and simply check if an injection corresponds to a combined injection or not.
This commit is contained in:
Pascal Kuthe 2023-07-14 00:55:12 +02:00 committed by Blaž Hrastnik
parent 2d5ff9ec8f
commit 68a98ac36b

View file

@ -1135,6 +1135,10 @@ impl Syntax {
layer.tree().root_node(), layer.tree().root_node(),
RopeProvider(source_slice), RopeProvider(source_slice),
); );
let mut combined_injections = vec![
(None, Vec::new(), IncludedChildren::default());
layer.config.combined_injections_patterns.len()
];
let mut injections = Vec::new(); let mut injections = Vec::new();
let mut last_injection_end = 0; let mut last_injection_end = 0;
for mat in matches { for mat in matches {
@ -1142,6 +1146,27 @@ impl Syntax {
.config .config
.injection_for_match(&layer.config.injections_query, &mat, source_slice); .injection_for_match(&layer.config.injections_query, &mat, source_slice);
// in case this is a combined injection save it for more processing later
if let Some(combined_injection_idx) = layer
.config
.combined_injections_patterns
.iter()
.position(|&pattern| pattern == mat.pattern_index)
{
let entry = &mut combined_injections[combined_injection_idx];
if injection_capture.is_some() {
entry.0 = injection_capture;
}
if let Some(content_node) = content_node {
if content_node.start_byte() >= last_injection_end {
entry.1.push(content_node);
last_injection_end = content_node.end_byte();
}
}
entry.2 = included_children;
continue;
}
// Explicitly remove this match so that none of its other captures will remain // Explicitly remove this match so that none of its other captures will remain
// in the stream of captures. // in the stream of captures.
mat.remove(); mat.remove();
@ -1166,43 +1191,13 @@ impl Syntax {
} }
} }
// Process combined injections. for (lang_name, content_nodes, included_children) in combined_injections {
if let Some(combined_injections_query) = &layer.config.combined_injections_query { if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) {
let mut injections_by_pattern_index = if let Some(config) = (injection_callback)(&lang_name) {
vec![ let ranges =
(None, Vec::new(), IncludedChildren::default()); intersect_ranges(&layer.ranges, &content_nodes, included_children);
combined_injections_query.pattern_count() if !ranges.is_empty() {
]; injections.push((config, ranges));
let matches = cursor.matches(
combined_injections_query,
layer.tree().root_node(),
RopeProvider(source_slice),
);
for mat in matches {
let entry = &mut injections_by_pattern_index[mat.pattern_index];
let (injection_capture, content_node, included_children) = layer
.config
.injection_for_match(combined_injections_query, &mat, source_slice);
if injection_capture.is_some() {
entry.0 = injection_capture;
}
if let Some(content_node) = content_node {
entry.1.push(content_node);
}
entry.2 = included_children;
}
for (lang_name, content_nodes, included_children) in injections_by_pattern_index
{
if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) {
if let Some(config) = (injection_callback)(&lang_name) {
let ranges = intersect_ranges(
&layer.ranges,
&content_nodes,
included_children,
);
if !ranges.is_empty() {
injections.push((config, ranges));
}
} }
} }
} }
@ -1565,7 +1560,7 @@ pub struct HighlightConfiguration {
pub language: Grammar, pub language: Grammar,
pub query: Query, pub query: Query,
injections_query: Query, injections_query: Query,
combined_injections_query: Option<Query>, combined_injections_patterns: Vec<usize>,
highlights_pattern_index: usize, highlights_pattern_index: usize,
highlight_indices: ArcSwap<Vec<Option<Highlight>>>, highlight_indices: ArcSwap<Vec<Option<Highlight>>>,
non_local_variable_patterns: Vec<bool>, non_local_variable_patterns: Vec<bool>,
@ -1681,26 +1676,15 @@ impl HighlightConfiguration {
} }
} }
let mut injections_query = Query::new(language, injection_query)?; let injections_query = Query::new(language, injection_query)?;
let combined_injections_patterns = (0..injections_query.pattern_count())
// Construct a separate query just for dealing with the 'combined injections'. .filter(|&i| {
// Disable the combined injection patterns in the main query. injections_query
let mut combined_injections_query = Query::new(language, injection_query)?; .property_settings(i)
let mut has_combined_queries = false; .iter()
for pattern_index in 0..injections_query.pattern_count() { .any(|s| &*s.key == "injection.combined")
let settings = injections_query.property_settings(pattern_index); })
if settings.iter().any(|s| &*s.key == "injection.combined") { .collect();
has_combined_queries = true;
injections_query.disable_pattern(pattern_index);
} else {
combined_injections_query.disable_pattern(pattern_index);
}
}
let combined_injections_query = if has_combined_queries {
Some(combined_injections_query)
} else {
None
};
// Find all of the highlighting patterns that are disabled for nodes that // Find all of the highlighting patterns that are disabled for nodes that
// have been identified as local variables. // have been identified as local variables.
@ -1749,7 +1733,7 @@ impl HighlightConfiguration {
language, language,
query, query,
injections_query, injections_query,
combined_injections_query, combined_injections_patterns,
highlights_pattern_index, highlights_pattern_index,
highlight_indices, highlight_indices,
non_local_variable_patterns, non_local_variable_patterns,