fix(checkhealth): wrong ABI version for treesitter parsers #35327

Don't print ABI version of duplicated parsers that are later in the
runtime path (see [#35326]).

Change the sorting from `name > path` to `name > rtpath_index`, this
ensures the first (loaded) parser is first in the list and any
subsequent parsers can be considered "not loaded".

This is fuzzy at best since `vim.treesitter.language.add` can take a
path to a parser and change the load order.

The correct solution is for `vim.treesitter.language.inspect` to return
the parser path so we can compare against it and/or for it to also be
able to take a path to a parser so we can inspect it without loading it
first.

(cherry picked from commit bd45e2be63)
This commit is contained in:
Jalil David Salamé Messina
2025-08-14 20:47:43 +02:00
committed by github-actions[bot]
parent 27282696fe
commit 30b801eff2

View File

@@ -23,23 +23,24 @@ function M.check()
---@class ParserEntry ---@class ParserEntry
---@field name string ---@field name string
---@field path string ---@field path string
---@field index integer runtime path index (unique)
local sorted_parsers = {} ---@type ParserEntry[] local sorted_parsers = {} ---@type ParserEntry[]
for _, parser in ipairs(parsers) do for i, parser in ipairs(parsers) do
local parsername = vim.fn.fnamemodify(parser, ':t:r') local parsername = vim.fn.fnamemodify(parser, ':t:r')
table.insert(sorted_parsers, { name = parsername, path = parser }) table.insert(sorted_parsers, { name = parsername, path = parser, index = i })
end end
table.sort(sorted_parsers, function(a, b) table.sort(sorted_parsers, function(a, b)
if a.name == b.name then if a.name == b.name then
return a.path < b.path return a.index < b.index -- if names are the same sort by rtpath index (unique)
else else
return a.name < b.name return a.name < b.name
end end
end) end)
for _, parser in ipairs(sorted_parsers) do for i, parser in ipairs(sorted_parsers) do
local is_loadable, err_or_nil = pcall(ts.language.add, parser.name) local is_loadable, err_or_nil = pcall(ts.language.add, parser.name)
if not is_loadable then if not is_loadable then
@@ -51,10 +52,15 @@ function M.check()
err_or_nil or '?' err_or_nil or '?'
) )
) )
elseif i > 1 and sorted_parsers[i - 1].name == parser.name then
-- Sorted by runtime path order (load order), thus, if the previous parser has the same name,
-- the current parser will not be loaded and `ts.language.inspect(parser.name)` with have
-- incorrect information.
health.ok(string.format('Parser: %-20s (not loaded), path: %s', parser.name, parser.path))
else else
local lang = ts.language.inspect(parser.name) local lang = ts.language.inspect(parser.name)
health.ok( health.ok(
string.format('Parser: %-20s ABI: %d, path: %s', parser.name, lang.abi_version, parser.path) string.format('Parser: %-25s ABI: %d, path: %s', parser.name, lang.abi_version, parser.path)
) )
end end
end end