diff options
| author | Yuan Fu | 2023-01-17 00:57:54 -0800 |
|---|---|---|
| committer | Yuan Fu | 2023-01-17 01:18:16 -0800 |
| commit | 7c61a304104fe3a35c47d412150d29b93a697c5e (patch) | |
| tree | 1296bb007bf5d3ed5a6364f2fe0d8d6f6353c6b2 /src | |
| parent | b36cc7e7bbb5a8d0c1b298b89a4cb562af746ecc (diff) | |
| download | emacs-7c61a304104fe3a35c47d412150d29b93a697c5e.tar.gz emacs-7c61a304104fe3a35c47d412150d29b93a697c5e.zip | |
Fix treesit-node-first-child-for-pos (bug#60127)
The problem is due to a bug in ts_node_first_child_for_pos, but
tree-sitter is moving pretty slowly right now so I reimplemented a
correct version of it in treesit.c.
* src/treesit.c (treesit_cursor_first_child_for_byte): New function.
(Ftreesit_node_first_child_for_pos): Use the new function.
Diffstat (limited to 'src')
| -rw-r--r-- | src/treesit.c | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/src/treesit.c b/src/treesit.c index adbed1427be..644d323d5cb 100644 --- a/src/treesit.c +++ b/src/treesit.c | |||
| @@ -2095,6 +2095,41 @@ return nil. */) | |||
| 2095 | return make_treesit_node (XTS_NODE (node)->parser, sibling); | 2095 | return make_treesit_node (XTS_NODE (node)->parser, sibling); |
| 2096 | } | 2096 | } |
| 2097 | 2097 | ||
| 2098 | /* Our reimplementation of ts_node_first_child_for_byte. The current | ||
| 2099 | implementation of that function has problems (see bug#60127), so | ||
| 2100 | before it's fixed upstream, we use our own reimplementation of it. | ||
| 2101 | Return true if there is a valid sibling, return false otherwise. | ||
| 2102 | If the return value is false, the position of the cursor is | ||
| 2103 | undefined. (We use cursor because technically we can't make a null | ||
| 2104 | node for ourselves, also, using cursor is more convenient.) | ||
| 2105 | |||
| 2106 | TODO: Remove this function once tree-sitter fixed the bug. */ | ||
| 2107 | static bool treesit_cursor_first_child_for_byte | ||
| 2108 | (TSTreeCursor *cursor, ptrdiff_t pos, bool named) | ||
| 2109 | { | ||
| 2110 | if (!ts_tree_cursor_goto_first_child (cursor)) | ||
| 2111 | return false; | ||
| 2112 | |||
| 2113 | TSNode node = ts_tree_cursor_current_node (cursor); | ||
| 2114 | while (ts_node_end_byte (node) <= pos) | ||
| 2115 | { | ||
| 2116 | if (ts_tree_cursor_goto_next_sibling (cursor)) | ||
| 2117 | node = ts_tree_cursor_current_node (cursor); | ||
| 2118 | else | ||
| 2119 | /* Reached the end and still can't find a valid sibling. */ | ||
| 2120 | return false; | ||
| 2121 | } | ||
| 2122 | while (named && (!ts_node_is_named (node))) | ||
| 2123 | { | ||
| 2124 | if (ts_tree_cursor_goto_next_sibling (cursor)) | ||
| 2125 | node = ts_tree_cursor_current_node (cursor); | ||
| 2126 | else | ||
| 2127 | /* Reached the end and still can't find a named sibling. */ | ||
| 2128 | return false; | ||
| 2129 | } | ||
| 2130 | return true; | ||
| 2131 | } | ||
| 2132 | |||
| 2098 | DEFUN ("treesit-node-first-child-for-pos", | 2133 | DEFUN ("treesit-node-first-child-for-pos", |
| 2099 | Ftreesit_node_first_child_for_pos, | 2134 | Ftreesit_node_first_child_for_pos, |
| 2100 | Streesit_node_first_child_for_pos, 2, 3, 0, | 2135 | Streesit_node_first_child_for_pos, 2, 3, 0, |
| @@ -2119,16 +2154,17 @@ Note that this function returns an immediate child, not the smallest | |||
| 2119 | 2154 | ||
| 2120 | ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, XFIXNUM (pos)); | 2155 | ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, XFIXNUM (pos)); |
| 2121 | TSNode treesit_node = XTS_NODE (node)->node; | 2156 | TSNode treesit_node = XTS_NODE (node)->node; |
| 2122 | TSNode child; | ||
| 2123 | if (NILP (named)) | ||
| 2124 | child = ts_node_first_child_for_byte (treesit_node, byte_pos - visible_beg); | ||
| 2125 | else | ||
| 2126 | child = ts_node_first_named_child_for_byte (treesit_node, | ||
| 2127 | byte_pos - visible_beg); | ||
| 2128 | 2157 | ||
| 2129 | if (ts_node_is_null (child)) | 2158 | TSTreeCursor cursor = ts_tree_cursor_new (treesit_node); |
| 2130 | return Qnil; | 2159 | ptrdiff_t treesit_pos = byte_pos - visible_beg; |
| 2160 | bool success; | ||
| 2161 | success = treesit_cursor_first_child_for_byte (&cursor, treesit_pos, | ||
| 2162 | !NILP (named)); | ||
| 2163 | TSNode child = ts_tree_cursor_current_node (&cursor); | ||
| 2164 | ts_tree_cursor_delete (&cursor); | ||
| 2131 | 2165 | ||
| 2166 | if (!success) | ||
| 2167 | return Qnil; | ||
| 2132 | return make_treesit_node (XTS_NODE (node)->parser, child); | 2168 | return make_treesit_node (XTS_NODE (node)->parser, child); |
| 2133 | } | 2169 | } |
| 2134 | 2170 | ||