aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuan Fu2023-01-17 00:57:54 -0800
committerYuan Fu2023-01-17 01:18:16 -0800
commit7c61a304104fe3a35c47d412150d29b93a697c5e (patch)
tree1296bb007bf5d3ed5a6364f2fe0d8d6f6353c6b2 /src
parentb36cc7e7bbb5a8d0c1b298b89a4cb562af746ecc (diff)
downloademacs-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.c52
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. */
2107static 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
2098DEFUN ("treesit-node-first-child-for-pos", 2133DEFUN ("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