Skip to content

Commit

Permalink
Change cursor to ignore child's end points
Browse files Browse the repository at this point in the history
...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.
  • Loading branch information
blmarket committed Apr 7, 2024
1 parent c76e5fa commit 1f45e4c
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 4 deletions.
7 changes: 4 additions & 3 deletions cli/src/tests/tree_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,12 +474,13 @@ 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, 6)), None);
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))
Expand Down Expand Up @@ -516,7 +517,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))
Expand Down
2 changes: 1 addition & 1 deletion lib/src/tree_cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 1f45e4c

Please sign in to comment.