diff options
| author | Stefan Kangas | 2022-12-25 06:30:21 +0100 |
|---|---|---|
| committer | Stefan Kangas | 2022-12-25 06:30:21 +0100 |
| commit | 48db8b68a8eb5c12d5682f2eb31cadc53186f5d7 (patch) | |
| tree | 3798efa0cd02c6ed2c3e6fe1f7cd8f3059fe492e /src | |
| parent | 4dc5bee98d5734b4f7113b961bafead1eb091bd0 (diff) | |
| parent | c36fe3df17b37a705299239d6ef0185ad55b1d3a (diff) | |
| download | emacs-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.c | 1 | ||||
| -rw-r--r-- | src/treesit.c | 138 | ||||
| -rw-r--r-- | src/xdisp.c | 8 |
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. */ | ||
| 410 | const ptrdiff_t treesit_recursion_limit = 1000; | ||
| 407 | bool treesit_initialized = false; | 411 | bool treesit_initialized = false; |
| 408 | 412 | ||
| 409 | static bool | 413 | static 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 | ||
| 1765 | static TSTreeCursor treesit_cursor_helper (TSNode, Lisp_Object); | 1769 | static bool treesit_cursor_helper (TSTreeCursor *, TSNode, Lisp_Object); |
| 1766 | 1770 | ||
| 1767 | DEFUN ("treesit-node-parent", | 1771 | DEFUN ("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. */ | ||
| 2651 | static bool | ||
| 2652 | treesit_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.) */ |
| 2649 | static TSTreeCursor | 2707 | static bool |
| 2650 | treesit_cursor_helper (TSNode node, Lisp_Object parser) | 2708 | treesit_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 |