client.lua 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. local uv = vim.uv
  2. local api = vim.api
  3. local lsp = vim.lsp
  4. local log = lsp.log
  5. local ms = lsp.protocol.Methods
  6. local changetracking = lsp._changetracking
  7. local validate = vim.validate
  8. --- @alias vim.lsp.client.on_init_cb fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult)
  9. --- @alias vim.lsp.client.on_attach_cb fun(client: vim.lsp.Client, bufnr: integer)
  10. --- @alias vim.lsp.client.on_exit_cb fun(code: integer, signal: integer, client_id: integer)
  11. --- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)
  12. --- @class vim.lsp.Client.Flags
  13. --- @inlinedoc
  14. ---
  15. --- Allow using incremental sync for buffer edits
  16. --- (default: `true`)
  17. --- @field allow_incremental_sync? boolean
  18. ---
  19. --- Debounce `didChange` notifications to the server by the given number in milliseconds.
  20. --- No debounce occurs if `nil`.
  21. --- (default: `150`)
  22. --- @field debounce_text_changes integer
  23. ---
  24. --- Milliseconds to wait for server to exit cleanly after sending the
  25. --- "shutdown" request before sending kill -15. If set to false, nvim exits
  26. --- immediately after sending the "shutdown" request to the server.
  27. --- (default: `false`)
  28. --- @field exit_timeout integer|false
  29. --- @class vim.lsp.ClientConfig
  30. --- command string[] that launches the language
  31. --- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like
  32. --- "~" are not expanded), or function that creates an RPC client. Function receives
  33. --- a `dispatchers` table and returns a table with member functions `request`, `notify`,
  34. --- `is_closing` and `terminate`.
  35. --- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|.
  36. --- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()|
  37. --- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
  38. ---
  39. --- Directory to launch the `cmd` process. Not related to `root_dir`.
  40. --- (default: cwd)
  41. --- @field cmd_cwd? string
  42. ---
  43. --- Environment flags to pass to the LSP on spawn.
  44. --- Must be specified using a table.
  45. --- Non-string values are coerced to string.
  46. --- Example:
  47. --- ```lua
  48. --- { PORT = 8080; HOST = "0.0.0.0"; }
  49. --- ```
  50. --- @field cmd_env? table
  51. ---
  52. --- Daemonize the server process so that it runs in a separate process group from Nvim.
  53. --- Nvim will shutdown the process on exit, but if Nvim fails to exit cleanly this could leave
  54. --- behind orphaned server processes.
  55. --- (default: true)
  56. --- @field detached? boolean
  57. ---
  58. --- List of workspace folders passed to the language server.
  59. --- For backwards compatibility rootUri and rootPath will be derived from the first workspace
  60. --- folder in this list. See `workspaceFolders` in the LSP spec.
  61. --- @field workspace_folders? lsp.WorkspaceFolder[]
  62. ---
  63. --- Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|,
  64. --- passed to the language server on initialization. Hint: use make_client_capabilities() and modify
  65. --- its result.
  66. --- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an
  67. --- array.
  68. --- @field capabilities? lsp.ClientCapabilities
  69. ---
  70. --- Map of language server method names to |lsp-handler|
  71. --- @field handlers? table<string,function>
  72. ---
  73. --- Map with language server specific settings.
  74. --- See the {settings} in |vim.lsp.Client|.
  75. --- @field settings? lsp.LSPObject
  76. ---
  77. --- Table that maps string of clientside commands to user-defined functions.
  78. --- Commands passed to `start()` take precedence over the global command registry. Each key
  79. --- must be a unique command name, and the value is a function which is called if any LSP action
  80. --- (code action, code lenses, ...) triggers the command.
  81. --- @field commands? table<string,fun(command: lsp.Command, ctx: table)>
  82. ---
  83. --- Values to pass in the initialization request as `initializationOptions`. See `initialize` in
  84. --- the LSP spec.
  85. --- @field init_options? lsp.LSPObject
  86. ---
  87. --- Name in log messages.
  88. --- (default: client-id)
  89. --- @field name? string
  90. ---
  91. --- Language ID as string. Defaults to the buffer filetype.
  92. --- @field get_language_id? fun(bufnr: integer, filetype: string): string
  93. ---
  94. --- Called "position encoding" in LSP spec, the encoding that the LSP server expects.
  95. --- Client does not verify this is correct.
  96. --- @field offset_encoding? 'utf-8'|'utf-16'|'utf-32'
  97. ---
  98. --- Callback invoked when the client operation throws an error. `code` is a number describing the error.
  99. --- Other arguments may be passed depending on the error kind. See `vim.lsp.rpc.client_errors`
  100. --- for possible errors. Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name.
  101. --- @field on_error? fun(code: integer, err: string)
  102. ---
  103. --- Callback invoked before the LSP "initialize" phase, where `params` contains the parameters
  104. --- being sent to the server and `config` is the config that was passed to |vim.lsp.start()|.
  105. --- You can use this to modify parameters before they are sent.
  106. --- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)
  107. ---
  108. --- Callback invoked after LSP "initialize", where `result` is a table of `capabilities`
  109. --- and anything else the server may send. For example, clangd sends
  110. --- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was sent to it.
  111. --- You can only modify the `client.offset_encoding` here before any notifications are sent.
  112. --- @field on_init? elem_or_list<fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult)>
  113. ---
  114. --- Callback invoked on client exit.
  115. --- - code: exit code of the process
  116. --- - signal: number describing the signal used to terminate (if any)
  117. --- - client_id: client handle
  118. --- @field on_exit? elem_or_list<fun(code: integer, signal: integer, client_id: integer)>
  119. ---
  120. --- Callback invoked when client attaches to a buffer.
  121. --- @field on_attach? elem_or_list<fun(client: vim.lsp.Client, bufnr: integer)>
  122. ---
  123. --- Passed directly to the language server in the initialize request. Invalid/empty values will
  124. --- (default: "off")
  125. --- @field trace? 'off'|'messages'|'verbose'
  126. ---
  127. --- A table with flags for the client. The current (experimental) flags are:
  128. --- @field flags? vim.lsp.Client.Flags
  129. ---
  130. --- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization.
  131. --- @field root_dir? string
  132. --- @class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}>
  133. --- @field pending table<lsp.ProgressToken,lsp.LSPAny>
  134. --- @class vim.lsp.Client
  135. ---
  136. --- The id allocated to the client.
  137. --- @field id integer
  138. ---
  139. --- If a name is specified on creation, that will be used. Otherwise it is just
  140. --- the client id. This is used for logs and messages.
  141. --- @field name string
  142. ---
  143. --- RPC client object, for low level interaction with the client.
  144. --- See |vim.lsp.rpc.start()|.
  145. --- @field rpc vim.lsp.rpc.PublicClient
  146. ---
  147. --- Called "position encoding" in LSP spec,
  148. --- the encoding used for communicating with the server.
  149. --- You can modify this in the `config`'s `on_init` method
  150. --- before text is sent to the server.
  151. --- @field offset_encoding string
  152. ---
  153. --- The handlers used by the client as described in |lsp-handler|.
  154. --- @field handlers table<string,lsp.Handler>
  155. ---
  156. --- The current pending requests in flight to the server. Entries are key-value
  157. --- pairs with the key being the request id while the value is a table with
  158. --- `type`, `bufnr`, and `method` key-value pairs. `type` is either "pending"
  159. --- for an active request, or "cancel" for a cancel request. It will be
  160. --- "complete" ephemerally while executing |LspRequest| autocmds when replies
  161. --- are received from the server.
  162. --- @field requests table<integer,{ type: string, bufnr: integer, method: string}?>
  163. ---
  164. --- copy of the table that was passed by the user
  165. --- to |vim.lsp.start()|.
  166. --- @field config vim.lsp.ClientConfig
  167. ---
  168. --- Response from the server sent on `initialize` describing the server's
  169. --- capabilities.
  170. --- @field server_capabilities lsp.ServerCapabilities?
  171. ---
  172. --- Response from the server sent on `initialize` describing information about
  173. --- the server.
  174. --- @field server_info lsp.ServerInfo?
  175. ---
  176. --- A ring buffer (|vim.ringbuf()|) containing progress messages
  177. --- sent by the server.
  178. --- @field progress vim.lsp.Client.Progress
  179. ---
  180. --- @field initialized true?
  181. ---
  182. --- The workspace folders configured in the client when the server starts.
  183. --- This property is only available if the client supports workspace folders.
  184. --- It can be `null` if the client supports workspace folders but none are
  185. --- configured.
  186. --- @field workspace_folders lsp.WorkspaceFolder[]?
  187. --- @field root_dir string?
  188. ---
  189. --- @field attached_buffers table<integer,true>
  190. ---
  191. --- @field private _log_prefix string
  192. ---
  193. --- Track this so that we can escalate automatically if we've already tried a
  194. --- graceful shutdown
  195. --- @field private _graceful_shutdown_failed true?
  196. ---
  197. --- The initial trace setting. If omitted trace is disabled ("off").
  198. --- trace = "off" | "messages" | "verbose";
  199. --- @field private _trace 'off'|'messages'|'verbose'
  200. ---
  201. --- Table of command name to function which is called if any LSP action
  202. --- (code action, code lenses, ...) triggers the command.
  203. --- Client commands take precedence over the global command registry.
  204. --- @field commands table<string,fun(command: lsp.Command, ctx: table)>
  205. ---
  206. --- Map with language server specific settings. These are returned to the
  207. --- language server if requested via `workspace/configuration`. Keys are
  208. --- case-sensitive.
  209. --- @field settings lsp.LSPObject
  210. ---
  211. --- A table with flags for the client. The current (experimental) flags are:
  212. --- @field flags vim.lsp.Client.Flags
  213. ---
  214. --- @field get_language_id fun(bufnr: integer, filetype: string): string
  215. ---
  216. --- The capabilities provided by the client (editor or tool)
  217. --- @field capabilities lsp.ClientCapabilities
  218. --- @field private registrations table<string,lsp.Registration[]>
  219. --- @field dynamic_capabilities lsp.DynamicCapabilities
  220. ---
  221. --- @field private _before_init_cb? vim.lsp.client.before_init_cb
  222. --- @field private _on_attach_cbs vim.lsp.client.on_attach_cb[]
  223. --- @field private _on_init_cbs vim.lsp.client.on_init_cb[]
  224. --- @field private _on_exit_cbs vim.lsp.client.on_exit_cb[]
  225. --- @field private _on_error_cb? fun(code: integer, err: string)
  226. local Client = {}
  227. Client.__index = Client
  228. --- @param obj table<string,any>
  229. --- @param cls table<string,function>
  230. --- @param name string
  231. local function method_wrapper(obj, cls, name)
  232. local meth = assert(cls[name])
  233. obj[name] = function(...)
  234. local arg = select(1, ...)
  235. if arg and getmetatable(arg) == cls then
  236. -- First argument is self, call meth directly
  237. return meth(...)
  238. end
  239. vim.deprecate('client.' .. name, 'client:' .. name, '0.13')
  240. -- First argument is not self, insert it
  241. return meth(obj, ...)
  242. end
  243. end
  244. local client_index = 0
  245. --- Checks whether a given path is a directory.
  246. --- @param filename (string) path to check
  247. --- @return boolean # true if {filename} exists and is a directory, false otherwise
  248. local function is_dir(filename)
  249. validate('filename', filename, 'string')
  250. local stat = uv.fs_stat(filename)
  251. return stat and stat.type == 'directory' or false
  252. end
  253. local valid_encodings = {
  254. ['utf-8'] = 'utf-8',
  255. ['utf-16'] = 'utf-16',
  256. ['utf-32'] = 'utf-32',
  257. ['utf8'] = 'utf-8',
  258. ['utf16'] = 'utf-16',
  259. ['utf32'] = 'utf-32',
  260. }
  261. --- Normalizes {encoding} to valid LSP encoding names.
  262. --- @param encoding string? Encoding to normalize
  263. --- @return string # normalized encoding name
  264. local function validate_encoding(encoding)
  265. validate('encoding', encoding, 'string', true)
  266. if not encoding then
  267. return valid_encodings.utf16
  268. end
  269. return valid_encodings[encoding:lower()]
  270. or error(
  271. string.format(
  272. "Invalid position encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'",
  273. encoding
  274. )
  275. )
  276. end
  277. --- Augments a validator function with support for optional (nil) values.
  278. --- @param fn (fun(v): boolean) The original validator function; should return a
  279. --- bool.
  280. --- @return fun(v): boolean # The augmented function. Also returns true if {v} is
  281. --- `nil`.
  282. local function optional_validator(fn)
  283. return function(v)
  284. return v == nil or fn(v)
  285. end
  286. end
  287. --- By default, get_language_id just returns the exact filetype it is passed.
  288. --- It is possible to pass in something that will calculate a different filetype,
  289. --- to be sent by the client.
  290. --- @param _bufnr integer
  291. --- @param filetype string
  292. local function default_get_language_id(_bufnr, filetype)
  293. return filetype
  294. end
  295. --- Validates a client configuration as given to |vim.lsp.start()|.
  296. --- @param config vim.lsp.ClientConfig
  297. local function validate_config(config)
  298. validate('config', config, 'table')
  299. validate('handlers', config.handlers, 'table', true)
  300. validate('capabilities', config.capabilities, 'table', true)
  301. validate('cmd_cwd', config.cmd_cwd, optional_validator(is_dir), 'directory')
  302. validate('cmd_env', config.cmd_env, 'table', true)
  303. validate('detached', config.detached, 'boolean', true)
  304. validate('name', config.name, 'string', true)
  305. validate('on_error', config.on_error, 'function', true)
  306. validate('on_exit', config.on_exit, { 'function', 'table' }, true)
  307. validate('on_init', config.on_init, { 'function', 'table' }, true)
  308. validate('on_attach', config.on_attach, { 'function', 'table' }, true)
  309. validate('settings', config.settings, 'table', true)
  310. validate('commands', config.commands, 'table', true)
  311. validate('before_init', config.before_init, { 'function', 'table' }, true)
  312. validate('offset_encoding', config.offset_encoding, 'string', true)
  313. validate('flags', config.flags, 'table', true)
  314. validate('get_language_id', config.get_language_id, 'function', true)
  315. assert(
  316. (
  317. not config.flags
  318. or not config.flags.debounce_text_changes
  319. or type(config.flags.debounce_text_changes) == 'number'
  320. ),
  321. 'flags.debounce_text_changes must be a number with the debounce time in milliseconds'
  322. )
  323. end
  324. --- @param trace string
  325. --- @return 'off'|'messages'|'verbose'
  326. local function get_trace(trace)
  327. local valid_traces = {
  328. off = 'off',
  329. messages = 'messages',
  330. verbose = 'verbose',
  331. }
  332. return trace and valid_traces[trace] or 'off'
  333. end
  334. --- @param id integer
  335. --- @param config vim.lsp.ClientConfig
  336. --- @return string
  337. local function get_name(id, config)
  338. local name = config.name
  339. if name then
  340. return name
  341. end
  342. if type(config.cmd) == 'table' and config.cmd[1] then
  343. return assert(vim.fs.basename(config.cmd[1]))
  344. end
  345. return tostring(id)
  346. end
  347. --- @nodoc
  348. --- @param config vim.lsp.ClientConfig
  349. --- @return vim.lsp.Client?
  350. function Client.create(config)
  351. validate_config(config)
  352. client_index = client_index + 1
  353. local id = client_index
  354. local name = get_name(id, config)
  355. --- @class vim.lsp.Client
  356. local self = {
  357. id = id,
  358. config = config,
  359. handlers = config.handlers or {},
  360. offset_encoding = validate_encoding(config.offset_encoding),
  361. name = name,
  362. _log_prefix = string.format('LSP[%s]', name),
  363. requests = {},
  364. attached_buffers = {},
  365. server_capabilities = {},
  366. registrations = {},
  367. commands = config.commands or {},
  368. settings = config.settings or {},
  369. flags = config.flags or {},
  370. get_language_id = config.get_language_id or default_get_language_id,
  371. capabilities = config.capabilities,
  372. workspace_folders = lsp._get_workspace_folders(config.workspace_folders or config.root_dir),
  373. root_dir = config.root_dir,
  374. _before_init_cb = config.before_init,
  375. _on_init_cbs = vim._ensure_list(config.on_init),
  376. _on_exit_cbs = vim._ensure_list(config.on_exit),
  377. _on_attach_cbs = vim._ensure_list(config.on_attach),
  378. _on_error_cb = config.on_error,
  379. _trace = get_trace(config.trace),
  380. --- Contains $/progress report messages.
  381. --- They have the format {token: integer|string, value: any}
  382. --- For "work done progress", value will be one of:
  383. --- - lsp.WorkDoneProgressBegin,
  384. --- - lsp.WorkDoneProgressReport (extended with title from Begin)
  385. --- - lsp.WorkDoneProgressEnd (extended with title from Begin)
  386. progress = vim.ringbuf(50) --[[@as vim.lsp.Client.Progress]],
  387. --- @deprecated use client.progress instead
  388. messages = { name = name, messages = {}, progress = {}, status = {} },
  389. }
  390. self.capabilities =
  391. vim.tbl_deep_extend('force', lsp.protocol.make_client_capabilities(), self.capabilities or {})
  392. --- @class lsp.DynamicCapabilities
  393. --- @nodoc
  394. self.dynamic_capabilities = {
  395. capabilities = self.registrations,
  396. client_id = id,
  397. register = function(_, registrations)
  398. return self:_register_dynamic(registrations)
  399. end,
  400. unregister = function(_, unregistrations)
  401. return self:_unregister_dynamic(unregistrations)
  402. end,
  403. get = function(_, method, opts)
  404. return self:_get_registration(method, opts and opts.bufnr)
  405. end,
  406. supports_registration = function(_, method)
  407. return self:_supports_registration(method)
  408. end,
  409. supports = function(_, method, opts)
  410. return self:_get_registration(method, opts and opts.bufnr) ~= nil
  411. end,
  412. }
  413. --- @type table<string|integer, string> title of unfinished progress sequences by token
  414. self.progress.pending = {}
  415. --- @type vim.lsp.rpc.Dispatchers
  416. local dispatchers = {
  417. notification = function(...)
  418. return self:_notification(...)
  419. end,
  420. server_request = function(...)
  421. return self:_server_request(...)
  422. end,
  423. on_error = function(...)
  424. return self:_on_error(...)
  425. end,
  426. on_exit = function(...)
  427. return self:_on_exit(...)
  428. end,
  429. }
  430. -- Start the RPC client.
  431. local config_cmd = config.cmd
  432. if type(config_cmd) == 'function' then
  433. self.rpc = config_cmd(dispatchers)
  434. else
  435. self.rpc = lsp.rpc.start(config_cmd, dispatchers, {
  436. cwd = config.cmd_cwd,
  437. env = config.cmd_env,
  438. detached = config.detached,
  439. })
  440. end
  441. setmetatable(self, Client)
  442. method_wrapper(self, Client, 'request')
  443. method_wrapper(self, Client, 'request_sync')
  444. method_wrapper(self, Client, 'notify')
  445. method_wrapper(self, Client, 'cancel_request')
  446. method_wrapper(self, Client, 'stop')
  447. method_wrapper(self, Client, 'is_stopped')
  448. method_wrapper(self, Client, 'on_attach')
  449. method_wrapper(self, Client, 'supports_method')
  450. return self
  451. end
  452. --- @private
  453. --- @param cbs function[]
  454. --- @param error_id integer
  455. --- @param ... any
  456. function Client:_run_callbacks(cbs, error_id, ...)
  457. for _, cb in pairs(cbs) do
  458. --- @type boolean, string?
  459. local status, err = pcall(cb, ...)
  460. if not status then
  461. self:write_error(error_id, err)
  462. end
  463. end
  464. end
  465. --- @nodoc
  466. function Client:initialize()
  467. local config = self.config
  468. local root_uri --- @type string?
  469. local root_path --- @type string?
  470. if self.workspace_folders then
  471. root_uri = self.workspace_folders[1].uri
  472. root_path = vim.uri_to_fname(root_uri)
  473. end
  474. local initialize_params = {
  475. -- The process Id of the parent process that started the server. Is null if
  476. -- the process has not been started by another process. If the parent
  477. -- process is not alive then the server should exit (see exit notification)
  478. -- its process.
  479. processId = uv.os_getpid(),
  480. -- Information about the client
  481. -- since 3.15.0
  482. clientInfo = {
  483. name = 'Neovim',
  484. version = tostring(vim.version()),
  485. },
  486. -- The rootPath of the workspace. Is null if no folder is open.
  487. --
  488. -- @deprecated in favour of rootUri.
  489. rootPath = root_path or vim.NIL,
  490. -- The rootUri of the workspace. Is null if no folder is open. If both
  491. -- `rootPath` and `rootUri` are set `rootUri` wins.
  492. rootUri = root_uri or vim.NIL,
  493. workspaceFolders = self.workspace_folders or vim.NIL,
  494. -- User provided initialization options.
  495. initializationOptions = config.init_options,
  496. capabilities = self.capabilities,
  497. trace = self._trace,
  498. workDoneToken = '1',
  499. }
  500. self:_run_callbacks(
  501. { self._before_init_cb },
  502. lsp.client_errors.BEFORE_INIT_CALLBACK_ERROR,
  503. initialize_params,
  504. config
  505. )
  506. log.trace(self._log_prefix, 'initialize_params', initialize_params)
  507. local rpc = self.rpc
  508. rpc.request('initialize', initialize_params, function(init_err, result)
  509. assert(not init_err, tostring(init_err))
  510. assert(result, 'server sent empty result')
  511. rpc.notify('initialized', vim.empty_dict())
  512. self.initialized = true
  513. -- These are the cleaned up capabilities we use for dynamically deciding
  514. -- when to send certain events to clients.
  515. self.server_capabilities =
  516. assert(result.capabilities, "initialize result doesn't contain capabilities")
  517. self.server_capabilities = assert(lsp.protocol.resolve_capabilities(self.server_capabilities))
  518. if self.server_capabilities.positionEncoding then
  519. self.offset_encoding = self.server_capabilities.positionEncoding
  520. end
  521. self.server_info = result.serverInfo
  522. if next(self.settings) then
  523. self:notify(ms.workspace_didChangeConfiguration, { settings = self.settings })
  524. end
  525. -- If server is being restarted, make sure to re-attach to any previously attached buffers.
  526. -- Save which buffers before on_init in case new buffers are attached.
  527. local reattach_bufs = vim.deepcopy(self.attached_buffers)
  528. self:_run_callbacks(self._on_init_cbs, lsp.client_errors.ON_INIT_CALLBACK_ERROR, self, result)
  529. for buf in pairs(reattach_bufs) do
  530. -- The buffer may have been detached in the on_init callback.
  531. if self.attached_buffers[buf] then
  532. self:on_attach(buf)
  533. end
  534. end
  535. log.info(
  536. self._log_prefix,
  537. 'server_capabilities',
  538. { server_capabilities = self.server_capabilities }
  539. )
  540. end)
  541. end
  542. --- @private
  543. --- Returns the handler associated with an LSP method.
  544. --- Returns the default handler if the user hasn't set a custom one.
  545. ---
  546. --- @param method (string) LSP method name
  547. --- @return lsp.Handler? handler for the given method, if defined, or the default from |vim.lsp.handlers|
  548. function Client:_resolve_handler(method)
  549. return self.handlers[method] or lsp.handlers[method]
  550. end
  551. --- @private
  552. --- @param id integer
  553. --- @param req_type 'pending'|'complete'|'cancel'|
  554. --- @param bufnr? integer (only required for req_type='pending')
  555. --- @param method? string (only required for req_type='pending')
  556. function Client:_process_request(id, req_type, bufnr, method)
  557. local pending = req_type == 'pending'
  558. validate('id', id, 'number')
  559. if pending then
  560. validate('bufnr', bufnr, 'number')
  561. validate('method', method, 'string')
  562. end
  563. local cur_request = self.requests[id]
  564. if pending and cur_request then
  565. log.error(
  566. self._log_prefix,
  567. ('Cannot create request with id %d as one already exists'):format(id)
  568. )
  569. return
  570. elseif not pending and not cur_request then
  571. log.error(
  572. self._log_prefix,
  573. ('Cannot find request with id %d whilst attempting to %s'):format(id, req_type)
  574. )
  575. return
  576. end
  577. if cur_request then
  578. bufnr = cur_request.bufnr
  579. method = cur_request.method
  580. end
  581. assert(bufnr and method)
  582. local request = { type = req_type, bufnr = bufnr, method = method }
  583. -- Clear 'complete' requests
  584. -- Note 'pending' and 'cancelled' requests are cleared when the server sends a response
  585. -- which is processed via the notify_reply_callback argument to rpc.request.
  586. self.requests[id] = req_type ~= 'complete' and request or nil
  587. api.nvim_exec_autocmds('LspRequest', {
  588. buffer = api.nvim_buf_is_valid(bufnr) and bufnr or nil,
  589. modeline = false,
  590. data = { client_id = self.id, request_id = id, request = request },
  591. })
  592. end
  593. --- Sends a request to the server.
  594. ---
  595. --- This is a thin wrapper around {client.rpc.request} with some additional
  596. --- checks for capabilities and handler availability.
  597. ---
  598. --- @param method string LSP method name.
  599. --- @param params? table LSP request params.
  600. --- @param handler? lsp.Handler Response |lsp-handler| for this method.
  601. --- @param bufnr? integer (default: 0) Buffer handle, or 0 for current.
  602. --- @return boolean status indicates whether the request was successful.
  603. --- If it is `false`, then it will always be `false` (the client has shutdown).
  604. --- @return integer? request_id Can be used with |Client:cancel_request()|.
  605. --- `nil` is request failed.
  606. --- to cancel the-request.
  607. --- @see |vim.lsp.buf_request_all()|
  608. function Client:request(method, params, handler, bufnr)
  609. if not handler then
  610. handler = assert(
  611. self:_resolve_handler(method),
  612. string.format('not found: %q request handler for client %q.', method, self.name)
  613. )
  614. end
  615. -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state
  616. changetracking.flush(self, bufnr)
  617. bufnr = vim._resolve_bufnr(bufnr)
  618. local version = lsp.util.buf_versions[bufnr]
  619. log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr)
  620. local success, request_id = self.rpc.request(method, params, function(err, result)
  621. handler(err, result, {
  622. method = method,
  623. client_id = self.id,
  624. bufnr = bufnr,
  625. params = params,
  626. version = version,
  627. })
  628. end, function(request_id)
  629. -- Called when the server sends a response to the request (including cancelled acknowledgment).
  630. self:_process_request(request_id, 'complete')
  631. end)
  632. if success and request_id then
  633. self:_process_request(request_id, 'pending', bufnr, method)
  634. end
  635. return success, request_id
  636. end
  637. -- TODO(lewis6991): duplicated from lsp.lua
  638. local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' }
  639. --- Concatenates and writes a list of strings to the Vim error buffer.
  640. ---
  641. --- @param ... string List to write to the buffer
  642. local function err_message(...)
  643. local chunks = { { table.concat(vim.iter({ ... }):flatten():totable()) } }
  644. if vim.in_fast_event() then
  645. vim.schedule(function()
  646. api.nvim_echo(chunks, true, { err = true })
  647. api.nvim_command('redraw')
  648. end)
  649. else
  650. api.nvim_echo(chunks, true, { err = true })
  651. api.nvim_command('redraw')
  652. end
  653. end
  654. --- Sends a request to the server and synchronously waits for the response.
  655. ---
  656. --- This is a wrapper around |Client:request()|
  657. ---
  658. --- @param method string LSP method name.
  659. --- @param params table LSP request params.
  660. --- @param timeout_ms integer? Maximum time in milliseconds to wait for
  661. --- a result. Defaults to 1000
  662. --- @param bufnr? integer (default: 0) Buffer handle, or 0 for current.
  663. --- @return {err: lsp.ResponseError?, result:any}? `result` and `err` from the |lsp-handler|.
  664. --- `nil` is the request was unsuccessful
  665. --- @return string? err On timeout, cancel or error, where `err` is a
  666. --- string describing the failure reason.
  667. --- @see |vim.lsp.buf_request_sync()|
  668. function Client:request_sync(method, params, timeout_ms, bufnr)
  669. local request_result = nil
  670. local function _sync_handler(err, result)
  671. request_result = { err = err, result = result }
  672. end
  673. local success, request_id = self:request(method, params, _sync_handler, bufnr)
  674. if not success then
  675. return nil
  676. end
  677. local wait_result, reason = vim.wait(timeout_ms or 1000, function()
  678. return request_result ~= nil
  679. end, 10)
  680. if not wait_result then
  681. if request_id then
  682. self:cancel_request(request_id)
  683. end
  684. return nil, wait_result_reason[reason]
  685. end
  686. return request_result
  687. end
  688. --- Sends a notification to an LSP server.
  689. ---
  690. --- @param method string LSP method name.
  691. --- @param params table? LSP request params.
  692. --- @return boolean status indicating if the notification was successful.
  693. --- If it is false, then the client has shutdown.
  694. function Client:notify(method, params)
  695. if method ~= ms.textDocument_didChange then
  696. changetracking.flush(self)
  697. end
  698. local client_active = self.rpc.notify(method, params)
  699. if client_active then
  700. vim.schedule(function()
  701. api.nvim_exec_autocmds('LspNotify', {
  702. modeline = false,
  703. data = {
  704. client_id = self.id,
  705. method = method,
  706. params = params,
  707. },
  708. })
  709. end)
  710. end
  711. return client_active
  712. end
  713. --- Cancels a request with a given request id.
  714. ---
  715. --- @param id integer id of request to cancel
  716. --- @return boolean status indicating if the notification was successful.
  717. --- @see |Client:notify()|
  718. function Client:cancel_request(id)
  719. self:_process_request(id, 'cancel')
  720. return self.rpc.notify(ms.dollar_cancelRequest, { id = id })
  721. end
  722. --- Stops a client, optionally with force.
  723. ---
  724. --- By default, it will just request the server to shutdown without force. If
  725. --- you request to stop a client which has previously been requested to
  726. --- shutdown, it will automatically escalate and force shutdown.
  727. ---
  728. --- @param force? boolean
  729. function Client:stop(force)
  730. local rpc = self.rpc
  731. if rpc.is_closing() then
  732. return
  733. end
  734. vim.lsp._watchfiles.cancel(self.id)
  735. if force or not self.initialized or self._graceful_shutdown_failed then
  736. rpc.terminate()
  737. return
  738. end
  739. -- Sending a signal after a process has exited is acceptable.
  740. rpc.request(ms.shutdown, nil, function(err, _)
  741. if err == nil then
  742. rpc.notify(ms.exit)
  743. else
  744. -- If there was an error in the shutdown request, then term to be safe.
  745. rpc.terminate()
  746. self._graceful_shutdown_failed = true
  747. end
  748. end)
  749. end
  750. --- Get options for a method that is registered dynamically.
  751. --- @param method string
  752. function Client:_supports_registration(method)
  753. local capability = vim.tbl_get(self.capabilities, unpack(vim.split(method, '/')))
  754. return type(capability) == 'table' and capability.dynamicRegistration
  755. end
  756. --- @private
  757. --- @param registrations lsp.Registration[]
  758. function Client:_register_dynamic(registrations)
  759. -- remove duplicates
  760. self:_unregister_dynamic(registrations)
  761. for _, reg in ipairs(registrations) do
  762. local method = reg.method
  763. if not self.registrations[method] then
  764. self.registrations[method] = {}
  765. end
  766. table.insert(self.registrations[method], reg)
  767. end
  768. end
  769. --- @param registrations lsp.Registration[]
  770. function Client:_register(registrations)
  771. self:_register_dynamic(registrations)
  772. local unsupported = {} --- @type string[]
  773. for _, reg in ipairs(registrations) do
  774. local method = reg.method
  775. if method == ms.workspace_didChangeWatchedFiles then
  776. vim.lsp._watchfiles.register(reg, self.id)
  777. elseif not self:_supports_registration(method) then
  778. unsupported[#unsupported + 1] = method
  779. end
  780. end
  781. if #unsupported > 0 then
  782. local warning_tpl = 'The language server %s triggers a registerCapability '
  783. .. 'handler for %s despite dynamicRegistration set to false. '
  784. .. 'Report upstream, this warning is harmless'
  785. log.warn(string.format(warning_tpl, self.name, table.concat(unsupported, ', ')))
  786. end
  787. end
  788. --- @private
  789. --- @param unregistrations lsp.Unregistration[]
  790. function Client:_unregister_dynamic(unregistrations)
  791. for _, unreg in ipairs(unregistrations) do
  792. local sreg = self.registrations[unreg.method]
  793. -- Unegister dynamic capability
  794. for i, reg in ipairs(sreg or {}) do
  795. if reg.id == unreg.id then
  796. table.remove(sreg, i)
  797. break
  798. end
  799. end
  800. end
  801. end
  802. --- @param unregistrations lsp.Unregistration[]
  803. function Client:_unregister(unregistrations)
  804. self:_unregister_dynamic(unregistrations)
  805. for _, unreg in ipairs(unregistrations) do
  806. if unreg.method == ms.workspace_didChangeWatchedFiles then
  807. vim.lsp._watchfiles.unregister(unreg, self.id)
  808. end
  809. end
  810. end
  811. --- @private
  812. function Client:_get_language_id(bufnr)
  813. return self.get_language_id(bufnr, vim.bo[bufnr].filetype)
  814. end
  815. --- @param method string
  816. --- @param bufnr? integer
  817. --- @return lsp.Registration?
  818. function Client:_get_registration(method, bufnr)
  819. bufnr = vim._resolve_bufnr(bufnr)
  820. for _, reg in ipairs(self.registrations[method] or {}) do
  821. if not reg.registerOptions or not reg.registerOptions.documentSelector then
  822. return reg
  823. end
  824. local documentSelector = reg.registerOptions.documentSelector
  825. local language = self:_get_language_id(bufnr)
  826. local uri = vim.uri_from_bufnr(bufnr)
  827. local fname = vim.uri_to_fname(uri)
  828. for _, filter in ipairs(documentSelector) do
  829. if
  830. not (filter.language and language ~= filter.language)
  831. and not (filter.scheme and not vim.startswith(uri, filter.scheme .. ':'))
  832. and not (filter.pattern and not vim.glob.to_lpeg(filter.pattern):match(fname))
  833. then
  834. return reg
  835. end
  836. end
  837. end
  838. end
  839. --- Checks whether a client is stopped.
  840. ---
  841. --- @return boolean # true if client is stopped or in the process of being
  842. --- stopped; false otherwise
  843. function Client:is_stopped()
  844. return self.rpc.is_closing()
  845. end
  846. --- Execute a lsp command, either via client command function (if available)
  847. --- or via workspace/executeCommand (if supported by the server)
  848. ---
  849. --- @param command lsp.Command
  850. --- @param context? {bufnr?: integer}
  851. --- @param handler? lsp.Handler only called if a server command
  852. function Client:exec_cmd(command, context, handler)
  853. context = vim.deepcopy(context or {}, true) --[[@as lsp.HandlerContext]]
  854. context.bufnr = vim._resolve_bufnr(context.bufnr)
  855. context.client_id = self.id
  856. local cmdname = command.command
  857. local fn = self.commands[cmdname] or lsp.commands[cmdname]
  858. if fn then
  859. fn(command, context)
  860. return
  861. end
  862. local command_provider = self.server_capabilities.executeCommandProvider
  863. local commands = type(command_provider) == 'table' and command_provider.commands or {}
  864. if not vim.list_contains(commands, cmdname) then
  865. vim.notify_once(
  866. string.format(
  867. 'Language server `%s` does not support command `%s`. This command may require a client extension.',
  868. self.name,
  869. cmdname
  870. ),
  871. vim.log.levels.WARN
  872. )
  873. return
  874. end
  875. -- Not using command directly to exclude extra properties,
  876. -- see https://github.com/python-lsp/python-lsp-server/issues/146
  877. --- @type lsp.ExecuteCommandParams
  878. local params = {
  879. command = cmdname,
  880. arguments = command.arguments,
  881. }
  882. self:request(ms.workspace_executeCommand, params, handler, context.bufnr)
  883. end
  884. --- Default handler for the 'textDocument/didOpen' LSP notification.
  885. ---
  886. --- @param bufnr integer Number of the buffer, or 0 for current
  887. function Client:_text_document_did_open_handler(bufnr)
  888. changetracking.init(self, bufnr)
  889. if not self:supports_method(ms.textDocument_didOpen) then
  890. return
  891. end
  892. if not api.nvim_buf_is_loaded(bufnr) then
  893. return
  894. end
  895. self:notify(ms.textDocument_didOpen, {
  896. textDocument = {
  897. version = lsp.util.buf_versions[bufnr],
  898. uri = vim.uri_from_bufnr(bufnr),
  899. languageId = self:_get_language_id(bufnr),
  900. text = lsp._buf_get_full_text(bufnr),
  901. },
  902. })
  903. -- Next chance we get, we should re-do the diagnostics
  904. vim.schedule(function()
  905. -- Protect against a race where the buffer disappears
  906. -- between `did_open_handler` and the scheduled function firing.
  907. if api.nvim_buf_is_valid(bufnr) then
  908. local namespace = lsp.diagnostic.get_namespace(self.id)
  909. vim.diagnostic.show(namespace, bufnr)
  910. end
  911. end)
  912. end
  913. --- Runs the on_attach function from the client's config if it was defined.
  914. --- Useful for buffer-local setup.
  915. --- @param bufnr integer Buffer number
  916. function Client:on_attach(bufnr)
  917. self:_text_document_did_open_handler(bufnr)
  918. lsp._set_defaults(self, bufnr)
  919. api.nvim_exec_autocmds('LspAttach', {
  920. buffer = bufnr,
  921. modeline = false,
  922. data = { client_id = self.id },
  923. })
  924. self:_run_callbacks(self._on_attach_cbs, lsp.client_errors.ON_ATTACH_ERROR, self, bufnr)
  925. -- schedule the initialization of semantic tokens to give the above
  926. -- on_attach and LspAttach callbacks the ability to schedule wrap the
  927. -- opt-out (deleting the semanticTokensProvider from capabilities)
  928. vim.schedule(function()
  929. if vim.tbl_get(self.server_capabilities, 'semanticTokensProvider', 'full') then
  930. lsp.semantic_tokens.start(bufnr, self.id)
  931. end
  932. end)
  933. self.attached_buffers[bufnr] = true
  934. end
  935. --- @private
  936. --- Logs the given error to the LSP log and to the error buffer.
  937. --- @param code integer Error code
  938. --- @param err any Error arguments
  939. function Client:write_error(code, err)
  940. local client_error = lsp.client_errors[code] --- @type string|integer
  941. log.error(self._log_prefix, 'on_error', { code = client_error, err = err })
  942. err_message(self._log_prefix, ': Error ', client_error, ': ', vim.inspect(err))
  943. end
  944. --- Checks if a client supports a given method.
  945. --- Always returns true for unknown off-spec methods.
  946. ---
  947. --- Note: Some language server capabilities can be file specific.
  948. --- @param method string
  949. --- @param bufnr? integer
  950. function Client:supports_method(method, bufnr)
  951. -- Deprecated form
  952. if type(bufnr) == 'table' then
  953. --- @diagnostic disable-next-line:no-unknown
  954. bufnr = bufnr.bufnr
  955. end
  956. local required_capability = lsp._request_name_to_capability[method]
  957. -- if we don't know about the method, assume that the client supports it.
  958. if not required_capability then
  959. return true
  960. end
  961. if vim.tbl_get(self.server_capabilities, unpack(required_capability)) then
  962. return true
  963. end
  964. local rmethod = lsp._resolve_to_request[method]
  965. if rmethod then
  966. if self:_supports_registration(rmethod) then
  967. local reg = self:_get_registration(rmethod, bufnr)
  968. return vim.tbl_get(reg or {}, 'registerOptions', 'resolveProvider') or false
  969. end
  970. else
  971. if self:_supports_registration(method) then
  972. return self:_get_registration(method, bufnr) ~= nil
  973. end
  974. end
  975. return false
  976. end
  977. --- Get options for a method that is registered dynamically.
  978. --- @param method string
  979. --- @param bufnr? integer
  980. --- @return lsp.LSPAny?
  981. function Client:_get_registration_options(method, bufnr)
  982. if not self:_supports_registration(method) then
  983. return
  984. end
  985. local reg = self:_get_registration(method, bufnr)
  986. if reg then
  987. return reg.registerOptions
  988. end
  989. end
  990. --- @private
  991. --- Handles a notification sent by an LSP server by invoking the
  992. --- corresponding handler.
  993. ---
  994. --- @param method string LSP method name
  995. --- @param params table The parameters for that method.
  996. function Client:_notification(method, params)
  997. log.trace('notification', method, params)
  998. local handler = self:_resolve_handler(method)
  999. if handler then
  1000. -- Method name is provided here for convenience.
  1001. handler(nil, params, { method = method, client_id = self.id })
  1002. end
  1003. end
  1004. --- @private
  1005. --- Handles a request from an LSP server by invoking the corresponding handler.
  1006. ---
  1007. --- @param method (string) LSP method name
  1008. --- @param params (table) The parameters for that method
  1009. --- @return any result
  1010. --- @return lsp.ResponseError error code and message set in case an exception happens during the request.
  1011. function Client:_server_request(method, params)
  1012. log.trace('server_request', method, params)
  1013. local handler = self:_resolve_handler(method)
  1014. if handler then
  1015. log.trace('server_request: found handler for', method)
  1016. return handler(nil, params, { method = method, client_id = self.id })
  1017. end
  1018. log.warn('server_request: no handler found for', method)
  1019. return nil, lsp.rpc_response_error(lsp.protocol.ErrorCodes.MethodNotFound)
  1020. end
  1021. --- @private
  1022. --- Invoked when the client operation throws an error.
  1023. ---
  1024. --- @param code integer Error code
  1025. --- @param err any Other arguments may be passed depending on the error kind
  1026. --- @see vim.lsp.rpc.client_errors for possible errors. Use
  1027. --- `vim.lsp.rpc.client_errors[code]` to get a human-friendly name.
  1028. function Client:_on_error(code, err)
  1029. self:write_error(code, err)
  1030. if self._on_error_cb then
  1031. --- @type boolean, string
  1032. local status, usererr = pcall(self._on_error_cb, code, err)
  1033. if not status then
  1034. log.error(self._log_prefix, 'user on_error failed', { err = usererr })
  1035. err_message(self._log_prefix, ' user on_error failed: ', tostring(usererr))
  1036. end
  1037. end
  1038. end
  1039. --- @private
  1040. --- Invoked on client exit.
  1041. ---
  1042. --- @param code integer) exit code of the process
  1043. --- @param signal integer the signal used to terminate (if any)
  1044. function Client:_on_exit(code, signal)
  1045. self:_run_callbacks(
  1046. self._on_exit_cbs,
  1047. lsp.client_errors.ON_EXIT_CALLBACK_ERROR,
  1048. code,
  1049. signal,
  1050. self.id
  1051. )
  1052. end
  1053. --- Add a directory to the workspace folders.
  1054. --- @param dir string?
  1055. function Client:_add_workspace_folder(dir)
  1056. for _, folder in pairs(self.workspace_folders or {}) do
  1057. if folder.name == dir then
  1058. print(dir, 'is already part of this workspace')
  1059. return
  1060. end
  1061. end
  1062. local wf = assert(lsp._get_workspace_folders(dir))
  1063. self:notify(ms.workspace_didChangeWorkspaceFolders, {
  1064. event = { added = wf, removed = {} },
  1065. })
  1066. if not self.workspace_folders then
  1067. self.workspace_folders = {}
  1068. end
  1069. vim.list_extend(self.workspace_folders, wf)
  1070. end
  1071. --- Remove a directory to the workspace folders.
  1072. --- @param dir string?
  1073. function Client:_remove_workspace_folder(dir)
  1074. local wf = assert(lsp._get_workspace_folders(dir))
  1075. self:notify(ms.workspace_didChangeWorkspaceFolders, {
  1076. event = { added = {}, removed = wf },
  1077. })
  1078. for idx, folder in pairs(self.workspace_folders) do
  1079. if folder.name == dir then
  1080. table.remove(self.workspace_folders, idx)
  1081. break
  1082. end
  1083. end
  1084. end
  1085. return Client