feat(lib): add ts_query_cursor_set_max_start_depth query API

This allows configuring cursors from traversing too deep into a tree.
This commit is contained in:
Lewis Russell 2023-03-17 14:22:20 +00:00 committed by Andrew Hlynskyi
parent 2c8861d5ca
commit 1e81a1b67f
5 changed files with 144 additions and 8 deletions

View file

@ -4469,6 +4469,103 @@ fn test_capture_quantifiers() {
});
}
#[test]
fn test_query_max_start_depth() {
struct Row {
description: &'static str,
pattern: &'static str,
depth: u32,
matches: &'static [(usize, &'static [(&'static str, &'static str)])],
}
let source = r#"
if (a1 && a2) {
if (b1 && b2) { }
if (c) { }
}
if (d) {
if (e1 && e2) { }
if (f) { }
}
"#;
let rows = &[
Row {
description: "depth 0: match none",
depth: 0,
pattern: r#"
(if_statement) @capture
"#,
matches: &[]
},
Row {
description: "depth 1: match 2 if statements at the top level",
depth: 1,
pattern: r#"
(if_statement) @capture
"#,
matches : &[
(0, &[("capture", "if (a1 && a2) {\n if (b1 && b2) { }\n if (c) { }\n }")]),
(0, &[("capture", "if (d) {\n if (e1 && e2) { }\n if (f) { }\n }")])
]
},
Row {
description: "depth 1 with deep pattern: match the only the first if statement",
depth: 1,
pattern: r#"
(if_statement
condition: (parenthesized_expression
(binary_expression)
)
) @capture
"#,
matches: &[
(0, &[("capture", "if (a1 && a2) {\n if (b1 && b2) { }\n if (c) { }\n }")]),
]
},
Row {
description: "depth 3 with deep pattern: match all if statements with a binexpr condition",
depth: 3,
pattern: r#"
(if_statement
condition: (parenthesized_expression
(binary_expression)
)
) @capture
"#,
matches: &[
(0, &[("capture", "if (a1 && a2) {\n if (b1 && b2) { }\n if (c) { }\n }")]),
(0, &[("capture", "if (b1 && b2) { }")]),
(0, &[("capture", "if (e1 && e2) { }")])
]
},
];
allocations::record(|| {
let language = get_language("c");
let mut parser = Parser::new();
parser.set_language(language).unwrap();
let tree = parser.parse(source, None).unwrap();
let mut cursor = QueryCursor::new();
for row in rows.iter() {
eprintln!(" query example: {:?}", row.description);
let query = Query::new(language, row.pattern).unwrap();
cursor.set_max_start_depth(row.depth);
let matches = cursor.matches(&query, tree.root_node(), source.as_bytes());
let expected = row
.matches
.iter()
.map(|x| (x.0, x.1.to_vec()))
.collect::<Vec<_>>();
assert_eq!(collect_matches(matches, &query, source), expected);
}
});
}
fn assert_query_matches(
language: Language,
query: &Query,