aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuan Fu2023-03-21 16:03:08 -0700
committerYuan Fu2023-03-24 12:29:33 -0700
commitc3a25bfb75c1cd41a1d2c613ec944a490cf8aff7 (patch)
treed42358aeb1be9469c8f10749044fe36f4c86300a
parent4a2dccd6a68625914ae6fa4b0bbb002f5ea079db (diff)
downloademacs-c3a25bfb75c1cd41a1d2c613ec944a490cf8aff7.tar.gz
emacs-c3a25bfb75c1cd41a1d2c613ec944a490cf8aff7.zip
Refactor Ftreesit_query_capture
Refactor some part of Ftreesit_query_capture out into separate functions, to pave the way for other query-based functions. * src/treesit.c (treesit_resolve_node): New function. (treesit_initialize_query): New function. (Ftreesit_query_capture): Refactor some part into new functions.
-rw-r--r--src/treesit.c153
1 files changed, 97 insertions, 56 deletions
diff --git a/src/treesit.c b/src/treesit.c
index 5a4fe3e8803..e728d697c9d 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -2631,8 +2631,8 @@ You can use `treesit-query-validate' to validate and debug a query. */)
2631 Lisp_Object signal_symbol = Qnil; 2631 Lisp_Object signal_symbol = Qnil;
2632 Lisp_Object signal_data = Qnil; 2632 Lisp_Object signal_data = Qnil;
2633 TSQuery *treesit_query = treesit_ensure_query_compiled (lisp_query, 2633 TSQuery *treesit_query = treesit_ensure_query_compiled (lisp_query,
2634 &signal_symbol, 2634 &signal_symbol,
2635 &signal_data); 2635 &signal_data);
2636 2636
2637 if (treesit_query == NULL) 2637 if (treesit_query == NULL)
2638 xsignal (signal_symbol, signal_data); 2638 xsignal (signal_symbol, signal_data);
@@ -2641,6 +2641,92 @@ You can use `treesit-query-validate' to validate and debug a query. */)
2641 } 2641 }
2642} 2642}
2643 2643
2644/* Resolve OBJ into a tree-sitter node Lisp_Object. OBJ can be a
2645 node, a parser, or a language symbol. Note that this function can
2646 signal. */
2647static Lisp_Object treesit_resolve_node (Lisp_Object obj)
2648{
2649 if (TS_NODEP (obj))
2650 {
2651 treesit_check_node (obj); /* Check if up-to-date. */
2652 return obj;
2653 }
2654 else if (TS_PARSERP (obj))
2655 {
2656 treesit_check_parser (obj); /* Check if deleted. */
2657 return Ftreesit_parser_root_node (obj);
2658 }
2659 else if (SYMBOLP (obj))
2660 {
2661 Lisp_Object parser
2662 = Ftreesit_parser_create (obj, Fcurrent_buffer (), Qnil);
2663 return Ftreesit_parser_root_node (parser);
2664 }
2665 else
2666 xsignal2 (Qwrong_type_argument,
2667 list4 (Qor, Qtreesit_node_p, Qtreesit_parser_p, Qsymbolp),
2668 obj);
2669}
2670
2671/* Create and initialize QUERY. When success, initialize TS_QUERY,
2672 CURSOR, and NEED_FREE, and return true; if failed, initialize
2673 SIGNAL_SYMBOL and SIGNAL_DATA, and return false. If NEED_FREE is
2674 initialized to true, the TS_QUERY and CURSOR needs to be freed
2675 after use; otherwise they shouldn't be freed by hand.
2676
2677 Basically this function looks at QUERY and check its type, if QUERY
2678 is a compiled query, this function takes out its query and cursor;
2679 if QUERY is a string or a cons, this function creates a new query
2680 and cursor (so they need to be manually freed).
2681
2682 This function assumes QUERY is either a compiled query, a string or
2683 a cons, the caller should make sure QUERY is valid.
2684
2685 LANG is the language to use if we need to create the query and
2686 cursor. */
2687static bool
2688treesit_initialize_query (Lisp_Object query, const TSLanguage *lang,
2689 TSQuery **ts_query, TSQueryCursor **cursor,
2690 bool *need_free, Lisp_Object *signal_symbol,
2691 Lisp_Object *signal_data)
2692{
2693 if (TS_COMPILED_QUERY_P (query))
2694 {
2695 *ts_query = treesit_ensure_query_compiled (query, signal_symbol,
2696 signal_data);
2697 *cursor = XTS_COMPILED_QUERY (query)->cursor;
2698 /* We don't need to free ts_query and cursor because they
2699 are stored in a lisp object, which is tracked by gc. */
2700 *need_free = false;
2701 return (*ts_query != NULL);
2702 }
2703 else
2704 {
2705 /* Since query is not TS_COMPILED_QUERY, it can only be a string
2706 or a cons. */
2707 if (CONSP (query))
2708 query = Ftreesit_query_expand (query);
2709 char *query_string = SSDATA (query);
2710 uint32_t error_offset;
2711 TSQueryError error_type;
2712 *ts_query = ts_query_new (lang, query_string, strlen (query_string),
2713 &error_offset, &error_type);
2714 if (*ts_query == NULL)
2715 {
2716 *signal_symbol = Qtreesit_query_error;
2717 *signal_data = treesit_compose_query_signal_data (error_offset,
2718 error_type, query);
2719 return false;
2720 }
2721 else
2722 {
2723 *cursor = ts_query_cursor_new ();
2724 *need_free = true;
2725 return true;
2726 }
2727 }
2728}
2729
2644DEFUN ("treesit-query-capture", 2730DEFUN ("treesit-query-capture",
2645 Ftreesit_query_capture, 2731 Ftreesit_query_capture,
2646 Streesit_query_capture, 2, 5, 0, 2732 Streesit_query_capture, 2, 5, 0,
@@ -2681,27 +2767,7 @@ the query. */)
2681 treesit_initialize (); 2767 treesit_initialize ();
2682 2768
2683 /* Resolve NODE into an actual node. */ 2769 /* Resolve NODE into an actual node. */
2684 Lisp_Object lisp_node; 2770 Lisp_Object lisp_node = treesit_resolve_node (node);
2685 if (TS_NODEP (node))
2686 {
2687 treesit_check_node (node); /* Check if up-to-date. */
2688 lisp_node = node;
2689 }
2690 else if (TS_PARSERP (node))
2691 {
2692 treesit_check_parser (node); /* Check if deleted. */
2693 lisp_node = Ftreesit_parser_root_node (node);
2694 }
2695 else if (SYMBOLP (node))
2696 {
2697 Lisp_Object parser
2698 = Ftreesit_parser_create (node, Fcurrent_buffer (), Qnil);
2699 lisp_node = Ftreesit_parser_root_node (parser);
2700 }
2701 else
2702 xsignal2 (Qwrong_type_argument,
2703 list4 (Qor, Qtreesit_node_p, Qtreesit_parser_p, Qsymbolp),
2704 node);
2705 2771
2706 /* Extract C values from Lisp objects. */ 2772 /* Extract C values from Lisp objects. */
2707 TSNode treesit_node 2773 TSNode treesit_node
@@ -2725,40 +2791,15 @@ the query. */)
2725 TSQuery *treesit_query; 2791 TSQuery *treesit_query;
2726 TSQueryCursor *cursor; 2792 TSQueryCursor *cursor;
2727 bool needs_to_free_query_and_cursor; 2793 bool needs_to_free_query_and_cursor;
2728 if (TS_COMPILED_QUERY_P (query)) 2794 Lisp_Object signal_symbol;
2729 { 2795 Lisp_Object signal_data;
2730 Lisp_Object signal_symbol = Qnil; 2796 if (!treesit_initialize_query (query, lang, &treesit_query, &cursor,
2731 Lisp_Object signal_data = Qnil; 2797 &needs_to_free_query_and_cursor,
2732 treesit_query = treesit_ensure_query_compiled (query, &signal_symbol, 2798 &signal_symbol, &signal_data))
2733 &signal_data); 2799 xsignal (signal_symbol, signal_data);
2734 cursor = XTS_COMPILED_QUERY (query)->cursor;
2735 /* We don't need to free ts_query and cursor because they
2736 are stored in a lisp object, which is tracked by gc. */
2737 needs_to_free_query_and_cursor = false;
2738 if (treesit_query == NULL)
2739 xsignal (signal_symbol, signal_data);
2740 }
2741 else
2742 {
2743 /* Since query is not TS_COMPILED_QUERY, it can only be a string
2744 or a cons. */
2745 if (CONSP (query))
2746 query = Ftreesit_query_expand (query);
2747 char *query_string = SSDATA (query);
2748 uint32_t error_offset;
2749 TSQueryError error_type;
2750 treesit_query = ts_query_new (lang, query_string, strlen (query_string),
2751 &error_offset, &error_type);
2752 if (treesit_query == NULL)
2753 xsignal (Qtreesit_query_error,
2754 treesit_compose_query_signal_data (error_offset,
2755 error_type, query));
2756 cursor = ts_query_cursor_new ();
2757 needs_to_free_query_and_cursor = true;
2758 }
2759 2800
2760 /* WARN: After this point, free treesit_query and cursor before every 2801 /* WARN: After this point, free TREESIT_QUERY and CURSOR before every
2761 signal and return. */ 2802 signal and return if NEEDS_TO_FREE_QUERY_AND_CURSOR is true. */
2762 2803
2763 /* Set query range. */ 2804 /* Set query range. */
2764 if (!NILP (beg) && !NILP (end)) 2805 if (!NILP (beg) && !NILP (end))