fix(rust): EqCapture accepted cases where number of captured nodes differed by one

Problem: When using alternations, the `#eq?` predicate does not always use the same capture name.

Solution: Iterate the left and right captured nodes more independently.
This commit is contained in:
Quentin LE DILAVREC 2025-08-27 10:25:29 +02:00 committed by GitHub
parent 0a7274678a
commit 79177a1cd5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 60 additions and 3 deletions

View file

@ -2999,6 +2999,61 @@ fn test_query_matches_with_deeply_nested_patterns_with_fields() {
});
}
#[test]
fn test_query_matches_with_alternations_and_predicates() {
allocations::record(|| {
let language = get_language("java");
let query = Query::new(
&language,
"
(block
[
(local_variable_declaration
(variable_declarator
(identifier) @def.a
(string_literal) @lit.a
)
)
(local_variable_declaration
(variable_declarator
(identifier) @def.b
(null_literal) @lit.b
)
)
]
(expression_statement
(method_invocation [
(argument_list
(identifier) @ref.a
(string_literal)
)
(argument_list
(null_literal)
(identifier) @ref.b
)
])
)
(#eq? @def.a @ref.a )
(#eq? @def.b @ref.b )
)
",
)
.unwrap();
assert_query_matches(
&language,
&query,
r#"
void test() {
int a = "foo";
f(null, b);
}
"#,
&[],
);
});
}
#[test]
fn test_query_matches_with_indefinite_step_containing_no_captures() {
allocations::record(|| {

View file

@ -3355,9 +3355,11 @@ impl<'tree> QueryMatch<'_, 'tree> {
.iter()
.all(|predicate| match predicate {
TextPredicateCapture::EqCapture(i, j, is_positive, match_all_nodes) => {
let mut nodes_1 = self.nodes_for_capture_index(*i);
let mut nodes_2 = self.nodes_for_capture_index(*j);
while let (Some(node1), Some(node2)) = (nodes_1.next(), nodes_2.next()) {
let mut nodes_1 = self.nodes_for_capture_index(*i).peekable();
let mut nodes_2 = self.nodes_for_capture_index(*j).peekable();
while nodes_1.peek().is_some() && nodes_2.peek().is_some() {
let node1 = nodes_1.next().unwrap();
let node2 = nodes_2.next().unwrap();
let mut text1 = text_provider.text(node1);
let mut text2 = text_provider.text(node2);
let text1 = node_text1.get_text(&mut text1);