Change back tree-sitter version requirement (bug#80108)

Now we use treesit_traverse_sibling_helper when it exists, and
use the old code otherwise. So we still support older
tree-sitter versions.

* configure.ac (LIBSYSTEMD_CFLAGS): Add back old config checking
for the malloc function. Add another check for
ts_tree_cursor_goto_previous_sibling.
* src/treesit.c: (treesit_traverse_sibling_helper): Add back the
old code that doesn't require
ts_tree_cursor_goto_previous_sibling.
This commit is contained in:
Yuan Fu 2026-02-17 17:55:18 -08:00
parent 437b27046f
commit 25149aec99
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
2 changed files with 96 additions and 4 deletions

View file

@ -4051,15 +4051,51 @@ TREE_SITTER_OBJ=
NEED_DYNLIB=no
if test "${with_tree_sitter}" != "no"; then
dnl Tree-sitter 0.20.10 added ts_tree_cursor_goto_previous_sibling, we
dnl need it for a more efficient implementation for traversing the
dnl parse tree backwards (bug#80108).
EMACS_CHECK_MODULES([TREE_SITTER], [tree-sitter >= 0.20.10],
dnl Tree-sitter 0.20.2 added support to change the malloc it uses
dnl at runtime, we need that feature. However, tree-sitter's
dnl Makefile has problems, until that's fixed, all tree-sitter
dnl libraries distributed are versioned 0.6.3. We try to
dnl accept a tree-sitter library that has incorrect version as long
dnl as it supports changing malloc.
EMACS_CHECK_MODULES([TREE_SITTER], [tree-sitter >= 0.20.2],
[HAVE_TREE_SITTER=yes], [HAVE_TREE_SITTER=no])
if test "${HAVE_TREE_SITTER}" = yes; then
AC_DEFINE(HAVE_TREE_SITTER, 1, [Define if using tree-sitter.])
NEED_DYNLIB=yes
else
EMACS_CHECK_MODULES([TREE_SITTER], [tree-sitter >= 0.6.3],
[HAVE_TREE_SITTER=yes], [HAVE_TREE_SITTER=no])
if test "${HAVE_TREE_SITTER}" = yes; then
OLD_CFLAGS=$CFLAGS
OLD_LIBS=$LIBS
CFLAGS="$CFLAGS $TREE_SITTER_CFLAGS"
LIBS="$TREE_SITTER_LIBS $LIBS"
AC_CHECK_FUNCS([ts_set_allocator])
CFLAGS=$OLD_CFLAGS
LIBS=$OLD_LIBS
if test "$ac_cv_func_ts_set_allocator" = yes; then
AC_DEFINE(HAVE_TREE_SITTER, 1, [Define if using tree-sitter.])
NEED_DYNLIB=yes
else
AC_MSG_ERROR([Tree-sitter library exists but its version is too old]);
TREE_SITTER_CFLAGS=
TREE_SITTER_LIBS=
fi
fi
fi
dnl Now we check if ts_tree_cursor_goto_previous_sibling exists. This
dnl function is added in v0.20.10.
if test "${HAVE_TREE_SITTER}" = yes; then
OLD_CFLAGS=$CFLAGS
OLD_LIBS=$LIBS
CFLAGS="$CFLAGS $TREE_SITTER_CFLAGS"
LIBS="$TREE_SITTER_LIBS $LIBS"
AC_CHECK_FUNCS([ts_tree_cursor_goto_previous_sibling])
CFLAGS=$OLD_CFLAGS
LIBS=$OLD_LIBS
fi
# Windows loads tree-sitter dynamically
if test "${opsys}" = "mingw32"; then
TREE_SITTER_LIBS=

View file

@ -85,7 +85,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#undef ts_tree_cursor_delete
#undef ts_tree_cursor_goto_first_child
#undef ts_tree_cursor_goto_first_child_for_byte
#ifdef HAVE_TS_TREE_CURSOR_GOTO_PREVIOUS_SIBLING
#undef ts_tree_cursor_goto_previous_sibling
#endif
#undef ts_tree_cursor_goto_next_sibling
#undef ts_tree_cursor_goto_parent
#undef ts_tree_cursor_new
@ -158,7 +160,9 @@ DEF_DLL_FN (void, ts_tree_cursor_delete, (const TSTreeCursor *));
DEF_DLL_FN (bool, ts_tree_cursor_goto_first_child, (TSTreeCursor *));
DEF_DLL_FN (int64_t, ts_tree_cursor_goto_first_child_for_byte, (TSTreeCursor *, uint32_t));
DEF_DLL_FN (bool, ts_tree_cursor_goto_next_sibling, (TSTreeCursor *));
#ifdef HAVE_TS_TREE_CURSOR_GOTO_PREVIOUS_SIBLING
DEF_DLL_FN (bool, ts_tree_cursor_goto_previous_sibling, (TSTreeCursor *));
#endif
DEF_DLL_FN (bool, ts_tree_cursor_goto_parent, (TSTreeCursor *));
DEF_DLL_FN (TSTreeCursor, ts_tree_cursor_new, (TSNode));
DEF_DLL_FN (void, ts_tree_delete, (TSTree *));
@ -226,7 +230,9 @@ init_treesit_functions (void)
LOAD_DLL_FN (library, ts_tree_cursor_goto_first_child);
LOAD_DLL_FN (library, ts_tree_cursor_goto_first_child_for_byte);
LOAD_DLL_FN (library, ts_tree_cursor_goto_next_sibling);
#ifdef HAVE_TS_TREE_CURSOR_GOTO_PREVIOUS_SIBLING
LOAD_DLL_FN (library, ts_tree_cursor_goto_previous_sibling);
#endif
LOAD_DLL_FN (library, ts_tree_cursor_goto_parent);
LOAD_DLL_FN (library, ts_tree_cursor_new);
LOAD_DLL_FN (library, ts_tree_delete);
@ -4277,6 +4283,7 @@ treesit_traverse_sibling_helper (TSTreeCursor *cursor,
return false;
}
else /* Backward. */
#ifdef HAVE_TS_TREE_CURSOR_GOTO_PREVIOUS_SIBLING
{
if (!named)
return ts_tree_cursor_goto_previous_sibling (cursor);
@ -4288,6 +4295,55 @@ treesit_traverse_sibling_helper (TSTreeCursor *cursor,
}
return false;
}
#else
{
/* Go to first child and go through each sibling, until we find
the one just before the starting node. */
TSNode start = ts_tree_cursor_current_node (cursor);
if (!ts_tree_cursor_goto_parent (cursor))
return false;
treesit_assume_true (ts_tree_cursor_goto_first_child (cursor));
/* Now CURSOR is at the first child. If we started at the first
child, then there is no further siblings. */
TSNode first_child = ts_tree_cursor_current_node (cursor);
if (ts_node_eq (first_child, start))
return false;
/* PROBE is always DELTA siblings ahead of CURSOR. */
TSTreeCursor probe = ts_tree_cursor_copy (cursor);
/* This is position of PROBE minus position of CURSOR. */
ptrdiff_t delta = 0;
TSNode probe_node;
TSNode cursor_node;
while (ts_tree_cursor_goto_next_sibling (&probe))
{
/* Move PROBE forward, if it equals to the starting node,
CURSOR points to the node we want (prev valid sibling of
the starting node). */
delta++;
probe_node = ts_tree_cursor_current_node (&probe);
/* PROBE matched, depending on NAMED, return true/false. */
if (ts_node_eq (probe_node, start))
{
ts_tree_cursor_delete (&probe);
cursor_node = ts_tree_cursor_current_node (cursor);
ts_tree_cursor_delete (&probe);
return (!named || (named && ts_node_is_named (cursor_node)));
}
/* PROBE didn't match, move CURSOR forward to PROBE's
position, but if we are looking for named nodes, only
move CURSOR to PROBE if PROBE is at a named node. */
if (!named || (named && ts_node_is_named (probe_node)))
for (; delta > 0; delta--)
treesit_assume_true (ts_tree_cursor_goto_next_sibling (cursor));
}
ts_tree_cursor_delete (&probe);
return false;
}
#endif
}
/* Move CURSOR to the first/last child. FORWARD controls the