[packages/neovim] - back-ported tree-sitter API update from master

qboosh qboosh at pld-linux.org
Sun Feb 8 14:49:40 CET 2026


commit a941881373b493464076116bb699d8b6b521955e
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date:   Sun Feb 8 14:49:58 2026 +0100

    - back-ported tree-sitter API update from master

 neovim-tree-sitter.patch | 251 +++++++++++++++++++++++++++++++++++++++++++++++
 neovim.spec              |  11 ++-
 2 files changed, 258 insertions(+), 4 deletions(-)
---
diff --git a/neovim.spec b/neovim.spec
index df666eb..c8dacdf 100644
--- a/neovim.spec
+++ b/neovim.spec
@@ -33,6 +33,8 @@ Patch0:		desktop.patch
 Patch1:		build-type.patch
 Patch2:		luv.patch
 Patch3:		luajit-lua52.patch
+# https://github.com/neovim/neovim/pull/33141.patch (already on master)
+Patch4:		neovim-tree-sitter.patch
 BuildRequires:	cmake >= 3.16
 BuildRequires:	gcc >= 6:4.4
 BuildRequires:	gettext-tools
@@ -103,10 +105,11 @@ Desktop files for Neovim.
 
 %prep
 %setup -q
-%patch -P 0 -p1
-%patch -P 1 -p1
-%patch -P 2 -p1 -R
-%patch -P 3 -p1
+%patch -P0 -p1
+%patch -P1 -p1
+%patch -P2 -p1 -R
+%patch -P3 -p1
+%patch -P4 -p1
 
 %build
 %cmake -B build \
diff --git a/neovim-tree-sitter.patch b/neovim-tree-sitter.patch
new file mode 100644
index 0000000..4800455
--- /dev/null
+++ b/neovim-tree-sitter.patch
@@ -0,0 +1,251 @@
+From a9c6564bcbee9fb0e00c056d8c88fd9f60e49e7e Mon Sep 17 00:00:00 2001
+From: Riley Bruins <ribru17 at hotmail.com>
+Date: Thu, 20 Mar 2025 14:50:15 -0700
+Subject: [PATCH] refactor(treesitter): migrate to ts parser callback API
+
+---
+ runtime/lua/vim/treesitter/_meta/misc.lua   |  4 +-
+ runtime/lua/vim/treesitter/languagetree.lua | 43 ++++++++++------
+ src/nvim/lua/treesitter.c                   | 57 +++++++++++----------
+ 3 files changed, 58 insertions(+), 46 deletions(-)
+
+diff --git a/runtime/lua/vim/treesitter/_meta/misc.lua b/runtime/lua/vim/treesitter/_meta/misc.lua
+index 07a1c921c744c3..9b9cc4eb5469d5 100644
+--- a/runtime/lua/vim/treesitter/_meta/misc.lua
++++ b/runtime/lua/vim/treesitter/_meta/misc.lua
+@@ -5,12 +5,10 @@ error('Cannot require a meta file')
+ --- at alias TSLoggerCallback fun(logtype: 'parse'|'lex', msg: string)
+ 
+ --- at class TSParser: userdata
+---- at field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: boolean): TSTree, (Range4|Range6)[]
++--- at field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: boolean, timeout_ns: integer?): TSTree?, (Range4|Range6)[]
+ --- at field reset fun(self: TSParser)
+ --- at field included_ranges fun(self: TSParser, include_bytes: boolean?): integer[]
+ --- at field set_included_ranges fun(self: TSParser, ranges: (Range6|TSNode)[])
+---- at field set_timeout fun(self: TSParser, timeout: integer)
+---- at field timeout fun(self: TSParser): integer
+ --- at field _set_logger fun(self: TSParser, lex: boolean, parse: boolean, cb: TSLoggerCallback)
+ --- at field _logger fun(self: TSParser): TSLoggerCallback
+ 
+diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
+index e7cee33a038866..6f0e377d2f920f 100644
+--- neovim-0.11.6/runtime/lua/vim/treesitter/languagetree.lua.orig	2026-01-26 16:27:53.000000000 +0100
++++ neovim-0.11.6/runtime/lua/vim/treesitter/languagetree.lua	2026-02-08 14:24:09.420882173 +0100
+@@ -43,8 +43,10 @@
+ local query = require('vim.treesitter.query')
+ local language = require('vim.treesitter.language')
+ local Range = require('vim.treesitter._range')
++local hrtime = vim.uv.hrtime
+ 
+-local default_parse_timeout_ms = 3
++-- Parse in 3ms chunks.
++local default_parse_timeout_ns = 3 * 1000000
+ 
+ --- at type Range2
+ local entire_document_range = { 0, math.huge }
+@@ -198,16 +200,16 @@ function LanguageTree:_set_logger()
+   self._parser:_set_logger(log_lex, log_parse, self._logger)
+ end
+ 
+----Measure execution time of a function
++---Measure execution time of a function, in nanoseconds.
+ --- at generic R1, R2, R3
+ --- at param f fun(): R1, R2, R3
+ --- at return number, R1, R2, R3
+ local function tcall(f, ...)
+-  local start = vim.uv.hrtime()
++  local start = hrtime()
+   --- at diagnostic disable-next-line
+   local r = { f(...) }
+   --- @type number
+-  local duration = (vim.uv.hrtime() - start) / 1000000
++  local duration = hrtime() - start
+   --- @diagnostic disable-next-line: redundant-return-value
+   return duration, unpack(r)
+ end
+@@ -388,18 +390,29 @@ function LanguageTree:_parse_regions(ran
+       )
+     then
+       self._parser:set_included_ranges(ranges)
+-      self._parser:set_timeout(thread_state.timeout and thread_state.timeout * 1000 or 0) -- ms -> micros
+ 
+-      local parse_time, tree, tree_changes =
+-        tcall(self._parser.parse, self._parser, self._trees[i], self._source, true)
++      local parse_time, tree, tree_changes = tcall(
++        self._parser.parse,
++        self._parser,
++        self._trees[i],
++        self._source,
++        true,
++        thread_state.timeout
++      )
+       while true do
+         if tree then
+           break
+         end
+         coroutine.yield(self._trees, false)
+ 
+-        parse_time, tree, tree_changes =
+-          tcall(self._parser.parse, self._parser, self._trees[i], self._source, true)
++        parse_time, tree, tree_changes = tcall(
++          self._parser.parse,
++          self._parser,
++          self._trees[i],
++          self._source,
++          true,
++          thread_state.timeout
++        )
+       end
+ 
+       self:_subtract_time(thread_state, parse_time)
+@@ -503,7 +516,7 @@ function LanguageTree:_async_parse(range
+   local buf = is_buffer_parser and vim.b[source] or nil
+   local ct = is_buffer_parser and buf.changedtick or nil
+   local total_parse_time = 0
+-  local redrawtime = vim.o.redrawtime
++  local redrawtime = vim.o.redrawtime * 1000000
+ 
+   local thread_state = {} --- at type ParserThreadState
+ 
+@@ -526,7 +539,7 @@ function LanguageTree:_async_parse(range
+       end
+     end
+ 
+-    thread_state.timeout = not vim.g._ts_force_sync_parsing and default_parse_timeout_ms or nil
++    thread_state.timeout = not vim.g._ts_force_sync_parsing and default_parse_timeout_ns or nil
+     local parse_time, trees, finished = tcall(parse, self, range, thread_state)
+     total_parse_time = total_parse_time + parse_time
+ 
+@@ -997,7 +1010,7 @@ function LanguageTree:_get_injections(ra
+ 
+   --- at type table<integer,vim.treesitter.languagetree.Injection>
+   local injections = {}
+-  local start = vim.uv.hrtime()
++  local start = hrtime()
+ 
+   local full_scan = range == true or self._injection_query.has_combined_injections
+ 
+@@ -1021,9 +1034,9 @@ function LanguageTree:_get_injections(ra
+       end
+ 
+       -- Check the current function duration against the timeout, if it exists.
+-      local current_time = vim.uv.hrtime()
+-      self:_subtract_time(thread_state, (current_time - start) / 1000000)
+-      start = current_time
++      local current_time = hrtime()
++      self:_subtract_time(thread_state, current_time - start)
++      start = hrtime()
+     end
+   end
+ 
+diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
+index a346bf59637fa0..5d3599920ea308 100644
+--- neovim-0.11.6/src/nvim/lua/treesitter.c.orig	2026-01-26 16:27:53.000000000 +0100
++++ neovim-0.11.6/src/nvim/lua/treesitter.c	2026-02-08 14:25:40.744696814 +0100
+@@ -15,6 +15,8 @@
+ #include <tree_sitter/api.h>
+ #include <uv.h>
+ 
++#include "nvim/os/time.h"
++
+ #ifdef HAVE_WASMTIME
+ # include <wasm.h>
+ 
+@@ -53,6 +55,11 @@ typedef struct {
+   const TSTree *tree;
+ } TSLuaTree;
+ 
++typedef struct {
++  uint64_t parse_start_time;
++  uint64_t timeout_threshold_ns;
++} TSLuaParserCallbackPayload;
++
+ #ifdef INCLUDE_GENERATED_DECLARATIONS
+ # include "lua/treesitter.c.generated.h"
+ #endif
+@@ -363,8 +370,6 @@ static struct luaL_Reg parser_meta[] = {
+   { "reset", parser_reset },
+   { "set_included_ranges", parser_set_ranges },
+   { "included_ranges", parser_get_ranges },
+-  { "set_timeout", parser_set_timeout },
+-  { "timeout", parser_get_timeout },
+   { "_set_logger", parser_set_logger },
+   { "_logger", parser_get_logger },
+   { NULL, NULL }
+@@ -488,6 +493,13 @@ static void push_ranges(lua_State *L, co
+   }
+ }
+ 
++static bool on_parser_progress(TSParseState *state)
++{
++  TSLuaParserCallbackPayload *payload = state->payload;
++  uint64_t parse_time = os_hrtime() - payload->parse_start_time;
++  return parse_time >= payload->timeout_threshold_ns;
++}
++
+ static int parser_parse(lua_State *L)
+ {
+   TSParser *p = parser_check(L, 1);
+@@ -525,7 +537,17 @@ static int parser_parse(lua_State *L)
+     }
+ 
+     input = (TSInput){ (void *)buf, input_cb, TSInputEncodingUTF8, NULL };
+-    new_tree = ts_parser_parse(p, old_tree, input);
++    if (!lua_isnil(L, 5)) {
++      uint64_t timeout_ns = (uint64_t)lua_tointeger(L, 5);
++      TSLuaParserCallbackPayload payload =
++        (TSLuaParserCallbackPayload){ .parse_start_time = os_hrtime(),
++                                      .timeout_threshold_ns = timeout_ns };
++      TSParseOptions parse_options = { .payload = &payload,
++                                       .progress_callback = on_parser_progress };
++      new_tree = ts_parser_parse_with_options(p, old_tree, input, parse_options);
++    } else {
++      new_tree = ts_parser_parse(p, old_tree, input);
++    }
+ 
+     break;
+ 
+@@ -535,12 +557,11 @@ static int parser_parse(lua_State *L)
+ 
+   bool include_bytes = (lua_gettop(L) >= 4) && lua_toboolean(L, 4);
+ 
+-  // Sometimes parsing fails (timeout, or wrong parser ABI)
+-  // In those case, just return an error.
+   if (!new_tree) {
+-    if (ts_parser_timeout_micros(p) == 0) {
+-      // No timeout set, must have had an error
+-      return luaL_error(L, "An error occurred when parsing.");
++    // Sometimes parsing fails (no language was set, or it was set to one with an incompatible ABI)
++    // In those cases, just return an error.
++    if (!ts_parser_language(p)) {
++      return luaL_error(L, "Language was unset, or has an incompatible ABI.");
+     }
+     return 0;
+   }
+@@ -671,26 +692,6 @@ static int parser_get_ranges(lua_State *
+   return 1;
+ }
+ 
+-static int parser_set_timeout(lua_State *L)
+-{
+-  TSParser *p = parser_check(L, 1);
+-
+-  if (lua_gettop(L) < 2) {
+-    luaL_error(L, "integer expected");
+-  }
+-
+-  uint32_t timeout = (uint32_t)luaL_checkinteger(L, 2);
+-  ts_parser_set_timeout_micros(p, timeout);
+-  return 0;
+-}
+-
+-static int parser_get_timeout(lua_State *L)
+-{
+-  TSParser *p = parser_check(L, 1);
+-  lua_pushinteger(L, (lua_Integer)ts_parser_timeout_micros(p));
+-  return 1;
+-}
+-
+ static void logger_cb(void *payload, TSLogType logtype, const char *s)
+ {
+   TSLuaLoggerOpts *opts = (TSLuaLoggerOpts *)payload;
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/neovim.git/commitdiff/a941881373b493464076116bb699d8b6b521955e



More information about the pld-cvs-commit mailing list