fix(query): skip passthrough steps when checking for fallible step splitting

Problem: In queries matching a parent node with anchored children
(siblings) where the first sibling has a quantifier and is not
captured, the check for fallible steps skips splitting the state because
the next node is a passthrough node (and not an is_immediate one). This
prevents the query from matching beyond the first occurrence.

Solution: In the check for fallible steps, skip the next steps if they
are passthrough steps.
This commit is contained in:
Lucas M. de Jong Larrarte 2026-05-18 00:08:35 +02:00 committed by Christian Clason
parent 8b43f42dca
commit 99bceec689
2 changed files with 39 additions and 2 deletions

View file

@ -1625,6 +1625,38 @@ fn test_matches_with_anchor_sibling_inside_parent() {
});
}
#[test]
fn test_matches_with_anchor_sibling_with_quantifier_inside_parent() {
allocations::record(|| {
let language = get_language("rust");
let query = Query::new(
&language,
"
(source_file
(line_comment)+
.
(function_item
name: (identifier) @name)
)",
)
.unwrap();
assert_query_matches(
&language,
&query,
"
// A
fn a() {}
// B
fn b() {}
",
&[(0, vec![("name", "a")]), (0, vec![("name", "b")])],
);
});
}
#[test]
fn test_matches_with_anchor_sibling_with_quantifier_captured_inside_parent() {
allocations::record(|| {

View file

@ -3287,9 +3287,14 @@ bool ts_query__step_is_fallible(
const TSQuery *self,
uint16_t step_index
) {
ts_assert((uint32_t)step_index + 1 < self->steps.size);
unsigned i = 1;
QueryStep *step = array_get(&self->steps, step_index);
QueryStep *next_step = array_get(&self->steps, step_index + 1);
QueryStep *next_step;
do {
ts_assert((uint32_t)step_index + i < self->steps.size);
next_step = array_get(&self->steps, step_index + i);
i++;
} while (next_step->is_pass_through);
return (
next_step->depth != PATTERN_DONE_MARKER &&
(next_step->depth > step->depth ||