From 3b3c47d977bbe27f7157557b6b0e25d1dcf07640 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Thu, 2 Feb 2023 13:32:41 +0200 Subject: [PATCH] (treesit_predicate_match): Match node text against regexp without consing * src/treesit.c (treesit_predicate_match): Match node text against regexp without creating a new string object (bug#60953). * src/search.c (search_buffer): Make not static. Delete declaration near the beginning of the file. * src/lisp.h: Declare it here. * lisp/progmodes/ruby-ts-mode.el (ruby-ts--builtin-method-p): Remove function. (ruby-ts--font-lock-settings): Use the regexp with :match directly. --- lisp/progmodes/ruby-ts-mode.el | 5 +---- src/lisp.h | 3 +++ src/search.c | 5 +---- src/treesit.c | 36 ++++++++++++++++++++++++++++++++-- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index 60215978176..7725d0824e3 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -209,9 +209,6 @@ values of OVERRIDE" (treesit-fontify-with-override (max plus-1 start) (min node-end end) font-lock-comment-face override))) -(defun ruby-ts--builtin-method-p (node) - (string-match-p ruby-ts--builtin-methods (treesit-node-text node t))) - (defun ruby-ts--font-lock-settings (language) "Tree-sitter font-lock settings for Ruby." (treesit-font-lock-rules @@ -340,7 +337,7 @@ values of OVERRIDE" :language language :feature 'builtin-function `((((identifier) @font-lock-builtin-face) - (:pred ruby-ts--builtin-method-p @font-lock-builtin-face))) + (:match ,ruby-ts--builtin-methods @font-lock-builtin-face))) ;; Yuan recommends also putting method definitions into the ;; 'function' category (thus keeping it in both). I've opted to diff --git a/src/lisp.h b/src/lisp.h index 70555b3ce91..1276285e2f2 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4802,6 +4802,9 @@ extern ptrdiff_t find_newline_no_quit (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t *); extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t *); +extern EMACS_INT search_buffer (Lisp_Object, ptrdiff_t, ptrdiff_t, + ptrdiff_t, ptrdiff_t, EMACS_INT, + int, Lisp_Object, Lisp_Object, bool); extern void syms_of_search (void); extern void clear_regexp_cache (void); diff --git a/src/search.c b/src/search.c index dbc5a83946f..0bb52c03eef 100644 --- a/src/search.c +++ b/src/search.c @@ -68,9 +68,6 @@ static EMACS_INT simple_search (EMACS_INT, unsigned char *, ptrdiff_t, static EMACS_INT boyer_moore (EMACS_INT, unsigned char *, ptrdiff_t, Lisp_Object, Lisp_Object, ptrdiff_t, ptrdiff_t, int); -static EMACS_INT search_buffer (Lisp_Object, ptrdiff_t, ptrdiff_t, - ptrdiff_t, ptrdiff_t, EMACS_INT, int, - Lisp_Object, Lisp_Object, bool); Lisp_Object re_match_object; @@ -1510,7 +1507,7 @@ search_buffer_non_re (Lisp_Object string, ptrdiff_t pos, return result; } -static EMACS_INT +EMACS_INT search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, ptrdiff_t lim, ptrdiff_t lim_byte, EMACS_INT n, int RE, Lisp_Object trt, Lisp_Object inverse_trt, bool posix) diff --git a/src/treesit.c b/src/treesit.c index 405aec1f47e..52953573061 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -2470,10 +2470,42 @@ treesit_predicate_match (Lisp_Object args, struct capture_range captures) build_string ("The second argument to `match' should " "be a capture name, not a string")); - Lisp_Object text = treesit_predicate_capture_name_to_text (capture_name, + Lisp_Object node = treesit_predicate_capture_name_to_node (capture_name, captures); - if (fast_string_match (regexp, text) >= 0) + struct buffer *old_buffer = current_buffer; + struct buffer *buffer = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer); + set_buffer_internal (buffer); + + TSNode treesit_node = XTS_NODE (node)->node; + ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg; + uint32_t start_byte_offset = ts_node_start_byte (treesit_node); + uint32_t end_byte_offset = ts_node_end_byte (treesit_node); + ptrdiff_t start_byte = visible_beg + start_byte_offset; + ptrdiff_t end_byte = visible_beg + end_byte_offset; + ptrdiff_t start_pos = buf_bytepos_to_charpos (buffer, start_byte); + ptrdiff_t end_pos = buf_bytepos_to_charpos (buffer, end_byte); + ptrdiff_t old_begv = BEGV; + ptrdiff_t old_begv_byte = BEGV_BYTE; + ptrdiff_t old_zv = ZV; + ptrdiff_t old_zv_byte = ZV_BYTE; + + BEGV = start_pos; + BEGV_BYTE = start_byte; + ZV = end_pos; + ZV_BYTE = end_byte; + + ptrdiff_t val = search_buffer (regexp, start_pos, start_byte, end_pos, end_byte, + 1, 1, Qnil, Qnil, false); + + BEGV = old_begv; + BEGV_BYTE = old_begv_byte; + ZV = old_zv; + ZV_BYTE = old_zv_byte; + + set_buffer_internal (old_buffer); + + if (val > 0) return true; else return false; -- 2.39.2