fix(lib): propagate last_child status to pattern alternatives in queries

Previously, when a pattern was marked as the last child in a query, its
alternatives weren't marked similarly, causing incorrect matching
behavior. Now, the `last_child` status is properly propagated through
all alternatives.
This commit is contained in:
Amaan Qureshi 2025-01-03 20:48:53 -05:00
parent f8e77aa99d
commit a7e6d01144
2 changed files with 92 additions and 1 deletions

View file

@ -5442,3 +5442,81 @@ fn test_wildcard_behavior_before_anchor() {
],
);
}
#[test]
fn test_pattern_alternatives_follow_last_child_constraint() {
let language = get_language("rust");
let mut parser = Parser::new();
parser.set_language(&language).unwrap();
let code = "
fn f() {
if a {} // <- should NOT match
if b {}
}";
let tree = parser.parse(code, None).unwrap();
let mut cursor = QueryCursor::new();
let query = Query::new(
&language,
"(block
[
(type_cast_expression)
(expression_statement)
] @last
.
)",
)
.unwrap();
let matches = {
let root_node = tree.root_node();
let matches = cursor.matches(&query, root_node, code.as_bytes());
collect_matches(matches, &query, code)
.into_iter()
.map(|(i, m)| {
(
i,
m.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>()
};
let flipped_query = Query::new(
&language,
"(block
[
(expression_statement)
(type_cast_expression)
] @last
.
)",
)
.unwrap();
let flipped_matches = {
let root_node = tree.root_node();
let matches = cursor.matches(&flipped_query, root_node, code.as_bytes());
collect_matches(matches, &flipped_query, code)
.into_iter()
.map(|(i, m)| {
(
i,
m.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>()
};
assert_eq!(
matches,
vec![(0, vec![(String::from("last"), String::from("if b {}"))])]
);
assert_eq!(matches, flipped_matches);
}