From 41ec8b41661bc0eaa0ff1b0bdebd7861267e77c4 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Fri, 19 May 2023 19:02:30 -0400 Subject: [PATCH 1/3] Partially revert d4d5e29 --- cli/src/tests/query_test.rs | 21 ++++++++++++--------- lib/binding_rust/bindings.rs | 2 +- lib/include/tree_sitter/api.h | 10 ++++++++-- lib/src/query.c | 6 +----- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index 1ca1e658..9e3f5303 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -4577,19 +4577,22 @@ fn test_query_max_start_depth() { #[rustfmt::skip] let rows = &[ Row { - description: "depth 0: match all", + description: "depth 0: match translation unit", + depth: 0, + pattern: r#" + (translation_unit) @capture + "#, + matches: &[ + (0, &[("capture", "if (a1 && a2) {\n if (b1 && b2) { }\n if (c) { }\n}\nif (d) {\n if (e1 && e2) { }\n if (f) { }\n}\n")]), + ] + }, + Row { + description: "depth 0: match none", depth: 0, pattern: r#" (if_statement) @capture "#, - matches: &[ - (0, &[("capture", "if (a1 && a2) {\n if (b1 && b2) { }\n if (c) { }\n}")]), - (0, &[("capture", "if (b1 && b2) { }")]), - (0, &[("capture", "if (c) { }")]), - (0, &[("capture", "if (d) {\n if (e1 && e2) { }\n if (f) { }\n}")]), - (0, &[("capture", "if (e1 && e2) { }")]), - (0, &[("capture", "if (f) { }")]), - ] + matches: &[] }, Row { description: "depth 1: match 2 if statements at the top level", diff --git a/lib/binding_rust/bindings.rs b/lib/binding_rust/bindings.rs index 912916c0..faec9d3b 100644 --- a/lib/binding_rust/bindings.rs +++ b/lib/binding_rust/bindings.rs @@ -639,7 +639,7 @@ extern "C" { ) -> bool; } extern "C" { - #[doc = " Set the maximum start depth for a cursor.\n\n This prevents cursors from exploring children nodes at a certain depth.\n Note if a pattern includes many children, then they will still be checked.\n\n Set to `0` to remove the maximum start depth."] + #[doc = " Set the maximum start depth for a query cursor.\n\n This prevents cursors from exploring children nodes at a certain depth.\n Note if a pattern includes many children, then they will still be checked.\n\n The zero max start depth value can be used as a special behavior and\n it helps to destructure a subtree by staying on a node and using captures\n for interested parts. Note that the zero max start depth only limit a search\n depth for a pattern's root node but other nodes that are parts of the pattern\n may be searched at any depth what defined by the pattern structure.\n\n Set to `UINT32_MAX` to remove the maximum start depth."] pub fn ts_query_cursor_set_max_start_depth(arg1: *mut TSQueryCursor, arg2: u32); } extern "C" { diff --git a/lib/include/tree_sitter/api.h b/lib/include/tree_sitter/api.h index d9560f24..349f6838 100644 --- a/lib/include/tree_sitter/api.h +++ b/lib/include/tree_sitter/api.h @@ -984,12 +984,18 @@ bool ts_query_cursor_next_capture( ); /** - * Set the maximum start depth for a cursor. + * Set the maximum start depth for a query cursor. * * This prevents cursors from exploring children nodes at a certain depth. * Note if a pattern includes many children, then they will still be checked. * - * Set to `0` to remove the maximum start depth. + * The zero max start depth value can be used as a special behavior and + * it helps to destructure a subtree by staying on a node and using captures + * for interested parts. Note that the zero max start depth only limit a search + * depth for a pattern's root node but other nodes that are parts of the pattern + * may be searched at any depth what defined by the pattern structure. + * + * Set to `UINT32_MAX` to remove the maximum start depth. */ void ts_query_cursor_set_max_start_depth(TSQueryCursor *, uint32_t); diff --git a/lib/src/query.c b/lib/src/query.c index ff4bb06c..be4464ea 100644 --- a/lib/src/query.c +++ b/lib/src/query.c @@ -4124,11 +4124,7 @@ void ts_query_cursor_set_max_start_depth( TSQueryCursor *self, uint32_t max_start_depth ) { - if (max_start_depth == 0) { - self->max_start_depth = UINT32_MAX; - } else { - self->max_start_depth = max_start_depth; - } + self->max_start_depth = max_start_depth; } #undef LOG From 7b01d8ee054644fc779c83cc16adf41ff9af5646 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sat, 20 May 2023 08:13:26 -0400 Subject: [PATCH 2/3] Add `test_query_max_start_depth_more` --- cli/src/tests/query_test.rs | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index 9e3f5303..28c01f4c 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -4723,3 +4723,75 @@ fn test_consecutive_zero_or_modifiers() { assert_eq!(len_1, test.contains("???")); } } + +#[test] +fn test_query_max_start_depth_more() { + struct Row { + depth: u32, + matches: &'static [(usize, &'static [(&'static str, &'static str)])], + } + + let source = indoc! {" + { + { } + { + { } + } + } + "}; + + #[rustfmt::skip] + let rows = &[ + Row { + depth: 0, + matches: &[ + (0, &[("capture", "{\n { }\n {\n { }\n }\n}")]) + ] + }, + Row { + depth: 1, + matches: &[ + (0, &[("capture", "{\n { }\n {\n { }\n }\n}")]), + (0, &[("capture", "{ }")]), + (0, &[("capture", "{\n { }\n }")]) + ] + }, + Row { + depth: 2, + matches: &[ + (0, &[("capture", "{\n { }\n {\n { }\n }\n}")]), + (0, &[("capture", "{ }")]), + (0, &[("capture", "{\n { }\n }")]), + (0, &[("capture", "{ }")]), + ] + }, + ]; + + 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(); + let query = Query::new(language, "(compound_statement) @capture").unwrap(); + + let mut matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); + let node = matches.next().unwrap().captures[0].node; + assert_eq!(node.kind(), "compound_statement"); + + for row in rows.iter() { + eprintln!(" depth: {}", row.depth); + + cursor.set_max_start_depth(row.depth); + + let matches = cursor.matches(&query, node, source.as_bytes()); + let expected = row + .matches + .iter() + .map(|x| (x.0, x.1.to_vec())) + .collect::>(); + + assert_eq!(collect_matches(matches, &query, source), expected); + } + }); +} From 485d19288027d9b92010c69b8951e7fb6ddd9df0 Mon Sep 17 00:00:00 2001 From: Andrew Hlynskyi Date: Sun, 21 May 2023 01:05:13 +0300 Subject: [PATCH 3/3] binding_rust: `set_max_start_depth` accepts optional to reset limit --- cli/src/tests/query_test.rs | 4 ++-- lib/binding_rust/lib.rs | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index 28c01f4c..c3bf54a2 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -4648,7 +4648,7 @@ fn test_query_max_start_depth() { eprintln!(" query example: {:?}", row.description); let query = Query::new(language, row.pattern).unwrap(); - cursor.set_max_start_depth(row.depth); + cursor.set_max_start_depth(Some(row.depth)); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); let expected = row @@ -4782,7 +4782,7 @@ fn test_query_max_start_depth_more() { for row in rows.iter() { eprintln!(" depth: {}", row.depth); - cursor.set_max_start_depth(row.depth); + cursor.set_max_start_depth(Some(row.depth)); let matches = cursor.matches(&query, node, source.as_bytes()); let expected = row diff --git a/lib/binding_rust/lib.rs b/lib/binding_rust/lib.rs index ad20507e..cc3ebe9b 100644 --- a/lib/binding_rust/lib.rs +++ b/lib/binding_rust/lib.rs @@ -2174,10 +2174,25 @@ impl QueryCursor { self } + /// Set the maximum start depth for a query cursor. + /// + /// This prevents cursors from exploring children nodes at a certain depth. + /// Note if a pattern includes many children, then they will still be checked. + /// + /// The zero max start depth value can be used as a special behavior and + /// it helps to destructure a subtree by staying on a node and using captures + /// for interested parts. Note that the zero max start depth only limit a search + /// depth for a pattern's root node but other nodes that are parts of the pattern + /// may be searched at any depth what defined by the pattern structure. + /// + /// Set to `None` to remove the maximum start depth. #[doc(alias = "ts_query_cursor_set_max_start_depth")] - pub fn set_max_start_depth(&mut self, max_start_depth: u32) -> &mut Self { + pub fn set_max_start_depth(&mut self, max_start_depth: Option) -> &mut Self { unsafe { - ffi::ts_query_cursor_set_max_start_depth(self.ptr.as_ptr(), max_start_depth); + ffi::ts_query_cursor_set_max_start_depth( + self.ptr.as_ptr(), + max_start_depth.unwrap_or(u32::MAX), + ); } self }