mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-01 19:17:02 -04:00
190 lines
5.8 KiB
Lua
190 lines
5.8 KiB
Lua
local install = require('nvim-treesitter.install')
|
|
local parsers = require('nvim-treesitter.parsers')
|
|
local config = require('nvim-treesitter.config')
|
|
local util = require('nvim-treesitter.util')
|
|
local tsq = vim.treesitter.query
|
|
local health = vim.health
|
|
|
|
local M = {}
|
|
|
|
local NVIM_TREESITTER_MINIMUM_ABI = 13
|
|
|
|
---@return string|nil
|
|
local function ts_cli_version()
|
|
if vim.fn.executable('tree-sitter') == 1 then
|
|
local result = assert(vim.system({ 'tree-sitter', '-V' }):wait().stdout)
|
|
return vim.split(result, '\n')[1]:match('[^tree%psitter ].*')
|
|
end
|
|
end
|
|
|
|
local function install_health()
|
|
health.start('Requirements')
|
|
|
|
if vim.fn.has('nvim-0.10') ~= 1 then
|
|
health.error('Nvim-treesitter requires Neovim Nightly')
|
|
end
|
|
|
|
if vim.fn.executable('tree-sitter') == 0 then
|
|
health.warn(
|
|
'`tree-sitter` executable not found (parser generator, only needed for :TSInstallFromGrammar,'
|
|
.. ' not required for :TSInstall)'
|
|
)
|
|
else
|
|
health.ok(
|
|
'`tree-sitter` found '
|
|
.. (ts_cli_version() or '(unknown version)')
|
|
.. ' (only needed for `:TSInstallFromGrammar`)'
|
|
)
|
|
end
|
|
|
|
if vim.fn.executable('node') == 0 then
|
|
health.warn('`node` executable not found (only needed for `:TSInstallFromGrammar`.')
|
|
else
|
|
local result = assert(vim.system({ 'node', '--version' }):wait().stdout)
|
|
local version = vim.split(result, '\n')[1]
|
|
health.ok('`node` found ' .. version .. ' (only needed for `:TSInstallFromGrammar`)')
|
|
end
|
|
|
|
if vim.fn.executable('git') == 0 then
|
|
health.error(
|
|
'`git` executable not found.',
|
|
'Install it with your package manager and check that your `$PATH` is set correctly.'
|
|
)
|
|
else
|
|
health.ok('`git` executable found.')
|
|
end
|
|
|
|
local cc = install.select_executable(install.compilers)
|
|
if not cc then
|
|
health.error('`cc` executable not found.', {
|
|
'Check that any of '
|
|
.. table.concat(install.compilers, ', ')
|
|
.. ' is in your $PATH'
|
|
.. ' or set `$CC` or `require"nvim-treesitter.install".compilers` explicitly.',
|
|
})
|
|
else
|
|
local version = assert(vim.system({ cc, cc == 'cl' and '' or '--version' }):wait().stdout)
|
|
health.ok(
|
|
'`'
|
|
.. cc
|
|
.. '` executable found, selected from: '
|
|
.. table.concat(install.compilers, ', ')
|
|
.. (version and ('\nVersion: ' .. version) or '')
|
|
)
|
|
end
|
|
if vim.treesitter.language_version then
|
|
if vim.treesitter.language_version >= NVIM_TREESITTER_MINIMUM_ABI then
|
|
health.ok(
|
|
'Neovim was compiled with tree-sitter runtime ABI version '
|
|
.. vim.treesitter.language_version
|
|
.. ' (required >='
|
|
.. NVIM_TREESITTER_MINIMUM_ABI
|
|
.. ').'
|
|
)
|
|
else
|
|
health.error(
|
|
'Neovim was compiled with tree-sitter runtime ABI version '
|
|
.. vim.treesitter.language_version
|
|
.. '.\n'
|
|
.. 'nvim-treesitter expects at least ABI version '
|
|
.. NVIM_TREESITTER_MINIMUM_ABI
|
|
.. '\n'
|
|
.. 'Please make sure that Neovim is linked against a recent tree-sitter library when building'
|
|
.. ' or raise an issue at your Neovim packager. Parsers must be compatible with runtime ABI.'
|
|
)
|
|
end
|
|
end
|
|
|
|
health.start('OS Info')
|
|
for k, v in pairs(vim.uv.os_uname()) do
|
|
health.info(k .. ': ' .. v)
|
|
end
|
|
|
|
local installdir = config.get_install_dir('')
|
|
health.start('Install directory for parsers and queries')
|
|
health.info(installdir)
|
|
if vim.uv.fs_access(installdir, 'w') then
|
|
health.ok('is writable.')
|
|
else
|
|
health.error('is not writable.')
|
|
end
|
|
if
|
|
vim.iter(vim.api.nvim_list_runtime_paths()):any(function(p)
|
|
if installdir == p .. '/' then
|
|
return true
|
|
end
|
|
end)
|
|
then
|
|
health.ok('is in runtimepath.')
|
|
else
|
|
health.error('is not in runtimepath.')
|
|
end
|
|
end
|
|
|
|
local function query_status(lang, query_group)
|
|
local ok, err = pcall(tsq.get, lang, query_group)
|
|
if not ok then
|
|
return 'x', err
|
|
elseif not err then
|
|
return '.'
|
|
else
|
|
return '✓'
|
|
end
|
|
end
|
|
|
|
function M.check()
|
|
--- @type {[1]: string, [2]: string, [3]: string}[]
|
|
local error_collection = {}
|
|
-- Installation dependency checks
|
|
install_health()
|
|
|
|
-- Parser installation checks
|
|
health.start('Installed languages' .. string.rep(' ', 5) .. 'H L F I J')
|
|
local languages = config.installed_parsers()
|
|
for _, lang in pairs(languages) do
|
|
local parser = parsers.configs[lang]
|
|
local out = lang .. string.rep(' ', 22 - #lang)
|
|
if parser.install_info then
|
|
for _, query_group in pairs(M.bundled_queries) do
|
|
local status, err = query_status(lang, query_group)
|
|
out = out .. status .. ' '
|
|
if err then
|
|
table.insert(error_collection, { lang, query_group, err })
|
|
end
|
|
end
|
|
end
|
|
if parser.requires then
|
|
for _, p in pairs(parser.requires) do
|
|
if not vim.list_contains(languages, p) then
|
|
table.insert(error_collection, { lang, 'queries', 'dependency ' .. p .. ' missing' })
|
|
end
|
|
end
|
|
end
|
|
health.info(vim.fn.trim(out, ' ', 2))
|
|
end
|
|
health.start(' Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[J]ections')
|
|
|
|
if #error_collection > 0 then
|
|
health.start('The following errors have been detected in query files:')
|
|
for _, p in ipairs(error_collection) do
|
|
local lang, type = p[1], p[2]
|
|
local lines = {}
|
|
table.insert(lines, lang .. '(' .. type .. '): ')
|
|
local files = tsq.get_files(lang, type)
|
|
if #files > 0 then
|
|
for _, file in ipairs(files) do
|
|
local query = util.read_file(file)
|
|
local _, file_err = pcall(tsq.parse, lang, query)
|
|
if file_err then
|
|
table.insert(lines, file)
|
|
end
|
|
end
|
|
end
|
|
health.error(table.concat(lines, ''))
|
|
end
|
|
end
|
|
end
|
|
|
|
M.bundled_queries = { 'highlights', 'locals', 'folds', 'indents', 'injections' }
|
|
|
|
return M
|