aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Kangas2022-12-25 06:30:21 +0100
committerStefan Kangas2022-12-25 06:30:21 +0100
commit48db8b68a8eb5c12d5682f2eb31cadc53186f5d7 (patch)
tree3798efa0cd02c6ed2c3e6fe1f7cd8f3059fe492e /src
parent4dc5bee98d5734b4f7113b961bafead1eb091bd0 (diff)
parentc36fe3df17b37a705299239d6ef0185ad55b1d3a (diff)
downloademacs-48db8b68a8eb5c12d5682f2eb31cadc53186f5d7.tar.gz
emacs-48db8b68a8eb5c12d5682f2eb31cadc53186f5d7.zip
Merge from origin/emacs-29
c36fe3df17b Fix c-ts-mode imenu defun name (bug#60296) a24e350170e Fix treesit--children-covering-range-recurse (bug#60301) fbb4eb919b4 Support treesit-defun-name in tree-sitter major modes 6253184afc2 ; * lisp/treesit.el (treesit-defun-at-point): Guard again... f8e219ebfaa Add treesit-defun-name and friends 35c2ca2ca64 Make treesit-node-at/on guess language at point 7f7def2ae62 ; Add treesit-no-parser error b6a2e1ddf66 * nt/INSTALL.W64: update instructions for setting up W64 ... 265b91d891a Revert "; Bump minimum supported Windows version for MinG... 75155e45860 ; Bump minimum supported Windows version for MinGW64 to W... 677f6c79eb9 ; Update minimum requirements of MinGW-w64 7723af5e4aa ; * lisp/progmodes/c-ts-mode.el: quote literal string in ... 38866510c7c ; * src/xdisp.c (redisplay_internal): Reinstate the FRAME... a825aa0b135 Fix definition of CNS 11643-15 charset a42b20dd95e ; * lisp/progmodes/c-ts-mode.el: Add outline section head... e4e36345399 Improve c-ts-mode block comment indent (bug#60270) e30621caa2c ; Add treesit_recursion_limit 6a43af58802 Fix block comment indent and filling for c-ts-mode (bug#5... e492c21e810 Fix treesit_cursor_helper (bug#60267) 4437dbedf7b Fix restart-emacs alarms (Bug#60220) 121a9ff9f6f Fix alternate stack test in configure 84888080eea Add more functions to "string" shortdoc c90f97d4e5d Make the Contour terminal an alias of xterm-256color c3fac9465fa ; Fix punctuation in last change. 756bb422a49 Correct wrong info in (info)Go to node a8c3424d28b Fix typo in TUTORIAL.fr (bug#60261) 24cd2f0daf1 Add some diff-fixup-modifs tests d32091199ae Fix quoted argument in emacsclient-mail.desktop Exec key 286c48137f6 ert-x: Move window selection logic to its own macro 823c49cea85 ; ert-x: Simplify `ert-with-test-buffer-selected' 38c6abe4d0b ; ert-x: Add test for buffer read-only state 0e39ad6fa56 Fix crash after X error
Diffstat (limited to 'src')
-rw-r--r--src/emacs.c1
-rw-r--r--src/treesit.c138
-rw-r--r--src/xdisp.c8
3 files changed, 91 insertions, 56 deletions
diff --git a/src/emacs.c b/src/emacs.c
index d8a2863fd9c..a2ba4b50f04 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -2910,6 +2910,7 @@ killed. */
2910 2910
2911 if (!NILP (restart)) 2911 if (!NILP (restart))
2912 { 2912 {
2913 turn_on_atimers (false);
2913#ifdef WINDOWSNT 2914#ifdef WINDOWSNT
2914 if (w32_reexec_emacs (initial_cmdline, initial_wd) < 0) 2915 if (w32_reexec_emacs (initial_cmdline, initial_wd) < 0)
2915#else 2916#else
diff --git a/src/treesit.c b/src/treesit.c
index c882d455137..ce8a2804439 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -404,6 +404,10 @@ init_treesit_functions (void)
404 404
405/*** Initialization */ 405/*** Initialization */
406 406
407/* This is the limit on recursion levels for some tree-sitter
408 functions. Remember to update docstrings when changing this
409 value. */
410const ptrdiff_t treesit_recursion_limit = 1000;
407bool treesit_initialized = false; 411bool treesit_initialized = false;
408 412
409static bool 413static bool
@@ -1762,7 +1766,7 @@ If NODE is nil, return nil. */)
1762 return build_string (string); 1766 return build_string (string);
1763} 1767}
1764 1768
1765static TSTreeCursor treesit_cursor_helper (TSNode, Lisp_Object); 1769static bool treesit_cursor_helper (TSTreeCursor *, TSNode, Lisp_Object);
1766 1770
1767DEFUN ("treesit-node-parent", 1771DEFUN ("treesit-node-parent",
1768 Ftreesit_node_parent, Streesit_node_parent, 1, 1, 0, 1772 Ftreesit_node_parent, Streesit_node_parent, 1, 1, 0,
@@ -1778,7 +1782,10 @@ Return nil if NODE has no parent. If NODE is nil, return nil. */)
1778 1782
1779 TSNode treesit_node = XTS_NODE (node)->node; 1783 TSNode treesit_node = XTS_NODE (node)->node;
1780 Lisp_Object parser = XTS_NODE (node)->parser; 1784 Lisp_Object parser = XTS_NODE (node)->parser;
1781 TSTreeCursor cursor = treesit_cursor_helper (treesit_node, parser); 1785 TSTreeCursor cursor;
1786 if (!treesit_cursor_helper (&cursor, treesit_node, parser))
1787 return return_value;
1788
1782 if (ts_tree_cursor_goto_parent (&cursor)) 1789 if (ts_tree_cursor_goto_parent (&cursor))
1783 { 1790 {
1784 TSNode parent = ts_tree_cursor_current_node (&cursor); 1791 TSNode parent = ts_tree_cursor_current_node (&cursor);
@@ -2637,8 +2644,59 @@ treesit_assume_true (bool val)
2637 eassert (val == true); 2644 eassert (val == true);
2638} 2645}
2639 2646
2647/* Tries to move CURSOR to point to TARGET. END_POS is the end of
2648 TARGET. If success, return true, otherwise move CURSOR back to
2649 starting position and return false. LIMIT is the recursion
2650 limit. */
2651static bool
2652treesit_cursor_helper_1 (TSTreeCursor *cursor, TSNode *target,
2653 uint32_t end_pos, ptrdiff_t limit)
2654{
2655 if (limit <= 0)
2656 return false;
2657
2658 TSNode cursor_node = ts_tree_cursor_current_node (cursor);
2659 if (ts_node_eq (cursor_node, *target))
2660 return true;
2661
2662 if (!ts_tree_cursor_goto_first_child (cursor))
2663 return false;
2664
2665 /* Skip nodes that definitely don't contain TARGET. */
2666 while (ts_node_end_byte (cursor_node) < end_pos)
2667 {
2668 if (!ts_tree_cursor_goto_next_sibling (cursor))
2669 break;
2670 cursor_node = ts_tree_cursor_current_node (cursor);
2671 }
2672
2673 /* Go through each sibling that could contain TARGET. Because of
2674 missing nodes (their width is 0), there could be multiple
2675 siblings that could contain TARGET. */
2676 while (ts_node_start_byte (cursor_node) <= end_pos)
2677 {
2678 if (treesit_cursor_helper_1 (cursor, target, end_pos, limit - 1))
2679 return true;
2680
2681 if (!ts_tree_cursor_goto_next_sibling (cursor))
2682 break;
2683 cursor_node = ts_tree_cursor_current_node (cursor);
2684 }
2685
2686 /* Couldn't find TARGET, must be not in this subtree, move cursor
2687 back and pray that other brothers and sisters can succeed. */
2688 treesit_assume_true (ts_tree_cursor_goto_parent (cursor));
2689 return false;
2690}
2691
2640/* Create a TSTreeCursor pointing at NODE. PARSER is the lisp parser 2692/* Create a TSTreeCursor pointing at NODE. PARSER is the lisp parser
2641 that produced NODE. 2693 that produced NODE. If success, return true, otherwise return
2694 false. This function should almost always succeed, but if the parse
2695 tree is strangely too deep and exceeds the recursion limit, this
2696 function will fail and return false.
2697
2698 If this function returns true, caller needs to free CURSOR; if
2699 returns false, caller don't need to free CURSOR.
2642 2700
2643 The reason we need this instead of simply using ts_tree_cursor_new 2701 The reason we need this instead of simply using ts_tree_cursor_new
2644 is that we have to create the cursor on the root node and traverse 2702 is that we have to create the cursor on the root node and traverse
@@ -2646,56 +2704,17 @@ treesit_assume_true (bool val)
2646 Otherwise going to sibling or parent of NODE wouldn't work. 2704 Otherwise going to sibling or parent of NODE wouldn't work.
2647 2705
2648 (Wow perfect filling.) */ 2706 (Wow perfect filling.) */
2649static TSTreeCursor 2707static bool
2650treesit_cursor_helper (TSNode node, Lisp_Object parser) 2708treesit_cursor_helper (TSTreeCursor *cursor, TSNode node, Lisp_Object parser)
2651{ 2709{
2652 uint32_t end_pos = ts_node_end_byte (node); 2710 uint32_t end_pos = ts_node_end_byte (node);
2653 TSNode root = ts_tree_root_node (XTS_PARSER (parser)->tree); 2711 TSNode root = ts_tree_root_node (XTS_PARSER (parser)->tree);
2654 TSTreeCursor cursor = ts_tree_cursor_new (root); 2712 *cursor = ts_tree_cursor_new (root);
2655 TSNode cursor_node = ts_tree_cursor_current_node (&cursor); 2713 bool success = treesit_cursor_helper_1 (cursor, &node, end_pos,
2656 /* This is like treesit-node-at. We go down from the root node, 2714 treesit_recursion_limit);
2657 either to first child or next sibling, repeatedly, and finally 2715 if (!success)
2658 arrive at NODE. */ 2716 ts_tree_cursor_delete (cursor);
2659 while (!ts_node_eq (node, cursor_node)) 2717 return success;
2660 {
2661 treesit_assume_true (ts_tree_cursor_goto_first_child (&cursor));
2662 cursor_node = ts_tree_cursor_current_node (&cursor);
2663 /* ts_tree_cursor_goto_first_child_for_byte is not reliable, so
2664 we just go through each sibling. */
2665 while (ts_node_is_missing (cursor_node)
2666 || ts_node_end_byte (cursor_node) < end_pos)
2667 {
2668 /* A "missing" node has zero width, so it's possible that
2669 its end = NODE.end but it's not NODE, so we skip them.
2670 But we need to make sure this missing node is not the
2671 node we are looking for before skipping it. */
2672 if (ts_node_is_missing (cursor_node)
2673 && ts_node_eq (node, cursor_node))
2674 return cursor;
2675 treesit_assume_true (ts_tree_cursor_goto_next_sibling (&cursor));
2676 cursor_node = ts_tree_cursor_current_node (&cursor);
2677 }
2678 /* Right now CURSOR.end >= NODE.end. But what if CURSOR.end =
2679 NODE.end, and there are missing nodes after CURSOR, and the
2680 missing node after CURSOR is the NODE we are looking for??
2681 Well, create a probe and look ahead. (This is tested by
2682 treesit-cursor-helper-with-missing-node.) */
2683 TSTreeCursor probe = ts_tree_cursor_copy (&cursor);
2684 TSNode probe_node;
2685 while (ts_tree_cursor_goto_next_sibling (&probe))
2686 {
2687 probe_node = ts_tree_cursor_current_node (&probe);
2688 if (!ts_node_is_missing (probe_node))
2689 break;
2690 if (ts_node_eq (probe_node, node))
2691 {
2692 ts_tree_cursor_delete (&cursor);
2693 return probe;
2694 }
2695 }
2696 ts_tree_cursor_delete (&probe);
2697 }
2698 return cursor;
2699} 2718}
2700 2719
2701/* Move CURSOR to the next/previous sibling. FORWARD controls the 2720/* Move CURSOR to the next/previous sibling. FORWARD controls the
@@ -2957,7 +2976,7 @@ Return the first matched node, or nil if none matches. */)
2957 2976
2958 /* We use a default limit of 1000. See bug#59426 for the 2977 /* We use a default limit of 1000. See bug#59426 for the
2959 discussion. */ 2978 discussion. */
2960 ptrdiff_t the_limit = 1000; 2979 ptrdiff_t the_limit = treesit_recursion_limit;
2961 if (!NILP (limit)) 2980 if (!NILP (limit))
2962 { 2981 {
2963 CHECK_FIXNUM (limit); 2982 CHECK_FIXNUM (limit);
@@ -2968,7 +2987,10 @@ Return the first matched node, or nil if none matches. */)
2968 2987
2969 Lisp_Object parser = XTS_NODE (node)->parser; 2988 Lisp_Object parser = XTS_NODE (node)->parser;
2970 Lisp_Object return_value = Qnil; 2989 Lisp_Object return_value = Qnil;
2971 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (node)->node, parser); 2990 TSTreeCursor cursor;
2991 if (!treesit_cursor_helper (&cursor, XTS_NODE (node)->node, parser))
2992 return return_value;
2993
2972 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward), 2994 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward),
2973 NILP (all), the_limit, false)) 2995 NILP (all), the_limit, false))
2974 { 2996 {
@@ -3022,7 +3044,10 @@ always traverse leaf nodes first, then upwards. */)
3022 3044
3023 Lisp_Object parser = XTS_NODE (start)->parser; 3045 Lisp_Object parser = XTS_NODE (start)->parser;
3024 Lisp_Object return_value = Qnil; 3046 Lisp_Object return_value = Qnil;
3025 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (start)->node, parser); 3047 TSTreeCursor cursor;
3048 if (!treesit_cursor_helper (&cursor, XTS_NODE (start)->node, parser))
3049 return return_value;
3050
3026 if (treesit_search_forward (&cursor, predicate, parser, 3051 if (treesit_search_forward (&cursor, predicate, parser,
3027 NILP (backward), NILP (all))) 3052 NILP (backward), NILP (all)))
3028 { 3053 {
@@ -3130,7 +3155,7 @@ a regexp. */)
3130 3155
3131 /* We use a default limit of 1000. See bug#59426 for the 3156 /* We use a default limit of 1000. See bug#59426 for the
3132 discussion. */ 3157 discussion. */
3133 ptrdiff_t the_limit = 1000; 3158 ptrdiff_t the_limit = treesit_recursion_limit;
3134 if (!NILP (limit)) 3159 if (!NILP (limit))
3135 { 3160 {
3136 CHECK_FIXNUM (limit); 3161 CHECK_FIXNUM (limit);
@@ -3141,7 +3166,10 @@ a regexp. */)
3141 3166
3142 Lisp_Object parser = XTS_NODE (root)->parser; 3167 Lisp_Object parser = XTS_NODE (root)->parser;
3143 Lisp_Object parent = Fcons (Qnil, Qnil); 3168 Lisp_Object parent = Fcons (Qnil, Qnil);
3144 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (root)->node, parser); 3169 TSTreeCursor cursor;
3170 if (!treesit_cursor_helper (&cursor, XTS_NODE (root)->node, parser))
3171 return Qnil;
3172
3145 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn, 3173 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn,
3146 the_limit, parser); 3174 the_limit, parser);
3147 ts_tree_cursor_delete (&cursor); 3175 ts_tree_cursor_delete (&cursor);
diff --git a/src/xdisp.c b/src/xdisp.c
index e8df230ef89..08565d55322 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -16838,6 +16838,13 @@ redisplay_internal (void)
16838 /* Only GC scrollbars when we redisplay the whole frame. */ 16838 /* Only GC scrollbars when we redisplay the whole frame. */
16839 = f->redisplay || !REDISPLAY_SOME_P (); 16839 = f->redisplay || !REDISPLAY_SOME_P ();
16840 bool f_redisplay_flag = f->redisplay; 16840 bool f_redisplay_flag = f->redisplay;
16841
16842 /* The X error handler may have deleted that frame
16843 before we went back to retry_frame. This must come
16844 before any accesses to f->terminal. */
16845 if (!FRAME_LIVE_P (f))
16846 continue;
16847
16841 /* Mark all the scroll bars to be removed; we'll redeem 16848 /* Mark all the scroll bars to be removed; we'll redeem
16842 the ones we want when we redisplay their windows. */ 16849 the ones we want when we redisplay their windows. */
16843 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook) 16850 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
@@ -16845,7 +16852,6 @@ redisplay_internal (void)
16845 16852
16846 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) 16853 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
16847 { 16854 {
16848
16849 /* Don't allow freeing images and faces for this 16855 /* Don't allow freeing images and faces for this
16850 frame as long as the frame's update wasn't 16856 frame as long as the frame's update wasn't
16851 completed. This prevents crashes when some Lisp 16857 completed. This prevents crashes when some Lisp