From: Yuan Fu Date: Sat, 26 Nov 2022 22:51:26 +0000 (-0800) Subject: Add default limit for tree-sitter recursive tree-traversing function X-Git-Tag: emacs-29.0.90~1472 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=cc086f37e89051f62538d5ead1c011580b667598;p=emacs.git Add default limit for tree-sitter recursive tree-traversing function This fixes bug#59426. * src/treesit.c (treesit_search_dfs) (treesit_build_sparse_tree): Remove no_limit parameter. (Ftreesit_search_forward, Ftreesit_induce_sparse_tree): Use default limit of 1000. * doc/lispref/parsing.texi (Retrieving Nodes): Update manual. --- diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index 0f6a99b299c..3223875320a 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi @@ -725,10 +725,11 @@ the first node that matches, or @code{nil} if none does. By default, this function only traverses named nodes, but if @var{all} is non-@code{nil}, it traverses all the nodes. If @var{backward} is -non-@code{nil}, it traverses backwards (i.e., it visits the last child first -when traversing down the tree). If @var{limit} is non-@code{nil}, it -must be a number that limits the tree traversal to that many levels -down the tree. +non-@code{nil}, it traverses backwards (i.e., it visits the last child +first when traversing down the tree). If @var{limit} is +non-@code{nil}, it must be a number that limits the tree traversal to +that many levels down the tree. If @var{limit} is @code{nil}, it +defaults to 1000. @end defun @defun treesit-search-forward start predicate &optional backward all @@ -814,10 +815,11 @@ b 1 2 b | | b c d @end group @end example -If @var{process-fn} is non-@code{nil}, instead of returning the matched -nodes, this function passes each node to @var{process-fn} and uses the -returned value instead. If non-@code{nil}, @var{limit} is the number of -levels to go down from @var{root}. +If @var{process-fn} is non-@code{nil}, instead of returning the +matched nodes, this function passes each node to @var{process-fn} and +uses the returned value instead. If non-@code{nil}, @var{limit} is +the number of levels to go down from @var{root}. If @var{limit} is +@code{nil}, it defaults to 1000. Each node in the returned tree looks like @w{@code{(@var{tree-sitter-node} . (@var{child} @dots{}))}}. The diff --git a/src/treesit.c b/src/treesit.c index ad7e43fbc5c..6526896061d 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -2644,19 +2644,18 @@ treesit_traverse_match_predicate (TSNode node, Lisp_Object pred, return true. If no node satisfies PRED, return FALSE. PARSER is the parser of ROOT. - LIMIT is the number of levels we descend in the tree. If NO_LIMIT - is true, LIMIT is ignored. FORWARD controls the direction in which - we traverse the tree, true means forward, false backward. If NAMED - is true, only traverse named nodes, if false, all nodes. If - SKIP_ROOT is true, don't match ROOT. */ + LIMIT is the number of levels we descend in the tree. FORWARD + controls the direction in which we traverse the tree, true means + forward, false backward. If NAMED is true, only traverse named + nodes, if false, all nodes. If SKIP_ROOT is true, don't match + ROOT. */ static bool treesit_search_dfs (TSNode *root, Lisp_Object pred, Lisp_Object parser, - bool named, bool forward, ptrdiff_t limit, bool no_limit, + bool named, bool forward, ptrdiff_t limit, bool skip_root) { /* TSTreeCursor doesn't allow us to move backward, so we can't use - it. We could use limit == -1 to indicate no_limit == true, but - separating them is safer. */ + it. */ TSNode node = *root; if (!skip_root && treesit_traverse_match_predicate (node, pred, parser)) @@ -2665,7 +2664,7 @@ treesit_search_dfs (TSNode *root, Lisp_Object pred, Lisp_Object parser, return true; } - if (!no_limit && limit <= 0) + if (limit <= 0) return false; else { @@ -2681,7 +2680,7 @@ treesit_search_dfs (TSNode *root, Lisp_Object pred, Lisp_Object parser, if (!ts_node_is_null (child) && treesit_search_dfs (&child, pred, parser, named, - forward, limit - 1, no_limit, false)) + forward, limit - 1, false)) { *root = child; return true; @@ -2757,7 +2756,8 @@ node's type, or a function that takes a node and returns nil/non-nil. By default, only traverse named nodes, but if ALL is non-nil, traverse all nodes. If BACKWARD is non-nil, traverse backwards. If LIMIT is -non-nil, only traverse nodes up to that number of levels down in the tree. +non-nil, only traverse nodes up to that number of levels down in the +tree. If LIMIT is nil, default to 1000. Return the first matched node, or nil if none matches. */) (Lisp_Object node, Lisp_Object predicate, Lisp_Object backward, @@ -2769,11 +2769,10 @@ Return the first matched node, or nil if none matches. */) CHECK_SYMBOL (all); CHECK_SYMBOL (backward); - ptrdiff_t the_limit = 0; - bool no_limit = false; - if (NILP (limit)) - no_limit = true; - else + /* We use a default limit to 1000. See bug#59426 for the + discussion. */ + ptrdiff_t the_limit = 1000; + if (!NILP (limit)) { CHECK_FIXNUM (limit); the_limit = XFIXNUM (limit); @@ -2784,7 +2783,7 @@ Return the first matched node, or nil if none matches. */) TSNode treesit_node = XTS_NODE (node)->node; Lisp_Object parser = XTS_NODE (node)->parser; if (treesit_search_dfs (&treesit_node, predicate, parser, NILP (all), - NILP (backward), the_limit, no_limit, false)) + NILP (backward), the_limit, false)) return make_treesit_node (parser, treesit_node); else return Qnil; @@ -2847,7 +2846,7 @@ always traverse leaf nodes first, then upwards. */) static void treesit_build_sparse_tree (TSTreeCursor *cursor, Lisp_Object parent, Lisp_Object pred, Lisp_Object process_fn, - ptrdiff_t limit, bool no_limit, Lisp_Object parser) + ptrdiff_t limit, Lisp_Object parser) { TSNode node = ts_tree_cursor_current_node (cursor); @@ -2866,8 +2865,7 @@ treesit_build_sparse_tree (TSTreeCursor *cursor, Lisp_Object parent, parent = this; } /* Go through each child. */ - if ((no_limit || limit > 0) - && ts_tree_cursor_goto_first_child (cursor)) + if (limit > 0 && ts_tree_cursor_goto_first_child (cursor)) { do { @@ -2875,7 +2873,7 @@ treesit_build_sparse_tree (TSTreeCursor *cursor, Lisp_Object parent, Then C compilers should be smart enough not to copy NODE to stack. */ treesit_build_sparse_tree (cursor, parent, pred, process_fn, - limit - 1, no_limit, parser); + limit - 1, parser); } while (ts_tree_cursor_goto_next_sibling (cursor)); /* Don't forget to come back to this node. */ @@ -2916,7 +2914,8 @@ If PROCESS-FN is non-nil, it should be a function of one argument. In that case, instead of returning the matched nodes, pass each node to PROCESS-FN, and use its return value instead. -If non-nil, LIMIT is the number of levels to go down the tree from ROOT. +If non-nil, LIMIT is the number of levels to go down the tree from +ROOT. If LIMIT is nil, default to 1000. Each node in the returned tree looks like (NODE . (CHILD ...)). The root of this tree might be nil, if ROOT doesn't match PREDICATE. @@ -2935,11 +2934,11 @@ a regexp. */) if (!NILP (process_fn)) CHECK_TYPE (FUNCTIONP (process_fn), Qfunctionp, process_fn); - ptrdiff_t the_limit = 0; - bool no_limit = false; - if (NILP (limit)) - no_limit = true; - else + + /* We use a default limit to 1000. See bug#59426 for the + discussion. */ + ptrdiff_t the_limit = 1000; + if (!NILP (limit)) { CHECK_FIXNUM (limit); the_limit = XFIXNUM (limit); @@ -2951,7 +2950,7 @@ a regexp. */) Lisp_Object parser = XTS_NODE (root)->parser; Lisp_Object parent = Fcons (Qnil, Qnil); treesit_build_sparse_tree (&cursor, parent, predicate, process_fn, - the_limit, no_limit, parser); + the_limit, parser); Fsetcdr (parent, Fnreverse (Fcdr (parent))); if (NILP (Fcdr (parent))) return Qnil;