health.lua (3268B)
1 local M = {} 2 local ts = vim.treesitter 3 local health = vim.health 4 5 --- Performs a healthcheck for treesitter integration 6 function M.check() 7 health.start('Treesitter features') 8 9 health.info( 10 string.format( 11 'Treesitter ABI support: min %d, max %d', 12 ts.minimum_language_version, 13 ts.language_version 14 ) 15 ) 16 17 local can_wasm = vim._ts_add_language_from_wasm ~= nil 18 health.info(string.format('WASM parser support: %s', tostring(can_wasm))) 19 20 health.start('Treesitter parsers') 21 local parsers = vim.api.nvim_get_runtime_file('parser/*', true) 22 23 ---@class ParserEntry 24 ---@field name string 25 ---@field path string 26 ---@field index integer runtime path index (unique) 27 28 local sorted_parsers = {} ---@type ParserEntry[] 29 30 for i, parser in ipairs(parsers) do 31 local parsername = vim.fn.fnamemodify(parser, ':t:r') 32 table.insert(sorted_parsers, { name = parsername, path = parser, index = i }) 33 end 34 35 table.sort(sorted_parsers, function(a, b) 36 if a.name == b.name then 37 return a.index < b.index -- if names are the same sort by rtpath index (unique) 38 else 39 return a.name < b.name 40 end 41 end) 42 43 for i, parser in ipairs(sorted_parsers) do 44 local is_loadable, err_or_nil = pcall(ts.language.add, parser.name) 45 46 if not is_loadable then 47 health.error( 48 string.format( 49 'Parser "%s" failed to load (path: %s): %s', 50 parser.name, 51 parser.path, 52 err_or_nil or '?' 53 ) 54 ) 55 elseif i > 1 and sorted_parsers[i - 1].name == parser.name then 56 -- Sorted by runtime path order (load order), thus, if the previous parser has the same name, 57 -- the current parser will not be loaded and `ts.language.inspect(parser.name)` with have 58 -- incorrect information. 59 health.ok(string.format('Parser: %-20s (not loaded), path: %s', parser.name, parser.path)) 60 else 61 local lang = ts.language.inspect(parser.name) 62 health.ok( 63 string.format('Parser: %-25s ABI: %d, path: %s', parser.name, lang.abi_version, parser.path) 64 ) 65 end 66 end 67 68 health.start('Treesitter queries') 69 local query_files = vim.api.nvim_get_runtime_file('queries/**/*.scm', true) 70 71 ---@class QueryEntry 72 ---@field lang string 73 ---@field type string 74 ---@field path string 75 ---@field index integer 76 local queries_by_lang = {} ---@type table<string, QueryEntry[]> 77 78 for i, query_file in ipairs(query_files) do 79 local lang, query_type = query_file:match('queries/([^/]+)/([^/]+)%.scm$') 80 if lang and query_type then 81 if not queries_by_lang[lang] then 82 queries_by_lang[lang] = {} 83 end 84 table.insert(queries_by_lang[lang], { 85 lang = lang, 86 type = query_type, 87 path = query_file, 88 index = i, 89 }) 90 end 91 end 92 93 if not vim.tbl_isempty(queries_by_lang) then 94 for lang, queries in vim.spairs(queries_by_lang) do 95 table.sort(queries, function(a, b) 96 if a.type == b.type then 97 return a.index < b.index 98 else 99 return a.type < b.type 100 end 101 end) 102 103 for _, query in ipairs(queries) do 104 local dir = vim.fs.dirname(query.path) 105 health.ok(string.format('%-15s %-15s %s', lang, query.type, dir)) 106 end 107 end 108 end 109 end 110 111 return M