From 5b162f886e50d12de4cbd6b5988c68ab48791760 Mon Sep 17 00:00:00 2001 From: "Jeong, Hun" Date: Sun, 7 Apr 2024 09:29:58 -0700 Subject: [PATCH] Change cursor to ignore child's end points ...when running goto_first_child_for_{byte or point}. My problem: I have a following markdown document ``` {Node document (0, 0) - (11, 0)} document 91 {Node section (0, 0) - (8, 0)} section 101 // .. ignorable details {Node section (8, 0) - (11, 0)} section 101 // .. ignorable details ``` (indent describes child) When I run `goto_first_child_for_point` with (8, 0), I expected to get the second section which spans (8, 0) to (11, 0). Instead I got the first section which spans (0, 0) to (8, 0). My suggestion: Given that the range is start-inclusive and end-exclusive, I'm wondering tree-sitter can change the walk behavior to follow the same semantics, by excluding the end position of the node when considering the child. Code change itself is trivial. Affected test cases were updated which I believe for a good reason. --- cli/src/tests/tree_test.rs | 6 +++--- lib/src/tree_cursor.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/src/tests/tree_test.rs b/cli/src/tests/tree_test.rs index f498c5fcfb..c0d45379f1 100644 --- a/cli/src/tests/tree_test.rs +++ b/cli/src/tests/tree_test.rs @@ -474,12 +474,12 @@ fn test_tree_cursor_child_for_point() { assert_eq!(c.node().kind(), "program"); // descend to expression statement - assert_eq!(c.goto_first_child_for_point(Point::new(6, 6)), Some(0)); + assert_eq!(c.goto_first_child_for_point(Point::new(6, 5)), Some(0)); assert_eq!(c.node().kind(), "expression_statement"); // step into ';' and back up assert_eq!(c.goto_first_child_for_point(Point::new(7, 0)), None); - assert_eq!(c.goto_first_child_for_point(Point::new(6, 6)), Some(1)); + assert_eq!(c.goto_first_child_for_point(Point::new(6, 5)), Some(1)); assert_eq!( (c.node().kind(), c.node().start_position()), (";", Point::new(6, 5)) @@ -516,7 +516,7 @@ fn test_tree_cursor_child_for_point() { assert!(c.goto_parent()); // step into first ',' and back up - assert_eq!(c.goto_first_child_for_point(Point::new(1, 12)), Some(2)); + assert_eq!(c.goto_first_child_for_point(Point::new(1, 11)), Some(2)); assert_eq!( (c.node().kind(), c.node().start_position()), (",", Point::new(1, 11)) diff --git a/lib/src/tree_cursor.c b/lib/src/tree_cursor.c index ddd7d66b5a..189a565905 100644 --- a/lib/src/tree_cursor.c +++ b/lib/src/tree_cursor.c @@ -274,7 +274,7 @@ static inline int64_t ts_tree_cursor_goto_first_child_for_byte_and_point( CursorChildIterator iterator = ts_tree_cursor_iterate_children(self); while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) { Length entry_end = length_add(entry.position, ts_subtree_size(*entry.subtree)); - bool at_goal = entry_end.bytes >= goal_byte && point_gte(entry_end.extent, goal_point); + bool at_goal = entry_end.bytes > goal_byte && point_gt(entry_end.extent, goal_point); uint32_t visible_child_count = ts_subtree_visible_child_count(*entry.subtree); if (at_goal) { if (visible) {