From d1d311a3b2222242b1b23fe0b86cd14866fd7cee Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Tue, 12 Sep 2023 00:36:07 -0700 Subject: [PATCH] Avoid unnecessary tree-sitter reparse when setting the same range * src/treesit.h (Lisp_TS_Parser) * src/treesit.c (make_treesit_parser): Remove has_range field, add last_set_ranges field. (Ftreesit_parser_set_included_ranges): Return early if the new range is the same as the old one. (Ftreesit_parser_included_ranges): Change has_range to last_set_ranges. --- src/treesit.c | 18 ++++++++++-------- src/treesit.h | 7 ++++--- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/treesit.c b/src/treesit.c index cc4f5f1998d..570329ca88b 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -1164,6 +1164,7 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser, lisp_parser->language_symbol = language_symbol; lisp_parser->after_change_functions = Qnil; lisp_parser->tag = tag; + lisp_parser->last_set_ranges = Qnil; lisp_parser->buffer = buffer; lisp_parser->parser = parser; lisp_parser->tree = tree; @@ -1174,7 +1175,6 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser, lisp_parser->visible_end = BUF_ZV_BYTE (XBUFFER (buffer)); lisp_parser->timestamp = 0; lisp_parser->deleted = false; - lisp_parser->has_range = false; eassert (lisp_parser->visible_beg <= lisp_parser->visible_end); return make_lisp_ptr (lisp_parser, Lisp_Vectorlike); } @@ -1656,6 +1656,10 @@ buffer. */) treesit_check_parser (parser); if (!NILP (ranges)) CHECK_CONS (ranges); + + if (Fequal (XTS_PARSER (parser)->last_set_ranges, ranges)) + return Qnil; + treesit_check_range_argument (ranges); treesit_initialize (); @@ -1663,10 +1667,10 @@ buffer. */) treesit_check_buffer_size (XBUFFER (XTS_PARSER (parser)->buffer)); treesit_sync_visible_region (parser); + XTS_PARSER (parser)->last_set_ranges = ranges; bool success; if (NILP (ranges)) { - XTS_PARSER (parser)->has_range = false; /* If RANGES is nil, make parser to parse the whole document. To do that we give tree-sitter a 0 length, the range is a dummy. */ @@ -1677,8 +1681,6 @@ buffer. */) else { /* Set ranges for PARSER. */ - XTS_PARSER (parser)->has_range = true; - if (list_length (ranges) > UINT32_MAX) xsignal (Qargs_out_of_range, list2 (ranges, Flength (ranges))); uint32_t len = (uint32_t) list_length (ranges); @@ -1734,10 +1736,10 @@ See also `treesit-parser-set-included-ranges'. */) /* When the parser doesn't have a range set and we call ts_parser_included_ranges on it, it doesn't return an empty list, - but rather return some garbled data. (A single range where - start_byte = 0, end_byte = UINT32_MAX). So we need to track - whether the parser is ranged ourselves. */ - if (!XTS_PARSER (parser)->has_range) + but rather return DEFAULT_RANGE. (A single range where start_byte + = 0, end_byte = UINT32_MAX). So we need to track whether the + parser is ranged ourselves. */ + if (NILP (XTS_PARSER (parser)->last_set_ranges)) return Qnil; uint32_t len; diff --git a/src/treesit.h b/src/treesit.h index ed5bab18733..ef7e2e15317 100644 --- a/src/treesit.h +++ b/src/treesit.h @@ -45,6 +45,10 @@ struct Lisp_TS_Parser same tag. A tag is primarily used to differentiate between parsers for the same language. */ Lisp_Object tag; + /* The Lisp ranges last set. This is use to compare to the new + ranges the users wants to set, and avoid reparse if the new + ranges is the same as the last set one. */ + Lisp_Object last_set_ranges; /* The buffer associated with this parser. */ Lisp_Object buffer; /* The pointer to the tree-sitter parser. Never NULL. */ @@ -76,9 +80,6 @@ struct Lisp_TS_Parser /* If this field is true, parser functions raises treesit-parser-deleted signal. */ bool deleted; - /* If this field is true, the parser has ranges set. See - Ftreesit_parser_included_ranges for why we need this. */ - bool has_range; }; /* A wrapper around a tree-sitter node. */ -- 2.39.5