1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
local api = vim.api
local fn = vim.fn
local queries = require "nvim-treesitter.query"
local info = require "nvim-treesitter.info"
local shell = require "nvim-treesitter.shell_command_selectors"
local install = require "nvim-treesitter.install"
local utils = require "nvim-treesitter.utils"
local health = vim.health or require "health"
local M = {}
local NVIM_TREESITTER_MINIMUM_ABI = 13
local function install_health()
health.report_start "Installation"
if fn.has "nvim-0.7" == 0 then
health.report_error "Nvim-treesitter requires Neovim 0.7.0+"
end
if fn.executable "tree-sitter" == 0 then
health.report_warn(
"`tree-sitter` executable not found (parser generator, only needed for :TSInstallFromGrammar,"
.. " not required for :TSInstall)"
)
else
health.report_ok(
"`tree-sitter` found "
.. (utils.ts_cli_version() or "(unknown version)")
.. " (parser generator, only needed for :TSInstallFromGrammar)"
)
end
if fn.executable "node" == 0 then
health.report_warn(
"`node` executable not found (only needed for :TSInstallFromGrammar," .. " not required for :TSInstall)"
)
else
local handle = io.popen "node --version"
local result = handle:read "*a"
handle:close()
local version = vim.split(result, "\n")[1]
health.report_ok("`node` found " .. version .. " (only needed for :TSInstallFromGrammar)")
end
if fn.executable "git" == 0 then
health.report_error("`git` executable not found.", {
"Install it with your package manager.",
"Check that your `$PATH` is set correctly.",
})
else
health.report_ok "`git` executable found."
end
local cc = shell.select_executable(install.compilers)
if not cc then
health.report_error("`cc` executable not found.", {
"Check that any of "
.. vim.inspect(install.compilers)
.. " is in your $PATH"
.. ' or set the environment variable CC or `require"nvim-treesitter.install".compilers` explicitly!',
})
else
local version = vim.fn.systemlist(cc .. (cc == "cl" and "" or " --version"))[1]
health.report_ok(
"`"
.. cc
.. "` executable found. Selected from "
.. vim.inspect(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.report_ok(
"Neovim was compiled with tree-sitter runtime ABI version "
.. vim.treesitter.language_version
.. " (required >="
.. NVIM_TREESITTER_MINIMUM_ABI
.. "). Parsers must be compatible with runtime ABI."
)
else
health.report_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 are recent tree-sitter runtime when building"
.. " or raise an issue at your Neovim packager. Parsers must be compatible with runtime ABI."
)
end
end
end
local function query_status(lang, query_group)
local ok, err = pcall(queries.get_query, lang, query_group)
if not ok then
return "x", err
elseif not err then
return "."
else
return "✓"
end
end
function M.check()
local error_collection = {}
-- Installation dependency checks
install_health()
queries.invalidate_query_cache()
-- Parser installation checks
local parser_installation = { "Parser/Features H L F I J" }
for _, parser_name in pairs(info.installed_parsers()) do
local installed = #api.nvim_get_runtime_file("parser/" .. parser_name .. ".so", false)
-- Only append information about installed parsers
if installed >= 1 then
local multiple_parsers = installed > 1 and "+" or ""
local out = " - " .. parser_name .. multiple_parsers .. string.rep(" ", 15 - (#parser_name + #multiple_parsers))
for _, query_group in pairs(queries.built_in_query_groups) do
local status, err = query_status(parser_name, query_group)
out = out .. status .. " "
if err then
table.insert(error_collection, { parser_name, query_group, err })
end
end
table.insert(parser_installation, vim.fn.trim(out, " ", 2))
end
end
local legend = [[
Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[j]ections
+) multiple parsers found, only one will be used
x) errors found in the query, try to run :TSUpdate {lang}]]
table.insert(parser_installation, legend)
-- Finally call the report function
health.report_start(table.concat(parser_installation, "\n"))
if #error_collection > 0 then
health.report_start "The following errors have been detected:"
for _, p in ipairs(error_collection) do
local lang, type, err = unpack(p)
local lines = {}
table.insert(lines, lang .. "(" .. type .. "): " .. err)
local files = vim.treesitter.query.get_query_files(lang, type)
if #files > 0 then
table.insert(lines, lang .. "(" .. type .. ") is concatenated from the following files:")
for _, file in ipairs(files) do
local fd = io.open(file, "r")
if fd then
local ok, file_err = pcall(vim.treesitter.query.parse_query, lang, fd:read "*a")
if ok then
table.insert(lines, '| [OK]:"' .. file .. '"')
else
table.insert(lines, '| [ERROR]:"' .. file .. '", failed to load: ' .. file_err)
end
fd:close()
end
end
end
health.report_error(table.concat(lines, "\n"))
end
end
end
return M
|