Skip to content

Commit 89596f9

Browse files
committed
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.
1 parent 0957a54 commit 89596f9

File tree

1 file changed

+44
-59
lines changed

1 file changed

+44
-59
lines changed

helix-core/src/syntax.rs

+44-59
Original file line numberDiff line numberDiff line change
@@ -1135,13 +1135,39 @@ impl Syntax {
11351135
layer.tree().root_node(),
11361136
RopeProvider(source_slice),
11371137
);
1138+
let mut combined_injections = vec![
1139+
(None, Vec::new(), IncludedChildren::default());
1140+
layer.config.combined_injections_patterns.len()
1141+
];
11381142
let mut injections = Vec::new();
11391143
let mut last_injection_end = 0;
11401144
for mat in matches {
11411145
let (injection_capture, content_node, included_children) = layer
11421146
.config
11431147
.injection_for_match(&layer.config.injections_query, &mat, source_slice);
11441148

1149+
// in case this is a combined injection save it for more processing later
1150+
if let Some(combined_injection_idx) = layer
1151+
.config
1152+
.combined_injections_patterns
1153+
.iter()
1154+
.position(|&pattern| pattern == mat.pattern_index)
1155+
{
1156+
let entry = &mut combined_injections[combined_injection_idx];
1157+
if injection_capture.is_some() {
1158+
entry.0 = injection_capture;
1159+
}
1160+
if let Some(content_node) = content_node {
1161+
if content_node.start_byte() >= last_injection_end {
1162+
entry.2 = included_children;
1163+
} else {
1164+
last_injection_end = content_node.end_byte();
1165+
}
1166+
entry.1.push(content_node);
1167+
}
1168+
continue;
1169+
}
1170+
11451171
// Explicitly remove this match so that none of its other captures will remain
11461172
// in the stream of captures.
11471173
mat.remove();
@@ -1167,43 +1193,13 @@ impl Syntax {
11671193
}
11681194
}
11691195

1170-
// Process combined injections.
1171-
if let Some(combined_injections_query) = &layer.config.combined_injections_query {
1172-
let mut injections_by_pattern_index =
1173-
vec![
1174-
(None, Vec::new(), IncludedChildren::default());
1175-
combined_injections_query.pattern_count()
1176-
];
1177-
let matches = cursor.matches(
1178-
combined_injections_query,
1179-
layer.tree().root_node(),
1180-
RopeProvider(source_slice),
1181-
);
1182-
for mat in matches {
1183-
let entry = &mut injections_by_pattern_index[mat.pattern_index];
1184-
let (injection_capture, content_node, included_children) = layer
1185-
.config
1186-
.injection_for_match(combined_injections_query, &mat, source_slice);
1187-
if injection_capture.is_some() {
1188-
entry.0 = injection_capture;
1189-
}
1190-
if let Some(content_node) = content_node {
1191-
entry.1.push(content_node);
1192-
}
1193-
entry.2 = included_children;
1194-
}
1195-
for (lang_name, content_nodes, included_children) in injections_by_pattern_index
1196-
{
1197-
if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) {
1198-
if let Some(config) = (injection_callback)(&lang_name) {
1199-
let ranges = intersect_ranges(
1200-
&layer.ranges,
1201-
&content_nodes,
1202-
included_children,
1203-
);
1204-
if !ranges.is_empty() {
1205-
injections.push((config, ranges));
1206-
}
1196+
for (lang_name, content_nodes, included_children) in combined_injections {
1197+
if let (Some(lang_name), false) = (lang_name, content_nodes.is_empty()) {
1198+
if let Some(config) = (injection_callback)(&lang_name) {
1199+
let ranges =
1200+
intersect_ranges(&layer.ranges, &content_nodes, included_children);
1201+
if !ranges.is_empty() {
1202+
injections.push((config, ranges));
12071203
}
12081204
}
12091205
}
@@ -1566,7 +1562,7 @@ pub struct HighlightConfiguration {
15661562
pub language: Grammar,
15671563
pub query: Query,
15681564
injections_query: Query,
1569-
combined_injections_query: Option<Query>,
1565+
combined_injections_patterns: Vec<usize>,
15701566
highlights_pattern_index: usize,
15711567
highlight_indices: ArcSwap<Vec<Option<Highlight>>>,
15721568
non_local_variable_patterns: Vec<bool>,
@@ -1682,26 +1678,15 @@ impl HighlightConfiguration {
16821678
}
16831679
}
16841680

1685-
let mut injections_query = Query::new(language, injection_query)?;
1686-
1687-
// Construct a separate query just for dealing with the 'combined injections'.
1688-
// Disable the combined injection patterns in the main query.
1689-
let mut combined_injections_query = Query::new(language, injection_query)?;
1690-
let mut has_combined_queries = false;
1691-
for pattern_index in 0..injections_query.pattern_count() {
1692-
let settings = injections_query.property_settings(pattern_index);
1693-
if settings.iter().any(|s| &*s.key == "injection.combined") {
1694-
has_combined_queries = true;
1695-
injections_query.disable_pattern(pattern_index);
1696-
} else {
1697-
combined_injections_query.disable_pattern(pattern_index);
1698-
}
1699-
}
1700-
let combined_injections_query = if has_combined_queries {
1701-
Some(combined_injections_query)
1702-
} else {
1703-
None
1704-
};
1681+
let injections_query = Query::new(language, injection_query)?;
1682+
let combined_injections_patterns = (0..injections_query.pattern_count())
1683+
.filter(|&i| {
1684+
injections_query
1685+
.property_settings(i)
1686+
.iter()
1687+
.any(|s| &*s.key == "injection.combined")
1688+
})
1689+
.collect();
17051690

17061691
// Find all of the highlighting patterns that are disabled for nodes that
17071692
// have been identified as local variables.
@@ -1750,7 +1735,7 @@ impl HighlightConfiguration {
17501735
language,
17511736
query,
17521737
injections_query,
1753-
combined_injections_query,
1738+
combined_injections_patterns,
17541739
highlights_pattern_index,
17551740
highlight_indices,
17561741
non_local_variable_patterns,

0 commit comments

Comments
 (0)